Visual Servoing Platform  version 3.4.1 under development (2021-10-17)
testMatrixInverse.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 various inversions.
33  *
34  * Authors:
35  * Fabien Spindler
36  *
37  *****************************************************************************/
38 
44 #include <cmath>
45 #include <fstream>
46 #include <iostream>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <vector>
50 
51 #include <visp3/core/vpColVector.h>
52 #include <visp3/core/vpMatrix.h>
53 #include <visp3/core/vpTime.h>
54 #include <visp3/io/vpParseArgv.h>
55 
56 // List of allowed command line options
57 #define GETOPTARGS "cdn:i:pf:R:C:vh"
58 
67 void usage(const char *name, const char *badparam)
68 {
69  fprintf(stdout, "\n\
70 Test matrix inversions\n\
71 using LU, QR and Cholesky methods as well as Pseudo-inverse.\n\
72 Outputs a comparison of these methods.\n\
73 \n\
74 SYNOPSIS\n\
75  %s [-n <number of matrices>] [-f <plot filename>]\n\
76  [-R <number of rows>] [-C <number of columns>]\n\
77  [-i <number of iterations>] [-p] [-h]\n", name);
78 
79  fprintf(stdout, "\n\
80 OPTIONS: Default\n\
81  -n <number of matrices> \n\
82  Number of matrices inverted during each test loop.\n\
83 \n\
84  -i <number of iterations> \n\
85  Number of iterations of the test.\n\
86 \n\
87  -f <plot filename> \n\
88  Set output path for plot output.\n\
89  The plot logs the times of \n\
90  the different inversion methods: \n\
91  QR,LU,Cholesky and Pseudo-inverse.\n\
92 \n\
93  -R <number of rows>\n\
94  Number of rows of the automatically generated matrices \n\
95  we test on.\n\
96 \n\
97  -C <number of columns>\n\
98  Number of colums of the automatically generated matrices \n\
99  we test on.\n\
100 \n\
101  -p \n\
102  Plot into filename in the gnuplot format. \n\
103  If this option is used, tests results will be logged \n\
104  into a filename specified with -f.\n\
105 \n\
106  -h\n\
107  Print the help.\n\n");
108 
109  if (badparam) {
110  fprintf(stderr, "ERROR: \n");
111  fprintf(stderr, "\nBad parameter [%s]\n", badparam);
112  }
113 }
114 
122 bool getOptions(int argc, const char **argv, unsigned int &nb_matrices, unsigned int &nb_iterations,
123  bool &use_plot_file, std::string &plotfile, unsigned int &nbrows, unsigned int &nbcols, bool &verbose)
124 {
125  const char *optarg_;
126  int c;
127  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
128 
129  switch (c) {
130  case 'h':
131  usage(argv[0], NULL);
132  return false;
133  break;
134  case 'n':
135  nb_matrices = (unsigned int)atoi(optarg_);
136  break;
137  case 'i':
138  nb_iterations = (unsigned int)atoi(optarg_);
139  break;
140  case 'f':
141  plotfile = optarg_;
142  use_plot_file = true;
143  break;
144  case 'p':
145  use_plot_file = true;
146  break;
147  case 'R':
148  nbrows = (unsigned int)atoi(optarg_);
149  break;
150  case 'C':
151  nbcols = (unsigned int)atoi(optarg_);
152  break;
153  case 'v':
154  verbose = true;
155  break;
156  // add default options -c -d
157  case 'c':
158  break;
159  case 'd':
160  break;
161  default:
162  usage(argv[0], optarg_);
163  return false;
164  break;
165  }
166  }
167 
168  if ((c == 1) || (c == -1)) {
169  // standalone param or error
170  usage(argv[0], NULL);
171  std::cerr << "ERROR: " << std::endl;
172  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
173  return false;
174  }
175 
176  return true;
177 }
178 
179 vpMatrix make_random_matrix(unsigned int nbrows, unsigned int nbcols)
180 {
181  vpMatrix A;
182  A.resize(nbrows, nbcols);
183 
184  for (unsigned int i = 0; i < A.getRows(); i++)
185  for (unsigned int j = 0; j < A.getCols(); j++)
186  A[i][j] = (double)rand() / (double)RAND_MAX;
187  return A;
188 }
189 
190 vpMatrix make_random_symmetric_positive_matrix(unsigned int n)
191 {
192  vpMatrix A;
193  A.resize(n, n);
194  vpMatrix I;
195  I.eye(n);
196 
197  for (unsigned int i = 0; i < A.getRows(); i++)
198  for (unsigned int j = 0; j < A.getCols(); j++)
199  A[i][j] = (double)rand() / (double)RAND_MAX;
200 
201  A = 0.5 * (A + A.t());
202  A = A + n * I;
203  return A;
204 }
205 
206 vpMatrix make_random_triangular_matrix(unsigned int nbrows)
207 {
208  vpMatrix A;
209  A.resize(nbrows, nbrows);
210 
211  for(unsigned int i=0; i < A.getRows(); i++) {
212  for(unsigned int j=i; j<A.getCols(); j++) {
213  A[i][j] = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
214  if (i != j) {
215  A[j][i] = 0;
216  }
217  }
218  }
219 
220  return A;
221 }
222 
223 void create_bench_random_matrix(unsigned int nb_matrices, unsigned int nb_rows, unsigned int nb_cols, bool verbose,
224  std::vector<vpMatrix> &bench)
225 {
226  if (verbose)
227  std::cout << "Create a bench of " << nb_matrices << " " << nb_rows << " by " << nb_cols << " matrices" << std::endl;
228  bench.clear();
229  for (unsigned int i = 0; i < nb_matrices; i++) {
230  vpMatrix M;
231 #if defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_LAPACK) || (VISP_HAVE_OPENCV_VERSION >= 0x020101)
232  double det = 0.;
233  // don't put singular matrices in the benchmark
234  for (M = make_random_matrix(nb_rows, nb_cols); std::fabs(det = M.AtA().det()) < .01;
235  M = make_random_matrix(nb_rows, nb_cols)) {
236  if (verbose) {
237  std::cout << " Generated random matrix AtA=" << std::endl << M.AtA() << std::endl;
238  std::cout << " Generated random matrix not invertible: det=" << det << ". Retrying..." << std::endl;
239  }
240  }
241 #else
242  M = make_random_matrix(nb_rows, nb_cols);
243 #endif
244  bench.push_back(M);
245  }
246 }
247 
248 void create_bench_symmetric_positive_matrix(unsigned int nb_matrices, unsigned int n, bool verbose,
249  std::vector<vpMatrix> &bench)
250 {
251  if (verbose)
252  std::cout << "Create a bench of " << nb_matrices << " " << n << " by " << n << " symmetric positive matrices"
253  << std::endl;
254  bench.clear();
255  for (unsigned int i = 0; i < nb_matrices; i++) {
256  vpMatrix M;
257 #if defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_LAPACK) || (VISP_HAVE_OPENCV_VERSION >= 0x020101)
258  double det = 0.;
259  // don't put singular matrices in the benchmark
260  for (M = make_random_symmetric_positive_matrix(n); std::fabs(det = M.det()) < .01;
261  M = make_random_symmetric_positive_matrix(n)) {
262  if (verbose) {
263  std::cout << " Generated random symmetric positive matrix A=" << std::endl << M << std::endl;
264  std::cout << " Generated random symmetric positive matrix not "
265  "invertibleL: det="
266  << det << ". Retrying..." << std::endl;
267  }
268  }
269 #else
270  M = make_random_symmetric_positive_matrix(n);
271 #endif
272  bench.push_back(M);
273  }
274 }
275 
276 void create_bench_random_triangular_matrix(unsigned int nb_matrices, unsigned int n, bool verbose,
277  std::vector<vpMatrix> &bench)
278 {
279  if (verbose)
280  std::cout << "Create a bench of " << nb_matrices << " " << n << " by " << n << " triangular matrices" << std::endl;
281  bench.clear();
282  for (unsigned int i = 0; i < nb_matrices; i++) {
283  vpMatrix M;
284 #if defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_LAPACK) || (VISP_HAVE_OPENCV_VERSION >= 0x020101)
285  double det = 0.;
286  // don't put singular matrices in the benchmark
287  for (M = make_random_triangular_matrix(n); std::fabs(det = M.det()) < .01;
288  M = make_random_triangular_matrix(n)) {
289  if (verbose) {
290  std::cout << " Generated random symmetric positive matrix A=" << std::endl << M << std::endl;
291  std::cout << " Generated random symmetric positive matrix not "
292  "invertibleL: det="
293  << det << ". Retrying..." << std::endl;
294  }
295  }
296 #else
297  M = make_random_triangular_matrix(n);
298 #endif
299  bench.push_back(M);
300  }
301 }
302 
303 int test_inverse(const std::vector<vpMatrix> &bench, const std::vector<vpMatrix> &result)
304 {
305  double epsilon = 1e-10;
306  for (unsigned int i = 0; i < bench.size(); i++) {
307  vpMatrix I = bench[i] * result[i];
308  if (std::fabs(I.frobeniusNorm() - sqrt(static_cast<double>(bench[0].AtA().getRows()))) > epsilon) {
309  std::cout << "Bad inverse[" << i << "]: " << I.frobeniusNorm() << " " << sqrt((double)bench[0].AtA().getRows())
310  << std::endl;
311  return EXIT_FAILURE;
312  }
313  }
314  return EXIT_SUCCESS;
315 }
316 
317 int test_inverse_lu_small(bool verbose, const std::vector<vpMatrix> &bench, double &time)
318 {
319  if (verbose)
320  std::cout << "Test inverse by LU on small matrices" << std::endl;
321  // Compute inverse
322  if (verbose)
323  std::cout << " Inverting " << bench[0].getRows() << "x" << bench[0].getCols()
324  << " small matrix." << std::endl;
325  std::vector<vpMatrix> result(bench.size());
326  double t = vpTime::measureTimeMs();
327  for (unsigned int i = 0; i < bench.size(); i++) {
328  result[i] = bench[i].inverseByLU();
329  }
330  time = vpTime::measureTimeMs() - t;
331 
332  // Test inverse
333  return test_inverse(bench, result);
334 }
335 
336 #if defined(VISP_HAVE_EIGEN3)
337 int test_inverse_lu_eigen3(bool verbose, const std::vector<vpMatrix> &bench, double &time)
338 {
339  if (verbose)
340  std::cout << "Test inverse by LU using Eigen3 3rd party" << std::endl;
341  // Compute inverse
342  if (verbose)
343  std::cout << " Inverting " << bench[0].AtA().getRows() << "x" << bench[0].AtA().getCols()
344  << " matrix using LU decomposition (Eigen3)." << std::endl;
345  std::vector<vpMatrix> result(bench.size());
346  double t = vpTime::measureTimeMs();
347  for (unsigned int i = 0; i < bench.size(); i++) {
348  result[i] = bench[i].AtA().inverseByLUEigen3() * bench[i].transpose();
349  }
350  time = vpTime::measureTimeMs() - t;
351 
352  // Test inverse
353  return test_inverse(bench, result);
354 }
355 #endif
356 
357 #if defined(VISP_HAVE_LAPACK)
358 int test_inverse_lu_lapack(bool verbose, const std::vector<vpMatrix> &bench, double &time)
359 {
360  if (verbose)
361  std::cout << "Test inverse by LU using Lapack 3rd party" << std::endl;
362  // Compute inverse
363  if (verbose)
364  std::cout << " Inverting " << bench[0].AtA().getRows() << "x" << bench[0].AtA().getCols()
365  << " matrix using LU decomposition (Lapack)." << std::endl;
366  std::vector<vpMatrix> result(bench.size());
367  double t = vpTime::measureTimeMs();
368  for (unsigned int i = 0; i < bench.size(); i++) {
369  result[i] = bench[i].AtA().inverseByLULapack() * bench[i].transpose();
370  }
371  time = vpTime::measureTimeMs() - t;
372 
373  // Test inverse
374  return test_inverse(bench, result);
375 }
376 
377 int test_inverse_cholesky_lapack(bool verbose, const std::vector<vpMatrix> &bench, double &time)
378 {
379  if (verbose)
380  std::cout << "Test inverse by Cholesky using Lapack 3rd party" << std::endl;
381  // Compute inverse
382  if (verbose)
383  std::cout << " Inverting " << bench[0].AtA().getRows() << "x" << bench[0].AtA().getCols()
384  << " matrix using cholesky decomposition (Lapack)." << std::endl;
385  std::vector<vpMatrix> result(bench.size());
386  double t = vpTime::measureTimeMs();
387  for (unsigned int i = 0; i < bench.size(); i++) {
388  result[i] = bench[i].AtA().inverseByCholeskyLapack() * bench[i].transpose();
389  }
390  time = vpTime::measureTimeMs() - t;
391 
392  // Test inverse
393  return test_inverse(bench, result);
394 }
395 
396 int test_inverse_qr_lapack(bool verbose, const std::vector<vpMatrix> &bench, double &time)
397 {
398  if (verbose)
399  std::cout << "Test inverse by QR using Lapack 3rd party" << std::endl;
400  // Compute inverse
401  if (verbose)
402  std::cout << " Inverting " << bench[0].AtA().getRows() << "x" << bench[0].AtA().getCols()
403  << " matrix using QR decomposition (Lapack)" << std::endl;
404  std::vector<vpMatrix> result(bench.size());
405  double t = vpTime::measureTimeMs();
406  for (unsigned int i = 0; i < bench.size(); i++) {
407  result[i] = bench[i].AtA().inverseByQRLapack() * bench[i].transpose();
408  }
409  time = vpTime::measureTimeMs() - t;
410 
411  // Test inverse
412  return test_inverse(bench, result);
413 }
414 #endif
415 
416 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
417 int test_inverse_lu_opencv(bool verbose, const std::vector<vpMatrix> &bench, double &time)
418 {
419  if (verbose)
420  std::cout << "Test inverse by LU using OpenCV 3rd party" << std::endl;
421  // Compute inverse
422  if (verbose)
423  std::cout << " Inverting " << bench[0].AtA().getRows() << "x" << bench[0].AtA().getCols()
424  << " matrix using LU decomposition (OpenCV)" << std::endl;
425  std::vector<vpMatrix> result(bench.size());
426  double t = vpTime::measureTimeMs();
427  for (unsigned int i = 0; i < bench.size(); i++) {
428  result[i] = bench[i].AtA().inverseByLUOpenCV() * bench[i].transpose();
429  }
430  time = vpTime::measureTimeMs() - t;
431 
432  // Test inverse
433  return test_inverse(bench, result);
434 }
435 
436 int test_inverse_cholesky_opencv(bool verbose, const std::vector<vpMatrix> &bench, double &time)
437 {
438  if (verbose)
439  std::cout << "Test inverse by Cholesky using OpenCV 3rd party" << std::endl;
440  // Compute inverse
441  if (verbose)
442  std::cout << " Inverting " << bench[0].AtA().getRows() << "x" << bench[0].AtA().getCols()
443  << " matrix using Cholesky decomposition (OpenCV)" << std::endl;
444  std::vector<vpMatrix> result(bench.size());
445  double t = vpTime::measureTimeMs();
446  for (unsigned int i = 0; i < bench.size(); i++) {
447  result[i] = bench[i].AtA().inverseByCholeskyOpenCV() * bench[i].transpose();
448  }
449  time = vpTime::measureTimeMs() - t;
450 
451  // Test inverse
452  return test_inverse(bench, result);
453 }
454 #endif
455 
456 #if defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || (VISP_HAVE_OPENCV_VERSION >= 0x020101)
457 // SVD is only available for these 3rd parties
458 int test_pseudo_inverse(bool verbose, const std::vector<vpMatrix> &bench, double &time)
459 {
460  if (verbose)
461  std::cout << "Test pseudo inverse using either Lapack, Eigen3 or OpenCV 3rd party"
462  << std::endl;
463  // Compute inverse
464  if (verbose)
465  std::cout << " Pseudo inverting " << bench[0].AtA().getRows() << "x" << bench[0].AtA().getCols() << " matrix"
466  << std::endl;
467  std::vector<vpMatrix> result(bench.size());
468  double t = vpTime::measureTimeMs();
469  for (unsigned int i = 0; i < bench.size(); i++) {
470  result[i] = bench[i].AtA().pseudoInverse() * bench[i].transpose();
471  }
472  time = vpTime::measureTimeMs() - t;
473 
474  // Test inverse
475  return test_inverse(bench, result);
476 }
477 
478 int test_inverse_triangular(bool verbose, const std::vector<vpMatrix> &bench, double &time)
479 {
480  if (verbose)
481  std::cout << "Test inverse triangular using Lapack" << std::endl;
482  // Compute inverse
483  if (verbose)
484  std::cout << " Triangular inverse " << bench[0].getRows() << "x" << bench[0].getCols() << " matrix"
485  << std::endl;
486  std::vector<vpMatrix> result(bench.size());
487  double t = vpTime::measureTimeMs();
488  for (unsigned int i = 0; i < bench.size(); i++) {
489  result[i] = bench[i].inverseTriangular(true);
490  }
491  time = vpTime::measureTimeMs() - t;
492 
493  // Test inverse
494  return test_inverse(bench, result);
495 }
496 #endif
497 
498 void save_time(const std::string &method, bool verbose, bool use_plot_file, std::ofstream &of, double time)
499 {
500  if (use_plot_file)
501  of << time << "\t";
502  if (verbose || !use_plot_file) {
503  std::cout << method << time << std::endl;
504  }
505 }
506 
507 int main(int argc, const char *argv[])
508 {
509  try {
510  unsigned int nb_matrices = 1000;
511  unsigned int nb_iterations = 10;
512  unsigned int nb_rows = 6;
513  unsigned int nb_cols = 6;
514  bool verbose = false;
515  std::string plotfile("plot-inv.csv");
516  bool use_plot_file = false;
517  std::ofstream of;
518 
519  // Read the command line options
520  if (getOptions(argc, argv, nb_matrices, nb_iterations, use_plot_file, plotfile, nb_rows, nb_cols, verbose) ==
521  false) {
522  exit(-1);
523  }
524 
525  if (use_plot_file) {
526  of.open(plotfile.c_str());
527  of << "iter"
528  << "\t";
529 
530 #if defined(VISP_HAVE_LAPACK)
531  of << "\"LU Lapack\""
532  << "\t";
533 #endif
534 #if defined(VISP_HAVE_EIGEN3)
535  of << "\"LU Eigen3\""
536  << "\t";
537 #endif
538 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
539  of << "\"LU OpenCV\""
540  << "\t";
541 #endif
542 
543 #if defined(VISP_HAVE_LAPACK)
544  of << "\"Cholesky Lapack\""
545  << "\t";
546 #endif
547 
548 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
549  of << "\"Cholesky OpenCV\""
550  << "\t";
551 #endif
552 
553 #if defined(VISP_HAVE_LAPACK)
554  of << "\"QR Lapack\""
555  << "\t";
556 #endif
557 
558 #if defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || (VISP_HAVE_OPENCV_VERSION >= 0x020101)
559  of << "\"Pseudo inverse (Lapack, Eigen3 or OpenCV)\""
560  << "\t";
561 #endif
562  of << std::endl;
563  }
564 
565  int ret = EXIT_SUCCESS;
566  for (unsigned int iter = 0; iter < nb_iterations; iter++) {
567  std::vector<vpMatrix> bench_random_matrices_11;
568  create_bench_random_matrix(nb_matrices, 1, 1, verbose, bench_random_matrices_11);
569  std::vector<vpMatrix> bench_random_matrices_22;
570  create_bench_random_matrix(nb_matrices, 2, 2, verbose, bench_random_matrices_22);
571  std::vector<vpMatrix> bench_random_matrices_33;
572  create_bench_random_matrix(nb_matrices, 3, 3, verbose, bench_random_matrices_33);
573 #if defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_LAPACK) || (VISP_HAVE_OPENCV_VERSION >= 0x020101)
574  std::vector<vpMatrix> bench_random_matrices;
575  create_bench_random_matrix(nb_matrices, nb_rows, nb_cols, verbose, bench_random_matrices);
576  std::vector<vpMatrix> bench_symmetric_positive_matrices;
577  create_bench_symmetric_positive_matrix(nb_matrices, nb_rows, verbose, bench_symmetric_positive_matrices);
578  std::vector<vpMatrix> bench_triangular_matrices;
579  create_bench_random_triangular_matrix(nb_matrices, nb_rows, verbose, bench_triangular_matrices);
580 #endif
581 
582  if (use_plot_file)
583  of << iter << "\t";
584 
585  double time;
586 
587  // LU inverse on 1 by 1 matrices
588  ret += test_inverse_lu_small(verbose, bench_random_matrices_11, time);
589  save_time("Inverse by LU 1x1: ", verbose, use_plot_file, of, time);
590  // LU inverse on 2 by 2 matrices
591  ret += test_inverse_lu_small(verbose, bench_random_matrices_22, time);
592  save_time("Inverse by LU 2x2: ", verbose, use_plot_file, of, time);
593  // LU inverse on 3 by 3 matrices
594  ret += test_inverse_lu_small(verbose, bench_random_matrices_33, time);
595  save_time("Inverse by LU 3x3: ", verbose, use_plot_file, of, time);
596 
597  // LU decomposition
598 #if defined(VISP_HAVE_LAPACK)
599  ret += test_inverse_lu_lapack(verbose, bench_random_matrices, time);
600  save_time("Inverse by LU (Lapack): ", verbose, use_plot_file, of, time);
601 #endif
602 
603 #if defined(VISP_HAVE_EIGEN3)
604  ret += test_inverse_lu_eigen3(verbose, bench_random_matrices, time);
605  save_time("Inverse by LU (Eigen3): ", verbose, use_plot_file, of, time);
606 #endif
607 
608 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
609  ret += test_inverse_lu_opencv(verbose, bench_random_matrices, time);
610  save_time("Inverse by LU (OpenCV): ", verbose, use_plot_file, of, time);
611 #endif
612 
613  // Cholesky for symmetric positive matrices
614 #if defined(VISP_HAVE_LAPACK)
615  ret += test_inverse_cholesky_lapack(verbose, bench_symmetric_positive_matrices, time);
616  save_time("Inverse by Cholesly (Lapack): ", verbose, use_plot_file, of, time);
617 #endif
618 
619 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
620  ret += test_inverse_cholesky_opencv(verbose, bench_symmetric_positive_matrices, time);
621  save_time("Inverse by Cholesky (OpenCV): ", verbose, use_plot_file, of, time);
622 #endif
623 
624  // QR decomposition
625 #if defined(VISP_HAVE_LAPACK)
626  ret += test_inverse_qr_lapack(verbose, bench_random_matrices, time);
627  save_time("Inverse by QR (Lapack): ", verbose, use_plot_file, of, time);
628 #endif
629 
630  // Pseudo-inverse with SVD
631 #if defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || (VISP_HAVE_OPENCV_VERSION >= 0x020101)
632  ret += test_pseudo_inverse(verbose, bench_random_matrices, time);
633  save_time("Pseudo inverse (Lapack, Eigen3, OpenCV): ", verbose, use_plot_file, of, time);
634 #endif
635 
636  // Test inverse triangular
637 #if defined(VISP_HAVE_LAPACK)
638  ret += test_inverse_triangular(verbose, bench_triangular_matrices, time);
639  save_time("Triangular inverse (Lapack): ", verbose, use_plot_file, of, time);
640 #endif
641 
642  if (use_plot_file)
643  of << std::endl;
644  }
645  if (use_plot_file) {
646  of.close();
647  std::cout << "Result saved in " << plotfile << std::endl;
648  }
649 
650  if (ret == EXIT_SUCCESS) {
651  std::cout << "Test succeed" << std::endl;
652  } else {
653  std::cout << "Test failed" << std::endl;
654  }
655 
656  return ret;
657  } catch (const vpException &e) {
658  std::cout << "Catch an exception: " << e.getStringMessage() << std::endl;
659  return EXIT_FAILURE;
660  }
661 }
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:153
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition: vpArray2D.h:304
double det(vpDetMethod method=LU_DECOMPOSITION) const
Definition: vpMatrix.cpp:6477
vpMatrix AtA() const
Definition: vpMatrix.cpp:629
error that can be emited by ViSP classes.
Definition: vpException.h:71
unsigned int getRows() const
Definition: vpArray2D.h:289
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:126
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
unsigned int getCols() const
Definition: vpArray2D.h:279
vpMatrix t() const
Definition: vpMatrix.cpp:464
const std::string & getStringMessage() const
Send a reference (constant) related the error message (can be empty).
Definition: vpException.cpp:92
double frobeniusNorm() const
Definition: vpMatrix.cpp:6704
void eye()
Definition: vpMatrix.cpp:449