<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: nabbisen</title>
    <description>The latest articles on DEV Community by nabbisen (@nabbisen).</description>
    <link>https://dev.to/nabbisen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F87972%2Fb8906b69-d11d-4d7c-b3b7-ba77da28d654.jpg</url>
      <title>DEV Community: nabbisen</title>
      <link>https://dev.to/nabbisen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nabbisen"/>
    <language>en</language>
    <item>
      <title>OpenBSD 7.8 を 7.9 へ アップグレード</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Fri, 04 Sep 2026 22:22:28 +0000</pubDate>
      <link>https://dev.to/nabbisen/openbsd-78-wo-79-he-atupuguredo-13pg</link>
      <guid>https://dev.to/nabbisen/openbsd-78-wo-79-he-atupuguredo-13pg</guid>
      <description>&lt;h2&gt;
  
  
  はじめに
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.openbsd.org/" rel="noopener noreferrer"&gt;OpenBSD&lt;/a&gt; プロジェクトから 2026 年 5 月 19 日に OS の &lt;a href="https://www.openbsd.org/79.html" rel="noopener noreferrer"&gt;7.9&lt;/a&gt; がリリースされました 🌷 60 回目のリリースに当たります。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb7lex0t8nzcjffxmk05o.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb7lex0t8nzcjffxmk05o.gif" alt="openbsd release"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.openbsd.org/79.html#new" rel="noopener noreferrer"&gt;What's New (英語)&lt;/a&gt; | &lt;a href="https://www.openbsd.org/plus79.html" rel="noopener noreferrer"&gt;Changelog (英語)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;本記事で OpenBSD 7.8 を 7.9 にアップグレードする手順を説明します。&lt;br&gt;
各手順はすばらしい &lt;a href="https://www.openbsd.org/faq/upgrade79.html" rel="noopener noreferrer"&gt;公式ガイド (英語)&lt;/a&gt; に基づいています。&lt;/p&gt;
&lt;h2&gt;
  
  
  チュートリアル
&lt;/h2&gt;

&lt;p&gt;実行するコマンド一式を示しながら、ステップ・バイ・ステップ形式で書いた、アップグレード用のガイドです。&lt;/p&gt;

&lt;center&gt;🌷 🐡 🌅&lt;/center&gt;
&lt;h3&gt;
  
  
  1. アップグレード前準備: 検証とカスタイマイズ
&lt;/h3&gt;

&lt;p&gt;公式のチュートリアルには &lt;a href="https://www.openbsd.org/faq/upgrade79.html#BeforeUpdate" rel="noopener noreferrer"&gt;Before using any upgrade method&lt;/a&gt; (私訳: アップグレード方法に関わらずその前に行うこと) セクションが設けられています。&lt;/p&gt;

&lt;p&gt;アップグレード方法としては &lt;a href="https://man.openbsd.org/sysupgrade" rel="noopener noreferrer"&gt;&lt;code&gt;sysupgrade&lt;/code&gt;&lt;/a&gt; を使うのが、たいていの場合、良い選択になるでしょう。&lt;/p&gt;
&lt;h4&gt;
  
  
  ディスク空き容量の確認
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;/usr&lt;/code&gt; に 1.1GB 以上の空きがあることが必要です。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt;
&lt;span class="go"&gt;Filesystem     Size    Used   Avail Capacity  Mounted on
(...)
/dev/sd0e      7.8G    1.8G    5.6G    25%    /usr
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK のようです :)&lt;/p&gt;

&lt;h4&gt;
  
  
  現在の利用内容がアップグレード結果に適合することの確認
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.openbsd.org/faq/upgrade79.html#ConfigChanges" rel="noopener noreferrer"&gt;設定と構文の変更 (英語)&lt;/a&gt; と &lt;a href="https://www.openbsd.org/faq/upgrade79.html#SpecialPackages" rel="noopener noreferrer"&gt;特別なパッケージ (英語)&lt;/a&gt; を確認しましょう。&lt;br&gt;
後者に関して、今回は &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; のメジャーアップデートが含まれています。&lt;a href="https://www.postgresql.org/docs/release/18.1/" rel="noopener noreferrer"&gt;18.1&lt;/a&gt; にアップデートされます。&lt;/p&gt;


&lt;h4&gt;
  
  
  バックアップ (必要な場合)
&lt;/h4&gt;

&lt;p&gt;適宜、事前にバックアップを取得しておきましょう。&lt;/p&gt;
&lt;h4&gt;
  
  
  アップグレード内容のカスタマイズ (必要な場合)
&lt;/h4&gt;

&lt;p&gt;ここは参照用であり、標準のアップグレードではスキップできます。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://man.openbsd.org/sysupgrade" rel="noopener noreferrer"&gt;/auto_upgrade.conf&lt;/a&gt; をレスポンス・ファイルとして利用できます。&lt;br&gt;
OpenBSD の &lt;a href="https://man.openbsd.org/autoinstall.8" rel="noopener noreferrer"&gt;autoinstall&lt;/a&gt; のドキュメントに、次のように書かれています:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If either &lt;em&gt;&lt;code&gt;/auto_install.conf&lt;/code&gt;&lt;/em&gt; or &lt;em&gt;&lt;code&gt;/auto_upgrade.conf&lt;/code&gt;&lt;/em&gt; is found on &lt;em&gt;&lt;code&gt;bsd.rd&lt;/code&gt;&lt;/em&gt;'s built-in RAM disk, &lt;strong&gt;&lt;code&gt;autoinstall&lt;/code&gt;&lt;/strong&gt; behaves as if the machine is netbooted, but uses the local response file. In case both files exist, &lt;em&gt;&lt;code&gt;/auto_install.conf&lt;/code&gt;&lt;/em&gt; takes precedence.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(私訳: &lt;em&gt;&lt;code&gt;/auto_install.conf&lt;/code&gt;&lt;/em&gt; または &lt;em&gt;&lt;code&gt;/auto_upgrade.conf&lt;/code&gt;&lt;/em&gt; が &lt;em&gt;&lt;code&gt;bsd.rd&lt;/code&gt;&lt;/em&gt; 内蔵の RAM ディスクに存在する場合、&lt;strong&gt;&lt;code&gt;autoinstall&lt;/code&gt;&lt;/strong&gt; は、ネットブートモードで起動されたマシンのように振る舞いますが、ローカルにあるレスポンス・ファイルを使用します。両方のファイルが存在する場合、&lt;em&gt;&lt;code&gt;/auto_install.conf&lt;/code&gt;&lt;/em&gt; が優先されます。)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/auto_upgrade.conf&lt;/code&gt; の完全な内容の一例は次のようなものです:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;Location&lt;/span&gt; &lt;span class="err"&gt;of&lt;/span&gt; &lt;span class="py"&gt;sets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;disk&lt;/span&gt;
&lt;span class="err"&gt;Pathname&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="py"&gt;sets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/home/_sysupgrade/&lt;/span&gt;
&lt;span class="err"&gt;Set&lt;/span&gt; &lt;span class="err"&gt;name(s)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;-x*&lt;/span&gt;
&lt;span class="err"&gt;Set&lt;/span&gt; &lt;span class="err"&gt;name(s)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;+xbase*&lt;/span&gt;
&lt;span class="err"&gt;Set&lt;/span&gt; &lt;span class="err"&gt;name(s)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;-game*&lt;/span&gt;
&lt;span class="err"&gt;Set&lt;/span&gt; &lt;span class="err"&gt;name(s)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;done&lt;/span&gt;
&lt;span class="err"&gt;Directory&lt;/span&gt; &lt;span class="err"&gt;does&lt;/span&gt; &lt;span class="err"&gt;not&lt;/span&gt; &lt;span class="err"&gt;contain&lt;/span&gt; &lt;span class="err"&gt;SHA256.sig.&lt;/span&gt; &lt;span class="err"&gt;Continue&lt;/span&gt; &lt;span class="err"&gt;without&lt;/span&gt; &lt;span class="py"&gt;verification&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;この場合、xbase を除く x 一式と game が、インストール対象外になります。&lt;/p&gt;

&lt;p&gt;それから &lt;a href="https://man.openbsd.org/upgrade.site.5" rel="noopener noreferrer"&gt;/upgrade.site&lt;/a&gt; を用いた指定も可能です。&lt;/p&gt;




&lt;h3&gt;
  
  
  2. &lt;code&gt;sysupgrade&lt;/code&gt; によるアップグレード
&lt;/h3&gt;

&lt;p&gt;準備は良いですか。&lt;/p&gt;

&lt;p&gt;* 注意: 以下のコマンド &lt;code&gt;sysupgrade&lt;/code&gt; は、ひとたび実行すると中断はできません。&lt;/p&gt;

&lt;p&gt;準備ができたら、以下のコマンドを実行しましょう。実行するのはこれだけです:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas sysupgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;以下のように出力されるでしょう:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Fetching from https://cdn.openbsd.org/pub/OpenBSD/7.9/amd64/
SHA256.sig   100% |******************************|  2144       00:00
Signature Verified
BUILDINFO    100% |******************************|    54       00:00
Verifying old sets.
INSTALL.amd64 100% |*****************************| 44889       00:00
base79.tgz   100% |******************************|   510 MB    04:24
bsd          100% |******************************| 32203 KB    00:22
bsd.mp       100% |******************************| 32331 KB    00:14
bsd.rd       100% |******************************|  4734 KB    00:04
comp79.tgz   100% |******************************| 88886 KB    00:12
game79.tgz   100% |******************************|  2742 KB    00:03
man79.tgz    100% |******************************|  8406 KB    00:04
xbase79.tgz  100% |******************************| 47835 KB    00:08
xfont79.tgz  100% |******************************| 23022 KB    00:05
xserv79.tgz  100% |******************************| 11815 KB    00:05
xshare79.tgz 100% |******************************|  4562 KB    00:04
Verifying sets.
Fetching updated firmware.
&lt;/span&gt;&lt;span class="gp"&gt;fw_update: add none;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;update intel,vmm
&lt;span class="go"&gt;Upgrading.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;マシンの再起動とシステムのアップグレードが行われます。ふたたび再起動が行われて、&lt;a href="https://man.openbsd.org/sysmerge" rel="noopener noreferrer"&gt;&lt;code&gt;sysmerge&lt;/code&gt;&lt;/a&gt; が自動で実行されます。それから &lt;code&gt;sshd&lt;/code&gt; 等のデーモンが、従来のように起動されます。"Checking for available binary patches..." と出力されて、もし対象が存在すれば "Run syspatch(8) to install:" と表示されるでしょう。&lt;/p&gt;

