The matrix library

Pacioli's built-in matrix operations.

Synopsis

_ :: One

abs :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v
abs_min :: for_unit a, b, P!u, Q!v, P!x, Q!y: for_index P, Q: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!u per Q!v
acos :: for_index P, Q: (P! per Q!) -> radian*P! per Q!
asin :: for_index P, Q: (P! per Q!) -> radian*P! per Q!
atan :: for_index P, Q: (P! per Q!) -> radian*P! per Q!
atan2 :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> radian*P! per Q!
bottom :: for_unit a, P!u, Q!v: for_index P, Q: (1, a*P!u per Q!v) -> a*P!u per Q!v
cbrt :: for_unit a, P!u, Q!v: for_index P, Q: (a^3*P!u^3 per Q!v^3) -> a*P!u per Q!v
ceiling :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v
cholesky_decomposition :: for_unit a, P!u: for_index P: (a^2/P!u per P!u) -> a/P!u per P!
closure :: for_unit P!u: for_index P: (P!u per P!u) -> P!u per P!u
column :: for_unit a, P!v: for_index P, Q: (a*P!v per Q!, Q) -> a*P!v
column_domain :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> List(Q)
column_unit :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v
columns :: for_unit a, P!u: for_index P, Q: (a*P!u per Q!) -> List(a*P!u)
compare_index :: for_index P: (P, P) -> 1
complement :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v
cos :: for_index P, Q: (radian*P! per Q!) -> P! per Q!
delta :: for_index P: (P) -> P!
diagonal :: for_unit a, P!u: for_index P: (a*P!u) -> a*P!u per P!u
diagonal2 :: for_unit a, P!u: for_index P: (a*P!u) -> a*P!u per P!
diagonal3 :: for_unit a, P!u: for_index P: (a*P!u) -> P! per P!
dim_div :: for_unit a, D!b, E!c, f, H!g: for_index D, E, H: (a*D!b per E!c, f*H!g per E!c) -> a*D!b per f*H!g
dim_inv :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v per a*P!u
div :: for_unit a, b, P!u, Q!v, P!x, Q!y: for_index P, Q: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!u/P!x per b*Q!v/Q!y
divide :: for_unit a, b, P!u, Q!v, P!x, Q!y: for_index P, Q: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!u/P!x per b*Q!v/Q!y
eigenvalue_decomposition :: for_unit a, P!u: for_index P: (a*P!u per P!u) -> Tuple(a*P!u per P!u, a*P!u per P!u)
eigenvalue_list :: for_unit a, P!u: for_index P: (a*P!u per P!u) -> List(Tuple(a, a, P!u))
exp :: for_index P, Q: (P! per Q!) -> P! per Q!
expt :: for_index P, Q: (P! per Q!, 1) -> P! per Q!
floor :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v
gcd :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> P! per Q!
get :: for_unit a: for_index P, Q: (a*P! per Q!, P, Q) -> a
get_num :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, P, Q) -> 1
greater :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> Boole
greater_eq :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> Boole
index_less :: for_index P: (P, P) -> Boole
inner :: for_unit a, b, P!u: for_index P: (a*P!u, b/P!u) -> a*b
inverse :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v per a*P!u
is_zero :: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> Boole
is_zero_column :: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c, E) -> Boole
is_zero_row :: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c, D) -> Boole
kleene :: for_unit P!u: for_index P: (P!u per P!u) -> P!u per P!u
left_divide :: for_unit a, b, P!u, Q!v, P!x, Q!y: for_index P, Q: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!x/P!u per b*Q!y/Q!v
left_division :: for_unit a, b, P!u, Q!v, R!w: for_index P, Q, R: (a*P!u per Q!v, b*P!u per R!w) -> b*Q!v per a*R!w
left_identity :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> P!u per P!u
left_inverse :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v per a*P!u
less :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> Boole
less_eq :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> Boole
ln :: for_index P, Q: (P! per Q!) -> P! per Q!
log :: for_index P, Q: (P! per Q!, 1) -> P! per Q!
lscale_down :: for_unit a, b, P!u, Q!v: for_index P, Q: (a, b*P!u per Q!v) -> a*P!u per b*Q!v
magnitude :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> P! per Q!
make_matrix :: for_unit a: for_index P, Q: (List(Tuple(P, Q, a))) -> a*P! per Q!
map_matrix :: for_unit a, b: for_index P, Q: ((a) -> b, a*P! per Q!) -> b*P! per Q!
mapnz :: for_unit a, P!u, Q!v: for_index P, Q: ((1) -> 1, a*P!u per Q!v) -> a*P!u per Q!v
max :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> a*P!u per Q!v
mexpt :: for_unit P!u: for_index P: (P!u per P!u, 1) -> P!u per P!u
min :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> a*P!u per Q!v
minus :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> a*P!u per Q!v
mmult :: for_unit a, b, P!u, Q!v, R!w: for_index P, Q, R: (a*P!u per Q!v, b*Q!v per R!w) -> a*b*P!u per R!w
mod :: for_unit a, b, P!u, Q!v, P!x, Q!y: for_index P, Q: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!u per Q!v
multiply :: for_unit a, b, P!u, P!w, Q!v, Q!z: for_index P, Q: (a*P!u per Q!v, b*P!w per Q!z) -> a*b*P!u*P!w per Q!v*Q!z
neg :: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> a*D!b per E!c
negative :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v
negative_support :: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> D! per E!
negatives :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v
norm :: for_unit a: for_index P: (a*P!) -> a
normalized :: for_unit a: for_index P: (a*P!) -> a*P!
outer :: for_unit a, b, P!u, Q!v: for_index P, Q: (a*P!u, b*Q!v) -> a*b*P!u per Q!v^-1
plu_decomposition :: for_unit a, P!u: for_index P: (a*P!u per P!u) -> Tuple(P!u per P!u, P!u per P!u, a*P!u per P!u)
positive_support :: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> D! per E!
positives :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v
precision :: () -> decimals
qr_decomposition :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Tuple(P!u per P!u, a*P!u per Q!v)
random :: () -> 1
ranking :: for_unit a: for_index P, Q: (a*P! per Q!) -> P! per Q!
reciprocal :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a^-1*P!u^-1 per Q!v^-1
rem :: for_index P, Q: for_unit a, b, P!u, Q!v, P!x, Q!y: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!u per Q!v
right_division :: for_unit a, b, P!u, Q!v, R!w: for_index P, Q, R: (a*P!u per Q!v, b*R!w per Q!v) -> a*P!u per b*R!w
right_identity :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v per Q!v
right_inverse :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v per a*P!u
round :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v
row :: for_unit a, Q!v: for_index P, Q: (a*P! per Q!v, P) -> a per Q!v
row_domain :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> List(P)
row_unit :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> P!u
rows :: for_unit a, Q!v: for_index P, Q: (a*P! per Q!v) -> List(a per Q!v)
rscale :: for_unit a, b, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, b) -> a*b*P!u per Q!v
scalar_unit :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a
scale :: for_unit a, b, P!u, Q!v: for_index P, Q: (a, b*P!u per Q!v) -> a*b*P!u per Q!v
scale_down :: for_unit a, b, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, b) -> a*P!u per b*Q!v
set_precision :: (decimals) -> Void
signum :: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> D! per E!
sin :: for_index P, Q: (radian*P! per Q!) -> P! per Q!
singular_value_list :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> List(Tuple(a, P!u, Q!v^-1))
solve :: for_unit a, b, P!u, Q!v, R!w: for_index P, Q, R: (a*P!u per Q!v, b*P!u per R!w) -> a^-1*b*Q!v per R!w
sqrt :: for_unit a, P!u, Q!v: for_index P, Q: (a^2*P!u^2 per Q!v^2) -> a*P!u per Q!v
sum :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> a*P!u per Q!v
support :: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> D! per E!
tan :: for_index P, Q: (radian*P! per Q!) -> P! per Q!
top :: for_unit a, P!u, Q!v: for_index P, Q: (1, a*P!u per Q!v) -> a*P!u per Q!v
total :: for_unit a: for_index P, Q: (a*P! per Q!) -> a
transpose :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*Q!v^-1 per P!u^-1
truncate :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v
unit :: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v

