<?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>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>
    <item>
      <title>jwt-encde: A simple way to handle JWTs on your desktop</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Wed, 21 Jan 2026 13:20:08 +0000</pubDate>
      <link>https://dev.to/nabbisen/jwt-encde-a-simple-way-to-handle-jwts-on-your-desktop-3fln</link>
      <guid>https://dev.to/nabbisen/jwt-encde-a-simple-way-to-handle-jwts-on-your-desktop-3fln</guid>
      <description>&lt;p&gt;If you're looking for a way to analyze JWTs without using online tools, &lt;a href="https://github.com/nabbisen/jwt-encde" rel="noopener noreferrer"&gt;&lt;strong&gt;jwt-encde&lt;/strong&gt;&lt;/a&gt; might be helpful.&lt;/p&gt;

&lt;p&gt;It is a dedicated GUI app that brings JWT decoding and encoding to your local desktop. The first stable version was released today, built with Rust and iced.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F647evd6uh7d6m646dqff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F647evd6uh7d6m646dqff.png" alt="screenshot" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why and when &lt;strong&gt;jwt-encde&lt;/strong&gt; ?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100% Offline: Total privacy and information security. No logs, no tracking, no leaks.&lt;/li&gt;
&lt;li&gt;Robust Design. Simple &amp;amp; Intuitive: Just a clean, high-performance and error-prevention UI ensures you focus on what's relevant to your current data.&lt;/li&gt;
&lt;li&gt;Smart Analysis: Includes JSON syntax highlighting and a built-in Unix timestamp converter to make debugging easier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And &lt;strong&gt;NOT&lt;/strong&gt; when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It doesn't support signature verification, as typically handled during integration tests with an IDaaS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Available for Windows, macOS, and Linux: &lt;a href="https://github.com/nabbisen/jwt-encde" rel="noopener noreferrer"&gt;https://github.com/nabbisen/jwt-encde&lt;/a&gt;&lt;/p&gt;

</description>
      <category>jwt</category>
      <category>gui</category>
      <category>iced</category>
      <category>security</category>
    </item>
    <item>
      <title>MariaDB 11.4 on OpenBSD 7.8: Install</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Wed, 03 Dec 2025 14:27:55 +0000</pubDate>
      <link>https://dev.to/nabbisen/mariadb-114-on-openbsd-78-install-9kc</link>
      <guid>https://dev.to/nabbisen/mariadb-114-on-openbsd-78-install-9kc</guid>
      <description>&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://mariadb.com/" rel="noopener noreferrer"&gt;MariaDB&lt;/a&gt; is one of the most popular relational database management systems (RDBMS), forked from &lt;a href="https://www.mysql.com/" rel="noopener noreferrer"&gt;MySQL&lt;/a&gt; by some of the original developers.&lt;br&gt;
It is open source &lt;a href="https://mariadb.com/kb/en/mariadb-licenses/" rel="noopener noreferrer"&gt;licensed&lt;/a&gt; under &lt;a href="http://www.gnu.org/licenses/gpl-2.0.html" rel="noopener noreferrer"&gt;GNU GPL 2&lt;/a&gt;, and ready for both community and enterprise use with long history and large knowledge to manage and maintain.&lt;/p&gt;

&lt;p&gt;To Install it on &lt;a href="https://www.openbsd.org/" rel="noopener noreferrer"&gt;OpenBSD&lt;/a&gt;, the solid and clean operating system, is easy thanks to the &lt;a href="https://www.openbsd.org/faq/faq15.html" rel="noopener noreferrer"&gt;Package Management&lt;/a&gt; system ("ports") maintained by the great project and the community.&lt;/p&gt;

&lt;p&gt;This post shows how to do it.&lt;/p&gt;
&lt;h3&gt;
  
  
  Environment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;OS: OpenBSD &lt;a href="https://www.openbsd.org/78.html" rel="noopener noreferrer"&gt;7.8&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Database: MariaDB &lt;a href="https://mariadb.com/resources/blog/mariadb-community-server-11-4-with-improved-query-performance-now-ga-with-long-term-maintenance/" rel="noopener noreferrer"&gt;11.4&lt;/a&gt;.9