&lt;p&gt;最終的に以下が表示されます:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;starting local daemons: cron.
Sat Sep  5 06:20:31 JST 2026

OpenBSD/amd64 ... (ttyC0)

login:
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ログインメッセージが表示されています。"OpenBSD 7.9 (GENERIC.MP)" とあります。&lt;/p&gt;

&lt;h3&gt;
  
  
  3. アップグレード後の操作: &lt;code&gt;sysmerge&lt;/code&gt; (必要に応じて)
&lt;/h3&gt;

&lt;p&gt;公式ドキュメントに &lt;a href="https://www.openbsd.org/faq/upgrade79.html#AfterSets" rel="noopener noreferrer"&gt;アップグレード後に行うこと (英語)&lt;/a&gt; が書かれています。大いに参考になるでしょう。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In some cases, configuration files cannot be modified automatically. Run&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# sysmerge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;to check and perform these configuration changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ここで言われているのは、手動で &lt;code&gt;sysmerge&lt;/code&gt; を実行することが必要な場合もある、ということです。&lt;br&gt;
以下のような conf ファイルを、手動でマージすることが必要な場合もあります。気を付けてください:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/etc/login.conf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;コマンドを実行してみましょう:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas sysmerge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;まず差分が出力されるでしょう。それから以下のようにたずねられます:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;  Use 'd' to delete the temporary ./etc/login.conf
  Use 'i' to install the temporary ./etc/login.conf
  Use 'm' to merge the temporary and installed versions
  Use 'v' to view the diff results again

  Default is to leave the temporary file to deal with by hand

How should I deal with this? [Leave it for later]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;最初の 3 つは、以下のような挙動になります:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;d&lt;/code&gt;: 現在の (ローカルの) ファイルを保持する。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;i&lt;/code&gt;: &lt;code&gt;sysupgrade&lt;/code&gt; が取得した新しいファイルでローカルを上書きする。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;m&lt;/code&gt;: 対話型形式で手動でマージする。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;m&lt;/code&gt; を入力するとマージモードが立ち上がります。一つ一つの差分について、いずれを採用するのかを確認されるでしょう:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;l&lt;/code&gt; を入力すると左側が採用されます。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;r&lt;/code&gt; は右側です。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;その後に、マージ結果ファイルに対して、どの操作を行うのかをたずねられます:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Use 'e' to edit the merged file
  Use 'i' to install the merged file
  Use 'n' to view a diff between the merged and new files
  Use 'o' to view a diff between the old and merged files
  Use 'r' to re-do the merge
  Use 'v' to view the merged file
  Use 'x' to delete the merged file and go back to previous menu
  Default is to leave the temporary file to deal with by hand

===&amp;gt; How should I deal with the merged file? [Leave it for later]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;e&lt;/code&gt; を入力すると、エディタが起動されてマージ結果ファイルを編集できるようになります。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;i&lt;/code&gt; を入力すると、マージ結果ファイルをマシンにインストールします:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;===&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Merging /etc/login.conf &lt;span class="o"&gt;(&lt;/span&gt;running cap_mkdb&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;, needs a relog&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. &lt;code&gt;syspatch&lt;/code&gt; の適用 (スキップ可能)
&lt;/h3&gt;

&lt;p&gt;ここからの 2 つのタスクは、日常的なメンテナンスで、システムをアップデートする時にも実施するものです。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;syspatch&lt;/code&gt; は重要なコマンドです。OpenBSD から、必要と判明し次第都度、継続的に提供される公式のバイナリ・パッチです。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas syspatch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. パッケージのアップデート
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.openbsd.org/79.html#new" rel="noopener noreferrer"&gt;What's new (英語)&lt;/a&gt; セクションがリリースページにありますが、そこの "Ports and packages" (Ports とパッケージ (英語)) に "Some highlights" (注目点 (英語)) が記載されています。例えば、VMM/VMD が今回も更新されています。&lt;/p&gt;

&lt;p&gt;次のコマンドはマシンにインストールされているすべてのパッケージをアップデートします:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas pkg_add &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;大量の出力が現れるでしょう。これらは慎重に読む必要があります。終わりの部分は特に、です。そこに重要な変更点や実施すべきアクションが書かれているかもしれません。私の場合、&lt;a href="https://fishshell.com/" rel="noopener noreferrer"&gt;fish&lt;/a&gt; をデフォルトのシェルとして使っているのですが、こちらが正常に起動することをいつも確認しています。というのも、かつて &lt;a href="https://www.python.org/" rel="noopener noreferrer"&gt;Python&lt;/a&gt; のアップグレードの影響でクラッシュするようになったことがあるからです 😅&lt;/p&gt;

&lt;h3&gt;
  
  
  6. 設定と構文の変更
&lt;/h3&gt;

&lt;p&gt;必要に応じて conf を更新して、&lt;a href="https://www.openbsd.org/faq/upgrade79.html#ConfigChanges" rel="noopener noreferrer"&gt;設定と構文の変更 (英語)&lt;/a&gt; に書かれている内容を適用しましょう。&lt;/p&gt;

&lt;h3&gt;
  
  
  7. 古くなったファイルの削除
&lt;/h3&gt;

&lt;p&gt;ここはシンプルな手順です。公式チュートリアルの &lt;a href="https://www.openbsd.org/faq/upgrade79.html#RmFiles" rel="noopener noreferrer"&gt;削除すべきファイル (英語)&lt;/a&gt; に書かれていることを行うだけです。&lt;/p&gt;

&lt;p&gt;今回の対象はありません。&lt;/p&gt;

&lt;h3&gt;
  
  
  8. 特別なパッケージ
&lt;/h3&gt;

&lt;p&gt;公式チュートリアルの &lt;a href="https://www.openbsd.org/faq/upgrade79.html#SpecialPackages" rel="noopener noreferrer"&gt;特別なパッケージ (英語)&lt;/a&gt; を確認しましょう。使っているものがあるかもしれません:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;aide&lt;/li&gt;
&lt;li&gt;caddy&lt;/li&gt;
&lt;li&gt;exim&lt;/li&gt;
&lt;li&gt;icinga&lt;/li&gt;
&lt;li&gt;lldpd&lt;/li&gt;
&lt;li&gt;postgresql&lt;/li&gt;
&lt;li&gt;puppet&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9. 再起動
&lt;/h3&gt;

&lt;p&gt;ゴールが見えて来ました ! 最後に必須では無いですが再起動しておくと良いしれません:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  おわりに
&lt;/h2&gt;

&lt;p&gt;新しいシステムとあなたが長く楽しい時間を過ごせますように :)&lt;/p&gt;

&lt;p&gt;OpenBSD プロジェクトとコミュニティへの深い感謝を込めつつ。&lt;/p&gt;

</description>
      <category>openbsd</category>
      <category>os</category>
      <category>upgrade</category>
      <category>migration</category>
    </item>
    <item>
      <title>OpenBSD Upgrade 7.8 to 7.9</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Fri, 04 Sep 2026 21:46:23 +0000</pubDate>
      <link>https://dev.to/nabbisen/openbsd-upgrade-78-to-79-1agm</link>
      <guid>https://dev.to/nabbisen/openbsd-upgrade-78-to-79-1agm</guid>
      <description>&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.openbsd.org/" rel="noopener noreferrer"&gt;OpenBSD&lt;/a&gt; project released &lt;a href="https://www.openbsd.org/79.html" rel="noopener noreferrer"&gt;7.9&lt;/a&gt; of their OS on 19 May 2026, as their 60th release 💫&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb7lex0t8nzcjffxmk05o.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb7lex0t8nzcjffxmk05o.gif" alt="openbsd release" width="200" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.openbsd.org/79.html#new" rel="noopener noreferrer"&gt;What's New&lt;/a&gt; | &lt;a href="https://www.openbsd.org/plus79.html" rel="noopener noreferrer"&gt;Changelog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post shows how to upgrade OpenBSD 7.8 to 7.9.&lt;br&gt;
The steps are based on &lt;a href="https://www.openbsd.org/faq/upgrade79.html" rel="noopener noreferrer"&gt;their official guide&lt;/a&gt; with appreciation to them.&lt;/p&gt;
&lt;h2&gt;
  
  
  Tutorial
&lt;/h2&gt;

&lt;p&gt;Here is a step-by-step guide with a set of command-lines to run.&lt;/p&gt;

&lt;center&gt;🌷 🐡 🌅&lt;/center&gt;
&lt;h3&gt;
  
  
  1. Pre-upgrade: Validate and customize
&lt;/h3&gt;

&lt;p&gt;The official tutorial includes &lt;a href="https://www.openbsd.org/faq/upgrade79.html#BeforeUpdate" rel="noopener noreferrer"&gt;Before using any upgrade method&lt;/a&gt; section.&lt;/p&gt;

