https://old.reddit.com/r/cpp/comments/128tnij/which_is_the_best_way_to_work_with_matrices_and/
https://youtu.be/ioJkA7Mw2-U?si=9htzDJ4vA6F3cZRO : heap is slow
11. Numerical libraries in Matrix Problems#
11.1. GSL : Gnu Scientific Library#
https://www.gnu.org/software/gsl/ Documentation: https://www.gnu.org/software/gsl/doc/html/index.html
11.1.1. Special functions example : Bessel function#
See: https://www.gnu.org/software/gsl/doc/html/specfunc.html
// Adapted to c++ from : https://www.gnu.org/software/gsl/doc/html/specfunc.html
// compile as: g++ -std=c++17 name.cpp -lgsl -lgslcblas
#include <cstdio>
#include <cmath>
#include <gsl/gsl_sf_bessel.h>
int main (void)
{
double x = 5.0;
double expected = -0.17759677131433830434739701;
double fromcmath = std::cyl_bessel_j(0, x);
double y = gsl_sf_bessel_J0 (x);
std::printf ("J0(5.0) = %.18f\n", y);
std::printf ("exact = %.18f\n", expected);
std::printf ("fromcmath = %.18f\n", fromcmath);
return 0;
}
Exercise: Write a program that prints the Bessel function of order zero for \(x \in [0, 10]\) in steps \(\Delta x = 0.01\). Plot it.
Exercise: Print and plot some of the Hypergeometric functions.
Exercise: What about linear algebra? check the examples.
11.2. Standard library for special functions#
Check the standard library for implementatios of many special functions.
Must compile with -std=c++17
11.3. Eigen : Linear Algebra#
http://eigen.tuxfamily.org/index.php?title=Main_Page Start by: http://eigen.tuxfamily.org/dox/GettingStarted.html
Basic matrix
#include <iostream>
#include <eigen3/Eigen/Dense>
int main(void)
{
Eigen::MatrixXd m(2, 2);
m(0, 1) = -9.877;
std::cout << m << std::endl;
return 0;
}
0 |
-9.877 |
0 |
0 |
Exercise: Create a 8x8 matrix and print it to the screen.
random matrix
#include <iostream>
#include <cstdlib>
#include <eigen3/Eigen/Dense>
int main(int argc, char **argv)
{
//const int SEED = std::atoi(argv[1]);
//srand(SEED); // control seed
Eigen::MatrixXd m = Eigen::MatrixXd::Random(5,5);
std::cout << m << std::endl;
return 0;
}
0.680375 |
-0.604897 |
-0.0452059 |
0.83239 |
-0.967399 |
-0.211234 |
-0.329554 |
0.257742 |
0.271423 |
-0.514226 |
0.566198 |
0.536459 |
-0.270431 |
0.434594 |
-0.725537 |
0.59688 |
-0.444451 |
0.0268018 |
-0.716795 |
0.608354 |
0.823295 |
0.10794 |
0.904459 |
0.213938 |
-0.686642 |
Exercise: Create a 8x8 random matrix and print it to the screen. Control the seed, print it twice to check that the elements are the same.
First example from the tutorial:
// First example on how to use eigen
// compile with: g++ -std=c++11 -I /usr/include/eigen3
#include <iostream>
#include <eigen3/Eigen/Dense>
int main()
{
// X = Dynamic size
// d = double
Eigen::MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;
}
3 |
-1 |
2.5 |
1.5 |
Second example from the tutorial: Matrix-vector multiplication
#include <iostream>
#include <eigen3/Eigen/Dense>
int main()
{
const int N = 3;
srand(10);
Eigen::MatrixXd m = Eigen::MatrixXd::Random(N, N);
m = (m + Eigen::MatrixXd::Constant(N, N, 1.2)) * 50;
std::cout << "m =" << std::endl << m << std::endl;
Eigen::VectorXd v(N);
v << 1, 2, 3;
std::cout << "m * v =" << std::endl << m * v << std::endl;
}
11.3.1. Linear Algebra#
In this example we are going to use eigen to solve the system \(\boldsymbol{A}\vec x = \vec{x}\) using HouseHolder QR decomposition as done in http://eigen.tuxfamily.org/dox/group__TutorialLinearAlgebra.html .
#include <iostream>
#include <eigen3/Eigen/Dense>
int main()
{
Eigen::Matrix3f A;
Eigen::Vector3f b;
A << 1,2,3, 4,5,6, 7,8,10;
b << 3, 3, 4;
std::cout << "Here is the matrix A:\n" << A << std::endl;
std::cout << "Here is the vector b:\n" << b << std::endl;
Eigen::Vector3f x = A.colPivHouseholderQr().solve(b);
std::cout << "The solution is:\n" << x << std::endl;
std::cout << "Verification:\n" << (A*x - b).norm() << std::endl;
}
Here |
is |
the |
matrix |
A: |
1 |
2 |
3 |
||
4 |
5 |
6 |
||
7 |
8 |
10 |
||
Here |
is |
the |
vector |
b: |
3 |
||||
3 |
||||
4 |
||||
The |
solution |
is: |
||
-2 |
||||
0.999997 |
||||
1 |
||||
Verification: |
||||
1.43051e-06 |
With double
:
#include <iostream>
#include <eigen3/Eigen/Dense>
int main()
{
Eigen::Matrix3d A;
Eigen::Vector3d b;
A << 1,2,3, 4,5,6, 7,8,10;
b << 3, 3, 4;
std::cout << "Here is the matrix A:\n" << A << std::endl;
std::cout << "Here is the vector b:\n" << b << std::endl;
Eigen::Vector3d x = A.colPivHouseholderQr().solve(b);
std::cout << "The solution is:\n" << x << std::endl;
std::cout << "Verification:\n" << (A*x - b).norm() << std::endl;
}
Here |
is |
the |
matrix |
A: |
1 |
2 |
3 |
||
4 |
5 |
6 |
||
7 |
8 |
10 |
||
Here |
is |
the |
vector |
b: |
3 |
||||
3 |
||||
4 |
||||
The |
solution |
is: |
||
-2 |
||||
1 |
||||
1 |
||||
Verification: |
||||
3.58036e-15 |
Exercise: Create a random 40x40 matrix \(A\), a random vector \(b\) of size 40, and solve the system \(Ax = b\) using
FullPivHouseholderQR
. Compare the execution time with a 100x100 problem size.Exercise: Compile the previous example with profiling, run under valgrind cachegrind, and check the output. Can you change or optimize any of that?
Now use eigen to compute the eigenvalues of a given matrix:
#include <iostream>
#include <eigen3/Eigen/Dense>
int main()
{
Eigen::Matrix2d A;
A << 1, 2, 2, 3;
std::cout << "Here is the matrix A:\n" << A << std::endl;
Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eigensolver(A);
std::cout << "The eigenvalues of A are:\n" << eigensolver.eigenvalues() << std::endl;
std::cout << "Here's a matrix whose columns are eigenvectors of A \n"
<< "corresponding to these eigenvalues:\n"
<< eigensolver.eigenvectors() << std::endl;
}
Exercise : Compute the eigen-values of a random matrix of size 20x20.