# Chapter 18. Persistent Matrices

A persistent matrix of dimension m by n is just a persistent array of size m*n. Like in C, the representation of a matrix in ATS is row-major. In other words, element (i, j) in a matrix of dimension m by n is element i*n+j in the underlying array that represents the matrix.

Given a viewtype VT and two integers M and N, the type matrixref(VT, M, N) is for persistent matrices of dimension M by N that contain elements of the viewtype VT. There is no dimension information attached to matrixref-values explicitly. The interfaces for various functions on persistent matrices can be found in the SATS file prelude/SATS/matrixref.sats, which is automatically loaded by atsopt.

The following function is commonly used to create a matrixref-value:

```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]
```

Given two sizes m and n plus an element x0, matrixref_make_elt returns a matrix of dimension m by n in which each cell is initialized with the element x0.

Also, the following cast function can be called to turn an array into a matrix:

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

For accessing and updating the content of a matrix-cell, the following two functions matrixref_get_at and matrixref_set_at can be called:

```//
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]
//
```

Note that it is not enough to just supply the coordinates of a matrix-cell in order to access it; the column dimension of the matrix needs to be supplied as well.

In the following presentation, I give an implementation of a function that turns a given square matrix into its transpose:

```//
extern
fun{a:t0p}
matrixref_transpose
{n:nat}
(
M: matrixref(a, n, n), n: size_t(n)
) : void // end of [matrixref_transpose]
//
implement
{a}(*tmp*)
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 // end of [then]
else let
val i1 = succ (i)
in
//
if i1 < n then loop(i1, succ(i1)) else ()
//
end // end of [else]
//
) (* end of [loop] *)
//
in
if (n > 0) then loop(i2sz(0), i2sz(1)) else ()
end // end of [matrixref_transpose]
```

Please find on-line the entirety of the code used in this chapter.