&lt;p&gt;Using &lt;a href="https://man.openbsd.org/sysupgrade" rel="noopener noreferrer"&gt;&lt;code&gt;sysupgrade&lt;/code&gt;&lt;/a&gt; is usually a good choice.&lt;/p&gt;
&lt;h4&gt;
  
  
  Validate available disk size
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;/usr&lt;/code&gt; should be greater than 1.1GB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt;
&lt;span class="go"&gt;Filesystem     Size    Used   Avail Capacity  Mounted on
(...)
/dev/sd0e      7.8G    1.8G    5.6G    25%    /usr
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK :)&lt;/p&gt;

&lt;h4&gt;
  
  
  Validate compatibility with the current usage
&lt;/h4&gt;

&lt;p&gt;See &lt;a href="https://www.openbsd.org/faq/upgrade79.html#ConfigChanges" rel="noopener noreferrer"&gt;Configuration and syntax changes&lt;/a&gt; and &lt;a href="https://www.openbsd.org/faq/upgrade79.html#SpecialPackages" rel="noopener noreferrer"&gt;Special packages&lt;/a&gt;.&lt;br&gt;
The latter this time includes &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; major update to &lt;a href="https://www.postgresql.org/docs/release/18.1/" rel="noopener noreferrer"&gt;18.1&lt;/a&gt;.&lt;/p&gt;


&lt;h4&gt;
  
  
  Backups (Optional)
&lt;/h4&gt;

&lt;p&gt;You might have to create some backups.&lt;/p&gt;
&lt;h4&gt;
  
  
  Customize upgrade (Optional)
&lt;/h4&gt;

&lt;p&gt;This step is just for reference, skippable with standard upgrade.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://man.openbsd.org/sysupgrade" rel="noopener noreferrer"&gt;/auto_upgrade.conf&lt;/a&gt; is available as the response file.&lt;/p&gt;

&lt;p&gt;Of course, you can skip this and go next if it's unnecessary. The default behavior is sufficient in most cases.&lt;/p&gt;

&lt;p&gt;Well, the OpenBSD manual page on &lt;a href="https://man.openbsd.org/autoinstall.8" rel="noopener noreferrer"&gt;autoinstall&lt;/a&gt; says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If either &lt;em&gt;&lt;code&gt;/auto_install.conf&lt;/code&gt;&lt;/em&gt; or &lt;em&gt;&lt;code&gt;/auto_upgrade.conf&lt;/code&gt;&lt;/em&gt; is found on &lt;em&gt;&lt;code&gt;bsd.rd&lt;/code&gt;&lt;/em&gt;'s built-in RAM disk, &lt;strong&gt;&lt;code&gt;autoinstall&lt;/code&gt;&lt;/strong&gt; behaves as if the machine is netbooted, but uses the local response file. In case both files exist, &lt;em&gt;&lt;code&gt;/auto_install.conf&lt;/code&gt;&lt;/em&gt; takes precedence.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The whole example of &lt;code&gt;/auto_upgrade.conf&lt;/code&gt; is like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;Location&lt;/span&gt; &lt;span class="err"&gt;of&lt;/span&gt; &lt;span class="py"&gt;sets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;disk&lt;/span&gt;
&lt;span class="err"&gt;Pathname&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="py"&gt;sets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/home/_sysupgrade/&lt;/span&gt;
&lt;span class="err"&gt;Set&lt;/span&gt; &lt;span class="err"&gt;name(s)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;-x*&lt;/span&gt;
&lt;span class="err"&gt;Set&lt;/span&gt; &lt;span class="err"&gt;name(s)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;+xbase*&lt;/span&gt;
&lt;span class="err"&gt;Set&lt;/span&gt; &lt;span class="err"&gt;name(s)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;-game*&lt;/span&gt;
&lt;span class="err"&gt;Set&lt;/span&gt; &lt;span class="err"&gt;name(s)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="err"&gt;done&lt;/span&gt;
&lt;span class="err"&gt;Directory&lt;/span&gt; &lt;span class="err"&gt;does&lt;/span&gt; &lt;span class="err"&gt;not&lt;/span&gt; &lt;span class="err"&gt;contain&lt;/span&gt; &lt;span class="err"&gt;SHA256.sig.&lt;/span&gt; &lt;span class="err"&gt;Continue&lt;/span&gt; &lt;span class="err"&gt;without&lt;/span&gt; &lt;span class="py"&gt;verification&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, x sets except xbase and game are excluded.&lt;/p&gt;

&lt;p&gt;Also, &lt;a href="https://man.openbsd.org/upgrade.site.5" rel="noopener noreferrer"&gt;/upgrade.site&lt;/a&gt; can be applied.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Upgrade with &lt;code&gt;sysupgrade&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;OK. You must be ready.&lt;/p&gt;

&lt;p&gt;* Caution: The command below, &lt;code&gt;sysupgrade&lt;/code&gt;,  is &lt;strong&gt;unable to stop&lt;/strong&gt; once it is run.&lt;/p&gt;

&lt;p&gt;Let's just run it, if ready:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas sysupgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will print out like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Fetching from https://cdn.openbsd.org/pub/OpenBSD/7.9/amd64/
SHA256.sig   100% |******************************|  2144       00:00
Signature Verified
BUILDINFO    100% |******************************|    54       00:00
Verifying old sets.
INSTALL.amd64 100% |*****************************| 44889       00:00
base79.tgz   100% |******************************|   510 MB    04:24
bsd          100% |******************************| 32203 KB    00:22
bsd.mp       100% |******************************| 32331 KB    00:14
bsd.rd       100% |******************************|  4734 KB    00:04
comp79.tgz   100% |******************************| 88886 KB    00:12
game79.tgz   100% |******************************|  2742 KB    00:03
man79.tgz    100% |******************************|  8406 KB    00:04
xbase79.tgz  100% |******************************| 47835 KB    00:08
xfont79.tgz  100% |******************************| 23022 KB    00:05
xserv79.tgz  100% |******************************| 11815 KB    00:05
xshare79.tgz 100% |******************************|  4562 KB    00:04
Verifying sets.
Fetching updated firmware.
&lt;/span&gt;&lt;span class="gp"&gt;fw_update: add none;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;update intel,vmm
&lt;span class="go"&gt;Upgrading.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The machine will reboot and upgrade the system. It will reboot again and &lt;a href="https://man.openbsd.org/sysmerge" rel="noopener noreferrer"&gt;&lt;code&gt;sysmerge&lt;/code&gt;&lt;/a&gt; will follow automatically. Then daemons such as &lt;code&gt;sshd&lt;/code&gt; will be started as usual. It will print out "Checking for available binary patches...", and you will see "Run syspatch(8) to install:" if there are.&lt;/p&gt;

&lt;p&gt;Finally, you will see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;starting local daemons: cron.
Sat Sep  5 06:20:31 JST 2026

OpenBSD/amd64 ... (ttyC0)

login:
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After all, when login is successful, you will see the login message including "OpenBSD 7.9 (GENERIC.MP)".&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Post-upgrade: &lt;code&gt;sysmerge&lt;/code&gt; if necessary
&lt;/h3&gt;

&lt;p&gt;The official documentation &lt;a href="https://www.openbsd.org/faq/upgrade79.html#AfterSets" rel="noopener noreferrer"&gt;describes on them&lt;/a&gt; and helps a lot.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In some cases, configuration files cannot be modified automatically. Run&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# sysmerge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;to check and perform these configuration changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It means manually running &lt;code&gt;sysmerge&lt;/code&gt; in addition may be sometimes necessary.&lt;br&gt;
Remember you sometimes have to manually merging conf files such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/etc/login.conf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas sysmerge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When there is difference to be manually merged, you will see the results first. Then you will be asked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;  Use 'd' to delete the temporary ./etc/login.conf
  Use 'i' to install the temporary ./etc/login.conf
  Use 'm' to merge the temporary and installed versions
  Use 'v' to view the diff results again

  Default is to leave the temporary file to deal with by hand

How should I deal with this? [Leave it for later]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each of the top 3 options work like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;d&lt;/code&gt;: to preserve the current file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;i&lt;/code&gt;: to overwrite it with the new file &lt;code&gt;sysupgrade&lt;/code&gt; brought.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;m&lt;/code&gt;: to merge them manually and interactively.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you type &lt;code&gt;m&lt;/code&gt; to start merge mode, you will be asked to type each of them at each difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;l&lt;/code&gt; to choose the left diff,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;r&lt;/code&gt; to choose the right.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then you will see the options to deal with the merged file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Use 'e' to edit the merged file
  Use 'i' to install the merged file
  Use 'n' to view a diff between the merged and new files
  Use 'o' to view a diff between the old and merged files
  Use 'r' to re-do the merge
  Use 'v' to view the merged file
  Use 'x' to delete the merged file and go back to previous menu
  Default is to leave the temporary file to deal with by hand

===&amp;gt; How should I deal with the merged file? [Leave it for later]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you type &lt;code&gt;e&lt;/code&gt;, editor will run with the merged file.&lt;/p&gt;