Values

_

:: One

The single entry for the One index set. Shorthand for One@_

Use this as index for a column vector (n by 1 matrix) or a row vector (1 by n matrix).

For example get(x, 2, _) gets the 2 entry from a column vector.

If x is a scalar then get(x, _, _) equals x.

Functions

abs

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v

Absolute value of a matrix. Each entry is negated if it is negative.

get(abs(A), p, q) = abs(get(A, p, q))

Primitive function

abs_min

:: for_unit a, b, P!u, Q!v, P!x, Q!y: for_index P, Q: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!u per Q!v

Element-wise absolute minimum.

The difference with the mod and rem functions is that the value is always between -B/2 and B/2.

Could be defined as

abs_min(A, B) = A - B*round(A/B)

Primitive function

acos

:: for_index P, Q: (P! per Q!) -> radian*P! per Q!

Element-wise arccos. The inverse of the cosine function.

asin

:: for_index P, Q: (P! per Q!) -> radian*P! per Q!

Element-wise arcsin. The inverse of the sine function.

atan

:: for_index P, Q: (P! per Q!) -> radian*P! per Q!

Element-wise arctan. The inverse of the tangent function.

atan2

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> radian*P! per Q!

Element-wise arctan2. The complete inverse of the tangent function.

bottom

:: for_unit a, P!u, Q!v: for_index P, Q: (1, a*P!u per Q!v) -> a*P!u per Q!v