&lt;ul&gt;
&lt;li&gt;It's &lt;a href="https://mariadb.org/about/#maintenance-policy" rel="noopener noreferrer"&gt;LTS&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Basic steps
&lt;/h3&gt;

&lt;p&gt;Just a few !!&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;pkg_add mariadb-server
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rcctl &lt;span class="nb"&gt;enable &lt;/span&gt;mysqld
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mariadb-install-db
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rcctl start mysqld
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mariadb-secure-installation
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# several questions will be given&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of the description is below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tutorial
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install the package
&lt;/h3&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 mariadb-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result was:&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;quirks-7.147 signed on 2025-12-01T09:05:47Z
mariadb-server-11.4.9v1:(...): ok
mariadb-server-11.4.9v1: ok
The following new rcscripts were installed: /etc/rc.d/mysqld
See rcctl(8) for details.
New and changed readme(s):
    /usr/local/share/doc/pkg-readmes/mariadb-server
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As above, the pkg-readme is brought as &lt;code&gt;/usr/local/share/doc/pkg-readmes/mariadb-server&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Activate daemon
&lt;/h3&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 rcctl &lt;span class="nb"&gt;enable &lt;/span&gt;mysqld
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run &lt;code&gt;mariadb-install-db&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Create the default database:&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 mariadb-install-db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result was:&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;Installing MariaDB/MySQL system tables in '/var/mysql' ...
OK


Two all-privilege accounts were created.
One is root@localhost, it has no password, but you need to
be system 'root' user to connect. Use, for example, sudo mariadb
The second is _mysql@localhost, it has no password either, but
you need to be the system '_mysql' user to connect.
After connecting you can set the password, if you would need to be
able to connect as any of these users with a password and without sudo

See the MariaDB Knowledgebase at https://mariadb.com/kb

You can start the MariaDB daemon with:
/etc/rc.d/mysqld start

Please report any problems at https://mariadb.org/jira

The latest information about MariaDB is available at https://mariadb.org/.

Consider joining MariaDB's strong and vibrant community:
https://mariadb.org/get-involved/

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Start daemon
&lt;/h3&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 rcctl start mysqld
&lt;span class="go"&gt;mysqld(ok)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run &lt;code&gt;mariadb-secure-installation&lt;/code&gt;
&lt;/h3&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 mariadb-secure-installation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Start (Before the questions)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Several questions given
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Q1: Current root password
&lt;/h5&gt;

&lt;p&gt;It must be none for the first time. Just push Enter.&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;In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.

Enter current password for root (enter for none): 
OK, successfully used password, moving on...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At all the questions below, my choice is written down. Actually, they are up to your environment.&lt;/p&gt;

&lt;h5&gt;
  
  
  Q2: Use unix_socket authentication instead of root password
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.

You already have your root account protected, so you can safely answer 'n'.

Switch to unix_socket authentication [Y/n] n
 ... skipping.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Q3: Set root password
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;You already have your root account protected, so you can safely answer 'n'.

Change the root password? [Y/n] y
New password: 
Re-enter new password: 
Password updated successfully!
Reloading privilege tables..
 ... Success!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Q4: Remove anonymous users
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Q5: Disallow root login remotely
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Q6: Remove test database
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Q7: Reload privilege tables
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  End (The rest)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;You may confirm your daemon is fine with:&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 rcctl check mysqld
&lt;span class="go"&gt;mysqld(ok)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, let's login to the server as client with &lt;code&gt;root&lt;/code&gt;, the superuser:&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;mysql &lt;span class="nt"&gt;-u&lt;/span&gt; root &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After entering the password, you must be welcomed:&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;Welcome to the MariaDB monitor.  Commands end with ;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;or &lt;span class="se"&gt;\g&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="go"&gt;Your MariaDB connection id is 11
Server version: 11.4.9-MariaDB OpenBSD port: mariadb-server-11.4.9v1

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

