Functions on Linear Algebra Structures
Introduction
Notation of vectors, matrices, tensors
In the Math module, multidimensional structures are not only required for calculations, they are also a possible result type of functions that do not just return one scalar value. Examples of this are string functions that search for certain patterns in a text. All hit positions and lengths are then returned in a matrix.
In principle, vectors, matrices and tensors can be created in the Math module using the [ ... ]
syntax. All numerical data types are possible, but not <str>
. Terms, constants or the content of other variables can be used as elements. The data type of the structure is always the one in which all elements can be represented in the best possible way.
Examples are
num = 3.14159; // example for a variable as source
vec = [1, -2, false, num, 5]; // data type is <dbl> to represent num
mat = [ [ 1.1, num ] // 1st row
, [-num, 2.2 ] // 2nd row
, [ 3.1, 3.2 ] ]; // 3rd row
ten = [ [ [ 111, num, 113 ] // 1st matrix, first row
, [ 121, 122, 123 ] ] // second row
, [ [ 211, 212, 213 ] // 2nd matrix, first row
, [ 221, 222, num ] ] // second row
, [ [ 311, 312, 313 ] // 3rd matrix, first row
, [ 321, num, 323 ] ] // second row
, [ [ num, 412, 413 ] // 4th matrix, first row
, [ 421, 422, 423 ] ] ]; // second row
If the sub-elements (rows of a matrix, matrices of a tensor) each have the same size, the size of the structure is only determined by the number of elements and sub-elements. In the example, vec
has 5 elements (in rows or columns depending on use), mat
has 3 rows and 2 columns and ten
has 4 matrix slices with 2 rows and 3 columns each. Differences in size are reported as errors during translation, there is no automatic padding.
Access to individual elements
An element of a vector, matrix or tensor is also addressed using the [ ... ]
syntax, whereby the indices - as is usual in programming languages - always count from 0. Indices can also originate from variables or calculations.
v_num = vec[3]; // reads the 4th element of the vector
m_num = mat[0, 1]; // reads the 2nd element in the 1st row
t_422 = ten[3, 1, 1]; // reads from the 4th matrix, 2nd row, 2nd column
Trivial operations on multidimensional objects
The following operations are implemented directly in the usual formula notation:
-
The comparison
==
and!=
is possible on multidimensional objects as long as both operands have the same size. -
Addition and subtraction of multidimensional objects is possible as long as both operands have the same size.
M_Sum = M_1 + M_2;
M_Dif = M_1 - M_2; -
Multiplication of a multidimensional object by a numerical scalar. The result is an object of the same dimension in which each individual element is scaled accordingly. The commutative law is applicable.
M_Scaled_0 = M_Base * 2.56;
M_Scaled_1 = 2.56 * M_Base;- Division of a multidimensional object by a numerical scalar. The result is an object of the same dimension in which each individual element is scaled accordingly. Division by a matrix or a vector is not permitted.
M_Scaled_2 = M_Base / 2.56;
-
Multiplication of two multidimensional objects is possible if the number of columns in the first operand matches the number of rows in the second operand. The result is a multidimensional object with the number of rows in the first operand and the number of columns in the second operand. A vector does not differentiate between rows and columns here, so that it is interpreted as a row vector as the first operand and as a column vector as the second operand. This certainly covers 95% of the typical interpretation in technical applications without having to work with a transpose function.
M_mult = M_1 * M_2;
V_row = V_1 * M; // V_1 interpreted as row-vector
V_col = M * V_2; // V_2 interpreted as column-vector
ScalarProduct = V_1 * V_2; // by definition
CrossProduct = Cross(V_1, V_2); // := V_1 x V_2
Assignment of a vector, a matrix or a tensor
A variable may only be described or created at a single point in the formula set. This also applies to vectors, matrices and tensors.
However, it is still possible to indirectly describe individual elements of the structure in this assignment. In this case, the indexed access to an element in the formula text must take place after the actual assignment of the structure so that the compiler can incorporate the assignment of the element into the assignment of the entire structure.
Circular references are not permitted here.
M_spare = Matrix(3, 3); // first creates a 3x3 matrix with 0
M_spare[0,1] = 101; // completes the first assignment for element [0,1]
M_spare[1,2] = 202; // completes the first assignment for element [1,2]
M_spare[2,0] = 303; // adds the first assignment for element [2,0]
Whenever the matrix M_spare
is used, it now has the following content:
This notation improves the readability of the formula text, especially for sparse matrices or vectors.
u_long = Vector(50, 3.14); // create a very long vector
u_long[ 3] = -3.14;
u_long[25] = -3.14;
u_long[44] = u_long[10] + u_long[11]; // not allowed !!!
All data sources are equally valid for updating the vector over time. The value of the entire vector therefore always changes when at least one element changes. There is no "intermediate status" in which the elements have not yet been assigned or have only been partially assigned.
Export parts of a multidimensional object
To extract a specific part from a multidimensional object, the functions GetCol()
, GetRow()
or GetSlice()
can be used.
In this way, a specific row or column can be exported from a matrix or a single matrix can be exported from a tensor with several matrix slices. GetSub()
allows any export of a range that is defined in each dimension by a range of rows/columns/slice indices.
Functions
Vector construction "Vector"
The following functions can be used to construct a vector
u = Vector(size); // Vector of dimension size x 1 initialized with 0
u = Vector(size, v); // Vector of dimension size x 1 initialized with v
The orientation of the vector as a row or column vector is not fixed and is interpreted in the best possible way in the respective application.
Unit vector "Normalize"
The Normalize()
function is used to determine a unit vector for the given vector.
If the magnitude of the vector is zero, either a zero vector or the replacement value is returned so that subsequent calculation steps are not blocked.
ev1 = Normalize(v);
ev2 = Normalize(v, v0);
Matrix construction "Matrix"
The following functions can be used to construct a matrix
A = Matrix(rows, columns); // Matrix of the dimensions rows x columns initialized with 0
B = Matrix(rows, columns, v); // Matrix of the dimensions rows x columns initialized with v
Identity matrix "MIdent"
The following function returns an identity matrix of the dimensions size x size
I = MIdent(size);
Rotation matrix "MRot"
It is possible to define rotation matrices of the following type
R_2 = MRot(alpha); // 2D rotation matrix around the angle alpha counterclockwise
R_3 = MRot(alpha, axis); // 3D rotation matrix around the axis labeled axis: x:0, y:1, z:2
M_3ypr = MRotYPR(y,p,r); // 3D rotation matrix that describes a rotation described by Yaw, Pitch and Roll
// described by yaw, pitch and roll
M_3euler = MRotEuler(a,b,g); // 3D rotation matrix that describes a rotation described by a, b, g
// Euler rotation described by a, b, g
With
-
and
-
is
See also: Rotation matrix - Wikipedia
With
- , (Yaw),
- , (Gear) and
- , (Roll) is
See also: Euler's angle
With
- , (input Z-axis),
- , (node line, rotated X-axis) and
- , (output Z-axis) is
See also: Euler's angle
Tensor construction "Tensor"
To construct a tensor with slices slices of the dimension rows x columns, use
T = Tensor(slices, rows, columns);
Properties of vectors, matrices, tensors
Check for the type of a variable "isScalar", "isVector", "isMatrix", "isTensor"
The following functions each return a true if the variable has the queried structure. This can be useful if a function, e.g. sFind()
, returns both a scalar (-1, not found) or a matrix with results and further processing is dependent on this.
test1 = isScalar(var);
test2 = isVector(var);
test3 = isMatrix(var);
test4 = isTensor(var);
Query the dimensions of an object "SizeOf"
Querying the dimensions of an object returns a vector of dimensions, e.g.
VectorSize = SizeOf(v); // => [ 1, size ]
MatrixSize = SizeOf(M); // => [ 2, columns, rows]
TensorSize = SizeOf(T); // => [ 3, columns, rows, slices ]
The first component provides the number of dimensions and the following components the number of elements in the respective dimension.
Access functions "GetCol", "GetRow", "GetSlice", "GetSub"
These functions are used to cut parts out of a multidimensional object, so that a multidimensional object is usually created again. The index syntax should be used more effectively to access a single element.
The section through a multidimensional object at a designated column index columnIndex can be carried out as follows
v1 = GetCol(D, columnIndex);
v2 = GetCol(D, {...}); // Configuration mandatory!
// Configuration for all variants
vx = GetCol(..., { col: <uint> // mandatory if no columnIndex
, rBeg: <uint>
, rEnd: <uint>
, sBeg: <uint>
, sEnd: <uint>
});
For a vector, the result is a single element, for a matrix a vector and for a tensor a matrix at the designated column index. For higher-order structures, the copied areas can also be restricted via the configuration object.
Property | Value | Description |
---|---|---|
col | <uint> | Column index for the section plane |
rBeg | <uint> | Optional range specification for rows |
rEnd | <uint> | Optional range specification for rows |
sBeg | <uint> | Optional range specification for slices |
sEnd | <uint> | Optional range specification for slices |
The section through a multidimensional object at a designated line index can be carried out as follows
v1 = GetRow(D, rowIndex);
v2 = GetRow(D, {...}); // Configuration mandatory!
// Configuration for all variants
vx = GetRow(..., { cBeg: <uint>
, cEnd: <uint>
, row: <uint> // mandatory if no rowIndex
, sBeg: <uint>
, sEnd: <uint>
});
For a vector, the result is a single element, for a matrix a vector and for a tensor a matrix at the designated row index. For higher-order structures, the copied areas can also be restricted via the configuration object.
Property | Value | Description |
---|---|---|
row | <uint> | Row index for the cutting plane |
cBeg | <uint> | Optional range specification for columns |
cEnd | <uint> | Optional range specification for columns |
sBeg | <uint> | Optional range specification for slices |
sEnd | <uint> | Optional range specification for slices |
The section through a multidimensional object at a designated slice index can be performed as follows
v1 = GetSlice(D, sliceIndex);
v2 = GetSlice(D, {...}); // Configuration mandatory!
// Configuration for all variants
vx = GetSlice(..., { cBeg: <uint>
, cEnd: <uint>
, rBeg: <uint>
, rEnd: <uint>
, slice:<uint> // mandatory if no sliceIndex
});
For a vector, the result is a single element, for a matrix a vector and for a tensor a matrix at the designated slice index. For higher-order structures, the copied areas can also be restricted via the configuration object.
Property | Value | Description |
---|---|---|
slice | <uint> | slice index for the slice plane |
cBeg | <uint> | Optional range specification for columns |
cEnd | <uint> | Optional area specification for columns |
rBeg | <uint> | Optional range specification for rows |
rEnd | <uint> | Optional range specification for rows |
A substructure of data is extracted from a structure of data as follows
D1 = GetSub(D, { cBeg: <uint>
, cEnd: <uint>
, rBeg: <uint>
, rEnd: <uint>
, sBeg: <uint>
, sEnd: <uint>
});
Property | Value | Description |
---|---|---|
cBeg | <uint> | Optional range specification for columns |
cEnd | <uint> | Optional range specification for columns |
rBeg | <uint> | Optional range specification for rows |
rEnd | <uint> | Optional range specification for rows |
sBeg | <uint> | Optional range specification for slices |
sEnd | <uint> | Optional range specification for slices |
Processing functions
Transposition "Trans"
The transposition of an M x N matrix returns an N x M matrix with rows and columns swapped and is calculated as follows
A_t = Trans(A);
Cross product "Cross"
The cross product of two vectors u and v of length 2 or 3 yields a vector perpendicular to this in the length of the area spanned by both vectors and is calculated as follows
w = Cross(u, v);
LU Decomposition "LUDecomp"
The LU decomposition of a matrix M returns a lower triangular matrix L and an upper triangular matrix U in the form of a tensor with two slices and can be performed as follows
T = LUDecomp(M);
L = GetSlice(T, 0);
U = GetSlice(T, 1);
Determinant "Det"
The determinant d of a square matrix M can be calculated as follows
d = Det(M);
Vector length "Length"
Calculation of the length of a vector, also called abs(...)
len = Length(v);