Matrix with only the x least elements. Every entry not in the bottom x is changed to zero.

Primitive function

cbrt

:: for_unit a, P!u, Q!v: for_index P, Q: (a^3*P!u^3 per Q!v^3) -> a*P!u per Q!v

Element-wise cube root.

get_num(cbrt(A), p, q) = cbrt(get_num(A, p, q))

or using the element-wise product *

cbrt(A) * cbrt(A) * cbrt(A) = cbrt(A)^3 = A

Primitive function

ceiling

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v

Element-wise ceiling.

Primitive function

cholesky_decomposition

:: for_unit a, P!u: for_index P: (a^2/P!u per P!u) -> a/P!u per P!

The Cholesky decomposition of a matrix.

Decomposes a matrix into product L '*' L^T, with L a lower triangular matrix.

It is an error if the matrix is not symmetric or is not positive definite.

Primitive function

closure

:: for_unit P!u: for_index P: (P!u per P!u) -> P!u per P!u

Kleene closure for matrices.

Equals the series

A + A'^'2 + A'^'3 ...

column

:: for_unit a, P!v: for_index P, Q: (a*P!v per Q!, Q) -> a*P!v

Extracts a single column from a matrix.

The matrix must be dimensionally uniform in the column dimension.

For all indices p it satisfies

get_num(column(A, x), p, _) = get_num(A, p, x)

Primitive function

column_domain

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> List(Q)

The matrix column domain. The index set elements for the column dimension.

Primitive function

column_unit

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v

The matrix's units in column dimension. The co-variant part of the matrix units.

Is part of the unit of a matrix. For any matrix A:

unit(A) = scalar_unit(A) '.*' row_unit(A) per column_unit(A)

Primitive function

columns

:: for_unit a, P!u: for_index P, Q: (a*P!u per Q!) -> List(a*P!u)

The columns of a matrix.

compare_index

:: for_index P: (P, P) -> 1

Comparison of indices. Negative if x comes before y, positive if y comes before x, zero if x and y are equal.

Is the order of the indices in the index set definition. See index_less

complement

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v

Logical complement.

Is defined as:

complement(A) = unit(A) - A

For example, with definitions

defindex Nibble = {bit0, bit1, bit2, bit3};

defmatrix nibble :: Nibble! = {
    bit0 -> 1,
    bit3 -> 1
};

expression complement(nibble) gives

Nibble        Value
-------------------
bit1              1
bit2              1

