🌊

Rust言語でMatrix型と和を実装する

2023/02/28に公開

概要

Rust言語を勉強するにあたり,Rustのジェネリクスなどを体感するために複素数や行列演算を定義してみようと思った。
(本記事のコードはかなりChatGPTで生成されたコードを参考にしています。)

対象読者

Rust言語に興味があり,利用しはじめたくらいの方

コード

本記事で紹介したコードは以下にまとめています。
https://github.com/Soyukke/linear_algebra_rust

ジェネリクスによるMatrix型の定義

https://github.com/Soyukke/linear_algebra_rust/blob/master/src/matrix.rs

まずはRustのstructを使ってMatrix構造体を定義する。
行列の構造体なので,シンプルに二次元配列形式のdataだけ持っている。

ここで,型Tの配列をROWS×COLSの行列で初期化できるようにパラメータを指定している。
Matrix<T, const ROWS: usize, const COLS: usize>

Rust言語では型パラメータTだけでなく,usize型の値などもパラメータとして指定することができるので,実装がシンプルになる。

#[derive(Debug, Clone)]
pub struct Matrix<T, const ROWS: usize, const COLS: usize> {
    pub data: [[T; COLS]; ROWS],
}

演算

Addの実装

演算子の実装はstd::ops::Addなどのトレイトを実装することで実現できる。
以下が行列の和の実装。

impl<T: Add<Output = T> + Default + Copy, const ROWS: usize, const COLS: usize> Add for Matrix<T, ROWS, COLS> {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        let mut result = Self::new();

        for i in 0..ROWS {
            for j in 0..COLS {
                result.data[i][j] = self.data[i][j] + other.data[i][j];
            }
        }

        result
    }
}

Rust言語を触り始めて私が戸惑った部分はここ。
<T: Add<Output = T> + Default + Copy, const ROWS: usize, const COLS: usize>
これは,「トレイト境界を設ける」などと解説されている部分で,ジェネリクスのパラメータTなどに制約を与えている。
Add<Output = T> + Default + Copyのように+で制約を追加しているイメージだ。
ここでのTの制約は,型T同士の和の出力の型がTであるようなAddトレイトが実装されており,Defaultトレイトが実装されており,Copyトレイトが実装されているという制約だ。
上記を満たすTについて,MatrixのAddを実装するということになる。

※Defaultトレイトは,型Tのゼロを返す関数が実装されている。(f32なら0.0, usizeなら0のように)

和の実装自体は,Addトレイトのadd関数で,行列の各要素の和を格納した新たなMatrixをreturnする関数を実装するだけで難しいポイントはなさそう。

制約さえ慣れてしまえば,自由自在に実装できそうだ。

Discussion