&lt;/span&gt;&lt;span class="gp"&gt;Type 'help;&lt;/span&gt;&lt;span class="s1"&gt;' or '&lt;/span&gt;&lt;span class="se"&gt;\h&lt;/span&gt;&lt;span class="s1"&gt;' for help. Type '&lt;/span&gt;&lt;span class="se"&gt;\c&lt;/span&gt;&lt;span class="s1"&gt;' to clear the current input statement.
&lt;/span&gt;&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;MariaDB [(none)]&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command line examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- create database&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;database&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;CHARACTER&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;utf8mb4&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;
    &lt;span class="k"&gt;COLLATE&lt;/span&gt; &lt;span class="n"&gt;utf8mb4_unicode_ci&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- create user for it&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;database&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;
    &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dbuser&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;
    &lt;span class="n"&gt;IDENTIFIED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;dbpass&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- reload privileges&lt;/span&gt;
&lt;span class="n"&gt;FLUSH&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;🎵 🐬 Happy storing digitally 🐬 🎵&lt;/p&gt;

</description>
      <category>mariadb</category>
      <category>database</category>
      <category>server</category>
      <category>install</category>
    </item>
    <item>
      <title>OpenBSD 7.7 を 7.8 へ アップグレード</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Sun, 16 Nov 2025 09:50:02 +0000</pubDate>
      <link>https://dev.to/nabbisen/openbsd-77-wo-78-he-atupuguredo-4g15</link>
      <guid>https://dev.to/nabbisen/openbsd-77-wo-78-he-atupuguredo-4g15</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; プロジェクトから 2025 年 10 月 22 日に OS の &lt;a href="https://www.openbsd.org/78.html" rel="noopener noreferrer"&gt;7.8&lt;/a&gt; がリリースされました 🌷 59 回目のリリースに当たります。&lt;/p&gt;

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

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

&lt;p&gt;本記事で OpenBSD 7.7 を 7.8 にアップグレードする手順を説明します。&lt;br&gt;
各手順はすばらしい &lt;a href="https://www.openbsd.org/faq/upgrade78.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/upgrade78.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/sd1e      7.6G    3.5G    3.7G    50%    /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/upgrade78.html#ConfigChanges" rel="noopener noreferrer"&gt;設定と構文の変更 (英語)&lt;/a&gt; と &lt;a href="https://www.openbsd.org/faq/upgrade78.html#SpecialPackages" rel="noopener noreferrer"&gt;特別なパッケージ (英語)&lt;/a&gt; を確認しましょう。&lt;br&gt;
後者に関して、今回は &lt;a href="https://www.php.net/" rel="noopener noreferrer"&gt;PHP&lt;/a&gt; が含まれています。デフォルトバージョンが &lt;a href="https://www.php.net/releases/8.3/ja.php" rel="noopener noreferrer"&gt;8.3&lt;/a&gt; に変更されています:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The default version of PHP in ports has changed from 8.2 to 8.3.&lt;/p&gt;
&lt;/blockquote&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.8/amd64/
SHA256.sig   100% |***********************************************************|  2324       00:00    
Signature Verified
BUILDINFO    100% |***********************************************************|    54       00:00    
Verifying old sets.
INSTALL.amd64 100% |**********************************************************| 44889       00:00    
base78.tgz   100% |***********************************************************|   498 MB    00:40    
bsd          100% |***********************************************************| 31408 KB    00:02    
bsd.mp       100% |***********************************************************| 31506 KB    00:02    
bsd.rd       100% |***********************************************************|  4691 KB    00:00    
comp78.tgz   100% |***********************************************************| 88484 KB    00:07    
game78.tgz   100% |***********************************************************|  2742 KB    00:00    
man78.tgz    100% |***********************************************************|  8286 KB    00:00    
xbase78.tgz  100% |***********************************************************| 74882 KB    00:06    
xfont78.tgz  100% |***********************************************************| 23018 KB    00:01    
xserv78.tgz  100% |***********************************************************| 11812 KB    00:00    
xshare78.tgz 100% |***********************************************************|  4553 KB    00:00    
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 
&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 plaintext"&gt;&lt;code&gt;starting local daemons: cron.
Sat Nov 15 16:45:30 JST 2025

OpenBSD/amd64 ... (ttyC0)

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

&lt;/div&gt;



&lt;p&gt;ログインメッセージが表示されています。"OpenBSD 7.8 (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/upgrade78.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/78.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/upgrade78.html#ConfigChanges" rel="noopener noreferrer"&gt;設定と構文の変更 (英語)&lt;/a&gt; に書かれている内容を適用しましょう。&lt;/p&gt;