cos

:: for_index P, Q: (radian*P! per Q!) -> P! per Q!

Element-wise cosine function.

get(cos(A), p, q) = cos(get(A, p, q))

Primitive function

delta

:: for_index P: (P) -> P!

Kronecker delta.

For example delta(Geom3@x) gives a base vector in the x direction in 3D space.

get(delta(p), x, _) = if p = x then 1 else 0 end

diagonal

:: for_unit a, P!u: for_index P: (a*P!u) -> a*P!u per P!u

diagonal2

:: for_unit a, P!u: for_index P: (a*P!u) -> a*P!u per P!

diagonal3

:: for_unit a, P!u: for_index P: (a*P!u) -> P! per P!

dim_div

:: for_unit a, D!b, E!c, f, H!g: for_index D, E, H: (a*D!b per E!c, f*H!g per E!c) -> a*D!b per f*H!g

Dimensional division. Equals multiplying with the dimensional inverse.

Corresponds with symbol per: A per B is parsed as dim_div(A, B).

dim_div(A, B) = A '*' B^D

Primitive function

dim_inv

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v per a*P!u

The dimensional inverse of a matrix.

Corresponds to the postfix ^D operator: dim_inv(A) = A^D.

Combines the transpose and the reciprocal: A^D = A^R^T = A^T^R

Primitive function

div

:: for_unit a, b, P!u, Q!v, P!x, Q!y: for_index P, Q: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!u/P!x per b*Q!v/Q!y

Element-wise integer division of two matrices.

For any a and b the following holds:

a = div(a, b) * b + rem(a, b)

Primitive function

divide

:: for_unit a, b, P!u, Q!v, P!x, Q!y: for_index P, Q: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!u/P!x per b*Q!v/Q!y

Element-wise division of two matrices.

Corresponds with operator /. Expression A / B is parsed as divide(A, B).

For all indices p and q it satisfies

get(A / B, p, q) = get_num(A, p, q) / get_num(B, p, q)

Primitive function

eigenvalue_decomposition

:: for_unit a, P!u: for_index P: (a*P!u per P!u) -> Tuple(a*P!u per P!u, a*P!u per P!u)

The eigenvalue decomposition of a matrix.

A pair of matrices (D, V) such that A = V '*' D '*' V'^'-1.

The input matrix A, and the output matrices D and V are n x n matrices.

Matrix D is a diagonal matrix. The diagonal elements are the eigenvalues. The colunms of V are the corresponding eigenvectors.

Primitive function

eigenvalue_list

:: for_unit a, P!u: for_index P: (a*P!u per P!u) -> List(Tuple(a, a, P!u))

List form of the eigenvalue decomposition of a matrix.

List of pairs (c, v) such that A '*' v = c '.*' v.

The scalars c are the eigenvalues. The vectors v are the corresponding eigenvectors.

Primitive function

exp

:: for_index P, Q: (P! per Q!) -> P! per Q!

Element-wise natural exponent e^x. Only defined for dimensionless matrices.

get(exp(A), p, q) = exp(get(A, p, q))

Primitive function

expt

:: for_index P, Q: (P! per Q!, 1) -> P! per Q!

Element-wise exponent of the matrix entries.

For all indices p and q it satisfies

get(expt(A, x), p, q) = expt(get(A, p, q), x)

Primitive function

floor

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v

Element wise floor.

Primitive function

gcd

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> P! per Q!

Element-wise greatest common divisor of two matrices.

Primitive function

get

:: for_unit a: for_index P, Q: (a*P! per Q!, P, Q) -> a

Gets a single entry from a matrix.

The matrix must be dimensionally uniform.

Primitive function

get_num

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, P, Q) -> 1

Gets the magnitude of a single entry from a matrix. Using it breaks unit safety so use with care!

Primitive function

greater

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> Boole

Is every entry in matrix A greater than the corresponding entry in matrix B?

Primitive function

greater_eq

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> Boole

Is every entry in matrix A greater than or equal to the corresponding entry in matrix B?

Primitive function

index_less