&lt;p&gt;If you type &lt;code&gt;i&lt;/code&gt;, the merged file will be installed directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;===&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Merging /etc/login.conf &lt;span class="o"&gt;(&lt;/span&gt;running cap_mkdb&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;, needs a relog&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Apply &lt;code&gt;syspatch&lt;/code&gt; (skippable)
&lt;/h3&gt;

&lt;p&gt;The next two tasks below are usual just in order to update the system, too.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;syspatch&lt;/code&gt; is an important command to install binary patches officially offered by OpenBSD successively as found to be needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas syspatch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Update packages
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.openbsd.org/79.html#new" rel="noopener noreferrer"&gt;What's new&lt;/a&gt; section in the release page also shows "Some highlights" in "Ports and packages". For example, VMM/VMD was improved this time, too.&lt;/p&gt;

&lt;p&gt;The command-line below will update all of the packages installed in the machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas pkg_add &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see a lot printed out, but should be careful to read, especially the trailings. They may tell there are some important changes or tasks to do. As to me, I always check if &lt;a href="https://fishshell.com/" rel="noopener noreferrer"&gt;fish&lt;/a&gt;, my default shell, starts normally, because I have experienced trouble which crashed it with &lt;a href="https://www.python.org/" rel="noopener noreferrer"&gt;Python&lt;/a&gt; upgrade 😅&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Configuration and syntax changes
&lt;/h3&gt;

&lt;p&gt;Update some conf as needed to apply what &lt;a&gt;Configuration and syntax changes&lt;/a&gt; describes.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Remove old files
&lt;/h3&gt;

&lt;p&gt;This is a simple step. All what to do is just follow &lt;a href="https://www.openbsd.org/faq/upgrade79.html#RmFiles" rel="noopener noreferrer"&gt;Files to remove&lt;/a&gt; in the official tutorial.&lt;/p&gt;

&lt;p&gt;There is nothing this time.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Special packages
&lt;/h3&gt;

&lt;p&gt;Check &lt;a href="https://www.openbsd.org/faq/upgrade79.html#SpecialPackages" rel="noopener noreferrer"&gt;Special packages&lt;/a&gt; in the official tutorial. You may use some of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;aide&lt;/li&gt;
&lt;li&gt;caddy&lt;/li&gt;
&lt;li&gt;exim&lt;/li&gt;
&lt;li&gt;icinga&lt;/li&gt;
&lt;li&gt;lldpd&lt;/li&gt;
&lt;li&gt;postgresql&lt;/li&gt;
&lt;li&gt;puppet&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9. Reboot
&lt;/h3&gt;

&lt;p&gt;Almost done ! Finally and optionally run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;doas reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hope the new system and you enjoy together long :)&lt;/p&gt;

&lt;p&gt;With great appreciation to the OpenBSD project and the community.&lt;/p&gt;

</description>
      <category>openbsd</category>
      <category>os</category>
      <category>upgrade</category>
      <category>migration</category>
    </item>
    <item>
      <title>matten: コンパニオン crates と、次のステップへの移行</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Wed, 08 Jul 2026 13:43:19 +0000</pubDate>
      <link>https://dev.to/nabbisen/matten-konpanion-crates-to-ci-nosutetupuhenoyi-xing-5ahc</link>
      <guid>https://dev.to/nabbisen/matten-konpanion-crates-to-ci-nosutetupuhenoyi-xing-5ahc</guid>
      <description>&lt;p&gt;これは &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;&lt;code&gt;matten&lt;/code&gt;&lt;/a&gt; を紹介する全 4 回シリーズの最終回です。これまでの記事では ライブラリが生まれた背景、数値計算コア、dynamic feature による取り込み を紹介しました。今回はコンパニオン crates と、より重要なこととして、&lt;code&gt;matten&lt;/code&gt; を使うのをやめる適切なタイミングについてです。&lt;/p&gt;




&lt;h2&gt;
  
  
  3 つのコンパニオン crates
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;matten&lt;/code&gt; ワークスペースはコアと並んで、3 つの小さなコンパニオン crates を公開しています。それぞれスコープが狭く、閉じています。いずれもコアの &lt;code&gt;matten&lt;/code&gt; crates への依存は追加しません。&lt;/p&gt;

&lt;h3&gt;
  
  
  matten-ndarray — ndarray へのブリッジ
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/matten-ndarray" rel="noopener noreferrer"&gt;&lt;code&gt;matten-ndarray&lt;/code&gt;&lt;/a&gt; は &lt;code&gt;matten::Tensor&lt;/code&gt; と &lt;code&gt;ndarray::ArrayD&amp;lt;f64&amp;gt;&lt;/code&gt; の間を変換します。それだけです。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten_ndarray&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;from_arrayd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_arrayd&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_arrayd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// Tensor      -&amp;gt; ArrayD&amp;lt;f64&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;back&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;from_arrayd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ArrayD&amp;lt;f64&amp;gt; -&amp;gt; Tensor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;これは「受け渡しの瞬間」のために存在します。概念実証がある程度成長し、ホットパスで &lt;code&gt;ndarray&lt;/code&gt; のパフォーマンスが必要になったとき、フラットな &lt;code&gt;Vec&amp;lt;f64&amp;gt;&lt;/code&gt; データはそのまま移行できます。ステータス：プロダクションレディ。&lt;/p&gt;

&lt;h3&gt;
  
  
  matten-mlprep — 小さな前処理ヘルパー
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/matten-mlprep" rel="noopener noreferrer"&gt;&lt;code&gt;matten-mlprep&lt;/code&gt;&lt;/a&gt; は、数値テンソルをどこか別のツールに渡す前に準備するための、シンプルで決定論的な関数を少し提供します。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten_mlprep&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;add_bias_column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;standardize_columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;train_test_split&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;7.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;standardize_columns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// 列ごとに平均 0、標準偏差 1 に&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add_bias_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// 切片列（1.0）を先頭に追加&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;train_test_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;minmax_scale_columns&lt;/code&gt; も使えます。モデルの学習、自動微分、乱数、隠れた状態は一切ありません。それらが必要になったら、本格的な ML crates を使ってください。この crates は意図的に前処理の手前で止まっています。ステータス：プロダクションレディ候補。&lt;/p&gt;

&lt;h3&gt;
  
  
  matten-data — 列名指定で CSV からテンソルへ
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/matten-data" rel="noopener noreferrer"&gt;&lt;code&gt;matten-data&lt;/code&gt;&lt;/a&gt; は、ヘッダー行付きの CSV ファイルからクリーンな数値テンソルへの変換を、列を名前で選びながら行うためのヘルパーです。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten_data&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"sales,cost,note&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;10,2,a&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;20,,b&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;30,4,c"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;tensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_csv_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="nf"&gt;.select_columns&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;"sales"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cost"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;  &lt;span class="c1"&gt;// 列を名前で選択&lt;/span&gt;
    &lt;span class="nf"&gt;.fill_missing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;                   &lt;span class="c1"&gt;// 欠損値を明示的にクリーニング&lt;/span&gt;
    &lt;span class="nf"&gt;.try_numeric&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;                       &lt;span class="c1"&gt;// 変換&lt;/span&gt;
    &lt;span class="nf"&gt;.to_tensor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                        &lt;span class="c1"&gt;// -&amp;gt; matten::Tensor, シェイプ [3, 2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;この crates は設計上 CSV 専用です。JSON の取り込みが必要であれば、コアの &lt;code&gt;matten&lt;/code&gt; crates にある &lt;code&gt;from_json&lt;/code&gt; や &lt;code&gt;from_json_dynamic&lt;/code&gt; を使ってください。ステータス：プロダクションレディ候補。&lt;/p&gt;




&lt;h2&gt;
  
  
  次のステップへ移行するタイミング
&lt;/h2&gt;

&lt;p&gt;ここがこの記事で一番大事な部分かもしれません。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;matten&lt;/code&gt; は初期段階の作業を想定しています。アルゴリズムを試す、データパイプラインの概要を描く、Rust での数値アイデアを素早く形にする。そういった用途です。いずれプロジェクトがその役割を超えることもあるでしょう。いつそうなるかについて、具体的に書いておきます。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;ndarray&lt;/code&gt; や &lt;code&gt;nalgebra&lt;/code&gt; にホットパスを移す&lt;/strong&gt; のは、そこのベンチマーク結果が気になり始めたときです。同じ環境で測ると、&lt;code&gt;matten&lt;/code&gt; の 64×64 行列積は &lt;code&gt;ndarray&lt;/code&gt; や &lt;code&gt;nalgebra&lt;/code&gt; の同等処理に比べておおむね 7〜9 倍の時間がかかります。一度だけ実行する計算なら問題ないことが多いですが、タイトなループの中で繰り返し呼ばれるなら話が変わります。&lt;code&gt;matten-ndarray&lt;/code&gt; ブリッジでデータを受け渡せます。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;ndarray&lt;/code&gt; に直接移行する&lt;/strong&gt; のは、ストライドビュー、ゼロコピースライス、BLAS 連携が必要になったときです。&lt;code&gt;matten&lt;/code&gt; のスライス API はデータをコピーします。&lt;code&gt;ndarray&lt;/code&gt; のビューはしません。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;専用の ML フレームワーク&lt;/strong&gt;（Candle、Burn、tch-rs）に移行するのは、自動微分、モデルの学習、GPU アクセラレーションが必要になったときです。&lt;code&gt;matten-mlprep&lt;/code&gt; は前処理をカバーしています。それらの代わりにはなりません。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;matten&lt;/code&gt; をそのまま使い続ける&lt;/strong&gt; のは、問題が小さく、データがメモリに十分収まり、実行時間よりも開発者の時間の方が貴重である間です。&lt;/p&gt;




&lt;p&gt;このライブラリはまだ pre-1.0 です。数値計算コアは実用上安定しており、コンパニオン crates は production-ready 候補です。v1 は、開発者 / メンテナーが準備できたと判断したときにリリースします — スケジュールで決めるものではありません。フィードバックや Issue はリポジトリでご連絡ください。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;リンク:&lt;/strong&gt; &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;crates.io&lt;/a&gt; · &lt;a href="https://docs.rs/matten" rel="noopener noreferrer"&gt;docs.rs&lt;/a&gt; · &lt;a href="https://nabbisen.github.io/matten/" rel="noopener noreferrer"&gt;mdBook&lt;/a&gt; · &lt;a href="https://github.com/nabbisen/matten" rel="noopener noreferrer"&gt;リポジトリ&lt;/a&gt;&lt;/p&gt;

