Advanced¶
We present here some advanced features of the matrix
class.
Working with complex numbers¶
It is possible to manipulate complex data with the matrix
class. The code below creates a complex-double matrix
using the predefined constant M_1I
which is equal to std::complex<double>(0,1)
and two matrices containing respectively the real and the imaginary part.
matrix<> Re = {1,0,-1,0};
matrix<> Im = {0,1,0,-1};
disp("Imaginary number matrix ('1i') : ");
disp(M_1I);
disp("Complex matrix : ");
auto Ac = Re + M_1I*Im;
disp(Ac);
Imaginary number matrix ('1i') :
(0,1)
Complex matrix :
(1.00000,0.00000) (0.00000,1.00000) (-1.00000,0.00000) (0.00000,-1.00000)
We can compute the conjugate of the elements, the absolute value, or extract the imaginary part.
disp(conj(Ac),2);
disp(abs(Ac),2);
disp(imag(Ac),2);
Matrix 1x4 of type 'St7complexIdE' (64 B):
(1.00000,-0.00000) (0.00000,-1.00000) (-1.00000,-0.00000) (0.00000,1.00000)
Matrix 1x4 of type 'd' (32 B):
1.00000 1.00000 1.00000 1.00000
Matrix 1x4 of type 'd' (32 B):
0 1.00000 0 -1.00000
Logical matrices¶
Because of the special behaviour of std::vector<bool>
, matrix does not use the native logical type bool
of the C++ standard library, but uses instead std::uint8_t
which corresponds to a unsigned short int
, or char
. Consequently, the bool
values are converted to std::uint8_t
where the value false
is converted to the value 0
and true
to the value 1
. A logical matrix
is displayed like:
matrix<int> A = eye(3);
matrix<int> B = ones(3);
disp("A && B :");
disp(A && B);
A && B :
1 0 0
0 1 0
0 0 1
WARNING (very important): a matrix<logical>
remains intrinsically a matrix<std::uint8_t>
meaning that it behaves like one. This behavior is not natural and will be corrected in a future release.
Using some algorithms¶
The matrix
class comes with a lot of built-in algorithms (see Algorithms for a full list). First, we create some random integer data in the range [0,10[
.
auto A = cast<int>(10*rand<>(1,10));
disp(A,2,std::cout,10,10);
Matrix 1x10 of type 'i' (40 B):
8 3 7 7 9 1 3 7 2 5
Remark: In the code above, we first call rand for the default double
type, then we multiply by 10
and finally cast the result to integers. In fact, the rand function generates intrinsically numbers of type double
in the range [0,1[
which are converted afterward in the template type. Unfortunately, calling rand<int>
will cast those numbers to zero. What we did is first generate double
numbers in the range [0,10[
, then cast them to int
.
What are the minimum, average, standard deviation, and the maximum values of A
?
disp(min(A));
disp(mean<double>(A));
disp(stddev<double>(A));
disp(max(A));
1
5.2
2.63818
9
Remark: Do not forget, in that particular case, to give the output type for the result of mean
and stddev
. Otherwise, the result will be cast in the template type which is int
!
The unique elements of A
are
disp(unique(A),2,std::cout,10,10);
Matrix 1x7 of type 'i' (28 B):
1 2 3 5 7 8 9
Now let us sort the elements.
auto A_sorted = sort(A);
disp(A_sorted,2,std::cout,10,10);
Matrix 1x10 of type 'i' (40 B):
1 2 3 3 5 7 7 7 8 9
We create a second smaller vector and we search the common elements.
auto B = cast<int>(10*rand<>(1,4));
disp(B,2);
disp(intersect(A,B),2);
Matrix 1x4 of type 'i' (16 B):
4 6 3 5
Matrix 1x2 of type 'i' (8 B):
3 5
We obtain the expected result.
View¶
The matrix provides operators to extract a submatrix from a matrix instance or to assign values of a submatrix to a matrix.
The operator ()
can take a list of indices to return an instance of class view
.
As the class view
contains a reference to the set of values corresponding to the list of indices, it is necessary to call the method eval
to use the viewed submatrix.
It is possible to give the list of indices in linear indexing A(L) or bilinear indexing A(I,J). The external functions all, col, range and row are useful to describe indices.
matrix<> A = {{0, 1, 2, 4},
{4, 5, 6, 7},
{8, 9,10,11}};
disp("Linear indexing");
disp(" extracting :");
matrix<> B = eval(A({1,3,5}));
disp(B);
disp(" assigning :");
A(range(0,4)) = 0;
disp(A);
disp("Bilinear indexing");
disp(" extracting :");
B = eval(A(1,range(0,3)));;
disp(B);
disp(" assigning :");
A({0,2}, col(A)) = 10;
disp(A);
Linear indexing
extracting :
1.00000 4.00000 5.00000
assigning :
0 0 0 0
4.00000 5.00000 6.00000 7.00000
8.00000 9.00000 10.00000 11.00000
Bilinear indexing
extracting :
4.00000 5.00000 6.00000
assigning :
10.00000 10.00000 10.00000 10.00000
4.00000 5.00000 6.00000 7.00000
10.00000 10.00000 10.00000 10.00000
Internal matrix tools¶
In addition to constructors and operators, the matrix class has few member functions (see internal tools list in class matrix description). The functions can be user-friendy for native C++ coding.
Notes:
The method
size
differs from the external functionsize
for the parameter dim=0. Indeed, in that case, the methodsize
returns the total number of elements in the matrix while the external functionsize
returns the two-element vector containing the number of rows and columns in the matrix.
matrix<> A = {{1,2,3},{4,5,6}};
disp("Method size :");
disp(A.size(0));
disp(A.size(1));
disp(A.size(2));
disp("External function size :");
disp(size(A));
disp(size(A,1));
disp(size(A,2));
Method size :
6
2
3
External function size :
2 3
2
3
The method
resize
is more efficient than the external functionresize
since the methode makes the maniplulation in-place which avoids a copy.