44 #include <visp3/core/vpColVector.h>
45 #include <visp3/core/vpMatrix.h>
46 #include <visp3/core/vpTime.h>
47 #include <visp3/io/vpParseArgv.h>
50 #define GETOPTARGS "cdn:i:pf:R:C:vh"
52 #ifdef ENABLE_VISP_NAMESPACE
64 void usage(
const char *name,
const char *badparam)
67 Test matrix pseudo-inverse.\n\
68 Outputs a comparison of the results obtained by supported 3rd parties.\n\
71 %s [-n <number of matrices>] [-f <plot filename>]\n\
72 [-R <number of rows>] [-C <number of columns>]\n\
73 [-i <number of iterations>] [-p] [-h]\n",
78 -n <number of matrices> \n\
79 Number of matrices inverted during each test loop.\n\
81 -i <number of iterations> \n\
82 Number of iterations of the test.\n\
84 -f <plot filename> \n\
85 Set output path for plot output.\n\
86 The plot logs the times of \n\
87 the different inversion methods: \n\
88 QR,LU,Cholesky and Pseudo-inverse.\n\
90 -R <number of rows>\n\
91 Number of rows of the automatically generated matrices \n\
94 -C <number of columns>\n\
95 Number of colums of the automatically generated matrices \n\
99 Plot into filename in the gnuplot format. \n\
100 If this option is used, tests results will be logged \n\
101 into a filename specified with -f.\n\
104 Print the help.\n\n");
107 fprintf(stderr,
"ERROR: \n");
108 fprintf(stderr,
"\nBad parameter [%s]\n", badparam);
119 bool getOptions(
int argc,
const char **argv,
unsigned int &nb_matrices,
unsigned int &nb_iterations,
120 bool &use_plot_file, std::string &plotfile,
unsigned int &nbrows,
unsigned int &nbcols,
bool &verbose)
128 usage(argv[0],
nullptr);
132 nb_matrices = (
unsigned int)atoi(optarg_);
135 nb_iterations = (
unsigned int)atoi(optarg_);
139 use_plot_file =
true;
142 use_plot_file =
true;
145 nbrows = (
unsigned int)atoi(optarg_);
148 nbcols = (
unsigned int)atoi(optarg_);
159 usage(argv[0], optarg_);
165 if ((c == 1) || (c == -1)) {
167 usage(argv[0],
nullptr);
168 std::cerr <<
"ERROR: " << std::endl;
169 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
176 vpMatrix make_random_matrix(
unsigned int nbrows,
unsigned int nbcols)
181 for (
unsigned int i = 0; i < A.
getRows(); i++) {
182 for (
unsigned int j = 0; j < A.
getCols(); j++) {
183 A[i][j] = (double)rand() / (double)RAND_MAX;
190 void create_bench_random_matrix(
unsigned int nb_matrices,
unsigned int nb_rows,
unsigned int nb_cols,
bool verbose,
191 std::vector<vpMatrix> &bench)
194 std::cout <<
"Create a bench of " << nb_matrices <<
" " << nb_rows <<
" by " << nb_cols <<
" matrices" << std::endl;
196 for (
unsigned int i = 0; i < nb_matrices; i++) {
197 vpMatrix M = make_random_matrix(nb_rows, nb_cols);
202 int test_pseudo_inverse(
const std::vector<vpMatrix> &A,
const std::vector<vpMatrix> &Api)
204 double allowed_error = 1e-3;
208 for (
unsigned int i = 0; i < A.size(); i++) {
209 error = (A[i] * Api[i] * A[i] - A[i]).frobeniusNorm();
210 if (error > allowed_error) {
211 std::cout <<
"Bad pseudo-inverse [" << i <<
"] test A A^+ A = A: euclidean norm: " << error << std::endl;
214 error = (Api[i] * A[i] * Api[i] - Api[i]).frobeniusNorm();
215 if (error > allowed_error) {
216 std::cout <<
"Bad pseudo-inverse [" << i <<
"] test A^+ A A^+ = A^+: euclidean norm: " << error << std::endl;
219 A_Api = A[i] * Api[i];
220 error = (A_Api.
transpose() - A_Api).frobeniusNorm();
221 if (error > allowed_error) {
222 std::cout <<
"Bad pseudo-inverse [" << i <<
"] test (A A^+)^T = A A^+: euclidean norm: " << error << std::endl;
225 Api_A = Api[i] * A[i];
226 error = (Api_A.
transpose() - Api_A).frobeniusNorm();
227 if (error > allowed_error) {
228 std::cout <<
"Bad pseudo-inverse [" << i <<
"] test (A^+ A )^T = A^+ A: euclidean norm: " << error << std::endl;
236 int test_pseudo_inverse(
const std::vector<vpMatrix> &A,
const std::vector<vpMatrix> &Api,
237 const std::vector<vpColVector> &sv,
const std::vector<vpMatrix> &imA,
238 const std::vector<vpMatrix> &imAt,
const std::vector<vpMatrix> &kerAt)
240 double allowed_error = 1e-3;
242 if (test_pseudo_inverse(A, Api) == EXIT_FAILURE) {
247 for (
unsigned int i = 0; i < kerAt.size(); i++) {
248 if (kerAt[i].size()) {
249 vpMatrix nullspace = A[i] * kerAt[i].
t();
251 if (error > allowed_error) {
252 std::cout <<
"Bad kernel [" << i <<
"]: euclidean norm: " << error << std::endl;
259 for (
unsigned int i = 0; i < kerAt.size(); i++) {
260 unsigned int rank = imA[i].getCols();
261 vpMatrix U, S(rank, A[i].getCols()), Vt(A[i].getCols(), A[i].getCols());
264 for (
unsigned int j = 0; j < rank; j++)
267 Vt.
insert(imAt[i].t(), 0, 0);
268 Vt.insert(kerAt[i], imAt[i].getCols(), 0);
270 double error = (U * S * Vt - A[i]).frobeniusNorm();
272 if (error > allowed_error) {
273 std::cout <<
"Bad imA, imAt, sv, kerAt [" << i <<
"]: euclidean norm: " << error << std::endl;
281 int test_pseudo_inverse_default(
bool verbose,
const std::vector<vpMatrix> &bench, std::vector<double> &time)
284 std::cout <<
"Test pseudo-inverse using default 3rd party" << std::endl;
286 std::cout <<
" Pseudo-inverse on a " << bench[0].getRows() <<
"x" << bench[0].getCols() <<
" matrix" << std::endl;
288 size_t size = bench.size();
289 std::vector<vpMatrix> PI(size), imA(size), imAt(size), kerAt(size);
290 std::vector<vpColVector> sv(size);
291 int ret = EXIT_SUCCESS;
296 for (
unsigned int i = 0; i < bench.size(); i++) {
297 PI[i] = bench[i].pseudoInverse();
300 for (
unsigned int i = 0; i < time.size(); i++) {
301 ret += test_pseudo_inverse(bench, PI);
306 for (
unsigned int i = 0; i < bench.size(); i++) {
307 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
308 unsigned int rank = bench[i].pseudoInverse(PI[i]);
309 if (rank != rank_bench) {
311 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
317 for (
unsigned int i = 0; i < time.size(); i++) {
318 ret += test_pseudo_inverse(bench, PI);
323 for (
unsigned int i = 0; i < bench.size(); i++) {
324 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
325 unsigned int rank = bench[i].pseudoInverse(PI[i], sv[i]);
326 if (rank != rank_bench) {
328 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
334 for (
unsigned int i = 0; i < time.size(); i++) {
335 ret += test_pseudo_inverse(bench, PI);
340 for (
unsigned int i = 0; i < bench.size(); i++) {
341 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
342 unsigned int rank = bench[i].pseudoInverse(PI[i], sv[i], 1e-6, imA[i], imAt[i]);
343 if (rank != rank_bench) {
345 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
351 for (
unsigned int i = 0; i < time.size(); i++) {
352 ret += test_pseudo_inverse(bench, PI);
357 for (
unsigned int i = 0; i < bench.size(); i++) {
358 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
359 unsigned int rank = bench[i].pseudoInverse(PI[i], sv[i], 1e-6, imA[i], imAt[i], kerAt[i]);
360 if (rank != rank_bench) {
362 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
368 for (
unsigned int i = 0; i < time.size(); i++) {
369 ret += test_pseudo_inverse(bench, PI, sv, imA, imAt, kerAt);
376 for (
unsigned int i = 0; i < bench.size(); i++) {
377 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
378 PI[i] = bench[i].pseudoInverse(
static_cast<int>(rank_bench));
381 for (
unsigned int i = 0; i < time.size(); i++) {
382 ret += test_pseudo_inverse(bench, PI);
387 for (
unsigned int i = 0; i < bench.size(); i++) {
388 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
389 unsigned int rank = bench[i].pseudoInverse(PI[i],
static_cast<int>(rank_bench));
390 if (rank != rank_bench) {
392 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
398 for (
unsigned int i = 0; i < time.size(); i++) {
399 ret += test_pseudo_inverse(bench, PI);
404 for (
unsigned int i = 0; i < bench.size(); i++) {
405 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
406 unsigned int rank = bench[i].pseudoInverse(PI[i], sv[i],
static_cast<int>(rank_bench));
407 if (rank != rank_bench) {
409 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
415 for (
unsigned int i = 0; i < time.size(); i++) {
416 ret += test_pseudo_inverse(bench, PI);
421 for (
unsigned int i = 0; i < bench.size(); i++) {
422 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
423 unsigned int rank = bench[i].pseudoInverse(PI[i], sv[i],
static_cast<int>(rank_bench), imA[i], imAt[i]);
424 if (rank != rank_bench) {
426 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
432 for (
unsigned int i = 0; i < time.size(); i++) {
433 ret += test_pseudo_inverse(bench, PI);
438 for (
unsigned int i = 0; i < bench.size(); i++) {
439 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
440 unsigned int rank = bench[i].pseudoInverse(PI[i], sv[i],
static_cast<int>(rank_bench), imA[i], imAt[i], kerAt[i]);
441 if (rank != rank_bench) {
443 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
449 for (
unsigned int i = 0; i < time.size(); i++) {
450 ret += test_pseudo_inverse(bench, PI, sv, imA, imAt, kerAt);
456 #if defined(VISP_HAVE_EIGEN3)
457 int test_pseudo_inverse_eigen3(
bool verbose,
const std::vector<vpMatrix> &bench, std::vector<double> &time)
460 std::cout <<
"Test pseudo-inverse using Eigen3 3rd party" << std::endl;
462 std::cout <<
" Pseudo-inverse on a " << bench[0].getRows() <<
"x" << bench[0].getCols() <<
" matrix" << std::endl;
464 size_t size = bench.size();
465 std::vector<vpMatrix> PI(size), imA(size), imAt(size), kerAt(size);
466 std::vector<vpColVector> sv(size);
467 int ret = EXIT_SUCCESS;
472 for (
unsigned int i = 0; i < bench.size(); i++) {
473 PI[i] = bench[i].pseudoInverseEigen3();
476 for (
unsigned int i = 0; i < time.size(); i++) {
477 ret += test_pseudo_inverse(bench, PI);
482 for (
unsigned int i = 0; i < bench.size(); i++) {
483 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
484 unsigned int rank = bench[i].pseudoInverseEigen3(PI[i]);
485 if (rank != rank_bench) {
487 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
493 for (
unsigned int i = 0; i < time.size(); i++) {
494 ret += test_pseudo_inverse(bench, PI);
499 for (
unsigned int i = 0; i < bench.size(); i++) {
500 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
501 unsigned int rank = bench[i].pseudoInverseEigen3(PI[i], sv[i]);
502 if (rank != rank_bench) {
504 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
510 for (
unsigned int i = 0; i < time.size(); i++) {
511 ret += test_pseudo_inverse(bench, PI);
516 for (
unsigned int i = 0; i < bench.size(); i++) {
517 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
518 unsigned int rank = bench[i].pseudoInverseEigen3(PI[i], sv[i], 1e-6, imA[i], imAt[i], kerAt[i]);
519 if (rank != rank_bench) {
521 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
527 for (
unsigned int i = 0; i < time.size(); i++) {
528 ret += test_pseudo_inverse(bench, PI, sv, imA, imAt, kerAt);
535 for (
unsigned int i = 0; i < bench.size(); i++) {
536 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
537 PI[i] = bench[i].pseudoInverseEigen3(
static_cast<int>(rank_bench));
540 for (
unsigned int i = 0; i < time.size(); i++) {
541 ret += test_pseudo_inverse(bench, PI);
546 for (
unsigned int i = 0; i < bench.size(); i++) {
547 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
548 unsigned int rank = bench[i].pseudoInverseEigen3(PI[i],
static_cast<int>(rank_bench));
549 if (rank != rank_bench) {
551 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
557 for (
unsigned int i = 0; i < time.size(); i++) {
558 ret += test_pseudo_inverse(bench, PI);
563 for (
unsigned int i = 0; i < bench.size(); i++) {
564 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
565 unsigned int rank = bench[i].pseudoInverseEigen3(PI[i], sv[i],
static_cast<int>(rank_bench));
566 if (rank != rank_bench) {
568 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
574 for (
unsigned int i = 0; i < time.size(); i++) {
575 ret += test_pseudo_inverse(bench, PI);
580 for (
unsigned int i = 0; i < bench.size(); i++) {
581 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
582 unsigned int rank = bench[i].pseudoInverseEigen3(PI[i], sv[i],
static_cast<int>(rank_bench), imA[i], imAt[i], kerAt[i]);
583 if (rank != rank_bench) {
585 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
592 for (
unsigned int i = 0; i < time.size(); i++) {
593 ret += test_pseudo_inverse(bench, PI, sv, imA, imAt, kerAt);
600 #if defined(VISP_HAVE_LAPACK)
601 int test_pseudo_inverse_lapack(
bool verbose,
const std::vector<vpMatrix> &bench, std::vector<double> &time)
604 std::cout <<
"Test pseudo-inverse using Eigen3 3rd party" << std::endl;
606 std::cout <<
" Pseudo-inverse on a " << bench[0].getRows() <<
"x" << bench[0].getCols() <<
" matrix" << std::endl;
608 size_t size = bench.size();
609 std::vector<vpMatrix> PI(size), imA(size), imAt(size), kerAt(size);
610 std::vector<vpColVector> sv(size);
611 int ret = EXIT_SUCCESS;
616 for (
unsigned int i = 0; i < bench.size(); i++) {
617 PI[i] = bench[i].pseudoInverseLapack();
620 for (
unsigned int i = 0; i < time.size(); i++) {
621 ret += test_pseudo_inverse(bench, PI);
626 for (
unsigned int i = 0; i < bench.size(); i++) {
627 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
628 unsigned int rank = bench[i].pseudoInverseLapack(PI[i]);
629 if (rank != rank_bench) {
631 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
637 for (
unsigned int i = 0; i < time.size(); i++) {
638 ret += test_pseudo_inverse(bench, PI);
643 for (
unsigned int i = 0; i < bench.size(); i++) {
644 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
645 unsigned int rank = bench[i].pseudoInverseLapack(PI[i], sv[i]);
646 if (rank != rank_bench) {
648 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
654 for (
unsigned int i = 0; i < time.size(); i++) {
655 ret += test_pseudo_inverse(bench, PI);
660 for (
unsigned int i = 0; i < bench.size(); i++) {
661 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
662 unsigned int rank = bench[i].pseudoInverseLapack(PI[i], sv[i], 1e-6, imA[i], imAt[i], kerAt[i]);
663 if (rank != rank_bench) {
665 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
671 for (
unsigned int i = 0; i < time.size(); i++) {
672 ret += test_pseudo_inverse(bench, PI, sv, imA, imAt, kerAt);
679 for (
unsigned int i = 0; i < bench.size(); i++) {
680 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
681 PI[i] = bench[i].pseudoInverseLapack(
static_cast<int>(rank_bench));
684 for (
unsigned int i = 0; i < time.size(); i++) {
685 ret += test_pseudo_inverse(bench, PI);
690 for (
unsigned int i = 0; i < bench.size(); i++) {
691 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
692 unsigned int rank = bench[i].pseudoInverseLapack(PI[i],
static_cast<int>(rank_bench));
693 if (rank != rank_bench) {
695 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
701 for (
unsigned int i = 0; i < time.size(); i++) {
702 ret += test_pseudo_inverse(bench, PI);
707 for (
unsigned int i = 0; i < bench.size(); i++) {
708 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
709 unsigned int rank = bench[i].pseudoInverseLapack(PI[i], sv[i],
static_cast<int>(rank_bench));
710 if (rank != rank_bench) {
712 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
718 for (
unsigned int i = 0; i < time.size(); i++) {
719 ret += test_pseudo_inverse(bench, PI);
724 for (
unsigned int i = 0; i < bench.size(); i++) {
725 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
726 unsigned int rank = bench[i].pseudoInverseLapack(PI[i], sv[i],
static_cast<int>(rank_bench), imA[i], imAt[i], kerAt[i]);
727 if (rank != rank_bench) {
729 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
736 for (
unsigned int i = 0; i < time.size(); i++) {
737 ret += test_pseudo_inverse(bench, PI, sv, imA, imAt, kerAt);
744 #if defined(VISP_HAVE_OPENCV)
745 int test_pseudo_inverse_opencv(
bool verbose,
const std::vector<vpMatrix> &bench, std::vector<double> &time)
748 std::cout <<
"Test pseudo-inverse using OpenCV 3rd party" << std::endl;
750 std::cout <<
" Pseudo-inverse on a " << bench[0].getRows() <<
"x" << bench[0].getCols() <<
" matrix" << std::endl;
752 size_t size = bench.size();
753 std::vector<vpMatrix> PI(size), imA(size), imAt(size), kerAt(size);
754 std::vector<vpColVector> sv(size);
755 int ret = EXIT_SUCCESS;
760 for (
unsigned int i = 0; i < bench.size(); i++) {
761 PI[i] = bench[i].pseudoInverseOpenCV();
764 for (
unsigned int i = 0; i < time.size(); i++) {
765 ret += test_pseudo_inverse(bench, PI);
770 for (
unsigned int i = 0; i < bench.size(); i++) {
771 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
772 unsigned int rank = bench[i].pseudoInverseOpenCV(PI[i]);
773 if (rank != rank_bench) {
775 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
781 for (
unsigned int i = 0; i < time.size(); i++) {
782 ret += test_pseudo_inverse(bench, PI);
787 for (
unsigned int i = 0; i < bench.size(); i++) {
788 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
789 unsigned int rank = bench[i].pseudoInverseOpenCV(PI[i], sv[i]);
790 if (rank != rank_bench) {
792 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
798 for (
unsigned int i = 0; i < time.size(); i++) {
799 ret += test_pseudo_inverse(bench, PI);
804 for (
unsigned int i = 0; i < bench.size(); i++) {
805 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
806 unsigned int rank = bench[i].pseudoInverseOpenCV(PI[i], sv[i], 1e-6, imA[i], imAt[i], kerAt[i]);
807 if (rank != rank_bench) {
809 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
815 for (
unsigned int i = 0; i < time.size(); i++) {
816 ret += test_pseudo_inverse(bench, PI, sv, imA, imAt, kerAt);
822 for (
unsigned int i = 0; i < bench.size(); i++) {
823 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
824 PI[i] = bench[i].pseudoInverseOpenCV(
static_cast<int>(rank_bench));
827 for (
unsigned int i = 0; i < time.size(); i++) {
828 ret += test_pseudo_inverse(bench, PI);
833 for (
unsigned int i = 0; i < bench.size(); i++) {
834 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
835 unsigned int rank = bench[i].pseudoInverseOpenCV(PI[i],
static_cast<int>(rank_bench));
836 if (rank != rank_bench) {
838 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
844 for (
unsigned int i = 0; i < time.size(); i++) {
845 ret += test_pseudo_inverse(bench, PI);
850 for (
unsigned int i = 0; i < bench.size(); i++) {
851 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
852 unsigned int rank = bench[i].pseudoInverseOpenCV(PI[i], sv[i],
static_cast<int>(rank_bench));
853 if (rank != rank_bench) {
855 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
861 for (
unsigned int i = 0; i < time.size(); i++) {
862 ret += test_pseudo_inverse(bench, PI);
867 for (
unsigned int i = 0; i < bench.size(); i++) {
868 unsigned int rank_bench = std::min(bench[i].getRows(), bench[i].getCols());
869 unsigned int rank = bench[i].pseudoInverseOpenCV(PI[i], sv[i],
static_cast<int>(rank_bench), imA[i], imAt[i], kerAt[i]);
870 if (rank != rank_bench) {
872 std::cout <<
" Error in the rank (" << rank <<
")" <<
" while expected rank is " << rank_bench << std::endl;
879 for (
unsigned int i = 0; i < time.size(); i++) {
880 ret += test_pseudo_inverse(bench, PI, sv, imA, imAt, kerAt);
887 void save_time(
const std::string &method,
unsigned int nrows,
unsigned int ncols,
bool verbose,
bool use_plot_file,
888 std::ofstream &of,
const std::vector<double> &time)
890 for (
size_t i = 0; i < time.size(); i++) {
892 of << time[i] <<
"\t";
894 std::cout <<
" " << method <<
" pseudo inverse (" << nrows <<
"x" << ncols <<
")"
895 <<
" time test " << i <<
": " << time[i] << std::endl;
900 int main(
int argc,
const char *argv[])
903 #if defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_OPENCV)
904 unsigned int nb_matrices = 10;
905 unsigned int nb_iterations = 10;
906 unsigned int nb_rows = 12;
907 unsigned int nb_cols = 6;
908 bool verbose =
false;
909 std::string plotfile(
"plot-pseudo-inv.csv");
910 bool use_plot_file =
false;
913 unsigned int nb_svd_functions = 4;
914 unsigned int nb_test_matrix_size = 3;
915 std::vector<double> time(nb_svd_functions);
916 std::vector<unsigned int> nrows(nb_test_matrix_size), ncols(nb_test_matrix_size);
919 if (getOptions(argc, argv, nb_matrices, nb_iterations, use_plot_file, plotfile, nb_rows, nb_cols, verbose) ==
924 for (
unsigned int s = 0; s < nb_test_matrix_size; s++) {
941 of.open(plotfile.c_str());
945 for (
unsigned int s = 0; s < nb_test_matrix_size; s++) {
946 for (
unsigned int i = 0; i < nb_svd_functions; i++)
947 of <<
"\"default " << nrows[s] <<
"x" << ncols[s] <<
" test " << i <<
"\""
950 #if defined(VISP_HAVE_LAPACK)
951 for (
unsigned int i = 0; i < nb_svd_functions; i++)
952 of <<
"\"Lapack " << nrows[s] <<
"x" << ncols[s] <<
" test " << i <<
"\""
955 #if defined(VISP_HAVE_EIGEN3)
956 for (
unsigned int i = 0; i < nb_svd_functions; i++)
957 of <<
"\"Eigen3 " << nrows[s] <<
"x" << ncols[s] <<
" test " << i <<
"\""
960 #if defined(VISP_HAVE_OPENCV)
961 for (
unsigned int i = 0; i < nb_svd_functions; i++)
962 of <<
"\"OpenCV " << nrows[s] <<
"x" << ncols[s] <<
" test " << i <<
"\""
969 int ret_default = EXIT_SUCCESS;
970 int ret_lapack = EXIT_SUCCESS;
971 int ret_eigen3 = EXIT_SUCCESS;
972 int ret_opencv = EXIT_SUCCESS;
974 for (
unsigned int iter = 0; iter < nb_iterations; iter++) {
979 for (
unsigned int s = 0; s < nb_test_matrix_size; s++) {
980 std::vector<vpMatrix> bench_random_matrices;
981 create_bench_random_matrix(nb_matrices, nrows[s], ncols[s], verbose, bench_random_matrices);
983 ret_default += test_pseudo_inverse_default(verbose, bench_random_matrices, time);
984 save_time(
"default -", nrows[s], ncols[s], verbose, use_plot_file, of, time);
986 #if defined(VISP_HAVE_LAPACK)
987 ret_lapack += test_pseudo_inverse_lapack(verbose, bench_random_matrices, time);
988 save_time(
"Lapack -", nrows[s], ncols[s], verbose, use_plot_file, of, time);
991 #if defined(VISP_HAVE_EIGEN3)
992 ret_eigen3 += test_pseudo_inverse_eigen3(verbose, bench_random_matrices, time);
993 save_time(
"Eigen3 -", nrows[s], ncols[s], verbose, use_plot_file, of, time);
996 #if defined(VISP_HAVE_OPENCV)
997 ret_opencv += test_pseudo_inverse_opencv(verbose, bench_random_matrices, time);
998 save_time(
"OpenCV -", nrows[s], ncols[s], verbose, use_plot_file, of, time);
1004 if (use_plot_file) {
1006 std::cout <<
"Result saved in " << plotfile << std::endl;
1009 std::cout <<
"Resume testing:" << std::endl;
1010 std::cout <<
" Pseudo-inverse (default): " << (ret_default ?
"failed" :
"success") << std::endl;
1011 #if defined(VISP_HAVE_LAPACK)
1012 std::cout <<
" Pseudo-inverse (lapack) : " << (ret_lapack ?
"failed" :
"success") << std::endl;
1014 #if defined(VISP_HAVE_EIGEN3)
1015 std::cout <<
" Pseudo-inverse (eigen3) : " << (ret_eigen3 ?
"failed" :
"success") << std::endl;
1017 #if defined(VISP_HAVE_OPENCV)
1018 std::cout <<
" Pseudo-inverse (opencv) : " << (ret_opencv ?
"failed" :
"success") << std::endl;
1021 int ret = ret_default + ret_lapack + ret_eigen3 + ret_opencv;
1023 std::cout <<
" Global test : " << (ret ?
"failed" :
"success") << std::endl;
1029 std::cout <<
"Test does nothing since you dont't have Lapack, Eigen3 or OpenCV 3rd party" << std::endl;
1030 return EXIT_SUCCESS;
1035 return EXIT_FAILURE;
unsigned int getCols() const
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
unsigned int getRows() const
error that can be emitted by ViSP classes.
const std::string & getStringMessage() const
Implementation of a matrix and operations on matrices.
double frobeniusNorm() const
void insert(const vpMatrix &A, unsigned int r, unsigned int c)
vpMatrix transpose() const
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
VISP_EXPORT double measureTimeMs()