</description>
      <category>math</category>
      <category>tensor</category>
      <category>matrix</category>
      <category>rust</category>
    </item>
    <item>
      <title>matten: Companion crates and when to move on</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Wed, 08 Jul 2026 13:41:46 +0000</pubDate>
      <link>https://dev.to/nabbisen/matten-companion-crates-and-when-to-move-on-4fkf</link>
      <guid>https://dev.to/nabbisen/matten-companion-crates-and-when-to-move-on-4fkf</guid>
      <description>&lt;p&gt;This is the last of four short posts about &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;&lt;code&gt;matten&lt;/code&gt;&lt;/a&gt;. The earlier posts covered why the library exists, the numeric core, and the dynamic ingestion feature. This one covers the companion crates and, more importantly, when the right answer is to stop using &lt;code&gt;matten&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three companion crates
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;matten&lt;/code&gt; workspace publishes three small companion crates alongside the core.&lt;br&gt;
Each has a narrow, closed scope. None of them adds a dependency to the core &lt;code&gt;matten&lt;/code&gt; crate.&lt;/p&gt;
&lt;h3&gt;
  
  
  matten-ndarray — the bridge to ndarray
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/matten-ndarray" rel="noopener noreferrer"&gt;&lt;code&gt;matten-ndarray&lt;/code&gt;&lt;/a&gt; converts between &lt;code&gt;matten::Tensor&lt;/code&gt; and &lt;code&gt;ndarray::ArrayD&amp;lt;f64&amp;gt;&lt;/code&gt;. That is all it does.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten_ndarray&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;from_arrayd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_arrayd&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_arrayd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// Tensor      -&amp;gt; ArrayD&amp;lt;f64&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;back&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;from_arrayd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ArrayD&amp;lt;f64&amp;gt; -&amp;gt; Tensor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This exists for the handoff moment: when a proof of concept has grown to the point where a hot path needs &lt;code&gt;ndarray&lt;/code&gt;'s performance, the flat &lt;code&gt;Vec&amp;lt;f64&amp;gt;&lt;/code&gt; data moves across without re-encoding. Status: production-ready.&lt;/p&gt;

&lt;h3&gt;
  
  
  matten-mlprep — small preprocessing helpers
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/matten-mlprep" rel="noopener noreferrer"&gt;&lt;code&gt;matten-mlprep&lt;/code&gt;&lt;/a&gt; provides a handful of plain, deterministic functions for preparing a numeric tensor before feeding it somewhere else.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten_mlprep&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;add_bias_column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;standardize_columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;train_test_split&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;7.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;standardize_columns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// zero mean, unit std per column&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add_bias_column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// prepend a 1.0 intercept column&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;train_test_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;minmax_scale_columns&lt;/code&gt; is also available. There is no model training, no autograd, no randomness, and no hidden state. When you need those things, reach for a real ML crate — this one deliberately stops at the preprocessing step. Status: production-ready candidate.&lt;/p&gt;

&lt;h3&gt;
  
  
  matten-data — CSV to Tensor via named columns
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/matten-data" rel="noopener noreferrer"&gt;&lt;code&gt;matten-data&lt;/code&gt;&lt;/a&gt; handles the step between a CSV file with a header row and a clean numeric tensor, letting you select columns by name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten_data&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"sales,cost,note&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;10,2,a&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;20,,b&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;30,4,c"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;tensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_csv_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="nf"&gt;.select_columns&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;"sales"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cost"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;  &lt;span class="c1"&gt;// pick numeric columns by name&lt;/span&gt;
    &lt;span class="nf"&gt;.fill_missing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;                   &lt;span class="c1"&gt;// clean missing values explicitly&lt;/span&gt;
    &lt;span class="nf"&gt;.try_numeric&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;                       &lt;span class="c1"&gt;// convert&lt;/span&gt;
    &lt;span class="nf"&gt;.to_tensor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                        &lt;span class="c1"&gt;// -&amp;gt; matten::Tensor, shape [3, 2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This crate is CSV-only by design. If you need JSON ingestion, that lives in the core &lt;code&gt;matten&lt;/code&gt; crate (&lt;code&gt;from_json&lt;/code&gt;, &lt;code&gt;from_json_dynamic&lt;/code&gt;). Status: production-ready candidate.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to move on
&lt;/h2&gt;

&lt;p&gt;This is probably the more useful part of this post.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;matten&lt;/code&gt; is designed for early-stage work: trying out an algorithm, sketching a data pipeline, getting a Rust numerical idea off the ground quickly. At some point a project may outgrow that role, and it is worth being specific about when that is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Move a hot path to &lt;code&gt;ndarray&lt;/code&gt; or &lt;code&gt;nalgebra&lt;/code&gt;&lt;/strong&gt; when benchmark numbers start to matter for that part of the code. A 64×64 matrix multiply in &lt;code&gt;matten&lt;/code&gt; currently runs at roughly 7–9× the time of the equivalent in &lt;code&gt;ndarray&lt;/code&gt; or &lt;code&gt;nalgebra&lt;/code&gt; on the same machine. For a one-off computation that is usually fine; for something called in a tight loop it is not. The &lt;code&gt;matten-ndarray&lt;/code&gt; bridge handles the data handoff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Move to &lt;code&gt;ndarray&lt;/code&gt; directly&lt;/strong&gt; when you need strided views, zero-copy slicing, or BLAS integration. &lt;code&gt;matten&lt;/code&gt;'s slice API copies data; &lt;code&gt;ndarray&lt;/code&gt;'s views do not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Move to a dedicated ML framework&lt;/strong&gt; (Candle, Burn, tch-rs) when you need autograd, model training, or GPU acceleration. &lt;code&gt;matten-mlprep&lt;/code&gt; covers preprocessing; it is not a substitute for any of those.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stay with &lt;code&gt;matten&lt;/code&gt;&lt;/strong&gt; for as long as the problem is small, the data fits comfortably in memory, and developer time is more constrained than runtime.&lt;/p&gt;




&lt;p&gt;The library is still pre-1.0. The numeric core is stable in practice, the companion crates are production-ready candidates, and v1 will come when the developers / maintainers are confident it is ready — not on a schedule. Feedback and issues are welcome on the repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt; &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;crates.io&lt;/a&gt; · &lt;a href="https://docs.rs/matten" rel="noopener noreferrer"&gt;docs.rs&lt;/a&gt; · &lt;a href="https://nabbisen.github.io/matten/" rel="noopener noreferrer"&gt;mdBook&lt;/a&gt; · &lt;a href="https://github.com/nabbisen/matten" rel="noopener noreferrer"&gt;repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>math</category>
      <category>tensor</category>
      <category>matrix</category>
      <category>rust</category>
    </item>
    <item>
      <title>matten: 不均一なデータを `--features dynamic` で扱う</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Thu, 02 Jul 2026 09:00:00 +0000</pubDate>
      <link>https://dev.to/nabbisen/matten-bu-jun-nadetawo-features-dynamic-dexi-u-2g9l</link>
      <guid>https://dev.to/nabbisen/matten-bu-jun-nadetawo-features-dynamic-dexi-u-2g9l</guid>
      <description>&lt;p&gt;これは &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;&lt;code&gt;matten&lt;/code&gt;&lt;/a&gt; を紹介する全 4 回シリーズの第 3 回です。前回は数値計算のコア部分を紹介しました。今回は雑然とした実世界のデータを取り込むしくみについてです。&lt;/p&gt;




&lt;h2&gt;
  
  
  課題事項
&lt;/h2&gt;

&lt;p&gt;前回紹介した &lt;code&gt;Tensor&lt;/code&gt; （数値テンソル）は、つくられた時点からクリーンです。すべてのセルが &lt;code&gt;f64&lt;/code&gt; です。データがすでにクリーンであれば、それで問題ありません。しかし、データが JSON API や CSV ファイル経由で投入され、その中に欠損セルや、整数と浮動小数点の混在、あるいは bool 値（フラグ）が含まれているような場合となると、どうでしょうか。話は変わって来ます。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dynamic&lt;/code&gt; feature は、そのような場合の助けになります。データ取り込みとクリーニングのレイヤーを追加します。ただし、これは&lt;strong&gt;第二の計算エンジンではありません&lt;/strong&gt; — dynamic テンソルで直接算術演算はできません。考え方はもっとシンプルです。不均一なデータを取り込み、検査してクリーニングし、データが整ったと確信したら数値テンソルに明示的に変換します。&lt;/p&gt;

&lt;p&gt;次のようにして有効化できます：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;matten&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.28"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"dynamic"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  混在データの取り込み
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;from_json_dynamic&lt;/code&gt; と &lt;code&gt;from_csv_dynamic&lt;/code&gt; は、型が混在したデータを受け付けます。各セルは &lt;code&gt;Element&lt;/code&gt; のバリアントに格納されます：&lt;code&gt;Float&lt;/code&gt;、&lt;code&gt;Int&lt;/code&gt;、&lt;code&gt;Bool&lt;/code&gt;、&lt;code&gt;Text&lt;/code&gt;、または &lt;code&gt;None&lt;/code&gt;（JSON の &lt;code&gt;null&lt;/code&gt; や CSV の空フィールド）。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// 数値の種類が混在し、かつ欠損セルが存在する JSON テーブル&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"[[1, 2.5, null], [4.0, 5, 6]]"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_json_dynamic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.is_dynamic&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.shape&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.count_none&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;同様の処理は CSV でも動きます：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"10.0,20.0,30.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;40.0,,60.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;70.0,80.0,&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 空セルが 2 つ&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_csv_dynamic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.count_none&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;フォーマットが異なるだけで、ワークフローは同じです。&lt;/p&gt;

&lt;h2&gt;
  
  
  欠損値の検査
&lt;/h2&gt;

&lt;p&gt;クリーニングの前に、どこに欠損があるか確認できます：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// none_mask: セルごとに 0.0 / 1.0 の数値テンソル&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.none_mask&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// [0,2] に null&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 値あり&lt;/span&gt;

&lt;span class="c1"&gt;// schema_summary で型の内訳を読みやすく確認&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.schema_summary&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// 例: "Float: 4, Int: 1, None: 1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  数値テンソルへの変換
&lt;/h2&gt;

