40 #include <visp3/core/vpConfig.h>
41 #include <visp3/core/vpDebug.h>
42 #include <visp3/core/vpGEMM.h>
43 #include <visp3/core/vpHomogeneousMatrix.h>
44 #include <visp3/core/vpMath.h>
45 #include <visp3/core/vpVelocityTwistMatrix.h>
52 #ifdef ENABLE_VISP_NAMESPACE
58 bool test_memory(
unsigned int nrows,
unsigned int ncols,
const vpMatrix &M,
const std::string &matrix_name,
bool pointer_is_null)
60 if (pointer_is_null) {
62 std::cerr <<
"Wrong data pointer (" << M.
data <<
") in matrix " << matrix_name <<
": should be null" << std::endl;
67 std::cerr <<
"Wrong data pointer (" << M.
data <<
") in matrix " << matrix_name <<
": should be non null" << std::endl;
73 std::cerr <<
"Wrong matrix " << matrix_name <<
"(" << nrows <<
", " << ncols <<
" size: "
77 std::cout <<
"Test matrix " << matrix_name <<
" succeed" << std::endl;
81 bool test(
const std::string &s,
const vpMatrix &M,
const std::vector<double> &bench)
83 static unsigned int cpt = 0;
84 std::cout <<
"** Test " << ++cpt << std::endl;
85 std::cout << s <<
"(" << M.
getRows() <<
"," << M.
getCols() <<
") = \n" << M << std::endl;
86 if (bench.size() != M.
size()) {
87 std::cout <<
"Test fails: bad size wrt bench" << std::endl;
90 for (
unsigned int i = 0; i < M.
size(); i++) {
91 if (std::fabs(M.
data[i] - bench[i]) > std::fabs(M.
data[i]) * std::numeric_limits<double>::epsilon()) {
92 std::cout <<
"Test fails: bad content" << std::endl;
100 double getRandomValues(
double min,
double max) {
return (max - min) * ((double)rand() / (double)RAND_MAX) + min; }
102 bool equalMatrix(
const vpMatrix &A,
const vpMatrix &B,
double tol = std::numeric_limits<double>::epsilon())
108 for (
unsigned int i = 0; i < A.
getRows(); i++) {
109 for (
unsigned int j = 0; j < A.
getCols(); j++) {
119 vpMatrix generateRandomMatrix(
unsigned int rows,
unsigned int cols,
double min,
double max)
123 for (
unsigned int i = 0; i < M.
getRows(); i++) {
124 for (
unsigned int j = 0; j < M.
getCols(); j++) {
125 M[i][j] = getRandomValues(min, max);
132 std::vector<double> computeHadamard(
const std::vector<double> &v1,
const std::vector<double> &v2)
134 std::vector<double> result;
135 std::transform(v1.begin(), v1.end(), v2.begin(), std::back_inserter(result), std::multiplies<double>());
140 int main(
int argc,
char *argv[])
144 for (
int i = 1; i < argc; i++) {
145 if (std::string(argv[i]) ==
"--benchmark") {
151 unsigned int nrows = 2, ncols = 3;
153 if (test_memory(nrows, ncols, A,
"A",
false) ==
false) {
157 if (test_memory(0, 0, B,
"B",
true) ==
false) {
160 if (test_memory(0, 0, C,
"C",
true)==
false) {
164 if (test_memory(nrows, ncols, B,
"B",
false)==
false) {
168 if (test_memory(0, 0, C,
"C",
true)==
false) {
173 const double val = 10.0;
175 M.
resize(5, 5,
false,
false);
177 for (
unsigned int i = 0; i < M.
getRows(); i++) {
178 for (
unsigned int j = 0; j < M.
getCols(); j++) {
179 if (!
vpMath::equal(M[i][j], val, std::numeric_limits<double>::epsilon())) {
180 std::cerr <<
"Issue with matrix assignment with value." << std::endl;
184 if (!
vpMath::equal(M2[i][j], val, std::numeric_limits<double>::epsilon())) {
185 std::cerr <<
"Issue with matrix constructor initialized with value." << std::endl;
193 std::vector<double> bench(9, 0);
194 bench[2] = bench[4] = bench[6] = 1.;
196 M[2][0] = M[1][1] = M[0][2] = 1.;
198 if (test(
"R1",
static_cast<vpMatrix>(R1), bench) ==
false)
202 if (test(
"R2",
static_cast<vpMatrix>(R2), bench) ==
false)
208 std::vector<double> bench(6, 1);
210 if (test(
"M1", M1, bench) ==
false)
213 if (test(
"M2", M2, bench) ==
false)
219 for (
unsigned int i = 0; i < M.
getRows(); i++) {
220 for (
unsigned int j = 0; j < M.
getCols(); j++) {
225 M.
print(std::cout, 4);
228 N.
init(M, 0, 1, 2, 3);
230 N.
print(std::cout, 4);
231 std::string header(
"My 4-by-5 matrix\nwith a second line");
235 std::cout <<
"Matrix saved in matrix.mat file" << std::endl;
243 std::cout <<
"Matrix loaded from matrix.mat file with header \"" << header_ <<
"\": \n" << M1 << std::endl;
246 if (header != std::string(header_)) {
247 std::cout <<
"Bad header in matrix.mat" << std::endl;
253 std::cout <<
"Matrix saved in matrix.bin file" << std::endl;
259 std::cout <<
"Matrix loaded from matrix.bin file with header \"" << header_ <<
"\": \n" << M1 << std::endl;
262 if (header != std::string(header_)) {
263 std::cout <<
"Bad header in matrix.bin" << std::endl;
269 std::cout <<
"Matrix saved in matrix.yml file" << std::endl;
276 std::cout <<
"Matrix loaded from matrix.yml file with header \"" << header_ <<
"\": \n" << M2 << std::endl;
279 if (header != std::string(header_)) {
280 std::cout <<
"Bad header in matrix.mat" << std::endl;
287 std::cout <<
"R: \n" << R << std::endl;
289 std::cout <<
"M1: \n" << M1 << std::endl;
291 std::cout <<
"M2: \n" << M2 << std::endl;
293 std::cout <<
"M3: \n" << M3 << std::endl;
295 std::cout <<
"M4: \n" << M4 << std::endl;
299 std::cout <<
"------------------------" << std::endl;
300 std::cout <<
"--- TEST PRETTY PRINT---" << std::endl;
301 std::cout <<
"------------------------" << std::endl;
305 std::cout <<
"call std::cout << M;" << std::endl;
306 std::cout << M << std::endl;
308 std::cout <<
"call M.print (std::cout, 4);" << std::endl;
309 M.
print(std::cout, 4);
311 std::cout <<
"------------------------" << std::endl;
317 std::cout <<
"call std::cout << M;" << std::endl;
318 std::cout << M << std::endl;
319 std::cout <<
"call M.print (std::cout, 6);" << std::endl;
320 M.
print(std::cout, 6);
321 std::cout << std::endl;
323 std::cout <<
"------------------------" << std::endl;
327 std::cout <<
"call std::cout << M;" << std::endl;
328 std::cout << M << std::endl;
330 std::cout <<
"call M.print (std::cout, 10);" << std::endl;
331 M.
print(std::cout, 10);
332 std::cout << std::endl;
334 std::cout <<
"call M.print (std::cout, 2);" << std::endl;
335 M.
print(std::cout, 2);
336 std::cout << std::endl;
338 std::cout <<
"------------------------" << std::endl;
341 M[0][2] = -0.0000876;
342 std::cout <<
"call std::cout << M;" << std::endl;
343 std::cout << M << std::endl;
345 std::cout <<
"call M.print (std::cout, 4);" << std::endl;
346 M.
print(std::cout, 4);
347 std::cout << std::endl;
348 std::cout <<
"call M.print (std::cout, 6, \"M\");" << std::endl;
349 M.
print(std::cout, 6,
"M");
350 std::cout << std::endl;
351 std::cout <<
"call M.print (std::cout, 10, \"M\");" << std::endl;
352 M.
print(std::cout, 10,
"M");
353 std::cout << std::endl;
362 std::cout <<
"call std::cout << M;" << std::endl;
363 std::cout << M << std::endl;
364 std::cout <<
"call M.print (std::cout, 5, \"M\");" << std::endl;
365 M.
print(std::cout, 5,
"M");
366 std::cout << std::endl;
375 std::cout <<
"call std::cout << M;" << std::endl;
376 std::cout << M << std::endl;
377 std::cout <<
"call M.print (std::cout, 5, \"M\");" << std::endl;
378 M.
print(std::cout, 5,
"M");
379 std::cout << std::endl;
381 std::cout <<
"------------------------" << std::endl;
382 std::cout <<
"--- TEST RESIZE --------" << std::endl;
383 std::cout <<
"------------------------" << std::endl;
384 std::cout <<
"5x5" << std::endl;
386 std::cout << M << std::endl;
387 std::cout <<
"3x2" << std::endl;
389 std::cout << M << std::endl;
390 std::cout <<
"2x2" << std::endl;
392 std::cout << M << std::endl;
393 std::cout <<
"------------------------" << std::endl;
402 std::cout <<
"------------------------" << std::endl;
403 std::cout <<
"--- TEST vpRowVector * vpColVector" << std::endl;
404 std::cout <<
"------------------------" << std::endl;
417 r.print(std::cout, 2,
"r");
418 c.print(std::cout, 2,
"c");
419 std::cout <<
"r * c = " << rc << std::endl;
421 std::cout <<
"------------------------" << std::endl;
422 std::cout <<
"--- TEST vpRowVector * vpMatrix" << std::endl;
423 std::cout <<
"------------------------" << std::endl;
432 r.
print(std::cout, 2,
"r");
433 M.print(std::cout, 10,
"M");
434 std::cout <<
"r * M = " << rM << std::endl;
436 std::cout <<
"------------------------" << std::endl;
437 std::cout <<
"--- TEST vpGEMM " << std::endl;
438 std::cout <<
"------------------------" << std::endl;
453 vpGEMM(M, N, 2, C, 3, D, VP_GEMM_A_T);
454 std::cout << D << std::endl;
458 std::cout <<
"------------------------" << std::endl;
459 std::cout <<
"--- TEST vpMatrix insert() with same colNum " << std::endl;
460 std::cout <<
"------------------------" << std::endl;
461 unsigned int nb = ctest ? 10 : 100;
462 const unsigned int size = ctest ? 10 : 100;
465 std::vector<vpMatrix> submatrices(nb);
466 for (
size_t cpt = 0; cpt < submatrices.size(); cpt++) {
469 for (
unsigned int i = 0; i < m.getRows(); i++) {
470 for (
unsigned int j = 0; j < m.getCols(); j++) {
471 m[i][j] = getRandomValues(-100.0, 100.0);
475 submatrices[cpt] = m;
479 for (
unsigned int i = 0; i < nb; i++) {
480 m_big.insert(submatrices[(
size_t)i], i * size, 0);
483 std::cout <<
"Matrix insert(): " << t <<
" ms" << std::endl;
485 for (
unsigned int cpt = 0; cpt < nb; cpt++) {
486 for (
unsigned int i = 0; i < size; i++) {
487 for (
unsigned int j = 0; j < 6; j++) {
488 if (!
vpMath::equal(m_big[cpt * size + i][j], submatrices[(
size_t)cpt][i][j],
489 std::numeric_limits<double>::epsilon())) {
490 std::cerr <<
"Problem with vpMatrix insert()!" << std::endl;
502 std::cout <<
"Insert empty matrices:" << std::endl;
503 std::cout <<
"m1:\n" << m1 << std::endl;
504 std::cout <<
"m2:\n" << m2 << std::endl;
505 std::cout <<
"m3:\n" << m3 << std::endl;
507 std::cout <<
"\n------------------------" << std::endl;
508 std::cout <<
"--- TEST vpMatrix stack()" << std::endl;
509 std::cout <<
"------------------------" << std::endl;
515 std::cout <<
"L:\n" << L << std::endl;
519 std::cout <<
"L:\n" << L << std::endl;
525 for (
unsigned int i = 0; i < nb; i++) {
526 m_big_stack.
stack(submatrices[(
size_t)i]);
529 std::cout <<
"Matrix stack(): " << t <<
" ms" << std::endl;
531 if (!equalMatrix(m_big, m_big_stack)) {
532 std::cerr <<
"Problem with vpMatrix stack()!" << std::endl;
537 std::cout <<
"\n------------------------" << std::endl;
538 std::cout <<
"--- TEST vpMatrix stack(vpRowVector)" << std::endl;
539 std::cout <<
"------------------------" << std::endl;
541 vpMatrix m_big_stack = generateRandomMatrix(10000, ctest ? 10 : 100, -1000.0, 1000.0);
542 std::cout <<
"m_big_stack: " << m_big_stack.
getRows() <<
"x" << m_big_stack.
getCols() << std::endl;
546 for (
unsigned int i = 0; i < m_big_stack.
getRows(); i++) {
550 std::cout <<
"Matrix stack(vpRowVector): " << t <<
" ms" << std::endl;
552 if (!equalMatrix(m_big_stack, m_big_stack_row)) {
553 std::cerr <<
"Problem with vpMatrix stack(vpRowVector)!" << std::endl;
557 std::cout <<
"\n------------------------" << std::endl;
558 std::cout <<
"--- TEST vpMatrix stack(vpColVector)" << std::endl;
559 std::cout <<
"------------------------" << std::endl;
563 for (
unsigned int j = 0; j < m_big_stack.
getCols(); j++) {
567 std::cout <<
"Matrix stack(vpColVector): " << t <<
" ms" << std::endl;
569 if (!equalMatrix(m_big_stack, m_big_stack_col)) {
570 std::cerr <<
"Problem with vpMatrix stack(vpColVector)!" << std::endl;
574 std::cout <<
"\n------------------------" << std::endl;
575 std::cout <<
"--- TEST vpMatrix::stack()" << std::endl;
576 std::cout <<
"------------------------" << std::endl;
582 std::cout <<
"L:\n" << L << std::endl;
587 std::cout <<
"L:\n" << L << std::endl;
591 vpMatrix m_big_stack_static, m_big_stack_static_tmp;
593 for (
unsigned int i = 0; i < nb; i++) {
594 vpMatrix::stack(m_big_stack_static_tmp, submatrices[(
size_t)i], m_big_stack_static);
595 m_big_stack_static_tmp = m_big_stack_static;
598 std::cout <<
"Matrix::stack(): " << t <<
" ms" << std::endl;
600 if (!equalMatrix(m_big, m_big_stack_static)) {
601 std::cerr <<
"Problem with vpMatrix::stack()!" << std::endl;
606 std::cout <<
"\n------------------------" << std::endl;
607 std::cout <<
"--- TEST vpMatrix::stack(vpMatrix, vpRowVector, vpMatrix)" << std::endl;
608 std::cout <<
"------------------------" << std::endl;
610 vpMatrix m_big_stack_static = generateRandomMatrix(ctest ? 100 : 1000, ctest ? 10 : 100, -1000.0, 1000.0);
611 std::cout <<
"m_big_stack_static: " << m_big_stack_static.
getRows() <<
"x" << m_big_stack_static.
getCols()
614 vpMatrix m_big_stack_static_row, m_big_stack_static_row_tmp;
616 for (
unsigned int i = 0; i < m_big_stack_static.
getRows(); i++) {
618 m_big_stack_static_row_tmp = m_big_stack_static_row;
621 std::cout <<
"Matrix::stack(vpMatrix, vpRowVector, vpMatrix): " << t <<
" ms" << std::endl;
623 if (!equalMatrix(m_big_stack_static, m_big_stack_static_row)) {
624 std::cerr <<
"Problem with vpMatrix::stack(vpMatrix, vpRowVector, "
630 std::cout <<
"\n------------------------" << std::endl;
631 std::cout <<
"--- TEST vpMatrix::stack(vpMatrix, vpColVector, vpMatrix)" << std::endl;
632 std::cout <<
"------------------------" << std::endl;
634 vpMatrix m_big_stack_static_col, m_big_stack_static_col_tmp;
636 for (
unsigned int j = 0; j < m_big_stack_static.
getCols(); j++) {
638 m_big_stack_static_col_tmp = m_big_stack_static_col;
641 std::cout <<
"Matrix::stack(vpMatrix, vpColVector, vpMatrix): " << t <<
" ms" << std::endl;
643 if (!equalMatrix(m_big_stack_static, m_big_stack_static_col)) {
644 std::cerr <<
"Problem with vpMatrix::stack(vpMatrix, vpColVector, "
653 for (
unsigned int i = 0; i < m2.
getRows(); i++) {
654 for (
unsigned int j = 0; j < m2.
getCols(); j++) {
655 m2[i][j] = getRandomValues(-100.0, 100.0);
659 unsigned int offset_i = 4, offset_j = 3;
660 m1.insert(m2, offset_i, offset_j);
662 for (
unsigned int i = 0; i < m2.
getRows(); i++) {
663 for (
unsigned int j = 0; j < m2.
getCols(); j++) {
664 if (!
vpMath::equal(m1[i + offset_i][j + offset_j], m2[i][j], std::numeric_limits<double>::epsilon())) {
665 std::cerr <<
"Problem with vpMatrix insert()!" << std::endl;
673 m1.insert(m2, offset_i, offset_j);
675 for (
unsigned int i = 0; i < m2.
getRows(); i++) {
676 for (
unsigned int j = 0; j < m2.
getCols(); j++) {
677 if (!
vpMath::equal(m1[i + offset_i][j + offset_j], m2[i][j], std::numeric_limits<double>::epsilon())) {
678 std::cerr <<
"Problem with vpMatrix insert()!" << std::endl;
686 m1.insert(m2, offset_i, offset_j);
688 for (
unsigned int i = 0; i < m2.
getRows(); i++) {
689 for (
unsigned int j = 0; j < m2.
getCols(); j++) {
690 if (!
vpMath::equal(m1[i + offset_i][j + offset_j], m2[i][j], std::numeric_limits<double>::epsilon())) {
691 std::cerr <<
"Problem with vpMatrix insert()!" << std::endl;
699 std::cout <<
"\n------------------------" << std::endl;
700 std::cout <<
"--- TEST vpMatrix::juxtaposeMatrices()" << std::endl;
701 std::cout <<
"------------------------" << std::endl;
704 for (
unsigned int i = 0; i < A.
getRows(); i++) {
705 for (
unsigned int j = 0; j < A.
getCols(); j++) {
709 B[i][j] = (i * B.
getCols() + j) * 10;
716 std::cout <<
"juxtaposeM:\n" << juxtaposeM << std::endl;
719 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
721 std::vector<vpMatrix> vec_mat;
722 vec_mat.emplace_back(5, 5);
728 std::cout <<
"\n1) A+B:\n" << res << std::endl;
732 std::cout <<
"\n2) A+B:\n" << res2 << std::endl;
737 std::cout <<
"\n------------------------" << std::endl;
738 std::cout <<
"--- TEST vpMatrix::hadamard()" << std::endl;
739 std::cout <<
"------------------------" << std::endl;
742 for (
unsigned int i = 0; i < M1.
size(); i++) {
748 std::vector<double> references = computeHadamard(std::vector<double>(M1.
data, M1.
data + M1.
size()),
751 std::cout <<
"M1:\n" << M1 << std::endl;
752 std::cout <<
"\nM2:\n" << M2 << std::endl;
754 std::cout <<
"\nRes:\n" << M2 << std::endl;
756 if (!test(
"M2", M2, references)) {
757 std::cerr <<
"Error with Hadamard product" << std::endl;
763 std::cout <<
"\n------------------------" << std::endl;
764 std::cout <<
"--- TEST vpMatrix::stackColums()" << std::endl;
765 std::cout <<
"------------------------" << std::endl;
767 for (
unsigned int j = 0; j < M.getCols(); j++) {
768 for (
unsigned int i = 0; i < M.getRows(); i++) {
769 M[i][j] = i + j * M.getRows();
772 std::cout <<
"M:\n" << M << std::endl;
774 std::cout <<
"Column stack: " << v.
t() << std::endl;
775 if (M.size() != v.
size()) {
776 std::cerr <<
"Problem in vpMatrix::stackColumns(): size differ" << std::endl;
779 for (
unsigned int i = 0; i < v.
size(); i++) {
780 if (std::fabs(v[i] -
static_cast<double>(i)) > std::numeric_limits<double>::epsilon()) {
781 std::cerr <<
"Problem in vpMatrix::stackColumns(): content differ" << std::endl;
788 std::cout <<
"\n------------------------" << std::endl;
789 std::cout <<
"--- TEST vpMatrix::stackRows()" << std::endl;
790 std::cout <<
"------------------------" << std::endl;
792 for (
unsigned int i = 0; i < M.getRows(); i++) {
793 for (
unsigned int j = 0; j < M.getCols(); j++) {
794 M[i][j] = i * M.getCols() + j;
797 std::cout <<
"M:\n" << M << std::endl;
799 std::cout <<
"Rows stack: " << v << std::endl;
800 if (M.size() != v.
size()) {
801 std::cerr <<
"Problem in vpMatrix::stackRows(): size differ" << std::endl;
804 for (
unsigned int i = 0; i < v.
size(); i++) {
805 if (std::fabs(v[i] -
static_cast<double>(i)) > std::numeric_limits<double>::epsilon()) {
806 std::cerr <<
"Problem in vpMatrix::stackRows(): content differ" << std::endl;
813 std::cout <<
"\n------------------------" << std::endl;
814 std::cout <<
"--- TEST vpMatrix::getCol()" << std::endl;
815 std::cout <<
"------------------------" << std::endl;
817 for (
unsigned int i = 0; i < A.
getRows(); i++)
818 for (
unsigned int j = 0; j < A.
getCols(); j++)
826 std::cerr <<
"Problem in vpMatrix::getCol(): values are different" << std::endl;
835 std::cerr <<
"Problem in vpMatrix::getCol(): values are different" << std::endl;
842 std::cout <<
"\n------------------------" << std::endl;
843 std::cout <<
"--- TEST vpMatrix::getRow()" << std::endl;
844 std::cout <<
"------------------------" << std::endl;
846 for (
unsigned int i = 0; i < A.
getRows(); i++)
847 for (
unsigned int j = 0; j < A.
getCols(); j++)
855 std::cerr <<
"Problem in vpMatrix::getRow(): values are different" << std::endl;
864 std::cerr <<
"Problem in vpMatrix::getRow(): values are different" << std::endl;
871 std::cout <<
"\n------------------------" << std::endl;
872 std::cout <<
"--- TEST vpMatrix::getDiag()" << std::endl;
873 std::cout <<
"------------------------" << std::endl;
875 for (
unsigned int i = 0; i < A.
getRows(); i++)
876 for (
unsigned int j = 0; j < A.
getCols(); j++)
881 ref << 0.0, 5.0, 10.0;
883 std::cerr <<
"Problem in vpMatrix::getDiag(): values are different" << std::endl;
888 std::cout <<
"\nAll tests succeeded" << std::endl;
892 std::cout <<
"Catch an exception: " << e << std::endl;
unsigned int getCols() const
Type * data
Address of the first element of the data array.
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
unsigned int size() const
Return the number of elements of the 2D array.
unsigned int getRows() const
Implementation of column vector and the associated operations.
error that can be emitted by ViSP classes.
static double rad(double deg)
static bool equal(double x, double y, double threshold=0.001)
Implementation of a matrix and operations on matrices.
vpMatrix hadamard(const vpMatrix &m) const
int print(std::ostream &s, unsigned int length, const std::string &intro="") const
void init(const vpMatrix &M, unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols)
static bool loadMatrix(const std::string &filename, vpArray2D< double > &M, bool binary=false, char *header=nullptr)
void stack(const vpMatrix &A)
static vpMatrix juxtaposeMatrices(const vpMatrix &A, const vpMatrix &B)
vpRowVector getRow(unsigned int i) const
vpColVector getDiag() const
vpColVector getCol(unsigned int j) const
void insert(const vpMatrix &A, unsigned int r, unsigned int c)
static bool saveMatrixYAML(const std::string &filename, const vpArray2D< double > &M, const char *header="")
static bool loadMatrixYAML(const std::string &filename, vpArray2D< double > &M, char *header=nullptr)
static bool saveMatrix(const std::string &filename, const vpArray2D< double > &M, bool binary=false, const char *header="")
Implementation of a rotation matrix and operations on such kind of matrices.
Implementation of row vector and the associated operations.
void resize(unsigned int i, bool flagNullify=true)
VISP_EXPORT double measureTimeMs()