&lt;p&gt;今回、&lt;code&gt;build&lt;/code&gt; ユーザーへの言及があります。LLVM 19 のビルドに関わることで、ログインクラスを変更する必要があります。&lt;/p&gt;

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

&lt;p&gt;ここはシンプルな手順です。公式チュートリアルの &lt;a href="https://www.openbsd.org/faq/upgrade78.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/upgrade78.html#SpecialPackages" rel="noopener noreferrer"&gt;特別なパッケージ (英語)&lt;/a&gt; を確認しましょう。使っているものがあるかもしれません:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;freetds&lt;/li&gt;
&lt;li&gt;php&lt;/li&gt;
&lt;li&gt;rbw&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.7 to 7.8</title>
      <dc:creator>nabbisen</dc:creator>
      <pubDate>Sun, 16 Nov 2025 09:37:28 +0000</pubDate>
      <link>https://dev.to/nabbisen/openbsd-upgrade-77-to-78-3b75</link>
      <guid>https://dev.to/nabbisen/openbsd-upgrade-77-to-78-3b75</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/78.html" rel="noopener noreferrer"&gt;7.8&lt;/a&gt; of their OS on 22 Oct 2025, as their 59th release 💫&lt;/p&gt;

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

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

&lt;p&gt;This post shows how to upgrade OpenBSD 7.7 to 7.8.&lt;br&gt;
The steps are based on &lt;a href="https://www.openbsd.org/faq/upgrade78.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/upgrade78.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/sd1e      7.6G    3.5G    3.7G    50%    /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/upgrade78.html#ConfigChanges" rel="noopener noreferrer"&gt;Configuration and syntax changes&lt;/a&gt; and &lt;a href="https://www.openbsd.org/faq/upgrade78.html#SpecialPackages" rel="noopener noreferrer"&gt;Special packages&lt;/a&gt;.&lt;br&gt;
The latter this time includes &lt;a href="https://www.php.net/" rel="noopener noreferrer"&gt;PHP&lt;/a&gt; default version switched to &lt;a href="https://www.php.net/releases/8.3/en.php" rel="noopener noreferrer"&gt;8.3&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The default version of PHP in ports has changed from 8.2 to 8.3.&lt;/p&gt;
&lt;/blockquote&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.8/amd64/
SHA256.sig   100% |***********************************************************|  2324       00:00    
Signature Verified
BUILDINFO    100% |***********************************************************|    54       00:00    
Verifying old sets.
INSTALL.amd64 100% |**********************************************************| 44889       00:00    
base78.tgz   100% |***********************************************************|   498 MB    00:40    
bsd          100% |***********************************************************| 31408 KB    00:02    
bsd.mp       100% |***********************************************************| 31506 KB    00:02    
bsd.rd       100% |***********************************************************|  4691 KB    00:00    
comp78.tgz   100% |***********************************************************| 88484 KB    00:07    
game78.tgz   100% |***********************************************************|  2742 KB    00:00    
man78.tgz    100% |***********************************************************|  8286 KB    00:00    
xbase78.tgz  100% |***********************************************************| 74882 KB    00:06    
xfont78.tgz  100% |***********************************************************| 23018 KB    00:01    
xserv78.tgz  100% |***********************************************************| 11812 KB    00:00    
xshare78.tgz 100% |***********************************************************|  4553 KB    00:00    
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 
&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 plaintext"&gt;&lt;code&gt;starting local daemons: cron.
Sat Nov 15 16:45:30 JST 2025

OpenBSD/amd64 ... (ttyC0)

login:
&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.8 (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/upgrade78.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/78.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 href="https://www.openbsd.org/faq/upgrade78.html#ConfigChanges" rel="noopener noreferrer"&gt;Configuration and syntax changes&lt;/a&gt; describes.&lt;/p&gt;

&lt;p&gt;This time &lt;code&gt;build&lt;/code&gt; user is referred to around LLVM 19 build: the login class needs to be modified.&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/upgrade78.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/upgrade78.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;freetds&lt;/li&gt;
&lt;li&gt;php&lt;/li&gt;
&lt;li&gt;rbw&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>
  </channel>
</rss>