:: for_index P: (P, P) -> Boole

Order on indices.

Is the order of the indices in the index set definition.

Primitive function

inner

:: for_unit a, b, P!u: for_index P: (a*P!u, b/P!u) -> a*b

The inner product between two vectors. The usual product x^T '*' y between two vectors.

inverse

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v per a*P!u

The inverse of a matrix. Solution to XA=AX=I

is_zero

:: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> Boole

Is every entry in the matrix zero?

Primitive function

is_zero_column

:: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c, E) -> Boole

Is every entry in the column zero?

is_zero_row

:: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c, D) -> Boole

Is every entry in the row zero?

kleene

:: for_unit P!u: for_index P: (P!u per P!u) -> P!u per P!u

Kleene star for matrices.

Equals the series

I + A + A'^'2 + A'^'3 ...

left_divide

:: for_unit a, b, P!u, Q!v, P!x, Q!y: for_index P, Q: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!x/P!u per b*Q!y/Q!v

Element-wise left division of two matrices.

Corresponds with operator \. Expression A \ B is parsed as left_divide(A, B).

Satisfies

left_divide(A, B) = divide(B, A)

Primitive function

left_division

:: for_unit a, b, P!u, Q!v, R!w: for_index P, Q, R: (a*P!u per Q!v, b*P!u per R!w) -> b*Q!v per a*R!w

Left division of matrices. Matrix division means multiplying with the inverse.

Corresponds with operator '\'. Expression A '\' B is parsed as left_division(A, B).

Defined as:

left_division(x,y) = inverse(x) '*' y

left_identity

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> P!u per P!u

The left identify of a matrix. Solution to X '*' A = A

Primitive function

left_inverse

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v per a*P!u

The left_inverse of a matrix. Solution to XA=I

In code:

left_inverse(A) '*' A = right_identity(A)

less

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> Boole

Is every entry in matrix A less than the corresponding entry in matrix B?

Primitive function

less_eq

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> Boole

Is every entry in matrix A less than or equal to the corresponding entry in matrix B?

Primitive function

ln

:: for_index P, Q: (P! per Q!) -> P! per Q!

Element-wise natural logarithm

get(ln(A), p, q) = ln(get(A, p, q))

Primitive function

log

:: for_index P, Q: (P! per Q!, 1) -> P! per Q!

Element-wise log.

get_num(log(A), p, q) = log(get_num(A, p, q))

Inverse of the exponent exp function. For scalars the following holds:

expt(b, log(x, b)) = x

Primitive function

lscale_down

:: for_unit a, b, P!u, Q!v: for_index P, Q: (a, b*P!u per Q!v) -> a*P!u per b*Q!v

Divides a scalar factor by a matrix.

Corresponds with operator './'. Expression x '/.' A is parsed as lscale_down(x, A).

get_num(lscale_down(x, A), p, q) = x / get_num(A, p, q)

Primitive function

magnitude

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> P! per Q!

The magnitude of a matrix. The magnitude of a dimensioned number is the scaling factor without the unit of measurement.

A dimensioned matrix A is an element-wise product RU with R a dimensionless magnitude matrix and U a unit matrix.

Using function unit this can be expressed as:

A = magnitude(A) * unit(A)

Primitive function

make_matrix

:: for_unit a: for_index P, Q: (List(Tuple(P, Q, a))) -> a*P! per Q!

Constructs a dimensionally uniform matrix from a list of entries. Each entry is a tuple with the entry's indices and the value.

For example

defindex Direction = {longitude, lattitude};

define foo =
    make_matrix([
        tuple(Direction@longitude, _, 10*|degree|), 
        tuple(Direction@lattitude, _, 20*|degree|)]);

creates a vector of type degree*Direction!

Primitive function

map_matrix

:: for_unit a, b: for_index P, Q: ((a) -> b, a*P! per Q!) -> b*P! per Q!

Applies a function to every matrix entry.

The matrix must be dimensionally uniform.

For example

map_matrix((x) -> x + 10*|metre|, A)

adds 10 metre to each matrix entry of A.

mapnz

