Open7

Rustのndarrayを使ってみる

TaroTaro

環境

MacBook Pro (M3 Pro)
macOS Sonoma 14.5
rustc 1.82.0 (f6e511eec 2024-10-15)
cargo 1.82.0 (8f40fc59f 2024-08-21)

TaroTaro

ndarrayを追加

$ cargo add ndarray
    Updating crates.io index
      Adding ndarray v0.16.1 to dependencies
             Features:
             + std
             - approx
             - blas
             - docs
             - matrixmultiply-threading
             - portable-atomic-critical-section
             - rayon
             - serde
             - serde-1
             - test
    Updating crates.io index
    Blocking waiting for file lock on package cache
     Locking 9 packages to latest compatible versions
      Adding autocfg v1.4.0
      Adding matrixmultiply v0.3.9
      Adding ndarray v0.16.1
      Adding num-complex v0.4.6
      Adding num-integer v0.1.46
      Adding num-traits v0.2.19
      Adding portable-atomic v1.9.0
      Adding portable-atomic-util v0.2.3
      Adding rawpointer v0.2.1
TaroTaro

element-wiseな四則演算

use ndarray::*;

fn main() {
    let arr1 = array![3., 1., 4., 1., 5., 9.];
    let arr2 = array![1., 4., 1., 4., 2., 1.];

    assert_eq!(&arr1 + &arr2, array![4., 5., 5., 5., 7., 10.]);
    assert_eq!(&arr1 - &arr2, array![2., -3., 3., -3., 3., 8.]);
    assert_eq!(&arr1 * &arr2, array![3., 4., 4., 4., 10., 9.]);
    assert_eq!(&arr1 / &arr2, array![3., 0.25, 4., 0.25, 2.5, 9.]);
}
TaroTaro

どうやら6次元(6階?)までしか対応していなそう

TaroTaro

より高階のを作るときはIxDynを使うとできる。

use ndarray::*;

fn main() {
    let arr1: ArrayBase<OwnedRepr<f64>, Dim<[usize; 1]>> = Array::range(0., 40320., 1.0);
    assert_eq!(arr1.shape(), &[40320]);

    let arr2 = arr1
        .into_shape_with_order(IxDyn(&[1, 2, 3, 4, 5, 6, 7, 8]))
        .unwrap();
    assert_eq!(arr2.shape(), &[1, 2, 3, 4, 5, 6, 7, 8]);
}
TaroTaro

shapeとかidx周りは型パズルが複雑になっていて中身の実装を追いづらく、エラー吐いた時の原因を突き止めるのが難しい