Back to TILs

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