:: for_unit a, P!u, Q!v: for_index P, Q: ((1) -> 1, a*P!u per Q!v) -> a*P!u per Q!v

Maps only the non-zero matrix elements. Experiment for more efficient handling of sparse matrices.

Primitive function

max

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> a*P!u per Q!v

Element-wise maximum of two matrices.

Primitive function

mexpt

:: for_unit P!u: for_index P: (P!u per P!u, 1) -> P!u per P!u

Exponent of a matrix.

For any matrices A and B it satisfies

get(expt(A, x), p, q) = expt(get(A, p, q), x)

Primitive function

min

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> a*P!u per Q!v

Element-wise minimum of two matrices.

Primitive function

minus

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> a*P!u per Q!v

Difference of two matrices.

Corresponds with operator -. Expression A - B is parsed as minus(A, B).

For all indices p and q it satisfies

get_num(A - B, p, q) = get_num(A, p, q) - get_num(B, p, q)

Primitive function

mmult

:: for_unit a, b, P!u, Q!v, R!w: for_index P, Q, R: (a*P!u per Q!v, b*Q!v per R!w) -> a*b*P!u per R!w

Matrix multiplication.

Corresponds with operator '*'. Expression A '*' B is parsed as mmult(A, B).

Primitive function

mod

:: for_unit a, b, P!u, Q!v, P!x, Q!y: for_index P, Q: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!u per Q!v

Element-wise mod of two matrices.

Could be defined as

mod(A, B) = A - abs(B)*floor(A/abs(B))

Primitive function

multiply

:: for_unit a, b, P!u, P!w, Q!v, Q!z: for_index P, Q: (a*P!u per Q!v, b*P!w per Q!z) -> a*b*P!u*P!w per Q!v*Q!z

Element-wise product of two matrices.

Corresponds with operator *. Expression A * B is parsed as multiply(A, B).

For all indices p and q it satisfies

get(A * B, p, q) = get_num(A, p, q) * get_num(B, p, q)

Primitive function

neg

:: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> a*D!b per E!c

negative

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v

The negation of a matrix.

Corresponds with prefix operator '-'. Expression -A is parsed as negative(A).

get_num(negative(A), p, q) = -get_num(A, p, q)

Primitive function

negative_support

:: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> D! per E!

A matrix's support is a mask for the non-zero entries. It contains a 1 where the original is negative and a 0 where the original is zero.

Satisfies:

get(support(A), p, q) = if get_num(A, p, q) < 0 then 1 else 0 end

Primitive function

negatives

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v

Matrix with only the negative entries. The positive entries become zero.

A matrix A can be factored in a positive and negative part as follows:

A = positives(A) + negatives(A)

norm

:: for_unit a: for_index P: (a*P!) -> a

The norm of a vector. The square root of the inner product sqrt(x^T '*' x)

The vector must be dimensionally uniform.

normalized

:: for_unit a: for_index P: (a*P!) -> a*P!

Vector in the same direction with norm 1. Scales the vector by dividing by the vector's norm.

outer

:: for_unit a, b, P!u, Q!v: for_index P, Q: (a*P!u, b*Q!v) -> a*b*P!u per Q!v^-1

The outer product between two vectors. The usual product x '*' y^T between a column and row vector.

plu_decomposition

:: for_unit a, P!u: for_index P: (a*P!u per P!u) -> Tuple(P!u per P!u, P!u per P!u, a*P!u per P!u)

The PLU decomposition of a matrix.

Decomposes the matrix in product A=PLU with P a permutation matrix, L a lower triangular matrix, and U an upper triangular matrix.

Primitive function

positive_support

:: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> D! per E!

A matrix's support is a bit matrix that indicates the positive entries of another matrix. It contains a 1 where the matrix is positive and a 0 where the matrix is zero.

Satisfies:

get(support(A), p, q) = if get_num(A, p, q) > 0 then 1 else 0 end

Primitive function

positives

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v

Matrix with only the positive entries. The negative entries become zero.

A matrix A can be factored in a positive and negative part as follows:

A = positives(A) + negatives(A)