&lt;p&gt;変換ステップは意図的に明示的にしています。&lt;code&gt;try_numeric()&lt;/code&gt; は厳格です。&lt;code&gt;None&lt;/code&gt;、&lt;code&gt;Bool&lt;/code&gt;、&lt;code&gt;Text&lt;/code&gt; が 1 つでもあれば変換を拒否します：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// データに null があるため失敗する&lt;/span&gt;
&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.try_numeric&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.is_err&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;try_numeric_with(policy)&lt;/code&gt; を使うと、各バリアントをどう扱うかを指定できます：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// None を 0.0 として扱い、Int と Float はそのまま f64 に&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.try_numeric_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.none_as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="nf"&gt;.is_dynamic&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="nf"&gt;.as_slice&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;その他の指定オプション：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// none_as_nan: 欠損を指定した値ではなく f64::NAN に&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.none_as_nan&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// allow_bool: true → 1.0, false → 0.0&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.allow_bool&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// allow_text_parse: テキストセルを f64 としてパースを試みる&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.allow_text_parse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// オプションを組み合わせる&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.none_as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.allow_bool&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// すべてのバリアントを受け入れる&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;permissive&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  変換前のクリーニング
&lt;/h2&gt;

&lt;p&gt;変換ステップの前に欠損値を埋めることもできます：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// None をすべて 0.0 で埋める&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;filled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.fill_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filled&lt;/span&gt;&lt;span class="nf"&gt;.is_numeric_convertible&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// そのあと厳格に変換&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;numeric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filled&lt;/span&gt;&lt;span class="nf"&gt;.try_numeric&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;時系列データ向けに &lt;code&gt;forward_fill_none&lt;/code&gt;（前の値で補完）も使えます。&lt;/p&gt;

&lt;h2&gt;
  
  
  dynamic でできないこと
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;dynamic&lt;/code&gt; feature には意図的に含まれていないものがあります：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dynamic テンソルでの算術演算は不可。事前に &lt;code&gt;try_numeric()&lt;/code&gt; を実行してください。&lt;/li&gt;
&lt;li&gt;dynamic テンソルの reshape、slice、reduction は不可。&lt;/li&gt;
&lt;li&gt;dynamic テンソルの serde シリアライズは不可。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;狙いは、きれいな受け渡しです。雑然とした入力 → 検査とクリーニング → 数値 &lt;code&gt;Tensor&lt;/code&gt; → 通常の数値計算。この境界は意図的なものです。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;リンク:&lt;/strong&gt; &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;crates.io&lt;/a&gt; · &lt;a href="https://docs.rs/matten" rel="noopener noreferrer"&gt;docs.rs&lt;/a&gt; · &lt;a href="https://nabbisen.github.io/matten/" rel="noopener noreferrer"&gt;mdBook&lt;/a&gt; · &lt;a href="https://github.com/nabbisen/matten" rel="noopener noreferrer"&gt;リポジトリ&lt;/a&gt;&lt;/p&gt;

</description>
      <category>math</category>
      <category>tensor</category>
      <category>matrix</category>
      <category>rust</category>
    </item>
    <item>
      <title>matten: Heterogeneous data with `--features dynamic`</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Thu, 02 Jul 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/nabbisen/matten-heterogeneous-data-with-features-dynamic-11mi</link>
      <guid>https://dev.to/nabbisen/matten-heterogeneous-data-with-features-dynamic-11mi</guid>
      <description>&lt;p&gt;This is the third of four short posts about &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;&lt;code&gt;matten&lt;/code&gt;&lt;/a&gt;. The previous post covered the numeric core. This one covers a separate feature: ingesting messy, real-world data.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;The numeric &lt;code&gt;Tensor&lt;/code&gt; in the previous post is clean by construction: every cell is an &lt;code&gt;f64&lt;/code&gt;. That is fine when your data is already clean. It is less fine when it arrives from a JSON API or a CSV file that has missing cells, integer values alongside floats, or the occasional boolean flag.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;dynamic&lt;/code&gt; feature adds an ingestion-and-cleanup layer for that case. It is &lt;strong&gt;not&lt;/strong&gt; a second compute engine — you cannot do arithmetic on a dynamic tensor directly. The idea is simpler: ingest heterogeneous data, inspect and clean it, then convert explicitly to a numeric tensor when you are confident the data is ready.&lt;/p&gt;

&lt;p&gt;Enable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;matten&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.28"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"dynamic"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ingesting mixed data
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;from_json_dynamic&lt;/code&gt; and &lt;code&gt;from_csv_dynamic&lt;/code&gt; accept data with mixed types. Each cell lands in an &lt;code&gt;Element&lt;/code&gt; variant: &lt;code&gt;Float&lt;/code&gt;, &lt;code&gt;Int&lt;/code&gt;, &lt;code&gt;Bool&lt;/code&gt;, &lt;code&gt;Text&lt;/code&gt;, or &lt;code&gt;None&lt;/code&gt; (for JSON &lt;code&gt;null&lt;/code&gt; or an empty CSV field).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// A JSON table with mixed numeric kinds and a missing cell&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"[[1, 2.5, null], [4.0, 5, 6]]"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_json_dynamic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.is_dynamic&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.shape&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.count_none&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same on-ramp works for CSV:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"10.0,20.0,30.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;40.0,,60.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;70.0,80.0,&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// two empty cells&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_csv_dynamic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.count_none&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The format differs; the workflow does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspecting missing values
&lt;/h2&gt;

&lt;p&gt;Before cleaning, you can see where the gaps are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// none_mask: a numeric tensor of 0.0 / 1.0, one per cell&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.none_mask&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// null at [0,2]&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// present&lt;/span&gt;

&lt;span class="c1"&gt;// schema_summary gives a readable type breakdown&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.schema_summary&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// e.g. "Float: 4, Int: 1, None: 1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Converting to a numeric tensor
&lt;/h2&gt;

&lt;p&gt;The conversion step is explicit by design. &lt;code&gt;try_numeric()&lt;/code&gt; is strict and refuses if any &lt;code&gt;None&lt;/code&gt;, &lt;code&gt;Bool&lt;/code&gt;, or &lt;code&gt;Text&lt;/code&gt; values are present:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This fails — there is a null in the data&lt;/span&gt;
&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.try_numeric&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.is_err&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;try_numeric_with(policy)&lt;/code&gt; lets you state exactly what to do with each variant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Treat None as 0.0; Int and Float both become f64&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.try_numeric_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.none_as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="nf"&gt;.is_dynamic&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="nf"&gt;.as_slice&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other policy options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// none_as_nan: missing → f64::NAN instead of a chosen sentinel&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.none_as_nan&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// allow_bool: true → 1.0, false → 0.0&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.allow_bool&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// allow_text_parse: try to parse text cells as f64&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.allow_text_parse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Chain options together&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.none_as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.allow_bool&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Accept all variants permissively&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;NumericPolicy&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;permissive&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cleaning before converting
&lt;/h2&gt;

&lt;p&gt;You can also fill missing values before the conversion step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Replace every None with 0.0 in place&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;filled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.fill_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filled&lt;/span&gt;&lt;span class="nf"&gt;.is_numeric_convertible&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// Then convert strictly&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;numeric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filled&lt;/span&gt;&lt;span class="nf"&gt;.try_numeric&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;forward_fill_none&lt;/code&gt; is also available for time-series-style forward propagation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What dynamic is not
&lt;/h2&gt;

&lt;p&gt;A few things that are intentionally absent from the &lt;code&gt;dynamic&lt;/code&gt; feature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No arithmetic on dynamic tensors. Call &lt;code&gt;try_numeric()&lt;/code&gt; first.&lt;/li&gt;
&lt;li&gt;No dynamic reshape, slice, or reduction.&lt;/li&gt;
&lt;li&gt;No serde for dynamic tensors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point is a clean handoff: messy input → inspect and clean → numeric &lt;code&gt;Tensor&lt;/code&gt; → ordinary numeric work. That boundary is deliberate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt; &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;crates.io&lt;/a&gt; · &lt;a href="https://docs.rs/matten" rel="noopener noreferrer"&gt;docs.rs&lt;/a&gt; · &lt;a href="https://nabbisen.github.io/matten/" rel="noopener noreferrer"&gt;mdBook&lt;/a&gt; · &lt;a href="https://github.com/nabbisen/matten" rel="noopener noreferrer"&gt;repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>math</category>
      <category>tensor</category>
      <category>matrix</category>
      <category>rust</category>
    </item>
    <item>
      <title>matten: `Tensor` コア</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Tue, 30 Jun 2026 02:30:00 +0000</pubDate>
      <link>https://dev.to/nabbisen/matten-tensor-koa-ea9</link>
      <guid>https://dev.to/nabbisen/matten-tensor-koa-ea9</guid>
      <description>&lt;p&gt;これは &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;&lt;code&gt;matten&lt;/code&gt;&lt;/a&gt; を紹介する全 4 回シリーズの第 2 回です。第 1 回では背景を説明しました。今回はライブラリの実際の使い方を紹介します。&lt;/p&gt;




&lt;h2&gt;
  
  
  はじめ方
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# Cargo.toml&lt;/span&gt;
&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;matten&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.28"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;デフォルトの features には &lt;code&gt;serde&lt;/code&gt;、&lt;code&gt;json&lt;/code&gt;、&lt;code&gt;csv&lt;/code&gt; が含まれています。依存関係をできるだけ小さくしたい場合は無効にします：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;matten&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.28"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;default-features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  テンソルをつくる
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;use matten::Tensor;&lt;/code&gt; をインポートするだけです。ジェネリクスの型パラメータも、ライフタイムアノテーションも不要です。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// データとシェイプを明示してつくる&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="nf"&gt;.shape&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="nf"&gt;.ndim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 便利なコンストラクタ&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ones&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;full&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;境界スタイルのコンストラクタを使うと、シェイプの不一致はパニックではなくエラーとして返ります：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;MattenError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;try_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;matches!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;MattenError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="p"&gt;})));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  算術演算とブロードキャスト
&lt;/h2&gt;

