Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
testMatrix.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Test some vpMatrix functionalities.
33  *
34  * Authors:
35  * Fabien Spindler
36  *
37  *****************************************************************************/
38 
45 #include <visp3/core/vpConfig.h>
46 #include <visp3/core/vpDebug.h>
47 #include <visp3/core/vpGEMM.h>
48 #include <visp3/core/vpHomogeneousMatrix.h>
49 #include <visp3/core/vpMath.h>
50 #include <visp3/core/vpVelocityTwistMatrix.h>
51 
52 #include <stdio.h>
53 #include <stdlib.h>
54 
55 namespace
56 {
57 bool test(const std::string &s, const vpMatrix &M, const std::vector<double> &bench)
58 {
59  static unsigned int cpt = 0;
60  std::cout << "** Test " << ++cpt << std::endl;
61  std::cout << s << "(" << M.getRows() << "," << M.getCols() << ") = \n" << M << std::endl;
62  if (bench.size() != M.size()) {
63  std::cout << "Test fails: bad size wrt bench" << std::endl;
64  return false;
65  }
66  for (unsigned int i = 0; i < M.size(); i++) {
67  if (std::fabs(M.data[i] - bench[i]) > std::fabs(M.data[i]) * std::numeric_limits<double>::epsilon()) {
68  std::cout << "Test fails: bad content" << std::endl;
69  return false;
70  }
71  }
72 
73  return true;
74 }
75 
76 double getRandomValues(const double min, const double max)
77 {
78  return (max - min) * ((double)rand() / (double)RAND_MAX) + min;
79 }
80 
81 bool equalMatrix(const vpMatrix &A, const vpMatrix &B, const double tol = std::numeric_limits<double>::epsilon())
82 {
83  if (A.getRows() != B.getRows() || A.getCols() != B.getCols()) {
84  return false;
85  }
86 
87  for (unsigned int i = 0; i < A.getRows(); i++) {
88  for (unsigned int j = 0; j < A.getCols(); j++) {
89  if (!vpMath::equal(A[i][j], B[i][j], tol)) {
90  return false;
91  }
92  }
93  }
94 
95  return true;
96 }
97 
98 vpMatrix generateRandomMatrix(const unsigned int rows, const unsigned int cols, const double min, const double max)
99 {
100  vpMatrix M(rows, cols);
101 
102  for (unsigned int i = 0; i < M.getRows(); i++) {
103  for (unsigned int j = 0; j < M.getCols(); j++) {
104  M[i][j] = getRandomValues(min, max);
105  }
106  }
107 
108  return M;
109 }
110 
111 #if defined(VISP_HAVE_LAPACK) && !defined(VISP_HAVE_LAPACK_BUILT_IN)
112 vpColVector generateRandomVector(const unsigned int rows, const double min, const double max)
113 {
114  vpColVector v(rows);
115 
116  for (unsigned int i = 0; i < v.getRows(); i++) {
117  v[i] = getRandomValues(min, max);
118  }
119 
120  return v;
121 }
122 
123 // Copy of vpMatrix::mult2Matrices
124 vpMatrix dgemm_regular(const vpMatrix &A, const vpMatrix &B)
125 {
126  vpMatrix C;
127 
128  if ((A.getRows() != C.getRows()) || (B.getCols() != C.getCols()))
129  C.resize(A.getRows(), B.getCols(), false);
130 
131  if (A.getCols() != B.getRows()) {
132  throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (%dx%d) matrix", A.getRows(),
133  A.getCols(), B.getRows(), B.getCols()));
134  }
135 
136  // 5/12/06 some "very" simple optimization to avoid indexation
137  unsigned int BcolNum = B.getCols();
138  unsigned int BrowNum = B.getRows();
139  unsigned int i, j, k;
140  for (i = 0; i < A.getRows(); i++) {
141  double *rowptri = A[i];
142  double *ci = C[i];
143  for (j = 0; j < BcolNum; j++) {
144  double s = 0;
145  for (k = 0; k < BrowNum; k++)
146  s += rowptri[k] * B[k][j];
147  ci[j] = s;
148  }
149  }
150 
151  return C;
152 }
153 
154 // Copy of vpMatrix::AtA
155 vpMatrix AtA_regular(const vpMatrix &A)
156 {
157  vpMatrix B;
158  B.resize(A.getCols(), A.getCols(), false);
159 
160  unsigned int i, j, k;
161  double s;
162  double *ptr;
163  for (i = 0; i < A.getCols(); i++) {
164  double *Bi = B[i];
165  for (j = 0; j < i; j++) {
166  ptr = A.data;
167  s = 0;
168  for (k = 0; k < A.getRows(); k++) {
169  s += (*(ptr + i)) * (*(ptr + j));
170  ptr += A.getCols();
171  }
172  *Bi++ = s;
173  B[j][i] = s;
174  }
175  ptr = A.data;
176  s = 0;
177  for (k = 0; k < A.getRows(); k++) {
178  s += (*(ptr + i)) * (*(ptr + i));
179  ptr += A.getCols();
180  }
181  *Bi = s;
182  }
183 
184  return B;
185 }
186 
187 // Copy of vpMatrix::multMatrixVector
188 vpMatrix dgemv_regular(const vpMatrix &A, const vpColVector &v)
189 {
190  vpColVector w;
191 
192  if (A.getCols() != v.getRows()) {
193  throw(vpException(vpException::dimensionError, "Cannot multiply a (%dx%d) matrix by a (%d) column vector",
194  A.getRows(), A.getCols(), v.getRows()));
195  }
196 
197  w.resize(A.getRows(), true);
198 
199  for (unsigned int j = 0; j < A.getCols(); j++) {
200  double vj = v[j]; // optimization em 5/12/2006
201  for (unsigned int i = 0; i < A.getRows(); i++) {
202  w[i] += A[i][j] * vj;
203  }
204  }
205 
206  return w;
207 }
208 
209 // Copy of vpMatrix::operator*(const vpVelocityTwistMatrix &V)
210 vpMatrix mat_mul_twist_matrix(const vpMatrix &A, const vpVelocityTwistMatrix &V)
211 {
212  vpMatrix M;
213 
214  if (A.getCols() != V.getRows()) {
215  throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (6x6) velocity twist matrix",
216  A.getRows(), A.getCols()));
217  }
218 
219  M.resize(A.getRows(), 6, false);
220 
221  unsigned int VcolNum = V.getCols();
222  unsigned int VrowNum = V.getRows();
223 
224  for (unsigned int i = 0; i < A.getRows(); i++) {
225  double *rowptri = A[i];
226  double *ci = M[i];
227  for (unsigned int j = 0; j < VcolNum; j++) {
228  double s = 0;
229  for (unsigned int k = 0; k < VrowNum; k++)
230  s += rowptri[k] * V[k][j];
231  ci[j] = s;
232  }
233  }
234 
235  return M;
236 }
237 #endif
238 }
239 
240 int main(int argc, char *argv[])
241 {
242  try {
243  bool ctest = true;
244  for (int i = 1; i < argc; i++) {
245  if (std::string(argv[i]) == "--benchmark") {
246  ctest = false;
247  }
248  }
249 
250  {
251  const double val = 10.0;
252  vpMatrix M, M2(5, 5, val);
253  M.resize(5, 5, false, false);
254  M = val;
255  for (unsigned int i = 0; i < M.getRows(); i++) {
256  for (unsigned int j = 0; j < M.getCols(); j++) {
257  if (!vpMath::equal(M[i][j], val, std::numeric_limits<double>::epsilon())) {
258  std::cerr << "Issue with matrix assignment with value." << std::endl;
259  return EXIT_FAILURE;
260  }
261 
262  if (!vpMath::equal(M2[i][j], val, std::numeric_limits<double>::epsilon())) {
263  std::cerr << "Issue with matrix constructor initialized with value." << std::endl;
264  return EXIT_FAILURE;
265  }
266  }
267  }
268  }
269  {
270  // Test vpRotationMatrix construction
271  std::vector<double> bench(9, 0);
272  bench[2] = bench[4] = bench[6] = 1.;
273  vpMatrix M(3, 3);
274  M[2][0] = M[1][1] = M[0][2] = 1.;
275  vpRotationMatrix R1(M);
276  if (test("R1", R1, bench) == false)
277  return EXIT_FAILURE;
278  vpRotationMatrix R2;
279  R2 = M;
280  if (test("R2", R2, bench) == false)
281  return EXIT_FAILURE;
282  }
283  {
284  vpColVector c(6, 1);
285  vpRowVector r(6, 1);
286  std::vector<double> bench(6, 1);
287  vpMatrix M1(c);
288  if (test("M1", M1, bench) == false)
289  return EXIT_FAILURE;
290  vpMatrix M2(r);
291  if (test("M2", M2, bench) == false)
292  return EXIT_FAILURE;
293  }
294  {
295  vpMatrix M(4, 5);
296  int val = 0;
297  for (unsigned int i = 0; i < M.getRows(); i++) {
298  for (unsigned int j = 0; j < M.getCols(); j++) {
299  M[i][j] = val++;
300  }
301  }
302  std::cout << "M ";
303  M.print(std::cout, 4);
304 
305  vpMatrix N;
306  N.init(M, 0, 1, 2, 3);
307  std::cout << "N ";
308  N.print(std::cout, 4);
309  std::string header("My 4-by-5 matrix\nwith a second line");
310 
311  // Save matrix in text format
312  if (vpMatrix::saveMatrix("matrix.mat", M, false, header.c_str()))
313  std::cout << "Matrix saved in matrix.mat file" << std::endl;
314  else
315  return EXIT_FAILURE;
316 
317  // Load matrix in text format
318  vpMatrix M1;
319  char header_[100];
320  if (vpMatrix::loadMatrix("matrix.mat", M1, false, header_))
321  std::cout << "Matrix loaded from matrix.mat file with header \"" << header_ << "\": \n" << M1 << std::endl;
322  else
323  return EXIT_FAILURE;
324  if (header != std::string(header_)) {
325  std::cout << "Bad header in matrix.mat" << std::endl;
326  return EXIT_FAILURE;
327  }
328 
329  // Save matrix in binary format
330  if (vpMatrix::saveMatrix("matrix.bin", M, true, header.c_str()))
331  std::cout << "Matrix saved in matrix.bin file" << std::endl;
332  else
333  return EXIT_FAILURE;
334 
335  // Load matrix in binary format
336  if (vpMatrix::loadMatrix("matrix.bin", M1, true, header_))
337  std::cout << "Matrix loaded from matrix.bin file with header \"" << header_ << "\": \n" << M1 << std::endl;
338  else
339  return EXIT_FAILURE;
340  if (header != std::string(header_)) {
341  std::cout << "Bad header in matrix.bin" << std::endl;
342  return EXIT_FAILURE;
343  }
344 
345  // Save matrix in YAML format
346  if (vpMatrix::saveMatrixYAML("matrix.yml", M, header.c_str()))
347  std::cout << "Matrix saved in matrix.yml file" << std::endl;
348  else
349  return EXIT_FAILURE;
350 
351  // Read matrix in YAML format
352  vpMatrix M2;
353  if (vpMatrix::loadMatrixYAML("matrix.yml", M2, header_))
354  std::cout << "Matrix loaded from matrix.yml file with header \"" << header_ << "\": \n" << M2 << std::endl;
355  else
356  return EXIT_FAILURE;
357  if (header != std::string(header_)) {
358  std::cout << "Bad header in matrix.mat" << std::endl;
359  return EXIT_FAILURE;
360  }
361  }
362 
363  {
365  std::cout << "R: \n" << R << std::endl;
366  vpMatrix M1(R);
367  std::cout << "M1: \n" << M1 << std::endl;
368  vpMatrix M2(M1);
369  std::cout << "M2: \n" << M2 << std::endl;
370  vpMatrix M3 = R;
371  std::cout << "M3: \n" << M3 << std::endl;
372  vpMatrix M4 = M1;
373  std::cout << "M4: \n" << M4 << std::endl;
374  }
375  {
376 
377  std::cout << "------------------------" << std::endl;
378  std::cout << "--- TEST PRETTY PRINT---" << std::endl;
379  std::cout << "------------------------" << std::endl;
380  vpMatrix M;
381  M.eye(4);
382 
383  std::cout << "call std::cout << M;" << std::endl;
384  std::cout << M << std::endl;
385 
386  std::cout << "call M.print (std::cout, 4);" << std::endl;
387  M.print(std::cout, 4);
388 
389  std::cout << "------------------------" << std::endl;
390  M.resize(3, 3);
391  M.eye(3);
392  M[1][0] = 1.235;
393  M[1][1] = 12.345;
394  M[1][2] = .12345;
395  std::cout << "call std::cout << M;" << std::endl;
396  std::cout << M;
397  std::cout << "call M.print (std::cout, 6);" << std::endl;
398  M.print(std::cout, 6);
399  std::cout << std::endl;
400 
401  std::cout << "------------------------" << std::endl;
402  M[0][0] = -1.235;
403  M[1][0] = -12.235;
404 
405  std::cout << "call std::cout << M;" << std::endl;
406  std::cout << M << std::endl;
407 
408  std::cout << "call M.print (std::cout, 10);" << std::endl;
409  M.print(std::cout, 10);
410  std::cout << std::endl;
411 
412  std::cout << "call M.print (std::cout, 2);" << std::endl;
413  M.print(std::cout, 2);
414  std::cout << std::endl;
415 
416  std::cout << "------------------------" << std::endl;
417  M.resize(3, 3);
418  M.eye(3);
419  M[0][2] = -0.0000000876;
420  std::cout << "call std::cout << M;" << std::endl;
421  std::cout << M << std::endl;
422 
423  std::cout << "call M.print (std::cout, 4);" << std::endl;
424  M.print(std::cout, 4);
425  std::cout << std::endl;
426  std::cout << "call M.print (std::cout, 10, \"M\");" << std::endl;
427  M.print(std::cout, 10, "M");
428  std::cout << std::endl;
429  std::cout << "call M.print (std::cout, 20, \"M\");" << std::endl;
430  M.print(std::cout, 20, "M");
431  std::cout << std::endl;
432 
433  std::cout << "------------------------" << std::endl;
434  std::cout << "--- TEST RESIZE --------" << std::endl;
435  std::cout << "------------------------" << std::endl;
436  std::cout << "5x5" << std::endl;
437  M.resize(5, 5, false);
438  std::cout << M << std::endl;
439  std::cout << "3x2" << std::endl;
440  M.resize(3, 2, false);
441  std::cout << M << std::endl;
442  std::cout << "2x2" << std::endl;
443  M.resize(2, 2, false);
444  std::cout << M << std::endl;
445  std::cout << "------------------------" << std::endl;
446 
448  vpMatrix A(1, 6), B;
449 
450  A = 1.0;
451  // vMe=1.0;
452  B = A * vMe;
453 
454  std::cout << "------------------------" << std::endl;
455  std::cout << "--- TEST vpRowVector * vpColVector" << std::endl;
456  std::cout << "------------------------" << std::endl;
457  vpRowVector r(3);
458  r[0] = 2;
459  r[1] = 3;
460  r[2] = 4;
461 
462  vpColVector c(3);
463  c[0] = 1;
464  c[1] = 2;
465  c[2] = -1;
466 
467  double rc = r * c;
468 
469  r.print(std::cout, 2, "r");
470  c.print(std::cout, 2, "c");
471  std::cout << "r * c = " << rc << std::endl;
472 
473  std::cout << "------------------------" << std::endl;
474  std::cout << "--- TEST vpRowVector * vpMatrix" << std::endl;
475  std::cout << "------------------------" << std::endl;
476  M.resize(3, 3);
477  M.eye(3);
478 
479  M[1][0] = 1.5;
480  M[2][0] = 2.3;
481 
482  vpRowVector rM = r * M;
483 
484  r.print(std::cout, 2, "r");
485  M.print(std::cout, 10, "M");
486  std::cout << "r * M = " << rM << std::endl;
487 
488  std::cout << "------------------------" << std::endl;
489  std::cout << "--- TEST vpGEMM " << std::endl;
490  std::cout << "------------------------" << std::endl;
491  M.resize(3, 3);
492  M.eye(3);
493  vpMatrix N(3, 3);
494  N[0][0] = 2;
495  N[1][0] = 1.2;
496  N[1][2] = 0.6;
497  N[2][2] = 0.25;
498 
499  vpMatrix C(3, 3);
500  C.eye(3);
501 
502  vpMatrix D;
503 
504  // realise the operation D = 2 * M^T * N + 3 C
505  vpGEMM(M, N, 2, C, 3, D, VP_GEMM_A_T);
506  std::cout << D << std::endl;
507  }
508 
509  {
510  std::cout << "------------------------" << std::endl;
511  std::cout << "--- TEST vpMatrix insert() with same colNum " << std::endl;
512  std::cout << "------------------------" << std::endl;
513  const unsigned int nb = ctest ? 10 : 100; // 10000;
514  const unsigned int size = ctest ? 10 : 100;
515 
516  vpMatrix m_big(nb * size, 6);
517  std::vector<vpMatrix> submatrices(nb);
518  for (size_t cpt = 0; cpt < submatrices.size(); cpt++) {
519  vpMatrix m(size, 6);
520 
521  for (unsigned int i = 0; i < m.getRows(); i++) {
522  for (unsigned int j = 0; j < m.getCols(); j++) {
523  m[i][j] = getRandomValues(-100.0, 100.0);
524  }
525  }
526 
527  submatrices[cpt] = m;
528  }
529 
530  double t = vpTime::measureTimeMs();
531  for (unsigned int i = 0; i < nb; i++) {
532  m_big.insert(submatrices[(size_t)i], i * size, 0);
533  }
534  t = vpTime::measureTimeMs() - t;
535  std::cout << "Matrix insert(): " << t << " ms" << std::endl;
536 
537  for (unsigned int cpt = 0; cpt < nb; cpt++) {
538  for (unsigned int i = 0; i < size; i++) {
539  for (unsigned int j = 0; j < 6; j++) {
540  if (!vpMath::equal(m_big[cpt * size + i][j], submatrices[(size_t)cpt][i][j],
541  std::numeric_limits<double>::epsilon())) {
542  std::cerr << "Problem with vpMatrix insert()!" << std::endl;
543  return EXIT_FAILURE;
544  }
545  }
546  }
547  }
548 
549  // Try to insert empty matrices
550  vpMatrix m1(2, 3), m2, m3;
551  m1.insert(m2, 0, 0);
552  m3.insert(m2, 0, 0);
553 
554  std::cout << "Insert empty matrices:" << std::endl;
555  std::cout << "m1:\n" << m1 << std::endl;
556  std::cout << "m2:\n" << m2 << std::endl;
557  std::cout << "m3:\n" << m3 << std::endl;
558 
559  std::cout << "\n------------------------" << std::endl;
560  std::cout << "--- TEST vpMatrix stack()" << std::endl;
561  std::cout << "------------------------" << std::endl;
562 
563  {
564  vpMatrix L, L2(2, 6);
565  L2 = 2;
566  L.stack(L2);
567  std::cout << "L:\n" << L << std::endl;
568  L2.resize(3, 6);
569  L2 = 3;
570  L.stack(L2);
571  std::cout << "L:\n" << L << std::endl;
572  }
573 
574  {
575  vpMatrix m_big_stack;
576  t = vpTime::measureTimeMs();
577  for (unsigned int i = 0; i < nb; i++) {
578  m_big_stack.stack(submatrices[(size_t)i]);
579  }
580  t = vpTime::measureTimeMs() - t;
581  std::cout << "Matrix stack(): " << t << " ms" << std::endl;
582 
583  if (!equalMatrix(m_big, m_big_stack)) {
584  std::cerr << "Problem with vpMatrix stack()!" << std::endl;
585  return EXIT_FAILURE;
586  }
587  }
588 
589  std::cout << "\n------------------------" << std::endl;
590  std::cout << "--- TEST vpMatrix stack(vpRowVector)" << std::endl;
591  std::cout << "------------------------" << std::endl;
592 
593  vpMatrix m_big_stack = generateRandomMatrix(10000, ctest ? 10 : 100, -1000.0, 1000.0);
594  std::cout << "m_big_stack: " << m_big_stack.getRows() << "x" << m_big_stack.getCols() << std::endl;
595 
596  vpMatrix m_big_stack_row;
597  t = vpTime::measureTimeMs();
598  for (unsigned int i = 0; i < m_big_stack.getRows(); i++) {
599  m_big_stack_row.stack(m_big_stack.getRow(i));
600  }
601  t = vpTime::measureTimeMs() - t;
602  std::cout << "Matrix stack(vpRowVector): " << t << " ms" << std::endl;
603 
604  if (!equalMatrix(m_big_stack, m_big_stack_row)) {
605  std::cerr << "Problem with vpMatrix stack(vpRowVector)!" << std::endl;
606  return EXIT_FAILURE;
607  }
608 
609  std::cout << "\n------------------------" << std::endl;
610  std::cout << "--- TEST vpMatrix stack(vpColVector)" << std::endl;
611  std::cout << "------------------------" << std::endl;
612 
613  vpMatrix m_big_stack_col;
614  t = vpTime::measureTimeMs();
615  for (unsigned int j = 0; j < m_big_stack.getCols(); j++) {
616  m_big_stack_col.stack(m_big_stack.getCol(j));
617  }
618  t = vpTime::measureTimeMs() - t;
619  std::cout << "Matrix stack(vpColVector): " << t << " ms" << std::endl;
620 
621  if (!equalMatrix(m_big_stack, m_big_stack_col)) {
622  std::cerr << "Problem with vpMatrix stack(vpColVector)!" << std::endl;
623  return EXIT_FAILURE;
624  }
625 
626  std::cout << "\n------------------------" << std::endl;
627  std::cout << "--- TEST vpMatrix::stack()" << std::endl;
628  std::cout << "------------------------" << std::endl;
629 
630  {
631  vpMatrix L, L2(2, 6), L_tmp;
632  L2 = 2;
633  vpMatrix::stack(L_tmp, L2, L);
634  std::cout << "L:\n" << L << std::endl;
635  L2.resize(3, 6);
636  L2 = 3;
637  L_tmp = L;
638  vpMatrix::stack(L_tmp, L2, L);
639  std::cout << "L:\n" << L << std::endl;
640  }
641 
642  {
643  vpMatrix m_big_stack_static, m_big_stack_static_tmp;
644  t = vpTime::measureTimeMs();
645  for (unsigned int i = 0; i < nb; i++) {
646  vpMatrix::stack(m_big_stack_static_tmp, submatrices[(size_t)i], m_big_stack_static);
647  m_big_stack_static_tmp = m_big_stack_static;
648  }
649  t = vpTime::measureTimeMs() - t;
650  std::cout << "Matrix::stack(): " << t << " ms" << std::endl;
651 
652  if (!equalMatrix(m_big, m_big_stack_static)) {
653  std::cerr << "Problem with vpMatrix::stack()!" << std::endl;
654  return EXIT_FAILURE;
655  }
656  }
657 
658  std::cout << "\n------------------------" << std::endl;
659  std::cout << "--- TEST vpMatrix::stack(vpMatrix, vpRowVector, vpMatrix)" << std::endl;
660  std::cout << "------------------------" << std::endl;
661 
662  vpMatrix m_big_stack_static = generateRandomMatrix(ctest ? 100 : 1000, ctest ? 10 : 100, -1000.0, 1000.0);
663  std::cout << "m_big_stack_static: " << m_big_stack_static.getRows() << "x" << m_big_stack_static.getCols() << std::endl;
664 
665  vpMatrix m_big_stack_static_row, m_big_stack_static_row_tmp;
666  t = vpTime::measureTimeMs();
667  for (unsigned int i = 0; i < m_big_stack_static.getRows(); i++) {
668  vpMatrix::stack(m_big_stack_static_row_tmp, m_big_stack_static.getRow(i), m_big_stack_static_row);
669  m_big_stack_static_row_tmp = m_big_stack_static_row;
670  }
671  t = vpTime::measureTimeMs() - t;
672  std::cout << "Matrix::stack(vpMatrix, vpRowVector, vpMatrix): " << t << " ms" << std::endl;
673 
674  if (!equalMatrix(m_big_stack_static, m_big_stack_static_row)) {
675  std::cerr << "Problem with vpMatrix::stack(vpMatrix, vpRowVector, "
676  "vpMatrix)!"
677  << std::endl;
678  return EXIT_FAILURE;
679  }
680 
681  std::cout << "\n------------------------" << std::endl;
682  std::cout << "--- TEST vpMatrix::stack(vpMatrix, vpColVector, vpMatrix)" << std::endl;
683  std::cout << "------------------------" << std::endl;
684 
685  vpMatrix m_big_stack_static_col, m_big_stack_static_col_tmp;
686  t = vpTime::measureTimeMs();
687  for (unsigned int j = 0; j < m_big_stack_static.getCols(); j++) {
688  vpMatrix::stack(m_big_stack_static_col_tmp, m_big_stack_static.getCol(j), m_big_stack_static_col);
689  m_big_stack_static_col_tmp = m_big_stack_static_col;
690  }
691  t = vpTime::measureTimeMs() - t;
692  std::cout << "Matrix::stack(vpMatrix, vpColVector, vpMatrix): " << t << " ms" << std::endl;
693 
694  if (!equalMatrix(m_big_stack_static, m_big_stack_static_col)) {
695  std::cerr << "Problem with vpMatrix::stack(vpMatrix, vpColVector, "
696  "vpMatrix)!"
697  << std::endl;
698  return EXIT_FAILURE;
699  }
700  }
701 
702  {
703  vpMatrix m1(11, 9), m2(3, 4);
704  for (unsigned int i = 0; i < m2.getRows(); i++) {
705  for (unsigned int j = 0; j < m2.getCols(); j++) {
706  m2[i][j] = getRandomValues(-100.0, 100.0);
707  }
708  }
709 
710  unsigned int offset_i = 4, offset_j = 3;
711  m1.insert(m2, offset_i, offset_j);
712 
713  for (unsigned int i = 0; i < m2.getRows(); i++) {
714  for (unsigned int j = 0; j < m2.getCols(); j++) {
715  if (!vpMath::equal(m1[i + offset_i][j + offset_j], m2[i][j], std::numeric_limits<double>::epsilon())) {
716  std::cerr << "Problem with vpMatrix insert()!" << std::endl;
717  return EXIT_FAILURE;
718  }
719  }
720  }
721 
722  offset_i = 4, offset_j = 5;
723  m1.insert(m2, offset_i, offset_j);
724 
725  for (unsigned int i = 0; i < m2.getRows(); i++) {
726  for (unsigned int j = 0; j < m2.getCols(); j++) {
727  if (!vpMath::equal(m1[i + offset_i][j + offset_j], m2[i][j], std::numeric_limits<double>::epsilon())) {
728  std::cerr << "Problem with vpMatrix insert()!" << std::endl;
729  return EXIT_FAILURE;
730  }
731  }
732  }
733 
734  offset_i = 8, offset_j = 5;
735  m1.insert(m2, offset_i, offset_j);
736 
737  for (unsigned int i = 0; i < m2.getRows(); i++) {
738  for (unsigned int j = 0; j < m2.getCols(); j++) {
739  if (!vpMath::equal(m1[i + offset_i][j + offset_j], m2[i][j], std::numeric_limits<double>::epsilon())) {
740  std::cerr << "Problem with vpMatrix insert()!" << std::endl;
741  return EXIT_FAILURE;
742  }
743  }
744  }
745  }
746 
747  {
748  std::cout << "\n------------------------" << std::endl;
749  std::cout << "--- TEST vpMatrix::juxtaposeMatrices()" << std::endl;
750  std::cout << "------------------------" << std::endl;
751 
752  vpMatrix A(5, 6), B(5, 4);
753  for (unsigned int i = 0; i < A.getRows(); i++) {
754  for (unsigned int j = 0; j < A.getCols(); j++) {
755  A[i][j] = i * A.getCols() + j;
756 
757  if (j < B.getCols()) {
758  B[i][j] = (i * B.getCols() + j) * 10;
759  }
760  }
761  }
762 
763  vpMatrix juxtaposeM;
764  vpMatrix::juxtaposeMatrices(A, B, juxtaposeM);
765  std::cout << "juxtaposeM:\n" << juxtaposeM << std::endl;
766  }
767 
768 #if defined(VISP_HAVE_LAPACK) && !defined(VISP_HAVE_LAPACK_BUILT_IN)
769  {
770  std::cout << "\n------------------------" << std::endl;
771  std::cout << "--- BENCHMARK dgemm/dgemv" << std::endl;
772  std::cout << "------------------------" << std::endl;
773 
774  size_t nb_matrices = ctest ? 100 : 10000;
775  unsigned int rows = 200, cols = 6;
776  double min = -1.0, max = 1.0;
777  std::vector<vpMatrix> vec_A, vec_B, vec_C, vec_C_regular;
778  vec_C.reserve(nb_matrices);
779  vec_C_regular.reserve(nb_matrices);
780 
781  for (size_t i = 0; i < nb_matrices; i++) {
782  vec_A.push_back(generateRandomMatrix(cols, rows, min, max));
783  vec_B.push_back(generateRandomMatrix(rows, cols, min, max));
784  }
785 
786  double t = vpTime::measureTimeMs();
787  for (size_t i = 0; i < nb_matrices; i++) {
788  vec_C.push_back(vec_A[i] * vec_B[i]);
789  }
790  t = vpTime::measureTimeMs() - t;
791  std::cout << nb_matrices << " matrix multiplication: (6x200) x (200x6)" << std::endl;
792  std::cout << "Lapack: " << t << " ms" << std::endl;
793  std::cout << "vec_C:\n" << vec_C.back() << std::endl;
794 
795  t = vpTime::measureTimeMs();
796  for (size_t i = 0; i < nb_matrices; i++) {
797  vec_C_regular.push_back(dgemm_regular(vec_A[i], vec_B[i]));
798  }
799  t = vpTime::measureTimeMs() - t;
800  std::cout << "\nRegular: " << t << " ms" << std::endl;
801  std::cout << "vec_C_regular:\n" << vec_C_regular.back() << std::endl;
802 
803  vpMatrix A = generateRandomMatrix(480, 640, min, max), B = generateRandomMatrix(640, 480, min, max);
804  vpMatrix AB, AB_regular;
805 
806  t = vpTime::measureTimeMs();
807  AB = A * B;
808  t = vpTime::measureTimeMs() - t;
809  std::cout << "\nMatrix multiplication: (480x640) x (640x480)" << std::endl;
810  std::cout << "Lapack: " << t << " ms" << std::endl;
811  std::cout << "Min=" << AB.getMinValue() << " ; Max=" << AB.getMaxValue() << std::endl;
812 
813  t = vpTime::measureTimeMs();
814  AB_regular = dgemm_regular(A, B);
815  t = vpTime::measureTimeMs() - t;
816  std::cout << "Regular: " << t << " ms" << std::endl;
817  std::cout << "Min=" << AB_regular.getMinValue() << " ; Max=" << AB_regular.getMaxValue() << std::endl;
818  bool res = equalMatrix(AB, AB_regular, 1e-9);
819  std::cout << "Check result: " << res << std::endl;
820  if (!res) {
821  std::cerr << "Problem with matrix multiplication!" << std::endl;
822  return EXIT_FAILURE;
823  }
824 
825  int nb_iterations = 1000;
826  vpMatrix L = generateRandomMatrix(1000, 6, min, max);
827  vpMatrix LTL, LTL_regular;
828 
829  t = vpTime::measureTimeMs();
830  for (int i = 0; i < nb_iterations; i++)
831  LTL = L.AtA();
832  t = vpTime::measureTimeMs() - t;
833  std::cout << "\n" << nb_iterations << " iterations of AtA for size: (1000x6)" << std::endl;
834  std::cout << "Lapack: " << t << " ms" << std::endl;
835  std::cout << "LTL:\n" << LTL << std::endl;
836 
837  t = vpTime::measureTimeMs();
838  for (int i = 0; i < nb_iterations; i++)
839  LTL_regular = AtA_regular(L);
840  t = vpTime::measureTimeMs() - t;
841  std::cout << "\nRegular: " << t << " ms" << std::endl;
842  std::cout << "LTL_regular:\n" << LTL_regular << std::endl;
843  res = equalMatrix(LTL, LTL_regular, 1e-9);
844  std::cout << "Check result: " << res << std::endl;
845  if (!res) {
846  std::cerr << "Problem with vpMatrix::AtA()!" << std::endl;
847  return EXIT_FAILURE;
848  }
849 
850  vpMatrix LT = generateRandomMatrix(6, 1000, min, max);
851  vpColVector R = generateRandomVector(1000, min, max);
852  vpMatrix LTR, LTR_regular;
853 
854  t = vpTime::measureTimeMs();
855  for (int i = 0; i < nb_iterations; i++)
856  LTR = LT * R;
857  t = vpTime::measureTimeMs() - t;
858  std::cout << "\n"
859  << nb_iterations
860  << " iterations of matrix vector multiplication: (6x1000) x "
861  "(1000x1)"
862  << std::endl;
863  std::cout << "Lapack: " << t << " ms" << std::endl;
864  std::cout << "LTR:\n" << LTR.t() << std::endl;
865 
866  t = vpTime::measureTimeMs();
867  for (int i = 0; i < nb_iterations; i++)
868  LTR_regular = dgemv_regular(LT, R);
869  t = vpTime::measureTimeMs() - t;
870  std::cout << "\nRegular: " << t << " ms" << std::endl;
871  std::cout << "LTR_regular:\n" << LTR_regular.t() << std::endl;
872  res = equalMatrix(LTR, LTR_regular, 1e-9);
873  std::cout << "Check result: " << res << std::endl;
874  if (!res) {
875  std::cerr << "Problem with dgemv!" << std::endl;
876  return EXIT_FAILURE;
877  }
878 
879  vpVelocityTwistMatrix V(getRandomValues(min, max), getRandomValues(min, max), getRandomValues(min, max),
880  getRandomValues(min, max), getRandomValues(min, max), getRandomValues(min, max));
881  vpMatrix LV, LV_regular;
882 
883  t = vpTime::measureTimeMs();
884  for (int i = 0; i < nb_iterations; i++)
885  LV = L * V;
886  t = vpTime::measureTimeMs() - t;
887  std::cout << "\n"
888  << nb_iterations
889  << " iterations of matrix velocity twist matrix "
890  "multiplication: (1000x6) x (6x6)"
891  << std::endl;
892  std::cout << "Lapack: " << t << " ms" << std::endl;
893 
894  t = vpTime::measureTimeMs();
895  for (int i = 0; i < nb_iterations; i++)
896  LV_regular = mat_mul_twist_matrix(L, V);
897  t = vpTime::measureTimeMs() - t;
898  std::cout << "Regular: " << t << " ms" << std::endl;
899  res = equalMatrix(LV, LV_regular, 1e-9);
900  std::cout << "Check result: " << res << std::endl;
901  if (!res) {
902  std::cerr << "Problem with matrix and velocity twist matrix multiplication!" << std::endl;
903  return EXIT_FAILURE;
904  }
905  }
906 #endif
907 
908 #ifdef VISP_HAVE_CPP11_COMPATIBILITY
909  {
910  std::vector<vpMatrix> vec_mat;
911  vec_mat.emplace_back(5, 5);
912 
913  vpMatrix A(4, 4), B(4, 4);
914  A = 1;
915  B = 2;
916  vpMatrix res = A + B;
917  std::cout << "\n1) A+B:\n" << res << std::endl;
918 
919  vpMatrix res2;
920  res2 = A + B;
921  std::cout << "\n2) A+B:\n" << res2 << std::endl;
922  }
923 #endif
924 
925  {
926  std::cout << "\n------------------------" << std::endl;
927  std::cout << "--- TEST vpMatrix::hadamard()" << std::endl;
928  std::cout << "------------------------" << std::endl;
929 
930  vpMatrix M1(3, 5), M2(3, 5);
931  for (unsigned int i = 0; i < M1.size(); i++) {
932  M1.data[i] = i;
933  M2.data[i] = i + 2;
934  }
935 
936  std::cout << "M1:\n" << M1 << std::endl;
937  std::cout << "\nM2:\n" << M2 << std::endl;
938  M2 = M1.hadamard(M2);
939  std::cout << "\nRes:\n" << M2 << std::endl;
940  }
941 
942  std::cout << "\nAll tests succeed" << std::endl;
943  return EXIT_SUCCESS;
944  } catch (const vpException &e) {
945  std::cout << "Catch an exception: " << e << std::endl;
946  return EXIT_FAILURE;
947  }
948 }
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:104
static vpMatrix juxtaposeMatrices(const vpMatrix &A, const vpMatrix &B)
Definition: vpMatrix.cpp:4114
static bool loadMatrix(const std::string &filename, vpArray2D< double > &M, const bool binary=false, char *header=NULL)
Definition: vpMatrix.h:618
Implementation of row vector and the associated operations.
Definition: vpRowVector.h:72
void resize(const unsigned int nrows, const unsigned int ncols, const bool flagNullify=true, const bool recopy_=true)
Definition: vpArray2D.h:171
static bool equal(double x, double y, double s=0.001)
Definition: vpMath.h:290
void stack(const vpMatrix &A)
Definition: vpMatrix.cpp:4462
error that can be emited by ViSP classes.
Definition: vpException.h:71
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:84
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:158
unsigned int getCols() const
Definition: vpArray2D.h:146
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:88
Implementation of a rotation matrix and operations on such kind of matrices.
vpRowVector getRow(const unsigned int i) const
Definition: vpMatrix.cpp:3844
void init(const vpMatrix &M, unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols)
Definition: vpMatrix.cpp:258
void insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
Definition: vpMatrix.cpp:4570
vpMatrix AtA() const
Definition: vpMatrix.cpp:524
vpColVector getCol(const unsigned int j) const
Definition: vpMatrix.cpp:3798
unsigned int getRows() const
Definition: vpArray2D.h:156
int print(std::ostream &s, unsigned int length, char const *intro=0) const
Definition: vpMatrix.cpp:4181
static double rad(double deg)
Definition: vpMath.h:102
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpRowVector.h:213
void vpGEMM(const vpArray2D< double > &A, const vpArray2D< double > &B, const double &alpha, const vpArray2D< double > &C, const double &beta, vpArray2D< double > &D, const unsigned int &ops=0)
Definition: vpGEMM.h:393
vpMatrix t() const
Definition: vpMatrix.cpp:375
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
int print(std::ostream &s, unsigned int length, char const *intro=0) const
static bool saveMatrixYAML(const std::string &filename, const vpArray2D< double > &M, const char *header="")
Definition: vpMatrix.h:671
static bool saveMatrix(const std::string &filename, const vpArray2D< double > &M, const bool binary=false, const char *header="")
Definition: vpMatrix.h:653
Type getMaxValue() const
Definition: vpArray2D.h:694
Type getMinValue() const
Definition: vpArray2D.h:677
void eye()
Definition: vpMatrix.cpp:360
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:244
static bool loadMatrixYAML(const std::string &filename, vpArray2D< double > &M, char *header=NULL)
Definition: vpMatrix.h:634
vpMatrix hadamard(const vpMatrix &m) const
Definition: vpMatrix.cpp:1513