precision

:: () -> decimals

The number of decimals that is used as treshold in approximations.

It is also used as a treshold to determine if a matrix entry is printed.

See set_precision

qr_decomposition

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Tuple(P!u per P!u, a*P!u per Q!v)

The QR decomposition of a matrix.

Decomposes the matrix in product A=QR with Q an orthonormal matrix and R an upper triangular matrix.

Primitive function

random

:: () -> 1

A random number at least zero and below one.

Primitive function

ranking

:: for_unit a: for_index P, Q: (a*P! per Q!) -> P! per Q!

Replaces each entry with its position when ordered.

Primitive function

reciprocal

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a^-1*P!u^-1 per Q!v^-1

The element-wise reciprocal of a matrix.

Corresponds with postfix operator ^R. Expression A^R is parsed as reciprocal(A).

get_num(reciprocal(A), p, q) = 1/get_num(A, p, q)

Primitive function

rem

:: for_index P, Q: for_unit a, b, P!u, Q!v, P!x, Q!y: (a*P!u per Q!v, b*P!x per Q!y) -> a*P!u per Q!v

Element-wise integer division remainder of two matrices.

Could be defined as

rem(A, B) = A - B*truncate(A/B)

For any a and b the following holds:

a = div(a, b) * b + rem(a, b)

Primitive function

right_division

:: for_unit a, b, P!u, Q!v, R!w: for_index P, Q, R: (a*P!u per Q!v, b*R!w per Q!v) -> a*P!u per b*R!w

Division of matrices. Matrix division means multiplying with the inverse.

Corresponds with operator '/'. Expression A '/' B is parsed as right_division(A, B).

Defined as:

right_division(x,y) = x '*' inverse(y)

right_identity

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v per Q!v

The right identify of a matrix. Solution to A '*' X = A

Primitive function

right_inverse

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> Q!v per a*P!u

The right-inverse of a matrix. Solution to AX=I

In code:

A '*' right_inverse(A) = left_identity(A)

round

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v

Rounds every matrix entry to the nearest integer. Halves are rounded up.

Could be defined as

round(A) = floor(A + 0.5 '.*' unit(A))

Primitive function

row

:: for_unit a, Q!v: for_index P, Q: (a*P! per Q!v, P) -> a per Q!v

Extracts a single row from a matrix.

The matrix must be dimensionally uniform in the row dimension.

For all indices q it satisfies

get_num(row(A, x), _, q) = get_num(A, x, q)

Primitive function

row_domain

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> List(P)

The matrix row domain. The index set elements for the row dimension.

Primitive function

row_unit

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> P!u

The matrix's units in row dimension. The contra-variant part of the matrix units.

Is part of the unit of a matrix. For any matrix A:

unit(A) = scalar_unit(A) '.*' row_unit(A) per column_unit(A)

Primitive function

rows

:: for_unit a, Q!v: for_index P, Q: (a*P! per Q!v) -> List(a per Q!v)

The rows of a matrix.

rscale

:: for_unit a, b, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, b) -> a*b*P!u per Q!v

Multiplies a matrix by a scalar factor.

Corresponds with operator '*.'. Expression A '*.' x is parsed as rscale(A, x).

get_num(rscale(A, x), p, q) = get_num(A, p, q) * x

Primitive function

scalar_unit

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a

The scalar unit factor of a matrix.

Is part of the unit of a matrix. For any matrix A:

unit(A) = scalar_unit(A) '.*' row_unit(A) per column_unit(A)

Primitive function

scale

:: for_unit a, b, P!u, Q!v: for_index P, Q: (a, b*P!u per Q!v) -> a*b*P!u per Q!v

Multiplies a matrix with a scalar factor.

Corresponds with operator '.*'. Expression x '.*' A is parsed as scale(x, A).

get_num(scale(x, A), p, q) = x * get_num(A, p, q)

Primitive function

scale_down

:: for_unit a, b, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, b) -> a*P!u per b*Q!v

Divides a matrix by a scalar factor.

Corresponds with operator '/.'. Expression A '/.' x is parsed as scale_down(A, x).