&lt;p&gt;演算子は参照を受け取ります。そのため、もとの値の所有権を保持したまま使えます。シェイプのブロードキャストは NumPy 方式の右揃えルールに従います。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ones&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// [2.0, 3.0, 4.0, 5.0]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// スカラーブロードキャスト: [2.0, 4.0, 6.0, 8.0]&lt;/span&gt;

&lt;span class="c1"&gt;// 行ベクトルを行列全体にブロードキャスト&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;mat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ones&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mat&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// シェイプ [3, 2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  シェイプ操作
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;flat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.flatten&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;           &lt;span class="c1"&gt;// シェイプ [6]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reshaped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;transposed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.transpose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// シェイプ [3, 2]&lt;/span&gt;

&lt;span class="c1"&gt;// リダクション&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.sum&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;          &lt;span class="c1"&gt;// スカラー&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;col_sums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.sum_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// シェイプ [3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  JSON と CSV
&lt;/h2&gt;

&lt;p&gt;どちらもデフォルトで有効です。境界部分では &lt;code&gt;Result&lt;/code&gt; を返すので、不正な入力はパニックではなくエラーとして扱われます。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// JSON — 受け付け可能な形式&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r#"{"shape":[2,2],"data":[1.0,2.0,3.0,4.0]}"#&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[[1.0, 2.0], [3.0, 4.0]]"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ファイルから読み込む&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;load_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data/tensor.json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// CSV&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1.0,2.0,3.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;4.0,5.0,6.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;load_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data/matrix.csv"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;serde 経由のシリアライズも使えます。&lt;code&gt;json&lt;/code&gt; または &lt;code&gt;serde&lt;/code&gt; feature が有効なとき、&lt;code&gt;serde_json::to_string(&amp;amp;t)&lt;/code&gt; と &lt;code&gt;serde_json::from_str(&amp;amp;json_str)&lt;/code&gt; で正しくラウンドトリップします。&lt;/p&gt;

&lt;h2&gt;
  
  
  エラーハンドリング
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;matten&lt;/code&gt; には、意図的に 2 つのエラー種別があります。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;シェイプ操作（&lt;code&gt;new&lt;/code&gt; での構築、reshape、スライス）はパニックし、わかりやすいメッセージを出します — 素早いプロトタイプ開発中に問題をすぐ見つけられるように。&lt;/li&gt;
&lt;li&gt;外部境界の操作（&lt;code&gt;from_json&lt;/code&gt;、&lt;code&gt;from_csv&lt;/code&gt;、&lt;code&gt;load_*&lt;/code&gt;）は常に &lt;code&gt;Result&amp;lt;Tensor, MattenError&amp;gt;&lt;/code&gt; を返し、通常の不正入力ではパニックしません。実際のデータは常にクリーンとは限らないので。

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MattenError&lt;/code&gt; は &lt;code&gt;#[non_exhaustive]&lt;/code&gt; です。気になるバリアントにマッチし、残りはワイルドカードで受けてください：
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;MattenError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1.0,not_a_number&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"shape {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.shape&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;MattenError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"不正な入力"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"その他のエラー: {e:?}"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;日常的な数値計算のコア部分は以上です。次の記事では少し異なる状況を扱います — 入力データがクリーンな &lt;code&gt;f64&lt;/code&gt; の行列ではないとき、つまり型が混在していたり、欠損値があったり、整数と浮動小数点が混在している場合です。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;リンク:&lt;/strong&gt; &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;crates.io&lt;/a&gt; · &lt;a href="https://docs.rs/matten" rel="noopener noreferrer"&gt;docs.rs&lt;/a&gt; · &lt;a href="https://nabbisen.github.io/matten/" rel="noopener noreferrer"&gt;mdBook&lt;/a&gt; · &lt;a href="https://github.com/nabbisen/matten" rel="noopener noreferrer"&gt;リポジトリ&lt;/a&gt;&lt;/p&gt;

</description>
      <category>math</category>
      <category>tensor</category>
      <category>matrix</category>
      <category>rust</category>
    </item>
    <item>
      <title>matten とは: ファミリーカー式テンソルライブラリ — Rust 言語</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Mon, 29 Jun 2026 20:30:00 +0000</pubDate>
      <link>https://dev.to/nabbisen/matten-toha-huamirikashi-tensoruraiburari-rust-yan-yu-2if8</link>
      <guid>https://dev.to/nabbisen/matten-toha-huamirikashi-tensoruraiburari-rust-yan-yu-2if8</guid>
      <description>&lt;p&gt;多次元配列を扱うための小さな Rust ライブラリ &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;&lt;code&gt;matten&lt;/code&gt;&lt;/a&gt; を公開しました。このライブラリが生まれた背景を記載します。&lt;/p&gt;




&lt;p&gt;Rust は数値計算やデータ処理に適した言語です。ただ、そういった作業を「始める」こと — 行列を用意して、足し算ができる状態にするだけ — が、プロトタイプの段階では必要以上に手間が掛かることがあります。&lt;/p&gt;

&lt;p&gt;既存のライブラリは高機能で、しっかりとメンテナンスされています。パフォーマンスが必要なら &lt;a href="https://crates.io/crates/ndarray" rel="noopener noreferrer"&gt;&lt;code&gt;ndarray&lt;/code&gt;&lt;/a&gt; や &lt;a href="https://crates.io/crates/nalgebra" rel="noopener noreferrer"&gt;&lt;code&gt;nalgebra&lt;/code&gt;&lt;/a&gt; を選ぶと良いでしょう。これらはプロダクション品質の数値計算コードに適したライブラリです。&lt;br&gt;
ただしそこには学習コストが伴います。ジェネリクスの型パラメーター、ストレージの抽象化、ビュー型、ライフタイムの考慮。そのコストが見合う場面は多いです。しかし、概念実証の初日から常に見合うとは限りません。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;matten&lt;/code&gt; が埋めようとしているのは、狭いけれど無視できないこともあるそのギャップです。&lt;strong&gt;初期段階の数値計算を、もう少し気軽に始められるようにする&lt;/strong&gt; — 最初の 1 時間を、型システムではなく問題そのものに使えるように。&lt;/p&gt;

&lt;p&gt;プロジェクトの説明で、これを「ファミリーカー」にたとえています。乗り込みやすく、運転が予測しやすく、日常のほとんどの用途に十分快適。レーシングカーではありません。そうなろうともしていません。&lt;/p&gt;

&lt;p&gt;具体的には以下を意味します：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ジェネリクスなしのシンプルな一つだけの公開型、&lt;code&gt;Tensor&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;通常の使い方でユーザーがライフタイムを意識する場面は無し。&lt;/li&gt;
&lt;li&gt;シェイプが合わないときは人間にとってわかりやすいエラーメッセージ。&lt;/li&gt;
&lt;li&gt;JSON と CSV サポートがデフォルトで有効。データの入出力を手軽に。&lt;/li&gt;
&lt;li&gt;コード全体で &lt;code&gt;#![forbid(unsafe_code)]&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;次のことは意味しません：ホットパスで既存ライブラリより速い。&lt;br&gt;&lt;br&gt;
この点はライブラリスコープ外です。このライブラリはその点を明示しています。プロトタイプが成熟してパフォーマンス要件を満たす必要が生じた時、その部分をより高性能なライブラリに移行するのが正しい判断です。&lt;br&gt;&lt;br&gt;
&lt;code&gt;matten-ndarray&lt;/code&gt; はまさにそのための橋渡しとして存在しており、フラットな &lt;code&gt;Vec&amp;lt;f64&amp;gt;&lt;/code&gt; のストレージ構造がデータの移動を簡単にしています。&lt;/p&gt;

&lt;p&gt;P.S. — ライブラリ名の由来は "&lt;strong&gt;mat&lt;/strong&gt;hematical &lt;strong&gt;ten&lt;/strong&gt;sor" ...ではありません 😜 方言「待ってん (待ったねん)」からとっています。私たちは時間をつくりながら開発しました。使う人にとっても自分の時間の中で楽な気持ちで使えるものでありますように。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;リンク:&lt;/strong&gt; &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;crates.io&lt;/a&gt; · &lt;a href="https://docs.rs/matten" rel="noopener noreferrer"&gt;docs.rs&lt;/a&gt; · &lt;a href="https://nabbisen.github.io/matten/" rel="noopener noreferrer"&gt;mdBook&lt;/a&gt; · &lt;a href="https://github.com/nabbisen/matten" rel="noopener noreferrer"&gt;リポジトリ&lt;/a&gt;&lt;/p&gt;

</description>
      <category>math</category>
      <category>tensor</category>
      <category>matrix</category>
      <category>rust</category>
    </item>
    <item>
      <title>matten: The core `Tensor`</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Mon, 29 Jun 2026 13:21:42 +0000</pubDate>
      <link>https://dev.to/nabbisen/matten-the-core-tensor-35ia</link>
      <guid>https://dev.to/nabbisen/matten-the-core-tensor-35ia</guid>
      <description>&lt;p&gt;This is the second of four short posts about &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;&lt;code&gt;matten&lt;/code&gt;&lt;/a&gt;. The first post explained the motivation. This one shows what the library looks like in practice.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# Cargo.toml&lt;/span&gt;
&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;matten&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.28"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default feature set includes &lt;code&gt;serde&lt;/code&gt;, &lt;code&gt;json&lt;/code&gt;, and &lt;code&gt;csv&lt;/code&gt;. If you want the smallest possible dependency footprint, you can turn them off:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;matten&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.28"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;default-features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating tensors
&lt;/h2&gt;

