Back to TILs

Getting started with Armadillo

Date: 2019-09-22Last modified: 2024-02-26

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: N4arma3MatIdEE
Type of S: N4arma3MatIdEE
Type of T: N4arma3MatIdEE
Type of A: N4arma3MatIdEE
A:
   0.1383   0.5448   0.4349
   0.6912   0.6917   0.1489

A:
   0.1383   0.5448   0.4349
   0.6912   0.6917   0.1489

A:
   0.1383   0.5448   0.4349
   0.6912   0.6917   0.1489

R:
   0.9312   0.3851   0.1698
   0.7090   0.9461   0.1287

R:
   0.9312   0.3851   0.1698
   0.7090   0.9461   0.1287

R:
   0.9312   0.3851   0.1698
   0.7090   0.9461   0.1287

A:
   0.1383   0.5448   0.4349
   0.6912   0.6917   0.1489

A.t:
   0.1383   0.6912
   0.5448   0.6917
   0.4349   0.1489

   0.4969   0.5535   0.1631
   0.5535   0.7752   0.3399
   0.1631   0.3399   0.2113

B:
   0.7697   0.7594   0.3825
   0.3710   0.4128   0.8314
   0.4641   0.5950   0.3182

Det: -0.0651421
C:
   0.6455   0.9586   0.1450
   0.1588   0.3722   0.7455
   0.4419   0.7973   0.7656

Det: -0.00598124
D:
   1.0000   2.0000   3.0000
   4.0000   5.0000   6.0000
   7.0000   8.0000   9.0000

Det: 0
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