get_num(scale_down(A, x), p, q) = get_num(A, p, q) / x

Primitive function

set_precision

:: (decimals) -> Void

Sets the number of decimals that is used in approximations.

It is also used as a treshold to determine if a matrix entry is printed.

This is a global effect.

See function precision

signum

:: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> D! per E!

A matrix with the sign of the matrix entries. An entry is 1 if the original value is positive, -1 if the value is negative, and 0 when the value is zero.

Satisfies:

signum(A) = positive_support(A) - negative_support(A)

Primitive function

sin

:: for_index P, Q: (radian*P! per Q!) -> P! per Q!

Element-wise sine function.

get(sin(A), p, q) = sin(get(A, p, q))

Primitive function

singular_value_list

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> List(Tuple(a, P!u, Q!v^-1))

List form of the singular value decomposition of a matrix.

List of tuples (s,v,w) such that

A = sum[s '.*' v '*' w^T | (s,v,w) <- svd(A)]

with scalar s the singular values, and vectors v and w the singular vectors.

Note: for dimensionally non-uniform matrices the inner product is not defined. Therefore the orthogonality of the singular vectors assumes the identity metric instead of the inner product (which is equivalent to ignoring the units). See function gsvd from the metrics library for a more general version that accepts other metrics.

Primitive function

solve

:: for_unit a, b, P!u, Q!v, R!w: for_index P, Q, R: (a*P!u per Q!v, b*P!u per R!w) -> a^-1*b*Q!v per R!w

Solves AX=B. Generalization of vector case Ax=b.

Primitive function

sqrt

:: for_unit a, P!u, Q!v: for_index P, Q: (a^2*P!u^2 per Q!v^2) -> a*P!u per Q!v

Element-wise square root.

get_num(sqrt(A), p, q) = sqrt(get_num(A, p, q))

or using the element-wise product *

sqrt(A) * sqrt(A) = sqrt(A)^2 = A

Primitive function

sum

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v, a*P!u per Q!v) -> a*P!u per Q!v

Sum of two matrices.

Corresponds with operator +. Expression A + B is parsed as sum(A, B).

For all indices p and q it satisfies

get_num(A + B, p, q) = get_num(A, p, q) + get_num(B, p, q)

Primitive function

support

:: for_unit a, D!b, E!c: for_index D, E: (a*D!b per E!c) -> D! per E!

A matrix's support is a mask for the non-zero entries. It contains a 1 where the original is non-zero and a 0 where the original is zero.

Satisfies:

get(support(A), p, q) = if get_num(A, p, q) = 0 then 0 else 1 end

Primitive function

tan

:: for_index P, Q: (radian*P! per Q!) -> P! per Q!

Element-wise tangent function.

get(tan(A), p, q) = tan(get(A, p, q))

Primitive function

top

:: for_unit a, P!u, Q!v: for_index P, Q: (1, a*P!u per Q!v) -> a*P!u per Q!v

Matrix with only the x greates elements. Every entry not in the top x is changed to zero.

Primitive function

total

:: for_unit a: for_index P, Q: (a*P! per Q!) -> a

The sum of all matrix entries.

The matrix must be dimensionally uniform.

Primitive function

transpose

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*Q!v^-1 per P!u^-1

The transpose of a matrix. Swaps the row and column dimensions.

Corresponds with postfix operator ^T: A^T

Is parsed as transpose(A).

Primitive function

truncate

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v

Gives the integral part of every matrix entry. Rounds towards zero.

Could be defined as

ceiling(negatives(A)) + floor(positives(A))

Primitive function

unit

:: for_unit a, P!u, Q!v: for_index P, Q: (a*P!u per Q!v) -> a*P!u per Q!v

The unit of a matrix.

Is defined as:

unit(A) = scalar_unit(A) '.*' row_unit(A) per column_unit(A)

Any matrix A is the product of a magnitude and a unit:

A = magnitude(A) * unit(A)

Version v0.6.0, 2026-03-05T15:49:19.223374150+01:00[Europe/Amsterdam]