&lt;p&gt;The whole import is &lt;code&gt;use matten::Tensor;&lt;/code&gt;. No generic parameters, no lifetime annotations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// From data and an explicit shape&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="nf"&gt;.shape&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="nf"&gt;.ndim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Convenience constructors&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ones&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;full&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Shape mismatches produce an actionable error rather than a panic when you use the boundary-style constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;MattenError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;try_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;matches!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;MattenError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="p"&gt;})));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Arithmetic and broadcasting
&lt;/h2&gt;

&lt;p&gt;The operators work on references, so you keep ownership of the originals. Shape broadcasting follows NumPy-style right-alignment rules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ones&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// [2.0, 3.0, 4.0, 5.0]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// scalar broadcast: [2.0, 4.0, 6.0, 8.0]&lt;/span&gt;

&lt;span class="c1"&gt;// Broadcasting a row across a matrix&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;mat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ones&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mat&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// shape [3, 2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Shape operations
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;flat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.flatten&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;           &lt;span class="c1"&gt;// shape [6]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reshaped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;transposed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.transpose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// shape [3, 2]&lt;/span&gt;

&lt;span class="c1"&gt;// Reductions&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.sum&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;          &lt;span class="c1"&gt;// scalar&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;col_sums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.sum_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// shape [3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  JSON and CSV
&lt;/h2&gt;

&lt;p&gt;Both are on by default. The API returns &lt;code&gt;Result&lt;/code&gt; at the boundary, so a malformed input gives you an error rather than a panic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// JSON — two accepted forms&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r#"{"shape":[2,2],"data":[1.0,2.0,3.0,4.0]}"#&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[[1.0, 2.0], [3.0, 4.0]]"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// From a file&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;load_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data/tensor.json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// CSV&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1.0,2.0,3.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;4.0,5.0,6.0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;load_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"data/matrix.csv"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Serialisation goes through serde, so &lt;code&gt;serde_json::to_string(&amp;amp;t)&lt;/code&gt; and &lt;code&gt;serde_json::from_str(&amp;amp;json_str)&lt;/code&gt; round-trip correctly when the &lt;code&gt;json&lt;/code&gt; or &lt;code&gt;serde&lt;/code&gt; feature is active.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error handling
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;matten&lt;/code&gt; has two deliberate error zones. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal shape operations (constructing from &lt;code&gt;new&lt;/code&gt;, reshaping, slicing) panic with an actionable message — useful during fast prototyping because you see the problem immediately.&lt;/li&gt;
&lt;li&gt;External boundary operations (&lt;code&gt;from_json&lt;/code&gt;, &lt;code&gt;from_csv&lt;/code&gt;, &lt;code&gt;load_*&lt;/code&gt;) always return &lt;code&gt;Result&amp;lt;Tensor, MattenError&amp;gt;&lt;/code&gt;, because real input data is not always clean.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MattenError&lt;/code&gt; is &lt;code&gt;#[non_exhaustive]&lt;/code&gt;, so match on the variant you care about and use a wildcard for the rest:
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;matten&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;MattenError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1.0,not_a_number&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"got shape {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="nf"&gt;.shape&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;MattenError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bad input"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"other error: {e:?}"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;That covers the everyday numeric core. The next post covers something different: what happens when the input data is not a clean &lt;code&gt;f64&lt;/code&gt; matrix — when it has mixed types, missing values, or integers alongside floats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt; &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;crates.io&lt;/a&gt; · &lt;a href="https://docs.rs/matten" rel="noopener noreferrer"&gt;docs.rs&lt;/a&gt; · &lt;a href="https://nabbisen.github.io/matten/" rel="noopener noreferrer"&gt;mdBook&lt;/a&gt; · &lt;a href="https://github.com/nabbisen/matten" rel="noopener noreferrer"&gt;repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>math</category>
      <category>tensor</category>
      <category>matrix</category>
      <category>rust</category>
    </item>
    <item>
      <title>matten Introduction: A family-car tensor library for Rust</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Mon, 29 Jun 2026 01:45:50 +0000</pubDate>
      <link>https://dev.to/nabbisen/matten-introduction-a-family-car-tensor-library-for-rust-52ak</link>
      <guid>https://dev.to/nabbisen/matten-introduction-a-family-car-tensor-library-for-rust-52ak</guid>
      <description>&lt;p&gt;I recently published &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;&lt;code&gt;matten&lt;/code&gt;&lt;/a&gt;, a small Rust library for working with multidimensional arrays. This is the first of four short posts introducing it. This one is about why it exists.&lt;/p&gt;




&lt;p&gt;Rust is a great language for numerical and data-oriented work. But starting that work — just getting to the point where you have a matrix and can add two of them together — takes more effort than it probably should at the prototype stage.&lt;/p&gt;

&lt;p&gt;The established libraries are capable and well-maintained. If you need performance, reach for &lt;a href="https://crates.io/crates/ndarray" rel="noopener noreferrer"&gt;&lt;code&gt;ndarray&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://crates.io/crates/nalgebra" rel="noopener noreferrer"&gt;&lt;code&gt;nalgebra&lt;/code&gt;&lt;/a&gt;. They are the right tools for production numerical code.&lt;br&gt;
But they come with a learning curve: generic type parameters, storage abstractions, view types, lifetime considerations. That overhead is often worth it. It is not always worth it on day one of a proof of concept.&lt;/p&gt;

&lt;p&gt;The gap &lt;code&gt;matten&lt;/code&gt; fills is narrow and deliberate: &lt;strong&gt;making early-stage numerical Rust work feel less ceremonial&lt;/strong&gt;, so you can spend the first hour on the problem rather than on the type system.&lt;/p&gt;

&lt;p&gt;The project description borrows a modest analogy: a family car. Easy to get into, predictable to drive, comfortable enough for most everyday trips. Not a racing car. Not trying to be one.&lt;/p&gt;

&lt;p&gt;Concretely that means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One primary public type, &lt;code&gt;Tensor&lt;/code&gt;, with no generic parameters.&lt;/li&gt;
&lt;li&gt;No user-visible lifetimes in ordinary usage.&lt;/li&gt;
&lt;li&gt;Human-readable error messages when shapes do not match.&lt;/li&gt;
&lt;li&gt;JSON and CSV support on by default, for moving data in and out without ceremony.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;#![forbid(unsafe_code)]&lt;/code&gt; throughout.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it does not mean: faster than the alternatives on hot paths. The library is explicit about this. When a prototype grows into something performance-critical, the right move is to migrate that part of the work to a more capable library. &lt;code&gt;matten-ndarray&lt;/code&gt; exists specifically for that handoff, and the flat &lt;code&gt;Vec&amp;lt;f64&amp;gt;&lt;/code&gt; storage makes the data easy to move.&lt;/p&gt;

&lt;p&gt;P.S. — The name is from &lt;strong&gt;mat&lt;/strong&gt;hematical &lt;strong&gt;ten&lt;/strong&gt;sor NOT 😜 It's from a Japanese charming dialect meaning "waited for". We took our time, and so can you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt; &lt;a href="https://crates.io/crates/matten" rel="noopener noreferrer"&gt;crates.io&lt;/a&gt; · &lt;a href="https://docs.rs/matten" rel="noopener noreferrer"&gt;docs.rs&lt;/a&gt; · &lt;a href="https://nabbisen.github.io/matten/" rel="noopener noreferrer"&gt;mdBook&lt;/a&gt; · &lt;a href="https://github.com/nabbisen/matten" rel="noopener noreferrer"&gt;repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>math</category>
      <category>tensor</category>
      <category>matrix</category>
      <category>rust</category>
    </item>
    <item>
      <title>mdka v2 Release</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Tue, 21 Apr 2026 22:36:15 +0000</pubDate>
      <link>https://dev.to/nabbisen/mdka-v2-release-3n95</link>
      <guid>https://dev.to/nabbisen/mdka-v2-release-3n95</guid>
      <description>&lt;p&gt;We have released v2 of &lt;a href="https://github.com/nabbisen/mdka-rs" rel="noopener noreferrer"&gt;mdka&lt;/a&gt;, a Rust-based HTML-to-Markdown converter. Originally developed as a core component for our internal systems, we have refined it into a general-purpose library for public release.&lt;/p&gt;

&lt;p&gt;v2 strikes a practical balance between conversion quality and runtime efficiency—delivering readable output without sacrificing speed or memory. By focusing solely on its core task, this "Unix-style" tool achieves a lightweight footprint while maintaining competitive performance. We are pleased to share this utility with the community.&lt;/p&gt;

&lt;p&gt;Full documentaions:&lt;br&gt;
&lt;a href="https://nabbisen.github.io/mdka-rs/" rel="noopener noreferrer"&gt;https://nabbisen.github.io/mdka-rs/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>markdown</category>
      <category>converter</category>
      <category>html</category>
    </item>
    <item>
      <title>jwt-encde 1.1: npm packages for cross-platform published</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Fri, 30 Jan 2026 09:11:20 +0000</pubDate>
      <link>https://dev.to/nabbisen/jwt-encde-11-npm-packages-for-cross-platform-published-504l</link>
      <guid>https://dev.to/nabbisen/jwt-encde-11-npm-packages-for-cross-platform-published-504l</guid>
      <description>&lt;p&gt;&lt;a href="https://scqr.net/en/blog/2026/01/21/jwt-encde-1_0-auth-test-helper//index.html" rel="noopener noreferrer"&gt;jwt-encde&lt;/a&gt;, local and fast GUI JWT encoder/decoder, 1.1 🎉 now supports installation via &lt;code&gt;npm&lt;/code&gt; 🤍&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; jwt-encde
npx jwt-encde
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>jwt</category>
      <category>test</category>
      <category>gui</category>
      <category>security</category>
    </item>
  </channel>
</rss>
