Getting started with Armadillo
Date: 2019-09-22Last modified: 2024-11-02
According to the Armadillo site it is a high quality linear algebra library (matrix maths) for the C++ language, aiming towards a good balance between speed and ease of use.
Installation
Debian
apt install libarmadillo-dev
MacOS
brew install armadillo
Sample code
Random matrix creation
// set the seed to a random value
arma_rng::set_seed_random();
Warning about use of the auto
C++11 keyword
I tried to use auto
for matrix declaration but this lead me
to a tricky error. The variable created by the keyword auto
was a random matrix generator and not a matrix.
I expect to declare R
, S
and A
as random initialized matrix:
auto R = randu(2, 3);
auto S = randu<mat>(2, 3);
auto T = (mat)randu(2, 3);
mat A = randu(2, 3);
cout << "Lets check the types of each variable:\n";
cout << "Type of R: " << typeid(R).name() << '\n';
cout << "Type of S: " << typeid(S).name() << '\n';
cout << "Type of T: " << typeid(T).name() << '\n';
cout << "Type of A: " << typeid(A).name() << '\n';
// Type of R: N4arma3GenINS_3MatIdEENS_9gen_randuEEE
// Type of S: N4arma3GenINS_3MatIdEENS_9gen_randuEEE
// Type of T: N4arma3MatIdEE
// Type of A: N4arma3MatIdEE
Note the types are slightly different.
The A
matrix presents the expected behavior, keeping the elements
unchanged:
cout << "A:\n" << A << '\n';
cout << "A:\n" << A << '\n';
cout << "A:\n" << A << '\n';
// A:
// 0.8512 0.8562 0.5564
// 0.0223 0.1000 0.0846
// A:
// 0.8512 0.8562 0.5564
// 0.0223 0.1000 0.0846
// A:
// 0.8512 0.8562 0.5564
// 0.0223 0.1000 0.0846
However the R
matrix generator return different values on each
cout << "R:\n" << R << '\n';
cout << "R:\n" << R << '\n';
cout << "R:\n" << R << '\n';
// R:
// 0.0718 0.9256 0.4991
// 0.7697 0.9635 0.8418
// R:
// 0.9830 0.7305 0.2061
// 0.2162 0.9320 0.2274
// R:
// 0.7011 0.6158 0.8350
// 0.6841 0.4025 0.0418
Transpose matrix
cout << "A:\n" << A << '\n';
cout << "A.t:\n" << A.t() << '\n';
// A:
// 0.8512 0.8562 0.5564
// 0.0223 0.1000 0.0846
//
// A.t:
// 0.8512 0.0223
// 0.8562 0.1000
// 0.5564 0.0846
Multiplication
cout << A.t() * A << '\n';
// 0.7251 0.7311 0.4755
// 0.7311 0.7431 0.4848
// 0.4755 0.4848 0.3167
Determinant
mat B(3, 3, fill::randu);
cout << "B:\n" << B << '\n';
// B:
// 0.9563 0.8955 0.0919
// 0.3291 0.3086 0.3452
// 0.1894 0.9898 0.8642
cout << "Det: " << det(B) << '\n';
// Det: -0.243228
mat C = randu(3, 3);
cout << "C:\n" << C << '\n';
// C:
// 0.5561 0.6219 0.2147
// 0.3105 0.2813 0.9172
// 0.3408 0.1925 0.4703
cout << "Det: " << det(C) << '\n';
// Det: -0.254525
mat D = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
cout << "D:\n" << D << '\n';
// D:
// 1.0000 2.0000 3.0000
// 4.0000 5.0000 6.0000
// 7.0000 8.0000 9.0000
cout << "Det: " << det(D) << '\n';
// Det: 6.66134e-16
Operation with rows and columns
D.row(0) = D.row(1) + D.row(2);
cout << "D:\n" << D << '\n';
// D:
// 11.0000 13.0000 15.0000
// 4.0000 5.0000 6.0000
// 7.0000 8.0000 9.0000
D.row(1) = D.row(1) * 5;
cout << "D:\n" << D << '\n';
// D:
// 11.0000 13.0000 15.0000
// 20.0000 25.0000 30.0000
// 7.0000 8.0000 9.0000
//
D.row(2).zeros();
cout << "D:\n" << D << '\n';
// D:
// 11.0000 13.0000 15.0000
// 20.0000 25.0000 30.0000
// 0 0 0
D.col(2) = D.col(2) + 10;
cout << "D:\n" << D << '\n';
// D:
// 11.0000 13.0000 25.0000
// 20.0000 25.0000 40.0000
// 0 0 10.0000
D = diagmat(D);
cout << "D:\n" << D << '\n';
// D:
// 11.0000 0 0
// 0 25.0000 0
// 0 0 10.0000
Save and load
D.save("D.bin");
D.save("D.txt", arma_ascii);
// ARMA_MAT_TXT_FN008
// 3 3
// 1.10000000000000e+01 0.00000000000000e+00 0.00000000000000e+00
// 0.00000000000000e+00 2.50000000000000e+01 0.00000000000000e+00
// 0.00000000000000e+00 0.00000000000000e+00 1.00000000000000e+01
mat O = ones(2, 2);
cout << "O:\n" << O << '\n';
// O:
// 1.0000 1.0000
// 1.0000 1.0000
auto Z = zeros(3, 5);
cout << "Z:\n" << Z << '\n';
// Z:
// 0 0 0 0 0
// 0 0 0 0 0
// 0 0 0 0 0
mat F1, F2;
F1.load("D.bin");
F2.load("D.txt");
cout << "F1:\n" << F1 << '\n';
// F1:
// 11.0000 0 0
// 0 25.0000 0
// 0 0 10.000
cout << "F1 - F1:\n" << F1 - F2 << '\n';
// F1 - F2:
// 0 0 0
// 0 0 0
// 0 0 0
mat F(2, 3);
F.fill(3.14);
cout << "F:\n" << F << '\n';
// F:
// 3.1400 3.1400 3.1400
// 3.1400 3.1400 3.1400
F = F.ones();
F.col(0) *= datum::pi;
F.col(1) *= datum::inf;
F.col(2) *= datum::nan;
cout << "F:\n" << F << '\n';
// F:
// 3.1416 inf nan
// 3.1416 inf nan
}
Possible output
Lets check the types of each variable:
Type of R: N4arma3GenINS_3MatIdEENS_9gen_randuEEE
Type of S: N4arma3GenINS_3MatIdEENS_9gen_randuEEE
Type of T: N4arma3MatIdEE
Type of A: N4arma3MatIdEE
A:
0.6310 0.2291 0.0765
0.3009 0.9423 0.9828
A:
0.6310 0.2291 0.0765
0.3009 0.9423 0.9828
A:
0.6310 0.2291 0.0765
0.3009 0.9423 0.9828
R:
0.6182 0.5614 0.2032
0.9431 0.7587 0.0228
R:
0.8644 0.8380 0.4838
0.2866 0.1582 0.4918
R:
0.8139 0.0478 0.9550
0.9049 0.5196 0.8300
A:
0.6310 0.2291 0.0765
0.3009 0.9423 0.9828
A.t:
0.6310 0.3009
0.2291 0.9423
0.0765 0.9828
0.4888 0.4282 0.3441
0.4282 0.9405 0.9437
0.3441 0.9437 0.9718
B:
0.6141 0.9689 0.2669
0.2267 0.0525 0.4769
0.3370 0.9721 0.3793
Det: -0.145965
C:
0.2886 0.2254 0.5511
0.1077 0.4531 0.2351
0.9293 0.1972 0.1447
Det: -0.169076
D:
1.0000 2.0000 3.0000
4.0000 5.0000 6.0000
7.0000 8.0000 9.0000
Det: 6.66134e-16
D:
11.0000 13.0000 15.0000
4.0000 5.0000 6.0000
7.0000 8.0000 9.0000
D:
11.0000 13.0000 15.0000
20.0000 25.0000 30.0000
7.0000 8.0000 9.0000
D:
11.0000 13.0000 15.0000
20.0000 25.0000 30.0000
0 0 0
D:
11.0000 13.0000 25.0000
20.0000 25.0000 40.0000
0 0 10.0000
D:
11.0000 0 0
0 25.0000 0
0 0 10.0000
O:
1.0000 1.0000
1.0000 1.0000
Z:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
F1:
11.0000 0 0
0 25.0000 0
0 0 10.0000
F1 - F1:
0 0 0
0 0 0
0 0 0
F:
3.1400 3.1400 3.1400
3.1400 3.1400 3.1400
F:
3.1416 inf nan
3.1416 inf nan
References
Complete source
https://gist.github.com/geraldolsribeiro/7765d983b678daf72f5dc0d2d611b4ca