46#include <visp3/core/vpColVector.h>
47#include <visp3/core/vpMatrix.h>
48#include <visp3/core/vpTime.h>
49#include <visp3/io/vpParseArgv.h>
52#define GETOPTARGS "cdn:i:pf:R:C:vh"
62void usage(
const char *name,
const char *badparam)
65Test matrix inversions\n\
66using LU, QR and Cholesky methods as well as Pseudo-inverse.\n\
67Outputs a comparison of these methods.\n\
70 %s [-n <number of matrices>] [-f <plot filename>]\n\
71 [-R <number of rows>] [-C <number of columns>]\n\
72 [-i <number of iterations>] [-p] [-h]\n",
77 -n <number of matrices> \n\
78 Number of matrices inverted during each test loop.\n\
80 -i <number of iterations> \n\
81 Number of iterations of the test.\n\
83 -f <plot filename> \n\
84 Set output path for plot output.\n\
85 The plot logs the times of \n\
86 the different inversion methods: \n\
87 QR,LU,Cholesky and Pseudo-inverse.\n\
89 -R <number of rows>\n\
90 Number of rows of the automatically generated matrices \n\
93 -C <number of columns>\n\
94 Number of colums of the automatically generated matrices \n\
98 Plot into filename in the gnuplot format. \n\
99 If this option is used, tests results will be logged \n\
100 into a filename specified with -f.\n\
103 Print the help.\n\n");
106 fprintf(stderr,
"ERROR: \n");
107 fprintf(stderr,
"\nBad parameter [%s]\n", badparam);
118bool getOptions(
int argc,
const char **argv,
unsigned int &nb_matrices,
unsigned int &nb_iterations,
119 bool &use_plot_file, std::string &plotfile,
unsigned int &nbrows,
unsigned int &nbcols,
bool &verbose)
127 usage(argv[0], NULL);
131 nb_matrices = (
unsigned int)atoi(optarg_);
134 nb_iterations = (
unsigned int)atoi(optarg_);
138 use_plot_file =
true;
141 use_plot_file =
true;
144 nbrows = (
unsigned int)atoi(optarg_);
147 nbcols = (
unsigned int)atoi(optarg_);
158 usage(argv[0], optarg_);
164 if ((c == 1) || (c == -1)) {
166 usage(argv[0], NULL);
167 std::cerr <<
"ERROR: " << std::endl;
168 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
175vpMatrix make_random_matrix(
unsigned int nbrows,
unsigned int nbcols)
180 for (
unsigned int i = 0; i < A.
getRows(); i++) {
181 for (
unsigned int j = 0; j < A.
getCols(); j++) {
182 A[i][j] =
static_cast<double>(rand()) /
static_cast<double>(RAND_MAX);
189vpMatrix make_random_symmetric_matrix(
unsigned int nbrows)
194 for (
unsigned int i = 0; i < A.
getRows(); i++) {
195 for (
unsigned int j = i; j < A.
getCols(); j++) {
196 A[i][j] =
static_cast<double>(rand()) /
static_cast<double>(RAND_MAX);
206void create_bench_random_matrix(
unsigned int nb_matrices,
unsigned int nb_rows,
unsigned int nb_cols,
bool verbose,
207 std::vector<vpMatrix> &bench)
210 std::cout <<
"Create a bench of " << nb_matrices <<
" " << nb_rows <<
" by " << nb_cols <<
" matrices" << std::endl;
212 for (
unsigned int i = 0; i < nb_matrices; i++) {
228 M = make_random_matrix(nb_rows, nb_cols);
234void create_bench_random_symmetric_matrix(
unsigned int nb_matrices,
unsigned int nb_rows,
bool verbose,
235 std::vector<vpMatrix> &bench)
238 std::cout <<
"Create a bench of " << nb_matrices <<
" " << nb_rows <<
" by " << nb_rows <<
" symmetric matrices"
241 for (
unsigned int i = 0; i < nb_matrices; i++) {
257 M = make_random_symmetric_matrix(nb_rows);
263int test_svd(std::vector<vpMatrix> M, std::vector<vpMatrix> U, std::vector<vpColVector> s, std::vector<vpMatrix> V)
265 for (
unsigned int i = 0; i < M.size(); i++) {
270 if (D.frobeniusNorm() > 1e-6) {
271 std::cout <<
"SVD decomposition failed" << std::endl;
278int test_eigen_values(std::vector<vpMatrix> M, std::vector<vpColVector> e, std::vector<vpMatrix> V,
279 std::vector<vpColVector> e2)
281 for (
unsigned int i = 0; i < M.size(); i++) {
284 std::cout <<
"Eigen values differ" << std::endl;
289 vpMatrix MV_VD = M[i] * V[i] - V[i] * D;
291 std::cout <<
"Eigen values/vector decomposition failed" << std::endl;
298#if defined(VISP_HAVE_EIGEN3)
299int test_svd_eigen3(
bool verbose,
const std::vector<vpMatrix> &bench,
double &time)
302 std::cout <<
"Test SVD using Eigen3 3rd party" << std::endl;
305 std::cout <<
" SVD on a " << bench[0].getRows() <<
"x" << bench[0].getCols() <<
" matrix" << std::endl;
307 std::vector<vpMatrix> U = bench;
308 std::vector<vpMatrix> V(bench.size());
309 std::vector<vpColVector> s(bench.size());
312 for (
unsigned int i = 0; i < bench.size(); i++) {
313 U[i].svdEigen3(s[i], V[i]);
318 return test_svd(bench, U, s, V);
322#if defined(VISP_HAVE_LAPACK)
323int test_svd_lapack(
bool verbose,
const std::vector<vpMatrix> &bench,
double &time)
326 std::cout <<
"Test SVD using Lapack 3rd party" << std::endl;
329 std::cout <<
" SVD on a " << bench[0].getRows() <<
"x" << bench[0].getCols() <<
" matrix" << std::endl;
331 std::vector<vpMatrix> U = bench;
332 std::vector<vpMatrix> V(bench.size());
333 std::vector<vpColVector> s(bench.size());
336 for (
unsigned int i = 0; i < bench.size(); i++) {
337 U[i].svdLapack(s[i], V[i]);
341 return test_svd(bench, U, s, V);
344int test_eigen_values_lapack(
bool verbose,
const std::vector<vpMatrix> &bench,
double &time)
347 std::cout <<
"Test eigenValues() using Lapack 3rd party" << std::endl;
349 std::vector<vpColVector> e(bench.size());
350 std::vector<vpColVector> e2(bench.size());
351 std::vector<vpMatrix> V(bench.size());
353 for (
unsigned int i = 0; i < bench.size(); i++) {
354 e2[i] = bench[i].eigenValues();
359 for (
unsigned int i = 0; i < bench.size(); i++) {
360 bench[i].eigenValues(e[i], V[i]);
364 return test_eigen_values(bench, e, V, e2);
368#if defined(VISP_HAVE_OPENCV)
369int test_svd_opencv(
bool verbose,
const std::vector<vpMatrix> &bench,
double &time)
372 std::cout <<
"Test SVD using OpenCV 3rd party" << std::endl;
375 std::cout <<
" SVD on a " << bench[0].getRows() <<
"x" << bench[0].getCols() <<
" matrix" << std::endl;
377 std::vector<vpMatrix> U = bench;
378 std::vector<vpMatrix> V(bench.size());
379 std::vector<vpColVector> s(bench.size());
382 for (
unsigned int i = 0; i < bench.size(); i++) {
383 U[i].svdOpenCV(s[i], V[i]);
387 return test_svd(bench, U, s, V);
391void save_time(
const std::string &method,
bool verbose,
bool use_plot_file, std::ofstream &of,
double time)
395 if (verbose || !use_plot_file) {
396 std::cout << method << time << std::endl;
400int main(
int argc,
const char *argv[])
403#if defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_OPENCV)
404 unsigned int nb_matrices = 100;
405 unsigned int nb_iterations = 10;
406 unsigned int nb_rows = 6;
407 unsigned int nb_cols = 6;
408 unsigned int nb_rows_sym = 5;
409 bool verbose =
false;
410 std::string plotfile(
"plot-svd.csv");
411 bool use_plot_file =
false;
415 if (getOptions(argc, argv, nb_matrices, nb_iterations, use_plot_file, plotfile, nb_rows, nb_cols, verbose) ==
421 of.open(plotfile.c_str());
425#if defined(VISP_HAVE_LAPACK)
426 of <<
"\"SVD Lapack\""
429#if defined(VISP_HAVE_EIGEN3)
430 of <<
"\"SVD Eigen3\""
433#if defined(VISP_HAVE_OPENCV)
434 of <<
"\"SVD OpenCV\""
440 int ret = EXIT_SUCCESS;
441 for (
unsigned int iter = 0; iter < nb_iterations; iter++) {
442 std::vector<vpMatrix> bench_random_matrices;
443 create_bench_random_matrix(nb_matrices, nb_rows, nb_cols, verbose, bench_random_matrices);
444 std::vector<vpMatrix> bench_random_symmetric_matrices;
445 create_bench_random_symmetric_matrix(nb_matrices, nb_rows_sym, verbose, bench_random_symmetric_matrices);
451#if defined(VISP_HAVE_LAPACK)
452 ret += test_svd_lapack(verbose, bench_random_matrices, time);
453 save_time(
"SVD (Lapack): ", verbose, use_plot_file, of, time);
456#if defined(VISP_HAVE_EIGEN3)
457 ret += test_svd_eigen3(verbose, bench_random_matrices, time);
458 save_time(
"SVD (Eigen3): ", verbose, use_plot_file, of, time);
461#if defined(VISP_HAVE_OPENCV)
462 ret += test_svd_opencv(verbose, bench_random_matrices, time);
463 save_time(
"SVD (OpenCV): ", verbose, use_plot_file, of, time);
466#if defined(VISP_HAVE_LAPACK)
467 ret += test_eigen_values_lapack(verbose, bench_random_symmetric_matrices, time);
468 save_time(
"Eigen values (Lapack): ", verbose, use_plot_file, of, time);
476 std::cout <<
"Result saved in " << plotfile << std::endl;
479 if (ret == EXIT_SUCCESS) {
480 std::cout <<
"Test succeed" << std::endl;
482 std::cout <<
"Test failed" << std::endl;
489 std::cout <<
"Test does nothing since you dont't have Lapack, Eigen3 or OpenCV 3rd party" << std::endl;
unsigned int getCols() const
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
unsigned int getRows() const
Implementation of column vector and the associated operations.
double frobeniusNorm() const
error that can be emitted by ViSP classes.
const std::string & getStringMessage() const
Implementation of a matrix and operations on matrices.
void diag(const double &val=1.0)
double frobeniusNorm() const
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
VISP_EXPORT double measureTimeMs()