Chapter 18. 永続化行列

次元 m, n の永続化行列は、単にサイズが m*n の永続化配列です。 C言語と同様に、ATS における行列表現は列優先 (row-major) です。 別の言い方をすると、次元 m, n の行列内の要素 (i, j) は、その行列を表現する配列内の要素 i*n+j です。

観型 VT と2つの整数 M と N が与えられたとき、 型 matrixref(VT, M, N) は観型 VT の要素を含む次元 M, N の永続化行列を表わします。 matrixref 値にどのような次元情報も付随しません。 永続化行列に関する様々な関数のインターフェイスを SATS ファイル prelude/SATS/matrixref.sats に見つけることができます。 これは atsopt によって自動的に読み込まれます。

次の関数は matrixref 値を生成するのに一般的に使用されます:

fun{a:t0p} matrixref_make_elt{m,n:int} (m: size_t m, n: size_t n, x0: a):<!wrt> matrixref (a, m, n) // end of [matrixref_make_elt]

2つのサイズ m, n と要素 x0 が与えられたとき、matrixref_make_elt はそれぞれのセルが要素 x0 で初期化された次元 m, n の行列を返します。

また、次のキャスト関数が呼び出されると、配列を行列に変化させます:

castfn arrayref2matrixref {a:vt0p}{m,n:nat} (A: arrayref (a, m*n)):<> matrixref (a, m, n) // end of [arrayref2matrixref]

行列セルの内容物にアクセスしたり更新するために、次の2つの関数 matrixref_get_atmatrixref_set_at を呼び出すことができます:

// fun{a:t0p} matrixref_get_at {m,n:int} ( A: matrixref (a, m, n), i: sizeLt(m), n: size_t(n), j: sizeLt(n) ) :<!ref> (a) // end of [matrixref_get_at] // fun{a:t0p} matrixref_set_at {m,n:int} ( A: matrixref (INV(a), m, n), i: sizeLt (m), n: size_t n, j: sizeLt (n), x: a ) :<!refwrt> void // end of [matrixref_set_at] //

アクセスするためには単に行列セルの座標を指定するだけでは十分ではないことに注意してください; その行列の行の次元も同様に指定する必要があります。

次は、与えられた正方行列を転置行列にする関数の実装です:

// extern fun{a:t0p} matrixref_transpose {n:nat} ( M: matrixref (a, n, n), n: size_t (n) ) : void // end of [matrixref_transpose] // implement{a} matrixref_transpose {n} (M, n) = let // macdef mget (i, j) = matrixref_get_at (M, ,(i), n, ,(j)) macdef mset (i, j, x) = matrixref_set_at (M, ,(i), n, ,(j), ,(x)) // fun loop {i,j:nat | i < j; j <= n } .<n-i,n-j>. ( i: size_t (i), j: size_t (j) ) : void = if j < n then let val x = mget(i, j) val () = mset(i, j, mget(j, i)) val () = mset(j, i, x) in loop (i, j+1) end else let val i1 = succ (i) in if i1 < n then loop (i1, succ(i1)) else () end // end of [if] // in if n > 0 then loop (i2sz(0), i2sz(1)) else () end // end of [matrixref_transpose]

この章で紹介したコード全体は オンライン から入手できます。