Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
vpMatrix.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  * Matrix manipulation.
33  *
34  * Authors:
35  * Eric Marchand
36  *
37  *****************************************************************************/
43 #include <algorithm>
44 #include <assert.h>
45 #include <cmath> // std::fabs
46 #include <fstream>
47 #include <limits> // numeric_limits
48 #include <sstream>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <string>
53 #include <vector>
54 
55 #include <visp3/core/vpConfig.h>
56 
57 #ifdef VISP_HAVE_GSL
58 #include <gsl/gsl_linalg.h>
59 #endif
60 
61 #include <visp3/core/vpCPUFeatures.h>
62 #include <visp3/core/vpColVector.h>
63 #include <visp3/core/vpDebug.h>
64 #include <visp3/core/vpException.h>
65 #include <visp3/core/vpMath.h>
66 #include <visp3/core/vpMatrix.h>
67 #include <visp3/core/vpTranslationVector.h>
68 
69 #define USE_SSE_CODE 1
70 #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
71 #include <emmintrin.h>
72 #define VISP_HAVE_SSE2 1
73 #endif
74 
75 #if VISP_HAVE_SSE2 && USE_SSE_CODE
76 #define USE_SSE 1
77 #endif
78 
79 // Prototypes of specific functions
80 vpMatrix subblock(const vpMatrix &, unsigned int, unsigned int);
81 
82 void compute_pseudo_inverse(const vpMatrix &a, const vpColVector &sv, const vpMatrix &v, unsigned int nrows,
83  unsigned int ncols, unsigned int nrows_orig, unsigned int ncols_orig, double svThreshold,
84  vpMatrix &Ap, unsigned int &rank)
85 {
86  vpMatrix a1(ncols, nrows);
87 
88  // compute the highest singular value and the rank of h
89  double maxsv = 0;
90  for (unsigned int i = 0; i < ncols; i++) {
91  if (fabs(sv[i]) > maxsv)
92  maxsv = fabs(sv[i]);
93  }
94 
95  rank = 0;
96 
97  for (unsigned int i = 0; i < ncols; i++) {
98  if (fabs(sv[i]) > maxsv * svThreshold) {
99  rank++;
100  }
101 
102  for (unsigned int j = 0; j < nrows; j++) {
103  a1[i][j] = 0.0;
104 
105  for (unsigned int k = 0; k < ncols; k++) {
106  if (fabs(sv[k]) > maxsv * svThreshold) {
107  a1[i][j] += v[i][k] * a[j][k] / sv[k];
108  }
109  }
110  }
111  }
112  if (nrows_orig >= ncols_orig)
113  Ap = a1;
114  else
115  Ap = a1.t();
116 }
117 
118 void compute_pseudo_inverse(const vpMatrix &U, const vpColVector &sv, const vpMatrix &V, unsigned int nrows_orig,
119  unsigned int ncols_orig, double svThreshold, vpMatrix &Ap, unsigned int &rank,
120  vpMatrix &imA, vpMatrix &imAt, vpMatrix &kerAt)
121 {
122  Ap.resize(ncols_orig, nrows_orig);
123 
124  // compute the highest singular value and the rank of h
125  double maxsv = fabs(sv[0]);
126 
127  rank = 0;
128 
129  for (unsigned int i = 0; i < ncols_orig; i++) {
130  if (fabs(sv[i]) > maxsv * svThreshold) {
131  rank++;
132  }
133 
134  for (unsigned int j = 0; j < nrows_orig; j++) {
135  // Ap[i][j] = 0.0;
136 
137  for (unsigned int k = 0; k < ncols_orig; k++) {
138  if (fabs(sv[k]) > maxsv * svThreshold) {
139  Ap[i][j] += V[i][k] * U[j][k] / sv[k];
140  }
141  }
142  }
143  }
144 
145  // Compute im(A) and im(At)
146  imA.resize(nrows_orig, rank);
147  imAt.resize(ncols_orig, rank);
148 
149  for (unsigned int i = 0; i < nrows_orig; i++) {
150  for (unsigned int j = 0; j < rank; j++) {
151  imA[i][j] = U[i][j];
152  }
153  }
154 
155  for (unsigned int i = 0; i < ncols_orig; i++) {
156  for (unsigned int j = 0; j < rank; j++) {
157  imAt[i][j] = V[i][j];
158  }
159  }
160 
161  kerAt.resize(ncols_orig - rank, ncols_orig);
162  if (rank != ncols_orig) {
163  for (unsigned int j = 0, k = 0; j < ncols_orig; j++) {
164  // if( v.col(j) in kernel and non zero )
165  if ((fabs(sv[j]) <= maxsv * svThreshold) &&
166  (std::fabs(V.getCol(j).sumSquare()) > std::numeric_limits<double>::epsilon())) {
167  for (unsigned int i = 0; i < V.getRows(); i++) {
168  kerAt[k][i] = V[i][j];
169  }
170  k++;
171  }
172  }
173  }
174 }
175 
181 vpMatrix::vpMatrix(const vpMatrix &M, unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols)
182  : vpArray2D<double>()
183 {
184  if (((r + nrows) > M.rowNum) || ((c + ncols) > M.colNum)) {
186  "Cannot construct a sub matrix (%dx%d) starting at "
187  "position (%d,%d) that is not contained in the "
188  "original matrix (%dx%d)",
189  nrows, ncols, r, c, M.rowNum, M.colNum));
190  }
191 
192  init(M, r, c, nrows, ncols);
193 }
194 
195 #ifdef VISP_HAVE_CPP11_COMPATIBILITY
197 {
198  rowNum = A.rowNum;
199  colNum = A.colNum;
200  rowPtrs = A.rowPtrs;
201  dsize = A.dsize;
202  data = A.data;
203 
204  A.rowNum = 0;
205  A.colNum = 0;
206  A.rowPtrs = NULL;
207  A.dsize = 0;
208  A.data = NULL;
209 }
210 #endif
211 
258 void vpMatrix::init(const vpMatrix &M, unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols)
259 {
260  unsigned int rnrows = r + nrows;
261  unsigned int cncols = c + ncols;
262 
263  if (rnrows > M.getRows())
264  throw(vpException(vpException::dimensionError, "Bad row dimension (%d > %d) used to initialize vpMatrix", rnrows,
265  M.getRows()));
266  if (cncols > M.getCols())
267  throw(vpException(vpException::dimensionError, "Bad column dimension (%d > %d) used to initialize vpMatrix", cncols,
268  M.getCols()));
269  resize(nrows, ncols, false, false);
270 
271  if (this->rowPtrs == NULL) // Fix coverity scan: explicit null dereferenced
272  return; // Noting to do
273  for (unsigned int i = 0; i < nrows; i++) {
274  memcpy((*this)[i], &M[i + r][c], ncols * sizeof(double));
275  }
276 }
277 
319 vpMatrix vpMatrix::extract(unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols) const
320 {
321  unsigned int rnrows = r + nrows;
322  unsigned int cncols = c + ncols;
323 
324  if (rnrows > getRows())
325  throw(vpException(vpException::dimensionError, "Bad row dimension (%d > %d) used to initialize vpMatrix", rnrows,
326  getRows()));
327  if (cncols > getCols())
328  throw(vpException(vpException::dimensionError, "Bad column dimension (%d > %d) used to initialize vpMatrix", cncols,
329  getCols()));
330 
331  vpMatrix M(nrows, ncols);
332  for (unsigned int i = 0; i < nrows; i++) {
333  memcpy(M[i], &(*this)[i + r][c], ncols * sizeof(double));
334  }
335 
336  return M;
337 }
338 
343 void vpMatrix::eye(unsigned int n) { eye(n, n); }
344 
349 void vpMatrix::eye(unsigned int m, unsigned int n)
350 {
351  resize(m, n);
352 
353  eye();
354 }
355 
361 {
362  for (unsigned int i = 0; i < rowNum; i++) {
363  for (unsigned int j = 0; j < colNum; j++) {
364  if (i == j)
365  (*this)[i][j] = 1.0;
366  else
367  (*this)[i][j] = 0;
368  }
369  }
370 }
371 
376 {
377  vpMatrix At;
378 
379  At.resize(colNum, rowNum, false, false);
380 
381  for (unsigned int i = 0; i < rowNum; i++) {
382  double *coli = (*this)[i];
383  for (unsigned int j = 0; j < colNum; j++)
384  At[j][i] = coli[j];
385  }
386  return At;
387 }
388 
395 {
396  vpMatrix At;
397  transpose(At);
398  return At;
399 }
400 
407 {
408  At.resize(colNum, rowNum, false, false);
409 
410  size_t A_step = colNum;
411  double **AtRowPtrs = At.rowPtrs;
412 
413  for (unsigned int i = 0; i < colNum; i++) {
414  double *row_ = AtRowPtrs[i];
415  double *col = rowPtrs[0] + i;
416  for (unsigned int j = 0; j < rowNum; j++, col += A_step)
417  *(row_++) = *col;
418  }
419 }
420 
427 {
428  vpMatrix B;
429 
430  AAt(B);
431 
432  return B;
433 }
434 
446 void vpMatrix::AAt(vpMatrix &B) const
447 {
448  if ((B.rowNum != rowNum) || (B.colNum != rowNum))
449  B.resize(rowNum, rowNum, false, false);
450 
451  // compute A*A^T
452  for (unsigned int i = 0; i < rowNum; i++) {
453  for (unsigned int j = i; j < rowNum; j++) {
454  double *pi = rowPtrs[i]; // row i
455  double *pj = rowPtrs[j]; // row j
456 
457  // sum (row i .* row j)
458  double ssum = 0;
459  for (unsigned int k = 0; k < colNum; k++)
460  ssum += *(pi++) * *(pj++);
461 
462  B[i][j] = ssum; // upper triangle
463  if (i != j)
464  B[j][i] = ssum; // lower triangle
465  }
466  }
467 }
468 
480 void vpMatrix::AtA(vpMatrix &B) const
481 {
482  if ((B.rowNum != colNum) || (B.colNum != colNum))
483  B.resize(colNum, colNum, false, false);
484 
485 #if defined(VISP_HAVE_LAPACK) && !defined(VISP_HAVE_LAPACK_BUILT_IN)
486  double alpha = 1.0;
487  double beta = 0.0;
488  char transa = 'n';
489  char transb = 't';
490 
491  vpMatrix::blas_dgemm(transa, transb, colNum, colNum, rowNum, alpha, data, colNum, data, colNum, beta, B.data, colNum);
492 #else
493  unsigned int i, j, k;
494  double s;
495  double *ptr;
496  for (i = 0; i < colNum; i++) {
497  double *Bi = B[i];
498  for (j = 0; j < i; j++) {
499  ptr = data;
500  s = 0;
501  for (k = 0; k < rowNum; k++) {
502  s += (*(ptr + i)) * (*(ptr + j));
503  ptr += colNum;
504  }
505  *Bi++ = s;
506  B[j][i] = s;
507  }
508  ptr = data;
509  s = 0;
510  for (k = 0; k < rowNum; k++) {
511  s += (*(ptr + i)) * (*(ptr + i));
512  ptr += colNum;
513  }
514  *Bi = s;
515  }
516 #endif
517 }
518 
525 {
526  vpMatrix B;
527 
528  AtA(B);
529 
530  return B;
531 }
532 
550 {
551  resize(A.getRows(), A.getCols(), false, false);
552 
553  if (data != NULL && A.data != NULL && data != A.data) {
554  memcpy(data, A.data, dsize * sizeof(double));
555  }
556 
557  return *this;
558 }
559 
560 #ifdef VISP_HAVE_CPP11_COMPATIBILITY
562 {
563  resize(A.getRows(), A.getCols(), false, false);
564 
565  if (data != NULL && A.data != NULL && data != A.data) {
566  memcpy(data, A.data, dsize * sizeof(double));
567  }
568 
569  return *this;
570 }
571 
573 {
574  if (this != &other) {
575  free(data);
576  free(rowPtrs);
577 
578  rowNum = other.rowNum;
579  colNum = other.colNum;
580  rowPtrs = other.rowPtrs;
581  dsize = other.dsize;
582  data = other.data;
583 
584  other.rowNum = 0;
585  other.colNum = 0;
586  other.rowPtrs = NULL;
587  other.dsize = 0;
588  other.data = NULL;
589  }
590 
591  return *this;
592 }
593 #endif
594 
597 {
598  std::fill(data, data + rowNum*colNum, x);
599  return *this;
600 }
601 
608 {
609  for (unsigned int i = 0; i < rowNum; i++) {
610  for (unsigned int j = 0; j < colNum; j++) {
611  rowPtrs[i][j] = *x++;
612  }
613  }
614  return *this;
615 }
616 
654 {
655  unsigned int rows = A.getRows();
656  this->resize(rows, rows);
657 
658  (*this) = 0;
659  for (unsigned int i = 0; i < rows; i++)
660  (*this)[i][i] = A[i];
661 }
662 
693 void vpMatrix::diag(const double &val)
694 {
695  (*this) = 0;
696  unsigned int min_ = (rowNum < colNum) ? rowNum : colNum;
697  for (unsigned int i = 0; i < min_; i++)
698  (*this)[i][i] = val;
699 }
700 
713 {
714  unsigned int rows = A.getRows();
715  DA.resize(rows, rows);
716 
717  for (unsigned int i = 0; i < rows; i++)
718  DA[i][i] = A[i];
719 }
720 
726 {
727  vpTranslationVector t_out;
728 
729  if (rowNum != 3 || colNum != 3) {
730  throw(vpException(vpException::dimensionError, "Cannot multiply a (%dx%d) matrix by a (%dx%d) translation vector",
731  rowNum, colNum, tv.getRows(), tv.getCols()));
732  }
733 
734  for (unsigned int j = 0; j < 3; j++)
735  t_out[j] = 0;
736 
737  for (unsigned int j = 0; j < 3; j++) {
738  double tj = tv[j]; // optimization em 5/12/2006
739  for (unsigned int i = 0; i < 3; i++) {
740  t_out[i] += rowPtrs[i][j] * tj;
741  }
742  }
743  return t_out;
744 }
745 
751 {
752  vpColVector v_out;
753  vpMatrix::multMatrixVector(*this, v, v_out);
754  return v_out;
755 }
756 
766 {
767  if (A.colNum != v.getRows()) {
768  throw(vpException(vpException::dimensionError, "Cannot multiply a (%dx%d) matrix by a (%d) column vector",
769  A.getRows(), A.getCols(), v.getRows()));
770  }
771 
772  if (A.rowNum != w.rowNum)
773  w.resize(A.rowNum, false);
774 
775 #if defined(VISP_HAVE_LAPACK) && !defined(VISP_HAVE_LAPACK_BUILT_IN)
776  double alpha = 1.0;
777  double beta = 0.0;
778  char trans = 't';
779  int incr = 1;
780 
781  vpMatrix::blas_dgemv(trans, A.colNum, A.rowNum, alpha, A.data, A.colNum, v.data, incr, beta, w.data, incr);
782 #else
783  w = 0.0;
784  for (unsigned int j = 0; j < A.colNum; j++) {
785  double vj = v[j]; // optimization em 5/12/2006
786  for (unsigned int i = 0; i < A.rowNum; i++) {
787  w[i] += A.rowPtrs[i][j] * vj;
788  }
789  }
790 #endif
791 }
792 
793 //---------------------------------
794 // Matrix operations.
795 //---------------------------------
796 
806 void vpMatrix::mult2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
807 {
808  if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum))
809  C.resize(A.rowNum, B.colNum, false, false);
810 
811  if (A.colNum != B.rowNum) {
812  throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (%dx%d) matrix", A.getRows(),
813  A.getCols(), B.getRows(), B.getCols()));
814  }
815 
816 #if defined(VISP_HAVE_LAPACK) && !defined(VISP_HAVE_LAPACK_BUILT_IN)
817  double alpha = 1.0;
818  double beta = 0.0;
819  char trans = 'n';
820 
821  vpMatrix::blas_dgemm(trans, trans, B.colNum, A.rowNum, A.colNum, alpha, B.data, B.colNum, A.data, A.colNum, beta,
822  C.data, B.colNum);
823 #else
824  // 5/12/06 some "very" simple optimization to avoid indexation
825  unsigned int BcolNum = B.colNum;
826  unsigned int BrowNum = B.rowNum;
827  unsigned int i, j, k;
828  double **BrowPtrs = B.rowPtrs;
829  for (i = 0; i < A.rowNum; i++) {
830  double *rowptri = A.rowPtrs[i];
831  double *ci = C[i];
832  for (j = 0; j < BcolNum; j++) {
833  double s = 0;
834  for (k = 0; k < BrowNum; k++)
835  s += rowptri[k] * BrowPtrs[k][j];
836  ci[j] = s;
837  }
838  }
839 #endif
840 }
841 
856 {
857  if (A.colNum != 3 || A.rowNum != 3 || B.colNum != 3 || B.rowNum != 3) {
859  "Cannot multiply (%dx%d) matrix by (%dx%d) matrix as a "
860  "rotation matrix",
861  A.getRows(), A.getCols(), B.getRows(), B.getCols()));
862  }
863 
864  // 5/12/06 some "very" simple optimization to avoid indexation
865  unsigned int BcolNum = B.colNum;
866  unsigned int BrowNum = B.rowNum;
867  unsigned int i, j, k;
868  double **BrowPtrs = B.rowPtrs;
869  for (i = 0; i < A.rowNum; i++) {
870  double *rowptri = A.rowPtrs[i];
871  double *ci = C[i];
872  for (j = 0; j < BcolNum; j++) {
873  double s = 0;
874  for (k = 0; k < BrowNum; k++)
875  s += rowptri[k] * BrowPtrs[k][j];
876  ci[j] = s;
877  }
878  }
879 }
880 
895 {
896  if (A.colNum != 4 || A.rowNum != 4 || B.colNum != 4 || B.rowNum != 4) {
898  "Cannot multiply (%dx%d) matrix by (%dx%d) matrix as a "
899  "rotation matrix",
900  A.getRows(), A.getCols(), B.getRows(), B.getCols()));
901  }
902 
903  // 5/12/06 some "very" simple optimization to avoid indexation
904  unsigned int BcolNum = B.colNum;
905  unsigned int BrowNum = B.rowNum;
906  unsigned int i, j, k;
907  double **BrowPtrs = B.rowPtrs;
908  for (i = 0; i < A.rowNum; i++) {
909  double *rowptri = A.rowPtrs[i];
910  double *ci = C[i];
911  for (j = 0; j < BcolNum; j++) {
912  double s = 0;
913  for (k = 0; k < BrowNum; k++)
914  s += rowptri[k] * BrowPtrs[k][j];
915  ci[j] = s;
916  }
917  }
918 }
919 
933 {
935 }
936 
942 {
943  vpMatrix C;
944 
945  vpMatrix::mult2Matrices(*this, B, C);
946 
947  return C;
948 }
949 
955 {
956  if (colNum != R.getRows()) {
957  throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (3x3) rotation matrix", rowNum,
958  colNum));
959  }
960  vpMatrix C(rowNum, 3);
961 
962  unsigned int RcolNum = R.getCols();
963  unsigned int RrowNum = R.getRows();
964  for (unsigned int i = 0; i < rowNum; i++) {
965  double *rowptri = rowPtrs[i];
966  double *ci = C[i];
967  for (unsigned int j = 0; j < RcolNum; j++) {
968  double s = 0;
969  for (unsigned int k = 0; k < RrowNum; k++)
970  s += rowptri[k] * R[k][j];
971  ci[j] = s;
972  }
973  }
974 
975  return C;
976 }
982 {
983  if (colNum != V.getRows()) {
984  throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (6x6) velocity twist matrix",
985  rowNum, colNum));
986  }
987  vpMatrix M;
988  M.resize(rowNum, 6, false, false);
989 
990 #if defined(VISP_HAVE_LAPACK) && !defined(VISP_HAVE_LAPACK_BUILT_IN)
991  double alpha = 1.0;
992  double beta = 0.0;
993  char trans = 'n';
994 
995  vpMatrix::blas_dgemm(trans, trans, V.colNum, rowNum, colNum, alpha, V.data, V.colNum, data, colNum, beta, M.data,
996  V.colNum);
997 #else
998  bool checkSSE2 = vpCPUFeatures::checkSSE2();
999 #if !USE_SSE
1000  checkSSE2 = false;
1001 #endif
1002 
1003  if (checkSSE2) {
1004 #if USE_SSE
1005  vpMatrix V_trans(6, 6);
1006  for (unsigned int i = 0; i < 6; i++) {
1007  for (unsigned int j = 0; j < 6; j++) {
1008  V_trans[i][j] = V[j][i];
1009  }
1010  }
1011 
1012  for (unsigned int i = 0; i < rowNum; i++) {
1013  double *rowptri = rowPtrs[i];
1014  double *ci = M[i];
1015 
1016  for (int j = 0; j < 6; j++) {
1017  __m128d v_mul = _mm_setzero_pd();
1018  for (int k = 0; k < 6; k += 2) {
1019  v_mul = _mm_add_pd(v_mul, _mm_mul_pd(_mm_loadu_pd(&rowptri[k]), _mm_loadu_pd(&V_trans[j][k])));
1020  }
1021 
1022  double v_tmp[2];
1023  _mm_storeu_pd(v_tmp, v_mul);
1024  ci[j] = v_tmp[0] + v_tmp[1];
1025  }
1026  }
1027 #endif
1028  } else {
1029  unsigned int VcolNum = V.getCols();
1030  unsigned int VrowNum = V.getRows();
1031  for (unsigned int i = 0; i < rowNum; i++) {
1032  double *rowptri = rowPtrs[i];
1033  double *ci = M[i];
1034  for (unsigned int j = 0; j < VcolNum; j++) {
1035  double s = 0;
1036  for (unsigned int k = 0; k < VrowNum; k++)
1037  s += rowptri[k] * V[k][j];
1038  ci[j] = s;
1039  }
1040  }
1041  }
1042 #endif
1043 
1044  return M;
1045 }
1051 {
1052  if (colNum != V.getRows()) {
1053  throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (6x6) force/torque twist matrix",
1054  rowNum, colNum));
1055  }
1056  vpMatrix M(rowNum, 6);
1057 
1058  unsigned int VcolNum = V.getCols();
1059  unsigned int VrowNum = V.getRows();
1060  for (unsigned int i = 0; i < rowNum; i++) {
1061  double *rowptri = rowPtrs[i];
1062  double *ci = M[i];
1063  for (unsigned int j = 0; j < VcolNum; j++) {
1064  double s = 0;
1065  for (unsigned int k = 0; k < VrowNum; k++)
1066  s += rowptri[k] * V[k][j];
1067  ci[j] = s;
1068  }
1069  }
1070 
1071  return M;
1072 }
1073 
1084 void vpMatrix::add2WeightedMatrices(const vpMatrix &A, const double &wA, const vpMatrix &B, const double &wB,
1085  vpMatrix &C)
1086 {
1087  if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum))
1088  C.resize(A.rowNum, B.colNum, false, false);
1089 
1090  if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
1091  throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
1092  A.getCols(), B.getRows(), B.getCols()));
1093  }
1094 
1095  double **ArowPtrs = A.rowPtrs;
1096  double **BrowPtrs = B.rowPtrs;
1097  double **CrowPtrs = C.rowPtrs;
1098 
1099  for (unsigned int i = 0; i < A.rowNum; i++)
1100  for (unsigned int j = 0; j < A.colNum; j++)
1101  CrowPtrs[i][j] = wB * BrowPtrs[i][j] + wA * ArowPtrs[i][j];
1102 }
1103 
1113 void vpMatrix::add2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
1114 {
1115  if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum))
1116  C.resize(A.rowNum, B.colNum, false, false);
1117 
1118  if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
1119  throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
1120  A.getCols(), B.getRows(), B.getCols()));
1121  }
1122 
1123  double **ArowPtrs = A.rowPtrs;
1124  double **BrowPtrs = B.rowPtrs;
1125  double **CrowPtrs = C.rowPtrs;
1126 
1127  for (unsigned int i = 0; i < A.rowNum; i++) {
1128  for (unsigned int j = 0; j < A.colNum; j++) {
1129  CrowPtrs[i][j] = BrowPtrs[i][j] + ArowPtrs[i][j];
1130  }
1131  }
1132 }
1133 
1147 {
1148  if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum))
1149  C.resize(A.rowNum);
1150 
1151  if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
1152  throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
1153  A.getCols(), B.getRows(), B.getCols()));
1154  }
1155 
1156  double **ArowPtrs = A.rowPtrs;
1157  double **BrowPtrs = B.rowPtrs;
1158  double **CrowPtrs = C.rowPtrs;
1159 
1160  for (unsigned int i = 0; i < A.rowNum; i++) {
1161  for (unsigned int j = 0; j < A.colNum; j++) {
1162  CrowPtrs[i][j] = BrowPtrs[i][j] + ArowPtrs[i][j];
1163  }
1164  }
1165 }
1166 
1172 {
1173  vpMatrix C;
1174  vpMatrix::add2Matrices(*this, B, C);
1175  return C;
1176 }
1177 
1194 {
1195  if ((A.rowNum != C.rowNum) || (A.colNum != C.colNum))
1196  C.resize(A.rowNum);
1197 
1198  if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
1199  throw(vpException(vpException::dimensionError, "Cannot substract (%dx%d) matrix to (%dx%d) matrix", A.getRows(),
1200  A.getCols(), B.getRows(), B.getCols()));
1201  }
1202 
1203  double **ArowPtrs = A.rowPtrs;
1204  double **BrowPtrs = B.rowPtrs;
1205  double **CrowPtrs = C.rowPtrs;
1206 
1207  for (unsigned int i = 0; i < A.rowNum; i++) {
1208  for (unsigned int j = 0; j < A.colNum; j++) {
1209  CrowPtrs[i][j] = ArowPtrs[i][j] - BrowPtrs[i][j];
1210  }
1211  }
1212 }
1213 
1226 void vpMatrix::sub2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
1227 {
1228  if ((A.rowNum != C.rowNum) || (A.colNum != C.colNum))
1229  C.resize(A.rowNum, A.colNum, false, false);
1230 
1231  if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
1232  throw(vpException(vpException::dimensionError, "Cannot substract (%dx%d) matrix to (%dx%d) matrix", A.getRows(),
1233  A.getCols(), B.getRows(), B.getCols()));
1234  }
1235 
1236  double **ArowPtrs = A.rowPtrs;
1237  double **BrowPtrs = B.rowPtrs;
1238  double **CrowPtrs = C.rowPtrs;
1239 
1240  for (unsigned int i = 0; i < A.rowNum; i++) {
1241  for (unsigned int j = 0; j < A.colNum; j++) {
1242  CrowPtrs[i][j] = ArowPtrs[i][j] - BrowPtrs[i][j];
1243  }
1244  }
1245 }
1246 
1252 {
1253  vpMatrix C;
1254  vpMatrix::sub2Matrices(*this, B, C);
1255  return C;
1256 }
1257 
1259 
1261 {
1262  if ((colNum != B.getCols()) || (rowNum != B.getRows())) {
1263  throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix to (%dx%d) matrix", rowNum, colNum,
1264  B.getRows(), B.getCols()));
1265  }
1266 
1267  double **BrowPtrs = B.rowPtrs;
1268 
1269  for (unsigned int i = 0; i < rowNum; i++)
1270  for (unsigned int j = 0; j < colNum; j++)
1271  rowPtrs[i][j] += BrowPtrs[i][j];
1272 
1273  return *this;
1274 }
1275 
1278 {
1279  if ((colNum != B.getCols()) || (rowNum != B.getRows())) {
1280  throw(vpException(vpException::dimensionError, "Cannot substract (%dx%d) matrix to (%dx%d) matrix", rowNum, colNum,
1281  B.getRows(), B.getCols()));
1282  }
1283 
1284  double **BrowPtrs = B.rowPtrs;
1285  for (unsigned int i = 0; i < rowNum; i++)
1286  for (unsigned int j = 0; j < colNum; j++)
1287  rowPtrs[i][j] -= BrowPtrs[i][j];
1288 
1289  return *this;
1290 }
1291 
1302 {
1303  if ((A.rowNum != C.rowNum) || (A.colNum != C.colNum))
1304  C.resize(A.rowNum, A.colNum, false, false);
1305 
1306  double **ArowPtrs = A.rowPtrs;
1307  double **CrowPtrs = C.rowPtrs;
1308 
1309  // t0=vpTime::measureTimeMicros();
1310  for (unsigned int i = 0; i < A.rowNum; i++)
1311  for (unsigned int j = 0; j < A.colNum; j++)
1312  CrowPtrs[i][j] = -ArowPtrs[i][j];
1313 }
1314 
1320 {
1321  vpMatrix C;
1322  vpMatrix::negateMatrix(*this, C);
1323  return C;
1324 }
1325 
1326 double vpMatrix::sum() const
1327 {
1328  double s = 0.0;
1329  for (unsigned int i = 0; i < rowNum; i++) {
1330  for (unsigned int j = 0; j < colNum; j++) {
1331  s += rowPtrs[i][j];
1332  }
1333  }
1334 
1335  return s;
1336 }
1337 
1338 //---------------------------------
1339 // Matrix/vector operations.
1340 //---------------------------------
1341 
1342 //---------------------------------
1343 // Matrix/real operations.
1344 //---------------------------------
1345 
1350 vpMatrix operator*(const double &x, const vpMatrix &B)
1351 {
1352  vpMatrix C(B.getRows(), B.getCols());
1353 
1354  unsigned int Brow = B.getRows();
1355  unsigned int Bcol = B.getCols();
1356 
1357  for (unsigned int i = 0; i < Brow; i++)
1358  for (unsigned int j = 0; j < Bcol; j++)
1359  C[i][j] = B[i][j] * x;
1360 
1361  return C;
1362 }
1363 
1369 {
1370  vpMatrix M(rowNum, colNum);
1371 
1372  for (unsigned int i = 0; i < rowNum; i++)
1373  for (unsigned int j = 0; j < colNum; j++)
1374  M[i][j] = rowPtrs[i][j] * x;
1375 
1376  return M;
1377 }
1378 
1381 {
1382  vpMatrix C;
1383 
1384  C.resize(rowNum, colNum, false, false);
1385 
1386  // if (x == 0) {
1387  if (std::fabs(x) <= std::numeric_limits<double>::epsilon()) {
1388  throw vpException(vpException::divideByZeroError, "Divide matrix by zero scalar");
1389  }
1390 
1391  double xinv = 1 / x;
1392 
1393  for (unsigned int i = 0; i < rowNum; i++)
1394  for (unsigned int j = 0; j < colNum; j++)
1395  C[i][j] = rowPtrs[i][j] * xinv;
1396 
1397  return C;
1398 }
1399 
1402 {
1403  for (unsigned int i = 0; i < rowNum; i++)
1404  for (unsigned int j = 0; j < colNum; j++)
1405  rowPtrs[i][j] += x;
1406 
1407  return *this;
1408 }
1409 
1412 {
1413  for (unsigned int i = 0; i < rowNum; i++)
1414  for (unsigned int j = 0; j < colNum; j++)
1415  rowPtrs[i][j] -= x;
1416 
1417  return *this;
1418 }
1419 
1425 {
1426  for (unsigned int i = 0; i < rowNum; i++)
1427  for (unsigned int j = 0; j < colNum; j++)
1428  rowPtrs[i][j] *= x;
1429 
1430  return *this;
1431 }
1432 
1435 {
1436  // if (x == 0)
1437  if (std::fabs(x) <= std::numeric_limits<double>::epsilon())
1438  throw vpException(vpException::divideByZeroError, "Divide matrix by zero scalar");
1439 
1440  double xinv = 1 / x;
1441 
1442  for (unsigned int i = 0; i < rowNum; i++)
1443  for (unsigned int j = 0; j < colNum; j++)
1444  rowPtrs[i][j] *= xinv;
1445 
1446  return *this;
1447 }
1448 
1449 //----------------------------------------------------------------
1450 // Matrix Operation
1451 //----------------------------------------------------------------
1452 
1458 {
1459  if ((out.rowNum != colNum * rowNum) || (out.colNum != 1))
1460  out.resize(colNum * rowNum, false, false);
1461 
1462  double *optr = out.data;
1463  for (unsigned int j = 0; j < colNum; j++) {
1464  for (unsigned int i = 0; i < rowNum; i++) {
1465  *(optr++) = rowPtrs[i][j];
1466  }
1467  }
1468 }
1469 
1475 {
1476  vpColVector out(colNum * rowNum);
1477  stackColumns(out);
1478  return out;
1479 }
1480 
1486 {
1487  if ((out.getRows() != 1) || (out.getCols() != colNum * rowNum))
1488  out.resize(colNum * rowNum, false, false);
1489 
1490  double *mdata = data;
1491  double *optr = out.data;
1492  for (unsigned int i = 0; i < dsize; i++) {
1493  *(optr++) = *(mdata++);
1494  }
1495 }
1501 {
1502  vpRowVector out(colNum * rowNum);
1503  stackRows(out);
1504  return out;
1505 }
1506 
1514 {
1515  if (m.getRows() != rowNum || m.getCols() != colNum) {
1516  throw(vpException(vpException::dimensionError, "In Hadamard product: bad dimension of input matrix"));
1517  }
1518 
1519  vpMatrix out;
1520  out.resize(rowNum, colNum, false);
1521 
1522  unsigned int i = 0;
1523 
1524 #if VISP_HAVE_SSE2
1525  if (vpCPUFeatures::checkSSE2() && dsize >= 2) {
1526  for (; i <= dsize - 2; i += 2) {
1527  __m128d vout = _mm_mul_pd(_mm_loadu_pd(data + i), _mm_loadu_pd(m.data + i));
1528  _mm_storeu_pd(out.data + i, vout);
1529  }
1530  }
1531 #endif
1532 
1533  for (; i < dsize; i++) {
1534  out.data[i] = data[i] * m.data[i];
1535  }
1536 
1537  return out;
1538 }
1539 
1546 void vpMatrix::kron(const vpMatrix &m1, const vpMatrix &m2, vpMatrix &out)
1547 {
1548  unsigned int r1 = m1.getRows();
1549  unsigned int c1 = m1.getCols();
1550  unsigned int r2 = m2.getRows();
1551  unsigned int c2 = m2.getCols();
1552 
1553  if (r1 * r2 != out.rowNum || c1 * c2 != out.colNum) {
1554  vpERROR_TRACE("Kronecker prodect bad dimension of output vpMatrix");
1555  throw(vpException(vpException::dimensionError, "In Kronecker product bad dimension of output matrix"));
1556  }
1557 
1558  for (unsigned int r = 0; r < r1; r++) {
1559  for (unsigned int c = 0; c < c1; c++) {
1560  double alpha = m1[r][c];
1561  double *m2ptr = m2[0];
1562  unsigned int roffset = r * r2;
1563  unsigned int coffset = c * c2;
1564  for (unsigned int rr = 0; rr < r2; rr++) {
1565  for (unsigned int cc = 0; cc < c2; cc++) {
1566  out[roffset + rr][coffset + cc] = alpha * *(m2ptr++);
1567  }
1568  }
1569  }
1570  }
1571 }
1572 
1579 void vpMatrix::kron(const vpMatrix &m, vpMatrix &out) const { kron(*this, m, out); }
1580 
1588 {
1589  unsigned int r1 = m1.getRows();
1590  unsigned int c1 = m1.getCols();
1591  unsigned int r2 = m2.getRows();
1592  unsigned int c2 = m2.getCols();
1593 
1594  vpMatrix out(r1 * r2, c1 * c2);
1595 
1596  for (unsigned int r = 0; r < r1; r++) {
1597  for (unsigned int c = 0; c < c1; c++) {
1598  double alpha = m1[r][c];
1599  double *m2ptr = m2[0];
1600  unsigned int roffset = r * r2;
1601  unsigned int coffset = c * c2;
1602  for (unsigned int rr = 0; rr < r2; rr++) {
1603  for (unsigned int cc = 0; cc < c2; cc++) {
1604  out[roffset + rr][coffset + cc] = alpha * *(m2ptr++);
1605  }
1606  }
1607  }
1608  }
1609  return out;
1610 }
1611 
1617 vpMatrix vpMatrix::kron(const vpMatrix &m) const { return kron(*this, m); }
1618 
1669 void vpMatrix::solveBySVD(const vpColVector &b, vpColVector &x) const { x = pseudoInverse(1e-6) * b; }
1670 
1721 {
1722  vpColVector X(colNum);
1723 
1724  solveBySVD(B, X);
1725  return X;
1726 }
1727 
1793 {
1794 #if defined(VISP_HAVE_LAPACK)
1795  svdLapack(w, V);
1796 #elif defined(VISP_HAVE_EIGEN3)
1797  svdEigen3(w, V);
1798 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
1799  svdOpenCV(w, V);
1800 #elif defined(VISP_HAVE_GSL)
1801  svdGsl(w, V);
1802 #else
1803  (void)w;
1804  (void)V;
1805  throw(vpException(vpException::fatalError, "Cannot compute SVD. Install Lapack, Eigen3, OpenCV or GSL 3rd party"));
1806 #endif
1807 }
1808 
1863 unsigned int vpMatrix::pseudoInverse(vpMatrix &Ap, double svThreshold) const
1864 {
1865 #if defined(VISP_HAVE_LAPACK)
1866  return pseudoInverseLapack(Ap, svThreshold);
1867 #elif defined(VISP_HAVE_EIGEN3)
1868  return pseudoInverseEigen3(Ap, svThreshold);
1869 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
1870  return pseudoInverseOpenCV(Ap, svThreshold);
1871 #elif defined(VISP_HAVE_GSL)
1872  return pseudoInverseGsl(Ap, svThreshold);
1873 #else
1874  (void)Ap;
1875  (void)svThreshold;
1876  throw(vpException(vpException::fatalError, "Cannot compute pseudo-inverse. "
1877  "Install Lapack, Eigen3, OpenCV "
1878  "or GSL 3rd party"));
1879 #endif
1880 }
1881 
1932 vpMatrix vpMatrix::pseudoInverse(double svThreshold) const
1933 {
1934 #if defined(VISP_HAVE_LAPACK)
1935  return pseudoInverseLapack(svThreshold);
1936 #elif defined(VISP_HAVE_EIGEN3)
1937  return pseudoInverseEigen3(svThreshold);
1938 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
1939  return pseudoInverseOpenCV(svThreshold);
1940 #elif defined(VISP_HAVE_GSL)
1941  return pseudoInverseGsl(svThreshold);
1942 #else
1943  (void)svThreshold;
1944  throw(vpException(vpException::fatalError, "Cannot compute pseudo-inverse. "
1945  "Install Lapack, Eigen3, OpenCV "
1946  "or GSL 3rd party"));
1947 #endif
1948 }
1949 
1950 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1951 #if defined(VISP_HAVE_LAPACK)
1952 
1988 vpMatrix vpMatrix::pseudoInverseLapack(double svThreshold) const
1989 {
1990  unsigned int nrows, ncols;
1991  unsigned int nrows_orig = getRows();
1992  unsigned int ncols_orig = getCols();
1993 
1994  vpMatrix Ap(ncols_orig, nrows_orig);
1995 
1996  if (nrows_orig >= ncols_orig) {
1997  nrows = nrows_orig;
1998  ncols = ncols_orig;
1999  } else {
2000  nrows = ncols_orig;
2001  ncols = nrows_orig;
2002  }
2003 
2004  vpMatrix U(nrows, ncols);
2005  vpMatrix V(ncols, ncols);
2006  vpColVector sv(ncols);
2007 
2008  if (nrows_orig >= ncols_orig)
2009  U = *this;
2010  else
2011  U = (*this).t();
2012 
2013  U.svdLapack(sv, V);
2014 
2015  unsigned int rank;
2016  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
2017 
2018  return Ap;
2019 }
2020 
2061 unsigned int vpMatrix::pseudoInverseLapack(vpMatrix &Ap, double svThreshold) const
2062 {
2063  unsigned int nrows, ncols;
2064  unsigned int nrows_orig = getRows();
2065  unsigned int ncols_orig = getCols();
2066  unsigned int rank;
2067 
2068  Ap.resize(ncols_orig, nrows_orig);
2069 
2070  if (nrows_orig >= ncols_orig) {
2071  nrows = nrows_orig;
2072  ncols = ncols_orig;
2073  } else {
2074  nrows = ncols_orig;
2075  ncols = nrows_orig;
2076  }
2077 
2078  vpMatrix U(nrows, ncols);
2079  vpMatrix V(ncols, ncols);
2080  vpColVector sv(ncols);
2081 
2082  if (nrows_orig >= ncols_orig)
2083  U = *this;
2084  else
2085  U = (*this).t();
2086 
2087  U.svdLapack(sv, V);
2088 
2089  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
2090 
2091  return rank;
2092 }
2140 unsigned int vpMatrix::pseudoInverseLapack(vpMatrix &Ap, vpColVector &sv, double svThreshold) const
2141 {
2142  unsigned int nrows, ncols;
2143  unsigned int nrows_orig = getRows();
2144  unsigned int ncols_orig = getCols();
2145  unsigned int rank;
2146 
2147  Ap.resize(ncols_orig, nrows_orig);
2148 
2149  if (nrows_orig >= ncols_orig) {
2150  nrows = nrows_orig;
2151  ncols = ncols_orig;
2152  } else {
2153  nrows = ncols_orig;
2154  ncols = nrows_orig;
2155  }
2156 
2157  vpMatrix U(nrows, ncols);
2158  vpMatrix V(ncols, ncols);
2159  sv.resize(ncols);
2160 
2161  if (nrows_orig >= ncols_orig)
2162  U = *this;
2163  else
2164  U = (*this).t();
2165 
2166  U.svdLapack(sv, V);
2167 
2168  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
2169 
2170  return rank;
2171 }
2172 
2280 unsigned int vpMatrix::pseudoInverseLapack(vpMatrix &Ap, vpColVector &sv, double svThreshold, vpMatrix &imA,
2281  vpMatrix &imAt, vpMatrix &kerA) const
2282 {
2283  unsigned int nrows = getRows();
2284  unsigned int ncols = getCols();
2285  unsigned int rank;
2286  vpMatrix U, V;
2287  vpColVector sv_;
2288 
2289  if (nrows < ncols) {
2290  U.resize(ncols, ncols);
2291  sv.resize(nrows);
2292  } else {
2293  U.resize(nrows, ncols);
2294  sv.resize(ncols);
2295  }
2296 
2297  U.insert(*this, 0, 0);
2298  U.svdLapack(sv_, V);
2299 
2300  compute_pseudo_inverse(U, sv_, V, nrows, ncols, svThreshold, Ap, rank, imA, imAt, kerA);
2301 
2302  // Remove singular values equal to to that correspond to the lines of 0
2303  // introduced when m < n
2304  for (unsigned int i = 0; i < sv.size(); i++)
2305  sv[i] = sv_[i];
2306 
2307  return rank;
2308 }
2309 #endif
2310 #if defined(VISP_HAVE_EIGEN3)
2311 
2347 vpMatrix vpMatrix::pseudoInverseEigen3(double svThreshold) const
2348 {
2349  unsigned int nrows, ncols;
2350  unsigned int nrows_orig = getRows();
2351  unsigned int ncols_orig = getCols();
2352 
2353  vpMatrix Ap(ncols_orig, nrows_orig);
2354 
2355  if (nrows_orig >= ncols_orig) {
2356  nrows = nrows_orig;
2357  ncols = ncols_orig;
2358  } else {
2359  nrows = ncols_orig;
2360  ncols = nrows_orig;
2361  }
2362 
2363  vpMatrix U(nrows, ncols);
2364  vpMatrix V(ncols, ncols);
2365  vpColVector sv(ncols);
2366 
2367  if (nrows_orig >= ncols_orig)
2368  U = *this;
2369  else
2370  U = (*this).t();
2371 
2372  U.svdEigen3(sv, V);
2373 
2374  unsigned int rank;
2375  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
2376 
2377  return Ap;
2378 }
2379 
2420 unsigned int vpMatrix::pseudoInverseEigen3(vpMatrix &Ap, double svThreshold) const
2421 {
2422  unsigned int nrows, ncols;
2423  unsigned int nrows_orig = getRows();
2424  unsigned int ncols_orig = getCols();
2425  unsigned int rank;
2426 
2427  Ap.resize(ncols_orig, nrows_orig);
2428 
2429  if (nrows_orig >= ncols_orig) {
2430  nrows = nrows_orig;
2431  ncols = ncols_orig;
2432  } else {
2433  nrows = ncols_orig;
2434  ncols = nrows_orig;
2435  }
2436 
2437  vpMatrix U(nrows, ncols);
2438  vpMatrix V(ncols, ncols);
2439  vpColVector sv(ncols);
2440 
2441  if (nrows_orig >= ncols_orig)
2442  U = *this;
2443  else
2444  U = (*this).t();
2445 
2446  U.svdEigen3(sv, V);
2447 
2448  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
2449 
2450  return rank;
2451 }
2499 unsigned int vpMatrix::pseudoInverseEigen3(vpMatrix &Ap, vpColVector &sv, double svThreshold) const
2500 {
2501  unsigned int nrows, ncols;
2502  unsigned int nrows_orig = getRows();
2503  unsigned int ncols_orig = getCols();
2504  unsigned int rank;
2505 
2506  Ap.resize(ncols_orig, nrows_orig);
2507 
2508  if (nrows_orig >= ncols_orig) {
2509  nrows = nrows_orig;
2510  ncols = ncols_orig;
2511  } else {
2512  nrows = ncols_orig;
2513  ncols = nrows_orig;
2514  }
2515 
2516  vpMatrix U(nrows, ncols);
2517  vpMatrix V(ncols, ncols);
2518  sv.resize(ncols);
2519 
2520  if (nrows_orig >= ncols_orig)
2521  U = *this;
2522  else
2523  U = (*this).t();
2524 
2525  U.svdEigen3(sv, V);
2526 
2527  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
2528 
2529  return rank;
2530 }
2531 
2639 unsigned int vpMatrix::pseudoInverseEigen3(vpMatrix &Ap, vpColVector &sv, double svThreshold, vpMatrix &imA,
2640  vpMatrix &imAt, vpMatrix &kerA) const
2641 {
2642  unsigned int nrows = getRows();
2643  unsigned int ncols = getCols();
2644  unsigned int rank;
2645  vpMatrix U, V;
2646  vpColVector sv_;
2647 
2648  if (nrows < ncols) {
2649  U.resize(ncols, ncols);
2650  sv.resize(nrows);
2651  } else {
2652  U.resize(nrows, ncols);
2653  sv.resize(ncols);
2654  }
2655 
2656  U.insert(*this, 0, 0);
2657  U.svdEigen3(sv_, V);
2658 
2659  compute_pseudo_inverse(U, sv_, V, nrows, ncols, svThreshold, Ap, rank, imA, imAt, kerA);
2660 
2661  // Remove singular values equal to to that correspond to the lines of 0
2662  // introduced when m < n
2663  for (unsigned int i = 0; i < sv.size(); i++)
2664  sv[i] = sv_[i];
2665 
2666  return rank;
2667 }
2668 #endif
2669 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
2670 
2706 vpMatrix vpMatrix::pseudoInverseOpenCV(double svThreshold) const
2707 {
2708  unsigned int nrows, ncols;
2709  unsigned int nrows_orig = getRows();
2710  unsigned int ncols_orig = getCols();
2711 
2712  vpMatrix Ap(ncols_orig, nrows_orig);
2713 
2714  if (nrows_orig >= ncols_orig) {
2715  nrows = nrows_orig;
2716  ncols = ncols_orig;
2717  } else {
2718  nrows = ncols_orig;
2719  ncols = nrows_orig;
2720  }
2721 
2722  vpMatrix U(nrows, ncols);
2723  vpMatrix V(ncols, ncols);
2724  vpColVector sv(ncols);
2725 
2726  if (nrows_orig >= ncols_orig)
2727  U = *this;
2728  else
2729  U = (*this).t();
2730 
2731  U.svdOpenCV(sv, V);
2732 
2733  unsigned int rank;
2734  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
2735 
2736  return Ap;
2737 }
2738 
2779 unsigned int vpMatrix::pseudoInverseOpenCV(vpMatrix &Ap, double svThreshold) const
2780 {
2781  unsigned int nrows, ncols;
2782  unsigned int nrows_orig = getRows();
2783  unsigned int ncols_orig = getCols();
2784  unsigned int rank;
2785 
2786  Ap.resize(ncols_orig, nrows_orig);
2787 
2788  if (nrows_orig >= ncols_orig) {
2789  nrows = nrows_orig;
2790  ncols = ncols_orig;
2791  } else {
2792  nrows = ncols_orig;
2793  ncols = nrows_orig;
2794  }
2795 
2796  vpMatrix U(nrows, ncols);
2797  vpMatrix V(ncols, ncols);
2798  vpColVector sv(ncols);
2799 
2800  if (nrows_orig >= ncols_orig)
2801  U = *this;
2802  else
2803  U = (*this).t();
2804 
2805  U.svdOpenCV(sv, V);
2806 
2807  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
2808 
2809  return rank;
2810 }
2858 unsigned int vpMatrix::pseudoInverseOpenCV(vpMatrix &Ap, vpColVector &sv, double svThreshold) const
2859 {
2860  unsigned int nrows, ncols;
2861  unsigned int nrows_orig = getRows();
2862  unsigned int ncols_orig = getCols();
2863  unsigned int rank;
2864 
2865  Ap.resize(ncols_orig, nrows_orig);
2866 
2867  if (nrows_orig >= ncols_orig) {
2868  nrows = nrows_orig;
2869  ncols = ncols_orig;
2870  } else {
2871  nrows = ncols_orig;
2872  ncols = nrows_orig;
2873  }
2874 
2875  vpMatrix U(nrows, ncols);
2876  vpMatrix V(ncols, ncols);
2877  sv.resize(ncols);
2878 
2879  if (nrows_orig >= ncols_orig)
2880  U = *this;
2881  else
2882  U = (*this).t();
2883 
2884  U.svdOpenCV(sv, V);
2885 
2886  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
2887 
2888  return rank;
2889 }
2890 
2998 unsigned int vpMatrix::pseudoInverseOpenCV(vpMatrix &Ap, vpColVector &sv, double svThreshold, vpMatrix &imA,
2999  vpMatrix &imAt, vpMatrix &kerA) const
3000 {
3001  unsigned int nrows = getRows();
3002  unsigned int ncols = getCols();
3003  unsigned int rank;
3004  vpMatrix U, V;
3005  vpColVector sv_;
3006 
3007  if (nrows < ncols) {
3008  U.resize(ncols, ncols);
3009  sv.resize(nrows);
3010  } else {
3011  U.resize(nrows, ncols);
3012  sv.resize(ncols);
3013  }
3014 
3015  U.insert(*this, 0, 0);
3016  U.svdOpenCV(sv_, V);
3017 
3018  compute_pseudo_inverse(U, sv_, V, nrows, ncols, svThreshold, Ap, rank, imA, imAt, kerA);
3019 
3020  // Remove singular values equal to to that correspond to the lines of 0
3021  // introduced when m < n
3022  for (unsigned int i = 0; i < sv.size(); i++)
3023  sv[i] = sv_[i];
3024 
3025  return rank;
3026 }
3027 #endif
3028 #if defined(VISP_HAVE_GSL)
3029 
3065 vpMatrix vpMatrix::pseudoInverseGsl(double svThreshold) const
3066 {
3067  unsigned int nrows, ncols;
3068  unsigned int nrows_orig = getRows();
3069  unsigned int ncols_orig = getCols();
3070 
3071  vpMatrix Ap(ncols_orig, nrows_orig);
3072 
3073  if (nrows_orig >= ncols_orig) {
3074  nrows = nrows_orig;
3075  ncols = ncols_orig;
3076  } else {
3077  nrows = ncols_orig;
3078  ncols = nrows_orig;
3079  }
3080 
3081  vpMatrix U(nrows, ncols);
3082  vpMatrix V(ncols, ncols);
3083  vpColVector sv(ncols);
3084 
3085  if (nrows_orig >= ncols_orig)
3086  U = *this;
3087  else
3088  U = (*this).t();
3089 
3090  U.svdGsl(sv, V);
3091 
3092  unsigned int rank;
3093  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
3094 
3095  return Ap;
3096 }
3097 
3138 unsigned int vpMatrix::pseudoInverseGsl(vpMatrix &Ap, double svThreshold) const
3139 {
3140  unsigned int nrows, ncols;
3141  unsigned int nrows_orig = getRows();
3142  unsigned int ncols_orig = getCols();
3143  unsigned int rank;
3144 
3145  Ap.resize(ncols_orig, nrows_orig);
3146 
3147  if (nrows_orig >= ncols_orig) {
3148  nrows = nrows_orig;
3149  ncols = ncols_orig;
3150  } else {
3151  nrows = ncols_orig;
3152  ncols = nrows_orig;
3153  }
3154 
3155  vpMatrix U(nrows, ncols);
3156  vpMatrix V(ncols, ncols);
3157  vpColVector sv(ncols);
3158 
3159  if (nrows_orig >= ncols_orig)
3160  U = *this;
3161  else
3162  U = (*this).t();
3163 
3164  U.svdGsl(sv, V);
3165 
3166  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
3167 
3168  return rank;
3169 }
3217 unsigned int vpMatrix::pseudoInverseGsl(vpMatrix &Ap, vpColVector &sv, double svThreshold) const
3218 {
3219  unsigned int nrows, ncols;
3220  unsigned int nrows_orig = getRows();
3221  unsigned int ncols_orig = getCols();
3222  unsigned int rank;
3223 
3224  Ap.resize(ncols_orig, nrows_orig);
3225 
3226  if (nrows_orig >= ncols_orig) {
3227  nrows = nrows_orig;
3228  ncols = ncols_orig;
3229  } else {
3230  nrows = ncols_orig;
3231  ncols = nrows_orig;
3232  }
3233 
3234  vpMatrix U(nrows, ncols);
3235  vpMatrix V(ncols, ncols);
3236  sv.resize(ncols);
3237 
3238  if (nrows_orig >= ncols_orig)
3239  U = *this;
3240  else
3241  U = (*this).t();
3242 
3243  U.svdGsl(sv, V);
3244 
3245  compute_pseudo_inverse(U, sv, V, nrows, ncols, nrows_orig, ncols_orig, svThreshold, Ap, rank);
3246 
3247  return rank;
3248 }
3249 
3356 unsigned int vpMatrix::pseudoInverseGsl(vpMatrix &Ap, vpColVector &sv, double svThreshold, vpMatrix &imA,
3357  vpMatrix &imAt, vpMatrix &kerA) const
3358 {
3359  unsigned int nrows = getRows();
3360  unsigned int ncols = getCols();
3361  unsigned int rank;
3362  vpMatrix U, V;
3363  vpColVector sv_;
3364 
3365  if (nrows < ncols) {
3366  U.resize(ncols, ncols);
3367  sv.resize(nrows);
3368  } else {
3369  U.resize(nrows, ncols);
3370  sv.resize(ncols);
3371  }
3372 
3373  U.insert(*this, 0, 0);
3374  U.svdGsl(sv_, V);
3375 
3376  compute_pseudo_inverse(U, sv_, V, nrows, ncols, svThreshold, Ap, rank, imA, imAt, kerA);
3377 
3378  // Remove singular values equal to to that correspond to the lines of 0
3379  // introduced when m < n
3380  for (unsigned int i = 0; i < sv.size(); i++)
3381  sv[i] = sv_[i];
3382 
3383  return rank;
3384 }
3385 #endif
3386 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
3387 
3449 unsigned int vpMatrix::pseudoInverse(vpMatrix &Ap, vpColVector &sv, double svThreshold) const
3450 {
3451 #if defined(VISP_HAVE_LAPACK)
3452  return pseudoInverseLapack(Ap, sv, svThreshold);
3453 #elif defined(VISP_HAVE_EIGEN3)
3454  return pseudoInverseEigen3(Ap, sv, svThreshold);
3455 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
3456  return pseudoInverseOpenCV(Ap, sv, svThreshold);
3457 #elif defined(VISP_HAVE_GSL)
3458  return pseudoInverseGsl(Ap, sv, svThreshold);
3459 #else
3460  (void)Ap;
3461  (void)sv;
3462  (void)svThreshold;
3463  throw(vpException(vpException::fatalError, "Cannot compute pseudo-inverse. "
3464  "Install Lapack, Eigen3, OpenCV "
3465  "or GSL 3rd party"));
3466 #endif
3467 }
3468 
3543 unsigned int vpMatrix::pseudoInverse(vpMatrix &Ap, vpColVector &sv, double svThreshold, vpMatrix &imA,
3544  vpMatrix &imAt) const
3545 {
3546  vpMatrix kerAt;
3547  return pseudoInverse(Ap, sv, svThreshold, imA, imAt, kerAt);
3548 }
3549 
3684 unsigned int vpMatrix::pseudoInverse(vpMatrix &Ap, vpColVector &sv, double svThreshold, vpMatrix &imA, vpMatrix &imAt,
3685  vpMatrix &kerAt) const
3686 {
3687 #if defined(VISP_HAVE_LAPACK)
3688  return pseudoInverseLapack(Ap, sv, svThreshold, imA, imAt, kerAt);
3689 #elif defined(VISP_HAVE_EIGEN3)
3690  return pseudoInverseEigen3(Ap, sv, svThreshold, imA, imAt, kerAt);
3691 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
3692  return pseudoInverseOpenCV(Ap, sv, svThreshold, imA, imAt, kerAt);
3693 #elif defined(VISP_HAVE_GSL)
3694  return pseudoInverseGsl(Ap, sv, svThreshold, imA, imAt, kerAt);
3695 #else
3696  (void)Ap;
3697  (void)sv;
3698  (void)svThreshold;
3699  (void)imA;
3700  (void)imAt;
3701  (void)kerAt;
3702  throw(vpException(vpException::fatalError, "Cannot compute pseudo-inverse. "
3703  "Install Lapack, Eigen3, OpenCV "
3704  "or GSL 3rd party"));
3705 #endif
3706 }
3707 
3749 vpColVector vpMatrix::getCol(const unsigned int j, const unsigned int i_begin, const unsigned int column_size) const
3750 {
3751  if (i_begin + column_size > getRows() || j >= getCols())
3752  throw(vpException(vpException::dimensionError, "Unable to extract column %u from the %ux%u matrix", j, getRows(), getCols()));
3753  vpColVector c(column_size);
3754  for (unsigned int i = 0; i < column_size; i++)
3755  c[i] = (*this)[i_begin + i][j];
3756  return c;
3757 }
3758 
3798 vpColVector vpMatrix::getCol(const unsigned int j) const
3799 {
3800  if (j >= getCols())
3801  throw(vpException(vpException::dimensionError, "Unable to extract column %u from the %ux%u matrix", j, getRows(), getCols()));
3802  unsigned int nb_rows = getRows();
3803  vpColVector c(nb_rows);
3804  for (unsigned int i = 0; i < nb_rows; i++)
3805  c[i] = (*this)[i][j];
3806  return c;
3807 }
3808 
3844 vpRowVector vpMatrix::getRow(const unsigned int i) const
3845 {
3846  if (i >= getRows())
3847  throw(vpException(vpException::dimensionError, "Unable to extract a row vector from the matrix"));
3848 
3849  vpRowVector r;
3850  r.resize(colNum, false);
3851 
3852  if (r.data != NULL && data != NULL && r.data != data) {
3853  memcpy(r.data, data + i * colNum, sizeof(double) * colNum);
3854  }
3855 
3856  return r;
3857 }
3858 
3896 vpRowVector vpMatrix::getRow(const unsigned int i, const unsigned int j_begin, const unsigned int row_size) const
3897 {
3898  if (j_begin + row_size > getCols() || i >= getRows())
3899  throw(vpException(vpException::dimensionError, "Unable to extract a row vector from the matrix"));
3900  vpRowVector r(row_size);
3901  for (unsigned int j = 0; j < row_size; j++)
3902  r[j] = (*this)[i][j_begin + i];
3903  return r;
3904 }
3905 
3917 {
3918  vpMatrix C;
3919 
3920  vpMatrix::stack(A, B, C);
3921 
3922  return C;
3923 }
3924 
3936 void vpMatrix::stack(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
3937 {
3938  unsigned int nra = A.getRows();
3939  unsigned int nrb = B.getRows();
3940 
3941  if (nra != 0) {
3942  if (A.getCols() != B.getCols()) {
3943  throw(vpException(vpException::dimensionError, "Cannot stack (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
3944  A.getCols(), B.getRows(), B.getCols()));
3945  }
3946  }
3947 
3948  if (A.data != NULL && A.data == C.data) {
3949  std::cerr << "A and C must be two different objects!" << std::endl;
3950  return;
3951  }
3952 
3953  if (B.data != NULL && B.data == C.data) {
3954  std::cerr << "B and C must be two different objects!" << std::endl;
3955  return;
3956  }
3957 
3958  C.resize(nra + nrb, B.getCols(), false, false);
3959 
3960  if (C.data != NULL && A.data != NULL && A.size() > 0) {
3961  // Copy A in C
3962  memcpy(C.data, A.data, sizeof(double) * A.size());
3963  }
3964 
3965  if (C.data != NULL && B.data != NULL && B.size() > 0) {
3966  // Copy B in C
3967  memcpy(C.data + A.size(), B.data, sizeof(double) * B.size());
3968  }
3969 }
3970 
3981 {
3982  vpMatrix C;
3983  vpMatrix::stack(A, r, C);
3984 
3985  return C;
3986 }
3987 
3999 void vpMatrix::stack(const vpMatrix &A, const vpRowVector &r, vpMatrix &C)
4000 {
4001  if (A.data != NULL && A.data == C.data) {
4002  std::cerr << "A and C must be two different objects!" << std::endl;
4003  return;
4004  }
4005 
4006  C = A;
4007  C.stack(r);
4008 }
4009 
4020 {
4021  vpMatrix C;
4022  vpMatrix::stack(A, c, C);
4023 
4024  return C;
4025 }
4026 
4038 void vpMatrix::stack(const vpMatrix &A, const vpColVector &c, vpMatrix &C)
4039 {
4040  if (A.data != NULL && A.data == C.data) {
4041  std::cerr << "A and C must be two different objects!" << std::endl;
4042  return;
4043  }
4044 
4045  C = A;
4046  C.stack(c);
4047 }
4048 
4061 vpMatrix vpMatrix::insert(const vpMatrix &A, const vpMatrix &B, const unsigned int r, const unsigned int c)
4062 {
4063  vpMatrix C;
4064 
4065  insert(A, B, C, r, c);
4066 
4067  return C;
4068 }
4069 
4083 void vpMatrix::insert(const vpMatrix &A, const vpMatrix &B, vpMatrix &C, const unsigned int r, const unsigned int c)
4084 {
4085  if (((r + B.getRows()) <= A.getRows()) && ((c + B.getCols()) <= A.getCols())) {
4086  C.resize(A.getRows(), A.getCols(), false, false);
4087 
4088  for (unsigned int i = 0; i < A.getRows(); i++) {
4089  for (unsigned int j = 0; j < A.getCols(); j++) {
4090  if (i >= r && i < (r + B.getRows()) && j >= c && j < (c + B.getCols())) {
4091  C[i][j] = B[i - r][j - c];
4092  } else {
4093  C[i][j] = A[i][j];
4094  }
4095  }
4096  }
4097  } else {
4098  throw vpException(vpException::dimensionError, "Cannot insert (%dx%d) matrix in (%dx%d) matrix at position (%d,%d)",
4099  B.getRows(), B.getCols(), A.getCols(), A.getRows(), r, c);
4100  }
4101 }
4102 
4115 {
4116  vpMatrix C;
4117 
4118  juxtaposeMatrices(A, B, C);
4119 
4120  return C;
4121 }
4122 
4136 {
4137  unsigned int nca = A.getCols();
4138  unsigned int ncb = B.getCols();
4139 
4140  if (nca != 0) {
4141  if (A.getRows() != B.getRows()) {
4142  throw(vpException(vpException::dimensionError, "Cannot juxtapose (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
4143  A.getCols(), B.getRows(), B.getCols()));
4144  }
4145  }
4146 
4147  if (B.getRows() == 0 || nca + ncb == 0) {
4148  std::cerr << "B.getRows() == 0 || nca+ncb == 0" << std::endl;
4149  return;
4150  }
4151 
4152  C.resize(B.getRows(), nca + ncb, false, false);
4153 
4154  C.insert(A, 0, 0);
4155  C.insert(B, 0, nca);
4156 }
4157 
4158 //--------------------------------------------------------------------
4159 // Output
4160 //--------------------------------------------------------------------
4161 
4181 int vpMatrix::print(std::ostream &s, unsigned int length, char const *intro) const
4182 {
4183  typedef std::string::size_type size_type;
4184 
4185  unsigned int m = getRows();
4186  unsigned int n = getCols();
4187 
4188  std::vector<std::string> values(m * n);
4189  std::ostringstream oss;
4190  std::ostringstream ossFixed;
4191  std::ios_base::fmtflags original_flags = oss.flags();
4192 
4193  // ossFixed <<std::fixed;
4194  ossFixed.setf(std::ios::fixed, std::ios::floatfield);
4195 
4196  size_type maxBefore = 0; // the length of the integral part
4197  size_type maxAfter = 0; // number of decimals plus
4198  // one place for the decimal point
4199  for (unsigned int i = 0; i < m; ++i) {
4200  for (unsigned int j = 0; j < n; ++j) {
4201  oss.str("");
4202  oss << (*this)[i][j];
4203  if (oss.str().find("e") != std::string::npos) {
4204  ossFixed.str("");
4205  ossFixed << (*this)[i][j];
4206  oss.str(ossFixed.str());
4207  }
4208 
4209  values[i * n + j] = oss.str();
4210  size_type thislen = values[i * n + j].size();
4211  size_type p = values[i * n + j].find('.');
4212 
4213  if (p == std::string::npos) {
4214  maxBefore = vpMath::maximum(maxBefore, thislen);
4215  // maxAfter remains the same
4216  } else {
4217  maxBefore = vpMath::maximum(maxBefore, p);
4218  maxAfter = vpMath::maximum(maxAfter, thislen - p - 1);
4219  }
4220  }
4221  }
4222 
4223  size_type totalLength = length;
4224  // increase totalLength according to maxBefore
4225  totalLength = vpMath::maximum(totalLength, maxBefore);
4226  // decrease maxAfter according to totalLength
4227  maxAfter = (std::min)(maxAfter, totalLength - maxBefore);
4228  if (maxAfter == 1)
4229  maxAfter = 0;
4230 
4231  // the following line is useful for debugging
4232  // std::cerr <<totalLength <<" " <<maxBefore <<" " <<maxAfter <<"\n";
4233 
4234  if (intro)
4235  s << intro;
4236  s << "[" << m << "," << n << "]=\n";
4237 
4238  for (unsigned int i = 0; i < m; i++) {
4239  s << " ";
4240  for (unsigned int j = 0; j < n; j++) {
4241  size_type p = values[i * n + j].find('.');
4242  s.setf(std::ios::right, std::ios::adjustfield);
4243  s.width((std::streamsize)maxBefore);
4244  s << values[i * n + j].substr(0, p).c_str();
4245 
4246  if (maxAfter > 0) {
4247  s.setf(std::ios::left, std::ios::adjustfield);
4248  if (p != std::string::npos) {
4249  s.width((std::streamsize)maxAfter);
4250  s << values[i * n + j].substr(p, maxAfter).c_str();
4251  } else {
4252  assert(maxAfter > 1);
4253  s.width((std::streamsize)maxAfter);
4254  s << ".0";
4255  }
4256  }
4257 
4258  s << ' ';
4259  }
4260  s << std::endl;
4261  }
4262 
4263  s.flags(original_flags); // restore s to standard state
4264 
4265  return (int)(maxBefore + maxAfter);
4266 }
4267 
4304 std::ostream &vpMatrix::matlabPrint(std::ostream &os) const
4305 {
4306  os << "[ ";
4307  for (unsigned int i = 0; i < this->getRows(); ++i) {
4308  for (unsigned int j = 0; j < this->getCols(); ++j) {
4309  os << (*this)[i][j] << ", ";
4310  }
4311  if (this->getRows() != i + 1) {
4312  os << ";" << std::endl;
4313  } else {
4314  os << "]" << std::endl;
4315  }
4316  }
4317  return os;
4318 }
4319 
4348 std::ostream &vpMatrix::maplePrint(std::ostream &os) const
4349 {
4350  os << "([ " << std::endl;
4351  for (unsigned int i = 0; i < this->getRows(); ++i) {
4352  os << "[";
4353  for (unsigned int j = 0; j < this->getCols(); ++j) {
4354  os << (*this)[i][j] << ", ";
4355  }
4356  os << "]," << std::endl;
4357  }
4358  os << "])" << std::endl;
4359  return os;
4360 }
4361 
4389 std::ostream &vpMatrix::csvPrint(std::ostream &os) const
4390 {
4391  for (unsigned int i = 0; i < this->getRows(); ++i) {
4392  for (unsigned int j = 0; j < this->getCols(); ++j) {
4393  os << (*this)[i][j];
4394  if (!(j == (this->getCols() - 1)))
4395  os << ", ";
4396  }
4397  os << std::endl;
4398  }
4399  return os;
4400 }
4401 
4438 std::ostream &vpMatrix::cppPrint(std::ostream &os, const std::string &matrixName, bool octet) const
4439 {
4440  os << "vpMatrix " << matrixName << " (" << this->getRows() << ", " << this->getCols() << "); " << std::endl;
4441 
4442  for (unsigned int i = 0; i < this->getRows(); ++i) {
4443  for (unsigned int j = 0; j < this->getCols(); ++j) {
4444  if (!octet) {
4445  os << matrixName << "[" << i << "][" << j << "] = " << (*this)[i][j] << "; " << std::endl;
4446  } else {
4447  for (unsigned int k = 0; k < sizeof(double); ++k) {
4448  os << "((unsigned char*)&(" << matrixName << "[" << i << "][" << j << "]) )[" << k << "] = 0x" << std::hex
4449  << (unsigned int)((unsigned char *)&((*this)[i][j]))[k] << "; " << std::endl;
4450  }
4451  }
4452  }
4453  os << std::endl;
4454  }
4455  return os;
4456 }
4457 
4463 {
4464  if (rowNum == 0) {
4465  *this = A;
4466  } else if (A.getRows() > 0) {
4467  if (colNum != A.getCols()) {
4468  throw(vpException(vpException::dimensionError, "Cannot stack (%dx%d) matrix with (%dx%d) matrix", rowNum, colNum,
4469  A.getRows(), A.getCols()));
4470  }
4471 
4472  unsigned int rowNumOld = rowNum;
4473  resize(rowNum + A.getRows(), colNum, false, false);
4474  insert(A, rowNumOld, 0);
4475  }
4476 }
4477 
4494 {
4495  if (rowNum == 0) {
4496  *this = r;
4497  } else {
4498  if (colNum != r.getCols()) {
4499  throw(vpException(vpException::dimensionError, "Cannot stack (%dx%d) matrix with (1x%d) row vector", rowNum,
4500  colNum, r.getCols()));
4501  }
4502 
4503  if (r.size() == 0) {
4504  return;
4505  }
4506 
4507  unsigned int oldSize = size();
4508  resize(rowNum + 1, colNum, false, false);
4509 
4510  if (data != NULL && r.data != NULL && data != r.data) {
4511  // Copy r in data
4512  memcpy(data + oldSize, r.data, sizeof(double) * r.size());
4513  }
4514  }
4515 }
4516 
4533 {
4534  if (colNum == 0) {
4535  *this = c;
4536  } else {
4537  if (rowNum != c.getRows()) {
4538  throw(vpException(vpException::dimensionError, "Cannot stack (%dx%d) matrix with (%dx1) column vector", rowNum,
4539  colNum, c.getRows()));
4540  }
4541 
4542  if (c.size() == 0) {
4543  return;
4544  }
4545 
4546  vpMatrix tmp = *this;
4547  unsigned int oldColNum = colNum;
4548  resize(rowNum, colNum + 1, false, false);
4549 
4550  if (data != NULL && tmp.data != NULL && data != tmp.data) {
4551  // Copy c in data
4552  for (unsigned int i = 0; i < rowNum; i++) {
4553  memcpy(data + i*colNum, tmp.data + i*oldColNum, sizeof(double) * oldColNum);
4554  rowPtrs[i][oldColNum] = c[i];
4555  }
4556  }
4557  }
4558 }
4559 
4570 void vpMatrix::insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
4571 {
4572  if ((r + A.getRows()) <= rowNum && (c + A.getCols()) <= colNum) {
4573  if (A.colNum == colNum && data != NULL && A.data != NULL && A.data != data) {
4574  memcpy(data + r * colNum, A.data, sizeof(double) * A.size());
4575  } else if (data != NULL && A.data != NULL && A.data != data) {
4576  for (unsigned int i = r; i < (r + A.getRows()); i++) {
4577  memcpy(data + i * colNum + c, A.data + (i - r) * A.colNum, sizeof(double) * A.colNum);
4578  }
4579  }
4580  } else {
4581  throw vpException(vpException::dimensionError, "Cannot insert (%dx%d) matrix in (%dx%d) matrix at position (%d,%d)",
4582  A.getRows(), A.getCols(), rowNum, colNum, r, c);
4583  }
4584 }
4585 
4625 {
4626  if (rowNum != colNum) {
4627  throw(vpException(vpException::dimensionError, "Cannot compute eigen values on a non square matrix (%dx%d)", rowNum,
4628  colNum));
4629  }
4630 
4631 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
4632  {
4633  // Check if the matrix is symetric: At - A = 0
4634  vpMatrix At_A = (*this).t() - (*this);
4635  for (unsigned int i = 0; i < rowNum; i++) {
4636  for (unsigned int j = 0; j < rowNum; j++) {
4637  // if (At_A[i][j] != 0) {
4638  if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
4639  throw(vpException(vpException::fatalError, "Cannot compute eigen values on a non symetric matrix"));
4640  }
4641  }
4642  }
4643 
4644  vpColVector evalue(rowNum); // Eigen values
4645 
4646  gsl_vector *eval = gsl_vector_alloc(rowNum);
4647  gsl_matrix *evec = gsl_matrix_alloc(rowNum, colNum);
4648 
4649  gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(rowNum);
4650  gsl_matrix *m = gsl_matrix_alloc(rowNum, colNum);
4651 
4652  unsigned int Atda = (unsigned int)m->tda;
4653  for (unsigned int i = 0; i < rowNum; i++) {
4654  unsigned int k = i * Atda;
4655  for (unsigned int j = 0; j < colNum; j++)
4656  m->data[k + j] = (*this)[i][j];
4657  }
4658  gsl_eigen_symmv(m, eval, evec, w);
4659 
4660  gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_ASC);
4661 
4662  for (unsigned int i = 0; i < rowNum; i++) {
4663  evalue[i] = gsl_vector_get(eval, i);
4664  }
4665 
4666  gsl_eigen_symmv_free(w);
4667  gsl_vector_free(eval);
4668  gsl_matrix_free(m);
4669  gsl_matrix_free(evec);
4670 
4671  return evalue;
4672  }
4673 #else
4674  {
4675  throw(vpException(vpException::functionNotImplementedError, "Eigen values computation is not implemented. You "
4676  "should install GSL rd party"));
4677  }
4678 #endif
4679 }
4680 
4734 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
4735 void vpMatrix::eigenValues(vpColVector &evalue, vpMatrix &evector) const
4736 #else
4737 void vpMatrix::eigenValues(vpColVector & /* evalue */, vpMatrix & /* evector */) const
4738 #endif
4739 {
4740  if (rowNum != colNum) {
4741  throw(vpException(vpException::dimensionError, "Cannot compute eigen values on a non square matrix (%dx%d)", rowNum,
4742  colNum));
4743  }
4744 
4745 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
4746  {
4747  // Check if the matrix is symetric: At - A = 0
4748  vpMatrix At_A = (*this).t() - (*this);
4749  for (unsigned int i = 0; i < rowNum; i++) {
4750  for (unsigned int j = 0; j < rowNum; j++) {
4751  // if (At_A[i][j] != 0) {
4752  if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
4753  throw(vpException(vpException::fatalError, "Cannot compute eigen values on a non symetric matrix"));
4754  }
4755  }
4756  }
4757 
4758  // Resize the output matrices
4759  evalue.resize(rowNum);
4760  evector.resize(rowNum, colNum);
4761 
4762  gsl_vector *eval = gsl_vector_alloc(rowNum);
4763  gsl_matrix *evec = gsl_matrix_alloc(rowNum, colNum);
4764 
4765  gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(rowNum);
4766  gsl_matrix *m = gsl_matrix_alloc(rowNum, colNum);
4767 
4768  unsigned int Atda = (unsigned int)m->tda;
4769  for (unsigned int i = 0; i < rowNum; i++) {
4770  unsigned int k = i * Atda;
4771  for (unsigned int j = 0; j < colNum; j++)
4772  m->data[k + j] = (*this)[i][j];
4773  }
4774  gsl_eigen_symmv(m, eval, evec, w);
4775 
4776  gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_ASC);
4777 
4778  for (unsigned int i = 0; i < rowNum; i++) {
4779  evalue[i] = gsl_vector_get(eval, i);
4780  }
4781  Atda = (unsigned int)evec->tda;
4782  for (unsigned int i = 0; i < rowNum; i++) {
4783  unsigned int k = i * Atda;
4784  for (unsigned int j = 0; j < rowNum; j++) {
4785  evector[i][j] = evec->data[k + j];
4786  }
4787  }
4788 
4789  gsl_eigen_symmv_free(w);
4790  gsl_vector_free(eval);
4791  gsl_matrix_free(m);
4792  gsl_matrix_free(evec);
4793  }
4794 #else
4795  {
4796  throw(vpException(vpException::functionNotImplementedError, "Eigen values computation is not implemented. You "
4797  "should install GSL rd party"));
4798  }
4799 #endif
4800 }
4801 
4821 unsigned int vpMatrix::kernel(vpMatrix &kerAt, double svThreshold) const
4822 {
4823  unsigned int nbline = getRows();
4824  unsigned int nbcol = getCols();
4825 
4826  vpMatrix U; // Copy of the matrix, SVD function is destructive
4827  vpColVector sv(nbcol); // singular values
4828  vpMatrix V(nbcol, nbcol); // V matrix of singular value decomposition
4829 
4830  // Copy and resize matrix to have at least as many rows as columns
4831  // kernel is computed in svd method only if the matrix has more rows than
4832  // columns
4833 
4834  if (nbline < nbcol)
4835  U.resize(nbcol, nbcol);
4836  else
4837  U.resize(nbline, nbcol);
4838 
4839  U.insert(*this, 0, 0);
4840 
4841  U.svd(sv, V);
4842 
4843  // Compute the highest singular value and rank of the matrix
4844  double maxsv = 0;
4845  for (unsigned int i = 0; i < nbcol; i++) {
4846  if (fabs(sv[i]) > maxsv) {
4847  maxsv = fabs(sv[i]);
4848  }
4849  }
4850 
4851  unsigned int rank = 0;
4852  for (unsigned int i = 0; i < nbcol; i++) {
4853  if (fabs(sv[i]) > maxsv * svThreshold) {
4854  rank++;
4855  }
4856  }
4857 
4858  kerAt.resize(nbcol - rank, nbcol);
4859  if (rank != nbcol) {
4860  for (unsigned int j = 0, k = 0; j < nbcol; j++) {
4861  // if( v.col(j) in kernel and non zero )
4862  if ((fabs(sv[j]) <= maxsv * svThreshold) &&
4863  (std::fabs(V.getCol(j).sumSquare()) > std::numeric_limits<double>::epsilon())) {
4864  for (unsigned int i = 0; i < V.getRows(); i++) {
4865  kerAt[k][i] = V[i][j];
4866  }
4867  k++;
4868  }
4869  }
4870  }
4871 
4872  return rank;
4873 }
4874 
4906 double vpMatrix::det(vpDetMethod method) const
4907 {
4908  double det = 0.;
4909 
4910  if (method == LU_DECOMPOSITION) {
4911  det = this->detByLU();
4912  }
4913 
4914  return (det);
4915 }
4916 
4925 {
4926  if (colNum != rowNum) {
4927  throw(vpException(vpException::dimensionError, "Cannot compute the exponential of a non square (%dx%d) matrix",
4928  rowNum, colNum));
4929  } else {
4930 #ifdef VISP_HAVE_GSL
4931  size_t size_ = rowNum * colNum;
4932  double *b = new double[size_];
4933  for (size_t i = 0; i < size_; i++)
4934  b[i] = 0.;
4935  gsl_matrix_view m = gsl_matrix_view_array(this->data, rowNum, colNum);
4936  gsl_matrix_view em = gsl_matrix_view_array(b, rowNum, colNum);
4937  gsl_linalg_exponential_ss(&m.matrix, &em.matrix, 0);
4938  // gsl_matrix_fprintf(stdout, &em.matrix, "%g");
4939  vpMatrix expA(rowNum, colNum);
4940  memcpy(expA.data, b, size_ * sizeof(double));
4941 
4942  delete[] b;
4943  return expA;
4944 #else
4945  vpMatrix _expE(rowNum, colNum);
4946  vpMatrix _expD(rowNum, colNum);
4947  vpMatrix _expX(rowNum, colNum);
4948  vpMatrix _expcX(rowNum, colNum);
4949  vpMatrix _eye(rowNum, colNum);
4950 
4951  _eye.eye();
4952  vpMatrix exp(*this);
4953 
4954  // double f;
4955  int e;
4956  double c = 0.5;
4957  int q = 6;
4958  int p = 1;
4959 
4960  double nA = 0;
4961  for (unsigned int i = 0; i < rowNum; i++) {
4962  double sum = 0;
4963  for (unsigned int j = 0; j < colNum; j++) {
4964  sum += fabs((*this)[i][j]);
4965  }
4966  if (sum > nA || i == 0) {
4967  nA = sum;
4968  }
4969  }
4970 
4971  /* f = */ frexp(nA, &e);
4972  // double s = (0 > e+1)?0:e+1;
4973  double s = e + 1;
4974 
4975  double sca = 1.0 / pow(2.0, s);
4976  exp = sca * exp;
4977  _expX = *this;
4978  _expE = c * exp + _eye;
4979  _expD = -c * exp + _eye;
4980  for (int k = 2; k <= q; k++) {
4981  c = c * ((double)(q - k + 1)) / ((double)(k * (2 * q - k + 1)));
4982  _expcX = exp * _expX;
4983  _expX = _expcX;
4984  _expcX = c * _expX;
4985  _expE = _expE + _expcX;
4986  if (p)
4987  _expD = _expD + _expcX;
4988  else
4989  _expD = _expD - _expcX;
4990  p = !p;
4991  }
4992  _expX = _expD.inverseByLU();
4993  exp = _expX * _expE;
4994  for (int k = 1; k <= s; k++) {
4995  _expE = exp * exp;
4996  exp = _expE;
4997  }
4998  return exp;
4999 #endif
5000  }
5001 }
5002 
5003 /**************************************************************************************************************/
5004 /**************************************************************************************************************/
5005 
5006 // Specific functions
5007 
5008 /*
5009 input:: matrix M(nCols,nRows), nCols > 3, nRows > 3 , nCols == nRows.
5010 
5011 output:: the complement matrix of the element (rowNo,colNo).
5012 This is the matrix obtained from M after elimenating the row rowNo and column
5013 colNo
5014 
5015 example:
5016 1 2 3
5017 M = 4 5 6
5018 7 8 9
5019 1 3
5020 subblock(M, 1, 1) give the matrix 7 9
5021 */
5022 vpMatrix subblock(const vpMatrix &M, unsigned int col, unsigned int row)
5023 {
5024  vpMatrix M_comp(M.getRows() - 1, M.getCols() - 1);
5025 
5026  for (unsigned int i = 0; i < col; i++) {
5027  for (unsigned int j = 0; j < row; j++)
5028  M_comp[i][j] = M[i][j];
5029  for (unsigned int j = row + 1; j < M.getRows(); j++)
5030  M_comp[i][j - 1] = M[i][j];
5031  }
5032  for (unsigned int i = col + 1; i < M.getCols(); i++) {
5033  for (unsigned int j = 0; j < row; j++)
5034  M_comp[i - 1][j] = M[i][j];
5035  for (unsigned int j = row + 1; j < M.getRows(); j++)
5036  M_comp[i - 1][j - 1] = M[i][j];
5037  }
5038  return M_comp;
5039 }
5040 
5045 double vpMatrix::cond() const
5046 {
5047  vpMatrix v;
5048  vpColVector w;
5049 
5050  vpMatrix M;
5051  M = *this;
5052 
5053  M.svd(w, v);
5054  double min = w[0];
5055  double max = w[0];
5056  for (unsigned int i = 0; i < M.getCols(); i++) {
5057  if (min > w[i])
5058  min = w[i];
5059  if (max < w[i])
5060  max = w[i];
5061  }
5062  return max / min;
5063 }
5064 
5071 void vpMatrix::computeHLM(const vpMatrix &H, const double &alpha, vpMatrix &HLM)
5072 {
5073  if (H.getCols() != H.getRows()) {
5074  throw(vpException(vpException::dimensionError, "Cannot compute HLM on a non square matrix (%dx%d)", H.getRows(),
5075  H.getCols()));
5076  }
5077  HLM.resize(H.getRows(), H.getCols(), false, false);
5078 
5079  for (unsigned int i = 0; i < H.getCols(); i++) {
5080  for (unsigned int j = 0; j < H.getCols(); j++) {
5081  HLM[i][j] = H[i][j];
5082  if (i == j)
5083  HLM[i][j] += alpha * H[i][j];
5084  }
5085  }
5086 }
5087 
5097 {
5098  double norm = 0.0;
5099  for (unsigned int i = 0; i < dsize; i++) {
5100  double x = *(data + i);
5101  norm += x * x;
5102  }
5103 
5104  return sqrt(norm);
5105 }
5106 
5118 {
5119  double norm = 0.0;
5120  for (unsigned int i = 0; i < rowNum; i++) {
5121  double x = 0;
5122  for (unsigned int j = 0; j < colNum; j++) {
5123  x += fabs(*(*(rowPtrs + i) + j));
5124  }
5125  if (x > norm) {
5126  norm = x;
5127  }
5128  }
5129  return norm;
5130 }
5131 
5138 double vpMatrix::sumSquare() const
5139 {
5140  double sum_square = 0.0;
5141  double x;
5142 
5143  for (unsigned int i = 0; i < rowNum; i++) {
5144  for (unsigned int j = 0; j < colNum; j++) {
5145  x = rowPtrs[i][j];
5146  sum_square += x * x;
5147  }
5148  }
5149 
5150  return sum_square;
5151 }
5152 
5164 vpMatrix vpMatrix::conv2(const vpMatrix &M, const vpMatrix &kernel, const std::string &mode)
5165 {
5166  vpMatrix res;
5167  conv2(M, kernel, res, mode);
5168  return res;
5169 }
5170 
5183 void vpMatrix::conv2(const vpMatrix &M, const vpMatrix &kernel, vpMatrix &res, const std::string &mode)
5184 {
5185  if (M.getRows()*M.getCols() == 0 || kernel.getRows()*kernel.getCols() == 0)
5186  return;
5187 
5188  if (mode == "valid") {
5189  if (kernel.getRows() > M.getRows() || kernel.getCols() > M.getCols())
5190  return;
5191  }
5192 
5193  vpMatrix M_padded, res_same;
5194 
5195  if (mode == "full" || mode == "same") {
5196  const unsigned int pad_x = kernel.getCols()-1;
5197  const unsigned int pad_y = kernel.getRows()-1;
5198  M_padded.resize(M.getRows() + 2*pad_y, M.getCols() + 2*pad_x, true, false);
5199  M_padded.insert(M, pad_y, pad_x);
5200 
5201  if (mode == "same") {
5202  res.resize(M.getRows(), M.getCols(), false, false);
5203  res_same.resize(M.getRows() + pad_y, M.getCols() + pad_x, true, false);
5204  } else {
5205  res.resize(M.getRows() + pad_y, M.getCols() + pad_x, true, false);
5206  }
5207  } else if (mode == "valid") {
5208  M_padded = M;
5209  res.resize(M.getRows()-kernel.getRows()+1, M.getCols()-kernel.getCols()+1);
5210  } else {
5211  return;
5212  }
5213 
5214  if (mode == "same") {
5215  for (unsigned int i = 0; i < res_same.getRows(); i++) {
5216  for (unsigned int j = 0; j < res_same.getCols(); j++) {
5217  for (unsigned int k = 0; k < kernel.getRows(); k++) {
5218  for (unsigned int l = 0; l < kernel.getCols(); l++) {
5219  res_same[i][j] += M_padded[i+k][j+l] * kernel[kernel.getRows()-k-1][kernel.getCols()-l-1];
5220  }
5221  }
5222  }
5223  }
5224 
5225  const unsigned int start_i = kernel.getRows()/2;
5226  const unsigned int start_j = kernel.getCols()/2;
5227  for (unsigned int i = 0; i < M.getRows(); i++) {
5228  memcpy(res.data + i*M.getCols(), res_same.data + (i+start_i)*res_same.getCols() + start_j, sizeof(double)*M.getCols());
5229  }
5230  } else {
5231  for (unsigned int i = 0; i < res.getRows(); i++) {
5232  for (unsigned int j = 0; j < res.getCols(); j++) {
5233  for (unsigned int k = 0; k < kernel.getRows(); k++) {
5234  for (unsigned int l = 0; l < kernel.getCols(); l++) {
5235  res[i][j] += M_padded[i+k][j+l] * kernel[kernel.getRows()-k-1][kernel.getCols()-l-1];
5236  }
5237  }
5238  }
5239  }
5240  }
5241 }
5242 
5243 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
5245 {
5246  return (vpMatrix)(vpColVector::stack(A, B));
5247 }
5248 
5250 {
5251  vpColVector::stack(A, B, C);
5252 }
5253 
5255 
5256 void vpMatrix::stackMatrices(const vpMatrix &A, const vpRowVector &B, vpMatrix &C) { vpMatrix::stack(A, B, C); }
5257 
5276 vpRowVector vpMatrix::row(const unsigned int i)
5277 {
5278  vpRowVector c(getCols());
5279 
5280  for (unsigned int j = 0; j < getCols(); j++)
5281  c[j] = (*this)[i - 1][j];
5282  return c;
5283 }
5284 
5302 vpColVector vpMatrix::column(const unsigned int j)
5303 {
5304  vpColVector c(getRows());
5305 
5306  for (unsigned int i = 0; i < getRows(); i++)
5307  c[i] = (*this)[i][j - 1];
5308  return c;
5309 }
5310 
5317 void vpMatrix::setIdentity(const double &val)
5318 {
5319  for (unsigned int i = 0; i < rowNum; i++)
5320  for (unsigned int j = 0; j < colNum; j++)
5321  if (i == j)
5322  (*this)[i][j] = val;
5323  else
5324  (*this)[i][j] = 0;
5325 }
5326 
5327 #endif //#if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
void svd(vpColVector &w, vpMatrix &V)
Definition: vpMatrix.cpp:1792
vpMatrix operator*(const double &x, const vpMatrix &B)
Definition: vpMatrix.cpp:1350
vpMatrix pseudoInverseEigen3(double svThreshold=1e-6) const
std::ostream & csvPrint(std::ostream &os) const
Definition: vpMatrix.cpp:4389
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:104
vpColVector eigenValues() const
Definition: vpMatrix.cpp:4624
static vpMatrix juxtaposeMatrices(const vpMatrix &A, const vpMatrix &B)
Definition: vpMatrix.cpp:4114
vpMatrix pseudoInverseOpenCV(double svThreshold=1e-6) const
vp_deprecated vpRowVector row(const unsigned int i)
Definition: vpMatrix.cpp:5276
double infinityNorm() const
Definition: vpMatrix.cpp:5117
static vpMatrix conv2(const vpMatrix &M, const vpMatrix &kernel, const std::string &mode="full")
Definition: vpMatrix.cpp:5164
vpMatrix pseudoInverseLapack(double svThreshold=1e-6) const
vpMatrix expm() const
Definition: vpMatrix.cpp:4924
Implementation of an homogeneous matrix and operations on such kind of matrices.
Implementation of row vector and the associated operations.
Definition: vpRowVector.h:72
std::ostream & cppPrint(std::ostream &os, const std::string &matrixName="A", bool octet=false) const
Definition: vpMatrix.cpp:4438
static void add2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
Definition: vpMatrix.cpp:1113
#define vpERROR_TRACE
Definition: vpDebug.h:393
void resize(const unsigned int nrows, const unsigned int ncols, const bool flagNullify=true, const bool recopy_=true)
Definition: vpArray2D.h:171
vpMatrix & operator*=(const double x)
Multiply all the element of the matrix by x : Aij = Aij * x.
Definition: vpMatrix.cpp:1424
void stack(const vpMatrix &A)
Definition: vpMatrix.cpp:4462
vpMatrix & operator/=(double x)
Divide all the element of the matrix by x : Aij = Aij / x.
Definition: vpMatrix.cpp:1434
error that can be emited by ViSP classes.
Definition: vpException.h:71
double * data
Address of the first element of the data array.
Definition: vpArray2D.h:84
vp_deprecated void stackMatrices(const vpMatrix &A)
Definition: vpMatrix.h:691
Implementation of a generic 2D array used as vase class of matrices and vectors.
Definition: vpArray2D.h:70
static void sub2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
Definition: vpMatrix.cpp:1226
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
vpMatrix & operator+=(const vpMatrix &B)
Operation A = A + B.
Definition: vpMatrix.cpp:1260
double sumSquare() const
Definition: vpMatrix.cpp:5138
vpMatrix()
Definition: vpMatrix.h:120
vp_deprecated vpColVector column(const unsigned int j)
Definition: vpMatrix.cpp:5302
std::ostream & maplePrint(std::ostream &os) const
Definition: vpMatrix.cpp:4348
double cond() const
Definition: vpMatrix.cpp:5045
void svdLapack(vpColVector &w, vpMatrix &V)
vpMatrix & operator-=(const vpMatrix &B)
Operation A = A - B.
Definition: vpMatrix.cpp:1277
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
Implementation of a rotation matrix and operations on such kind of matrices.
vpRowVector getRow(const unsigned int i) const
Definition: vpMatrix.cpp:3844
unsigned int rowNum
Number of rows in the array.
Definition: vpArray2D.h:74
void insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
Definition: vpMatrix.cpp:4570
void solveBySVD(const vpColVector &B, vpColVector &x) const
Definition: vpMatrix.cpp:1669
vp_deprecated void setIdentity(const double &val=1.0)
Definition: vpMatrix.cpp:5317
vpMatrix extract(unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols) const
Definition: vpMatrix.cpp:319
vpMatrix AtA() const
Definition: vpMatrix.cpp:524
vpMatrix AAt() const
Definition: vpMatrix.cpp:426
void diag(const double &val=1.0)
Definition: vpMatrix.cpp:693
vp_deprecated void init()
Definition: vpMatrix.h:686
static void add2WeightedMatrices(const vpMatrix &A, const double &wA, const vpMatrix &B, const double &wB, vpMatrix &C)
Definition: vpMatrix.cpp:1084
VISP_EXPORT bool checkSSE2()
static void multMatrixVector(const vpMatrix &A, const vpColVector &v, vpColVector &w)
Definition: vpMatrix.cpp:765
vpColVector getCol(const unsigned int j) const
Definition: vpMatrix.cpp:3798
static void mult2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
Definition: vpMatrix.cpp:806
vpMatrix operator+(const vpMatrix &B) const
Definition: vpMatrix.cpp:1171
vpMatrix transpose() const
Definition: vpMatrix.cpp:394
double detByLU() const
void svdOpenCV(vpColVector &w, vpMatrix &V)
vpMatrix pseudoInverseGsl(double svThreshold=1e-6) const
unsigned int getRows() const
Definition: vpArray2D.h:156
double det(vpDetMethod method=LU_DECOMPOSITION) const
Definition: vpMatrix.cpp:4906
unsigned int colNum
Number of columns in the array.
Definition: vpArray2D.h:76
int print(std::ostream &s, unsigned int length, char const *intro=0) const
Definition: vpMatrix.cpp:4181
void svdGsl(vpColVector &w, vpMatrix &V)
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpRowVector.h:213
double sumSquare() const
vpMatrix t() const
Definition: vpMatrix.cpp:375
double sum() const
Definition: vpMatrix.cpp:1326
void kron(const vpMatrix &m1, vpMatrix &out) const
Definition: vpMatrix.cpp:1579
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
void stack(double d)
double euclideanNorm() const
Definition: vpMatrix.cpp:5096
std::ostream & matlabPrint(std::ostream &os) const
Definition: vpMatrix.cpp:4304
vpMatrix inverseByLU() const
vpRowVector stackRows()
Definition: vpMatrix.cpp:1500
vpMatrix operator/(const double x) const
Cij = Aij / x (A is unchanged)
Definition: vpMatrix.cpp:1380
static void createDiagonalMatrix(const vpColVector &A, vpMatrix &DA)
Definition: vpMatrix.cpp:712
vpMatrix operator*(const vpMatrix &B) const
Definition: vpMatrix.cpp:941
vpColVector stackColumns()
Definition: vpMatrix.cpp:1474
vpMatrix operator-() const
Definition: vpMatrix.cpp:1319
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Definition: vpMatrix.cpp:1932
unsigned int kernel(vpMatrix &kerAt, double svThreshold=1e-6) const
Definition: vpMatrix.cpp:4821
unsigned int dsize
Current array size (rowNum * colNum)
Definition: vpArray2D.h:80
static void negateMatrix(const vpMatrix &A, vpMatrix &C)
Definition: vpMatrix.cpp:1301
static void computeHLM(const vpMatrix &H, const double &alpha, vpMatrix &HLM)
Definition: vpMatrix.cpp:5071
Function not implemented.
Definition: vpException.h:90
Class that consider the case of a translation vector.
void eye()
Definition: vpMatrix.cpp:360
double ** rowPtrs
Address of the first element of each rows.
Definition: vpArray2D.h:78
void svdEigen3(vpColVector &w, vpMatrix &V)
vpMatrix & operator=(const vpArray2D< double > &A)
Definition: vpMatrix.cpp:549
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:244
vpMatrix & operator<<(double *)
Definition: vpMatrix.cpp:607
vpMatrix hadamard(const vpMatrix &m) const
Definition: vpMatrix.cpp:1513