読者です 読者をやめる 読者になる 読者になる

いものやま。

雑多な知識の寄せ集め

Swiftでの行列計算について調べてみた。(その3)

技術 Swift

昨日はベクトルとSplatの説明をした。

今日はこれらを使った演算について。

転置

まずは転置。
次の関数が用意されている:

// 転置した行列を生成して返す。
la_object_t
la_transpose(
    la_object_t matrix);  // 行列

スカラー

次はスカラー倍。

// スカラー倍した行列を生成して返す。
la_object_t
la_scale_with_float(
    la_object_t matrix,  // 行列
    float scalar);       // 何倍するか
la_object_t
la_scale_with_double(
    la_object_t matrix,  // 行列
    double scalar);      // 何倍するか

2つの行列の和と差

2つの行列の和と差の計算。

// 2つの行列の和を生成して返す。
// (サイズが同じでないとダメ)
la_object_t
la_sum(
    la_object_t obj_left,    // 左項
    la_object_t obj_right);  // 右項

// 2つの行列の差を生成して返す。
// (サイズが同じでないとダメ)
la_object_t
la_difference(
    la_object_t obj_left,    // 左項
    la_object_t obj_right);  // 右項

なお、サイズが違うなどで計算が正しくできなかった場合には返されるオブジェクトの状態がエラーになるので、la_status()で状態をチェックする。
(以降の他の関数も同様)

2つのベクトルの内積外積(直積)

2つのベクトル  \boldsymbol{v}, \boldsymbol{w}内積  \langle \boldsymbol{v}, \boldsymbol{w} \rangle = \boldsymbol{v}^{\mathrm{T}} \boldsymbol{w}、および外積(直積) \boldsymbol{v} \otimes \boldsymbol{w} = \boldsymbol{v} \boldsymbol{w}^{\mathrm{T}} は、次の関数で計算できる:

// ベクトルの内積。
// (サイズが同じでないとダメ)
// 結果がスカラーでなく1x1の行列になることに注意。
la_object_t
la_inner_product(
    la_object_t vector_left,    // 左項
    la_object_t vector_right);  // 右項

// ベクトルの外積(直積)。
la_object_t
la_outer_product(
    la_object_t vector_left,    // 左項
    la_object_t vector_right);  // 右項

なお、コメントにも書いた通り、内積スカラーではなくて1x1の行列になるので、注意が必要。
(確かに、1行の行列と1列の行列の積が内積なので、1x1行列ではあるんだけど・・・)

あと、ベクトルには列ベクトル・行ベクトルのいずれを指定してもいい。

2つの行列の積、アダマール

2つの行列  A, B の積  AB、およびアダマール積(要素ごとの積) A \odot B は、次の関数で計算できる:

// 行列の積。
// (左項の列数と右項の行数が同じでないとダメ)
la_object_t
la_matrix_product(
    la_object_t matrix_left,    // 左項
    la_object_t matrix_right);  // 右項

// 行列のアダマール積(要素ごとの積)
// (サイズが同じでないとダメ)
// ただし、ベクトルについては、列ベクトルか行ベクトルかは問われない。
// (列ベクトルと行ベクトルが指定された場合、列ベクトルになる)
la_object_t
la_elementwise_product(
    la_object_t obj_left,    // 左項
    la_object_t obj_right);  // 右項

ベクトルのノルムと正規化

ベクトルのノルムは、次の関数で計算できる:

// ベクトルのノルム
float
la_norm_as_float(
    la_object_t vector,      // ベクトル
    la_norm_t vector_norm);  // ノルムの種類
double
la_norm_as_double(
    la_object_t vector,      // ベクトル
    la_norm_t vector_norm);  // ノルムの種類

la_norm_tはノルムの種類を指定するためのもので、次のように定義されている:

typedef unsigned long la_norm_t;
#define LA_L1_NORM 1    // L1ノルム
#define LA_L2_NORM 2    // L2ノルム
#define LA_LINF_NORM 3  // 無限大ノルム(最大値ノルム)

また、ベクトルの正規化を行うための関数も用意されている:

// 指定されたノルムで正規化したベクトルを生成する。
la_object_t
la_normalized_vector(
    la_object_t vector,      // ベクトル
    la_norm_t vector_norm);  // ノルムの種類

連立一次方程式の解を求める

連立一次方程式(を複数並べたもの) AX = B を満たす行列  X を求める関数が用意されている:

// AX = Bの解Xを返す。
la_object_t
la_solve(
    la_object_t matrix_system,  // Aにあたる行列
    la_object_t obj_rhs);       // Bにあたる行列

用意されているインタフェースはこれで終わりなんだけど、C言語の関数の形なので、Swiftで使うにはちょっと野暮な感じ。
なので、明日はラッパークラスを作ってみる。

今日はここまで!