Matrices
Creating matrices
A matrix can be created as follows.
You can use functions to create a matrix as well.
Mat.make
returns a matrix initialized by a given value.
Note that it takes two dimensions: the first parameter three
is the number of
columns (i.e., the height) of the matrix and the second five
is the number of
rows (i.e., the width). Thus Mat.make three five x
returns a three-by-five
matrix initialized by the value of x
.
Creating of matrices is the same as that of vectors except for passing two
dimensions. You can also use Mat.create
(which returns an uninitialized matrix
for working memory), Mat.make0
(which creates a matrix initialized by zero;
i.e., Mat.make0 m n
is Mat.make m n 0.0
), Mat.make1
(which returns a
matrix initialized by one), Mat.init
(which creates a matrix initialized by
a given function) and Mat.random
(which returns a randomly-initialized
matrix). We show the following examples of Mat.init
and Mat.random
.
Mat.init m n f
returns an m
-by-n
matrix whose element in the (i,j)
position is initialized by the result of calling of f i j
(where 1 <= i <= m
and 1 <= j <= n
).
Mat.random
is similar to Vec.random
. The elements of a created matrix are in
interval [from, from + range]
. Arguments from
and range
are optional.
If they are omitted, -1.0
and 2.0
are passed, respectively, i.e., the
interval is [-1.0, +1.0]
.
Matrix types
Basically, the strange types of the matrices are the same as those of vectors.
Consider the type of the following matrix a
, again.
- The first type parameter of the matrix type represents the number of columns
(i.e., the height) of a matrix, and the second corresponds to the number
of rows (i.e., the width). Types
three
(=Slap.Size.three
),five
(=Slap.Size.five
) correspond to natural numbers “3” and “5”, respectively. The size information of these type parameters is used for static size checking. - The third type parameter is a “contiguous or discrete” flag. For the time being, you do not need to consider it because we only use contiguous matrices).
Matrix-vector operations
Matrix-vector operations (Level 2 BLAS routines) are defined under Slap.D
.
For example, gemv
multiplies a general rectangular matrix and a vector.
gemv ?beta ?y ~trans ?alpha a x
basically computes
y := alpha * a * x + beta * y
where alpha
(= 1 by default) and beta
(= 0 by default) are scalar values, x
and y
are vectors, and a
is a
matrix:
The above example calculates
The parameter trans
indicates whether matrix a
is transposed, or not:
when normal
(= Slap.Common.normal
) is passed, a
is not transposed;
in contrast, trans
(= Slap.Common.trans
) means that a
is transposed as
follows.
The latter example computes
For example, you can use gemv
for affine transformation.
Matrix-matrix operations
Matrix-matrix operations (Level 3 BLAS routines) are defined under Slap.D
as well as matrix-vector operations. We only explain gemm
and symm
as
examples, but more routines are supported.
gemm: multiplication of two general matrices
gemm
multiplies two general rectangular matrices. Basically,
gemm ?beta ?c ~transa ?alpha a ~transb b
executes
c := alpha * a * b + beta * c
where alpha
(= 1 by default) and beta
(= 0
by default) are scalar values, and a
, b
and c
are matrices:
The above code computes
The parameters transa
and transb
indicate whether matrices a
and b
are
transposed, or not, respectively. They have the same effect as argument trans
of gemv
. Differently from gemv
, gemm
takes two transpose flags because it
takes two matrices. As mentioned above, a
is not transposed when normal
(= Slap.Common.normal
) is given to transa
. trans
(= Slap.Common.trans
)
means transposition as follows.
In this case, a four-by-four matrix is returned because
$\bm{A}^\top \bm{A}$ is executed. Similarly, you can specify
whether b
is transposed, or not though transb
:
The above example calculates $\bm{A} \bm{A}^\top$.
Nothing to say, both a
and b
can be transposed at the same time.
symm: multiplication of a symmetric matrix and a general matrix
symm
multiplies a symmetric matrix and a general matrix. Basically,
symm ~side ?up ?beta ?c ?alpha a b
executes c := alpha * a * b + beta * c
where alpha
(= 1 by default) and beta
(= 0 by default) are scalar values,
a
is a symmetrix matrix, and b
and c
are general rectangular matrices.
symm
does not have arguments to indicate transposition (e.g., transa
and
transb
of gemm
) because a symmetric matrix is equal to the transpose of
itself. Instead of them, symm
takes side flags to specify direction of
the multiplication via argument side
: when side
= Slap.Common.left
,
a
is multiplied from the left by b
, i.e., c := alpha * a * b + beta * c
;
conversely, if side
= Slap.Common.right
, a
is right-multiplied by b
,
c := alpha * b * a + beta * c
.
For example, the following code left-multiplies symmetric matrix a
by
general matrix b
.
It computes
You can also right-multiply a
by b'
:
The latter example computes
Optional argument up
of symm
specifies whether the upper or lower part of
a
is used for computation. By default, up
is true
, so the upper part is
used, i.e., accessed by symm
. If up
is false
, the lower part is supplied
for symm
.
Iteration
SLAP supports many iterator functions such as map
and fold_left
on matrices.
They are defined in Slap.D.Mat
.
For example, map
applies a given function to each element of a given matrix:
(Mat.scal
is faster than the above to multiply each element by a scalar
value.)
fold_left
folds column vectors of a given matrix from left to right:
The above example creates a list containing column vectors of a
in reverse.
(SLAP does not distinguish a column vector from a row vector on data structure.)
fold_right
, fold_top
(folding row vectors from top to bottom) and
fold_bottom
(folding row vectors from bottom to top) are also supported.
Conversion into lists or arrays
You can easily convert a matrix into a list or an array by Mat.to_list
or
Mat.to_array
.
However, conversion into a matrix from a list or an array is not as easy as them. We will describe such conversion in a later chapter.
Index-based access
You can access an element in a matrix with indices by Mat.get_dyn
and
Mat.set_dyn
.
SLAP cannot statically verify whether given indices is valid, or not.
get_dyn
and set_dyn
functions are low-level operations in SLAP. You should
use high-level functions like map
or arithmetic operations instead of them
whenever possible because maybe static size checking does not work well. We will
explain the reason in a later chapter.
(In addition, get_dyn
and set_dyn
are not fast.)