Visual Servoing Platform  version 3.1.0
vpMatrix.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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  memcpy(data, A.data, dsize * sizeof(double));
554 
555  return *this;
556 }
557 
558 #ifdef VISP_HAVE_CPP11_COMPATIBILITY
560 {
561  resize(A.getRows(), A.getCols(), false);
562 
563  memcpy(data, A.data, dsize * sizeof(double));
564 
565  return *this;
566 }
567 
569 {
570  if (this != &other) {
571  free(data);
572  free(rowPtrs);
573 
574  rowNum = other.rowNum;
575  colNum = other.colNum;
576  rowPtrs = other.rowPtrs;
577  dsize = other.dsize;
578  data = other.data;
579 
580  other.rowNum = 0;
581  other.colNum = 0;
582  other.rowPtrs = NULL;
583  other.dsize = 0;
584  other.data = NULL;
585  }
586 
587  return *this;
588 }
589 #endif
590 
593 {
594  for (unsigned int i = 0; i < rowNum; i++)
595  for (unsigned int j = 0; j < colNum; j++)
596  rowPtrs[i][j] = x;
597 
598  return *this;
599 }
600 
607 {
608  for (unsigned int i = 0; i < rowNum; i++) {
609  for (unsigned int j = 0; j < colNum; j++) {
610  rowPtrs[i][j] = *x++;
611  }
612  }
613  return *this;
614 }
615 
653 {
654  unsigned int rows = A.getRows();
655  this->resize(rows, rows);
656 
657  (*this) = 0;
658  for (unsigned int i = 0; i < rows; i++)
659  (*this)[i][i] = A[i];
660 }
661 
692 void vpMatrix::diag(const double &val)
693 {
694  (*this) = 0;
695  unsigned int min_ = (rowNum < colNum) ? rowNum : colNum;
696  for (unsigned int i = 0; i < min_; i++)
697  (*this)[i][i] = val;
698 }
699 
712 {
713  unsigned int rows = A.getRows();
714  DA.resize(rows, rows);
715 
716  for (unsigned int i = 0; i < rows; i++)
717  DA[i][i] = A[i];
718 }
719 
725 {
726  vpTranslationVector t_out;
727 
728  if (rowNum != 3 || colNum != 3) {
729  throw(vpException(vpException::dimensionError, "Cannot multiply a (%dx%d) matrix by a (%dx%d) translation vector",
730  rowNum, colNum, tv.getRows(), tv.getCols()));
731  }
732 
733  for (unsigned int j = 0; j < 3; j++)
734  t_out[j] = 0;
735 
736  for (unsigned int j = 0; j < 3; j++) {
737  double tj = tv[j]; // optimization em 5/12/2006
738  for (unsigned int i = 0; i < 3; i++) {
739  t_out[i] += rowPtrs[i][j] * tj;
740  }
741  }
742  return t_out;
743 }
744 
750 {
751  vpColVector v_out;
752  vpMatrix::multMatrixVector(*this, v, v_out);
753  return v_out;
754 }
755 
765 {
766  if (A.colNum != v.getRows()) {
767  throw(vpException(vpException::dimensionError, "Cannot multiply a (%dx%d) matrix by a (%d) column vector",
768  A.getRows(), A.getCols(), v.getRows()));
769  }
770 
771  if (A.rowNum != w.rowNum)
772  w.resize(A.rowNum, false);
773 
774 #if defined(VISP_HAVE_LAPACK) && !defined(VISP_HAVE_LAPACK_BUILT_IN)
775  double alpha = 1.0;
776  double beta = 0.0;
777  char trans = 't';
778  int incr = 1;
779 
780  vpMatrix::blas_dgemv(trans, A.colNum, A.rowNum, alpha, A.data, A.colNum, v.data, incr, beta, w.data, incr);
781 #else
782  w = 0.0;
783  for (unsigned int j = 0; j < A.colNum; j++) {
784  double vj = v[j]; // optimization em 5/12/2006
785  for (unsigned int i = 0; i < A.rowNum; i++) {
786  w[i] += A.rowPtrs[i][j] * vj;
787  }
788  }
789 #endif
790 }
791 
792 //---------------------------------
793 // Matrix operations.
794 //---------------------------------
795 
805 void vpMatrix::mult2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
806 {
807  if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum))
808  C.resize(A.rowNum, B.colNum, false, false);
809 
810  if (A.colNum != B.rowNum) {
811  throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (%dx%d) matrix", A.getRows(),
812  A.getCols(), B.getRows(), B.getCols()));
813  }
814 
815 #if defined(VISP_HAVE_LAPACK) && !defined(VISP_HAVE_LAPACK_BUILT_IN)
816  double alpha = 1.0;
817  double beta = 0.0;
818  char trans = 'n';
819 
820  vpMatrix::blas_dgemm(trans, trans, B.colNum, A.rowNum, A.colNum, alpha, B.data, B.colNum, A.data, A.colNum, beta,
821  C.data, B.colNum);
822 #else
823  // 5/12/06 some "very" simple optimization to avoid indexation
824  unsigned int BcolNum = B.colNum;
825  unsigned int BrowNum = B.rowNum;
826  unsigned int i, j, k;
827  double **BrowPtrs = B.rowPtrs;
828  for (i = 0; i < A.rowNum; i++) {
829  double *rowptri = A.rowPtrs[i];
830  double *ci = C[i];
831  for (j = 0; j < BcolNum; j++) {
832  double s = 0;
833  for (k = 0; k < BrowNum; k++)
834  s += rowptri[k] * BrowPtrs[k][j];
835  ci[j] = s;
836  }
837  }
838 #endif
839 }
840 
855 {
856  if (A.colNum != 3 || A.rowNum != 3 || B.colNum != 3 || B.rowNum != 3) {
858  "Cannot multiply (%dx%d) matrix by (%dx%d) matrix as a "
859  "rotation matrix",
860  A.getRows(), A.getCols(), B.getRows(), B.getCols()));
861  }
862 
863  // 5/12/06 some "very" simple optimization to avoid indexation
864  unsigned int BcolNum = B.colNum;
865  unsigned int BrowNum = B.rowNum;
866  unsigned int i, j, k;
867  double **BrowPtrs = B.rowPtrs;
868  for (i = 0; i < A.rowNum; i++) {
869  double *rowptri = A.rowPtrs[i];
870  double *ci = C[i];
871  for (j = 0; j < BcolNum; j++) {
872  double s = 0;
873  for (k = 0; k < BrowNum; k++)
874  s += rowptri[k] * BrowPtrs[k][j];
875  ci[j] = s;
876  }
877  }
878 }
879 
894 {
895  if (A.colNum != 4 || A.rowNum != 4 || B.colNum != 4 || B.rowNum != 4) {
897  "Cannot multiply (%dx%d) matrix by (%dx%d) matrix as a "
898  "rotation matrix",
899  A.getRows(), A.getCols(), B.getRows(), B.getCols()));
900  }
901 
902  // 5/12/06 some "very" simple optimization to avoid indexation
903  unsigned int BcolNum = B.colNum;
904  unsigned int BrowNum = B.rowNum;
905  unsigned int i, j, k;
906  double **BrowPtrs = B.rowPtrs;
907  for (i = 0; i < A.rowNum; i++) {
908  double *rowptri = A.rowPtrs[i];
909  double *ci = C[i];
910  for (j = 0; j < BcolNum; j++) {
911  double s = 0;
912  for (k = 0; k < BrowNum; k++)
913  s += rowptri[k] * BrowPtrs[k][j];
914  ci[j] = s;
915  }
916  }
917 }
918 
932 {
934 }
935 
941 {
942  vpMatrix C;
943 
944  vpMatrix::mult2Matrices(*this, B, C);
945 
946  return C;
947 }
948 
954 {
955  if (colNum != R.getRows()) {
956  throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (3x3) rotation matrix", rowNum,
957  colNum));
958  }
959  vpMatrix C(rowNum, 3);
960 
961  unsigned int RcolNum = R.getCols();
962  unsigned int RrowNum = R.getRows();
963  for (unsigned int i = 0; i < rowNum; i++) {
964  double *rowptri = rowPtrs[i];
965  double *ci = C[i];
966  for (unsigned int j = 0; j < RcolNum; j++) {
967  double s = 0;
968  for (unsigned int k = 0; k < RrowNum; k++)
969  s += rowptri[k] * R[k][j];
970  ci[j] = s;
971  }
972  }
973 
974  return C;
975 }
981 {
982  if (colNum != V.getRows()) {
983  throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (6x6) velocity twist matrix",
984  rowNum, colNum));
985  }
986  vpMatrix M;
987  M.resize(rowNum, 6, false, false);
988 
989 #if defined(VISP_HAVE_LAPACK) && !defined(VISP_HAVE_LAPACK_BUILT_IN)
990  double alpha = 1.0;
991  double beta = 0.0;
992  char trans = 'n';
993 
994  vpMatrix::blas_dgemm(trans, trans, V.colNum, rowNum, colNum, alpha, V.data, V.colNum, data, colNum, beta, M.data,
995  V.colNum);
996 #else
997  bool checkSSE2 = vpCPUFeatures::checkSSE2();
998 #if !USE_SSE
999  checkSSE2 = false;
1000 #endif
1001 
1002  if (checkSSE2) {
1003 #if USE_SSE
1004  vpMatrix V_trans(6, 6);
1005  for (unsigned int i = 0; i < 6; i++) {
1006  for (unsigned int j = 0; j < 6; j++) {
1007  V_trans[i][j] = V[j][i];
1008  }
1009  }
1010 
1011  for (unsigned int i = 0; i < rowNum; i++) {
1012  double *rowptri = rowPtrs[i];
1013  double *ci = M[i];
1014 
1015  for (int j = 0; j < 6; j++) {
1016  __m128d v_mul = _mm_setzero_pd();
1017  for (int k = 0; k < 6; k += 2) {
1018  v_mul = _mm_add_pd(v_mul, _mm_mul_pd(_mm_loadu_pd(&rowptri[k]), _mm_loadu_pd(&V_trans[j][k])));
1019  }
1020 
1021  double v_tmp[2];
1022  _mm_storeu_pd(v_tmp, v_mul);
1023  ci[j] = v_tmp[0] + v_tmp[1];
1024  }
1025  }
1026 #endif
1027  } else {
1028  unsigned int VcolNum = V.getCols();
1029  unsigned int VrowNum = V.getRows();
1030  for (unsigned int i = 0; i < rowNum; i++) {
1031  double *rowptri = rowPtrs[i];
1032  double *ci = M[i];
1033  for (unsigned int j = 0; j < VcolNum; j++) {
1034  double s = 0;
1035  for (unsigned int k = 0; k < VrowNum; k++)
1036  s += rowptri[k] * V[k][j];
1037  ci[j] = s;
1038  }
1039  }
1040  }
1041 #endif
1042 
1043  return M;
1044 }
1050 {
1051  if (colNum != V.getRows()) {
1052  throw(vpException(vpException::dimensionError, "Cannot multiply (%dx%d) matrix by (6x6) force/torque twist matrix",
1053  rowNum, colNum));
1054  }
1055  vpMatrix M(rowNum, 6);
1056 
1057  unsigned int VcolNum = V.getCols();
1058  unsigned int VrowNum = V.getRows();
1059  for (unsigned int i = 0; i < rowNum; i++) {
1060  double *rowptri = rowPtrs[i];
1061  double *ci = M[i];
1062  for (unsigned int j = 0; j < VcolNum; j++) {
1063  double s = 0;
1064  for (unsigned int k = 0; k < VrowNum; k++)
1065  s += rowptri[k] * V[k][j];
1066  ci[j] = s;
1067  }
1068  }
1069 
1070  return M;
1071 }
1072 
1083 void vpMatrix::add2WeightedMatrices(const vpMatrix &A, const double &wA, const vpMatrix &B, const double &wB,
1084  vpMatrix &C)
1085 {
1086  if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum))
1087  C.resize(A.rowNum, B.colNum, false, false);
1088 
1089  if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
1090  throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
1091  A.getCols(), B.getRows(), B.getCols()));
1092  }
1093 
1094  double **ArowPtrs = A.rowPtrs;
1095  double **BrowPtrs = B.rowPtrs;
1096  double **CrowPtrs = C.rowPtrs;
1097 
1098  for (unsigned int i = 0; i < A.rowNum; i++)
1099  for (unsigned int j = 0; j < A.colNum; j++)
1100  CrowPtrs[i][j] = wB * BrowPtrs[i][j] + wA * ArowPtrs[i][j];
1101 }
1102 
1112 void vpMatrix::add2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
1113 {
1114  if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum))
1115  C.resize(A.rowNum, B.colNum, false, false);
1116 
1117  if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
1118  throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
1119  A.getCols(), B.getRows(), B.getCols()));
1120  }
1121 
1122  double **ArowPtrs = A.rowPtrs;
1123  double **BrowPtrs = B.rowPtrs;
1124  double **CrowPtrs = C.rowPtrs;
1125 
1126  for (unsigned int i = 0; i < A.rowNum; i++) {
1127  for (unsigned int j = 0; j < A.colNum; j++) {
1128  CrowPtrs[i][j] = BrowPtrs[i][j] + ArowPtrs[i][j];
1129  }
1130  }
1131 }
1132 
1146 {
1147  if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum))
1148  C.resize(A.rowNum);
1149 
1150  if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
1151  throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
1152  A.getCols(), B.getRows(), B.getCols()));
1153  }
1154 
1155  double **ArowPtrs = A.rowPtrs;
1156  double **BrowPtrs = B.rowPtrs;
1157  double **CrowPtrs = C.rowPtrs;
1158 
1159  for (unsigned int i = 0; i < A.rowNum; i++) {
1160  for (unsigned int j = 0; j < A.colNum; j++) {
1161  CrowPtrs[i][j] = BrowPtrs[i][j] + ArowPtrs[i][j];
1162  }
1163  }
1164 }
1165 
1171 {
1172  vpMatrix C;
1173  vpMatrix::add2Matrices(*this, B, C);
1174  return C;
1175 }
1176 
1193 {
1194  if ((A.rowNum != C.rowNum) || (A.colNum != C.colNum))
1195  C.resize(A.rowNum);
1196 
1197  if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
1198  throw(vpException(vpException::dimensionError, "Cannot substract (%dx%d) matrix to (%dx%d) matrix", A.getRows(),
1199  A.getCols(), B.getRows(), B.getCols()));
1200  }
1201 
1202  double **ArowPtrs = A.rowPtrs;
1203  double **BrowPtrs = B.rowPtrs;
1204  double **CrowPtrs = C.rowPtrs;
1205 
1206  for (unsigned int i = 0; i < A.rowNum; i++) {
1207  for (unsigned int j = 0; j < A.colNum; j++) {
1208  CrowPtrs[i][j] = ArowPtrs[i][j] - BrowPtrs[i][j];
1209  }
1210  }
1211 }
1212 
1225 void vpMatrix::sub2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
1226 {
1227  if ((A.rowNum != C.rowNum) || (A.colNum != C.colNum))
1228  C.resize(A.rowNum, A.colNum, false, false);
1229 
1230  if ((A.colNum != B.getCols()) || (A.rowNum != B.getRows())) {
1231  throw(vpException(vpException::dimensionError, "Cannot substract (%dx%d) matrix to (%dx%d) matrix", A.getRows(),
1232  A.getCols(), B.getRows(), B.getCols()));
1233  }
1234 
1235  double **ArowPtrs = A.rowPtrs;
1236  double **BrowPtrs = B.rowPtrs;
1237  double **CrowPtrs = C.rowPtrs;
1238 
1239  for (unsigned int i = 0; i < A.rowNum; i++) {
1240  for (unsigned int j = 0; j < A.colNum; j++) {
1241  CrowPtrs[i][j] = ArowPtrs[i][j] - BrowPtrs[i][j];
1242  }
1243  }
1244 }
1245 
1251 {
1252  vpMatrix C;
1253  vpMatrix::sub2Matrices(*this, B, C);
1254  return C;
1255 }
1256 
1258 
1260 {
1261  if ((colNum != B.getCols()) || (rowNum != B.getRows())) {
1262  throw(vpException(vpException::dimensionError, "Cannot add (%dx%d) matrix to (%dx%d) matrix", rowNum, colNum,
1263  B.getRows(), B.getCols()));
1264  }
1265 
1266  double **BrowPtrs = B.rowPtrs;
1267 
1268  for (unsigned int i = 0; i < rowNum; i++)
1269  for (unsigned int j = 0; j < colNum; j++)
1270  rowPtrs[i][j] += BrowPtrs[i][j];
1271 
1272  return *this;
1273 }
1274 
1277 {
1278  if ((colNum != B.getCols()) || (rowNum != B.getRows())) {
1279  throw(vpException(vpException::dimensionError, "Cannot substract (%dx%d) matrix to (%dx%d) matrix", rowNum, colNum,
1280  B.getRows(), B.getCols()));
1281  }
1282 
1283  double **BrowPtrs = B.rowPtrs;
1284  for (unsigned int i = 0; i < rowNum; i++)
1285  for (unsigned int j = 0; j < colNum; j++)
1286  rowPtrs[i][j] -= BrowPtrs[i][j];
1287 
1288  return *this;
1289 }
1290 
1301 {
1302  if ((A.rowNum != C.rowNum) || (A.colNum != C.colNum))
1303  C.resize(A.rowNum, A.colNum, false, false);
1304 
1305  double **ArowPtrs = A.rowPtrs;
1306  double **CrowPtrs = C.rowPtrs;
1307 
1308  // t0=vpTime::measureTimeMicros();
1309  for (unsigned int i = 0; i < A.rowNum; i++)
1310  for (unsigned int j = 0; j < A.colNum; j++)
1311  CrowPtrs[i][j] = -ArowPtrs[i][j];
1312 }
1313 
1319 {
1320  vpMatrix C;
1321  vpMatrix::negateMatrix(*this, C);
1322  return C;
1323 }
1324 
1325 double vpMatrix::sum() const
1326 {
1327  double s = 0.0;
1328  for (unsigned int i = 0; i < rowNum; i++) {
1329  for (unsigned int j = 0; j < colNum; j++) {
1330  s += rowPtrs[i][j];
1331  }
1332  }
1333 
1334  return s;
1335 }
1336 
1337 //---------------------------------
1338 // Matrix/vector operations.
1339 //---------------------------------
1340 
1341 //---------------------------------
1342 // Matrix/real operations.
1343 //---------------------------------
1344 
1349 vpMatrix operator*(const double &x, const vpMatrix &B)
1350 {
1351  vpMatrix C(B.getRows(), B.getCols());
1352 
1353  unsigned int Brow = B.getRows();
1354  unsigned int Bcol = B.getCols();
1355 
1356  for (unsigned int i = 0; i < Brow; i++)
1357  for (unsigned int j = 0; j < Bcol; j++)
1358  C[i][j] = B[i][j] * x;
1359 
1360  return C;
1361 }
1362 
1368 {
1369  vpMatrix M(rowNum, colNum);
1370 
1371  for (unsigned int i = 0; i < rowNum; i++)
1372  for (unsigned int j = 0; j < colNum; j++)
1373  M[i][j] = rowPtrs[i][j] * x;
1374 
1375  return M;
1376 }
1377 
1380 {
1381  vpMatrix C;
1382 
1383  C.resize(rowNum, colNum, false, false);
1384 
1385  // if (x == 0) {
1386  if (std::fabs(x) <= std::numeric_limits<double>::epsilon()) {
1387  throw vpException(vpException::divideByZeroError, "Divide matrix by zero scalar");
1388  }
1389 
1390  double xinv = 1 / x;
1391 
1392  for (unsigned int i = 0; i < rowNum; i++)
1393  for (unsigned int j = 0; j < colNum; j++)
1394  C[i][j] = rowPtrs[i][j] * xinv;
1395 
1396  return C;
1397 }
1398 
1401 {
1402  for (unsigned int i = 0; i < rowNum; i++)
1403  for (unsigned int j = 0; j < colNum; j++)
1404  rowPtrs[i][j] += x;
1405 
1406  return *this;
1407 }
1408 
1411 {
1412  for (unsigned int i = 0; i < rowNum; i++)
1413  for (unsigned int j = 0; j < colNum; j++)
1414  rowPtrs[i][j] -= x;
1415 
1416  return *this;
1417 }
1418 
1424 {
1425  for (unsigned int i = 0; i < rowNum; i++)
1426  for (unsigned int j = 0; j < colNum; j++)
1427  rowPtrs[i][j] *= x;
1428 
1429  return *this;
1430 }
1431 
1434 {
1435  // if (x == 0)
1436  if (std::fabs(x) <= std::numeric_limits<double>::epsilon())
1437  throw vpException(vpException::divideByZeroError, "Divide matrix by zero scalar");
1438 
1439  double xinv = 1 / x;
1440 
1441  for (unsigned int i = 0; i < rowNum; i++)
1442  for (unsigned int j = 0; j < colNum; j++)
1443  rowPtrs[i][j] *= xinv;
1444 
1445  return *this;
1446 }
1447 
1448 //----------------------------------------------------------------
1449 // Matrix Operation
1450 //----------------------------------------------------------------
1451 
1457 {
1458  if ((out.rowNum != colNum * rowNum) || (out.colNum != 1))
1459  out.resize(colNum * rowNum, false, false);
1460 
1461  double *optr = out.data;
1462  for (unsigned int j = 0; j < colNum; j++) {
1463  for (unsigned int i = 0; i < rowNum; i++) {
1464  *(optr++) = rowPtrs[i][j];
1465  }
1466  }
1467 }
1468 
1474 {
1475  vpColVector out(colNum * rowNum);
1476  stackColumns(out);
1477  return out;
1478 }
1479 
1485 {
1486  if ((out.getRows() != 1) || (out.getCols() != colNum * rowNum))
1487  out.resize(colNum * rowNum, false, false);
1488 
1489  double *mdata = data;
1490  double *optr = out.data;
1491  for (unsigned int i = 0; i < dsize; i++) {
1492  *(optr++) = *(mdata++);
1493  }
1494 }
1500 {
1501  vpRowVector out(colNum * rowNum);
1502  stackRows(out);
1503  return out;
1504 }
1505 
1513 {
1514  if (m.getRows() != rowNum || m.getCols() != colNum) {
1515  throw(vpException(vpException::dimensionError, "In Hadamard product: bad dimension of input matrix"));
1516  }
1517 
1518  vpMatrix out;
1519  out.resize(rowNum, colNum, false);
1520 
1521  unsigned int i = 0;
1522 
1523 #if VISP_HAVE_SSE2
1524  if (vpCPUFeatures::checkSSE2() && dsize >= 2) {
1525  for (; i <= dsize - 2; i += 2) {
1526  __m128d vout = _mm_mul_pd(_mm_loadu_pd(data + i), _mm_loadu_pd(m.data + i));
1527  _mm_storeu_pd(out.data + i, vout);
1528  }
1529  }
1530 #endif
1531 
1532  for (; i < dsize; i++) {
1533  out.data[i] = data[i] * m.data[i];
1534  }
1535 
1536  return out;
1537 }
1538 
1545 void vpMatrix::kron(const vpMatrix &m1, const vpMatrix &m2, vpMatrix &out)
1546 {
1547  unsigned int r1 = m1.getRows();
1548  unsigned int c1 = m1.getCols();
1549  unsigned int r2 = m2.getRows();
1550  unsigned int c2 = m2.getCols();
1551 
1552  if (r1 * r2 != out.rowNum || c1 * c2 != out.colNum) {
1553  vpERROR_TRACE("Kronecker prodect bad dimension of output vpMatrix");
1554  throw(vpException(vpException::dimensionError, "In Kronecker product bad dimension of output matrix"));
1555  }
1556 
1557  for (unsigned int r = 0; r < r1; r++) {
1558  for (unsigned int c = 0; c < c1; c++) {
1559  double alpha = m1[r][c];
1560  double *m2ptr = m2[0];
1561  unsigned int roffset = r * r2;
1562  unsigned int coffset = c * c2;
1563  for (unsigned int rr = 0; rr < r2; rr++) {
1564  for (unsigned int cc = 0; cc < c2; cc++) {
1565  out[roffset + rr][coffset + cc] = alpha * *(m2ptr++);
1566  }
1567  }
1568  }
1569  }
1570 }
1571 
1578 void vpMatrix::kron(const vpMatrix &m, vpMatrix &out) const { kron(*this, m, out); }
1579 
1587 {
1588  unsigned int r1 = m1.getRows();
1589  unsigned int c1 = m1.getCols();
1590  unsigned int r2 = m2.getRows();
1591  unsigned int c2 = m2.getCols();
1592 
1593  vpMatrix out(r1 * r2, c1 * c2);
1594 
1595  for (unsigned int r = 0; r < r1; r++) {
1596  for (unsigned int c = 0; c < c1; c++) {
1597  double alpha = m1[r][c];
1598  double *m2ptr = m2[0];
1599  unsigned int roffset = r * r2;
1600  unsigned int coffset = c * c2;
1601  for (unsigned int rr = 0; rr < r2; rr++) {
1602  for (unsigned int cc = 0; cc < c2; cc++) {
1603  out[roffset + rr][coffset + cc] = alpha * *(m2ptr++);
1604  }
1605  }
1606  }
1607  }
1608  return out;
1609 }
1610 
1616 vpMatrix vpMatrix::kron(const vpMatrix &m) const { return kron(*this, m); }
1617 
1668 void vpMatrix::solveBySVD(const vpColVector &b, vpColVector &x) const { x = pseudoInverse(1e-6) * b; }
1669 
1720 {
1721  vpColVector X(colNum);
1722 
1723  solveBySVD(B, X);
1724  return X;
1725 }
1726 
1792 {
1793 #if defined(VISP_HAVE_LAPACK)
1794  svdLapack(w, V);
1795 #elif defined(VISP_HAVE_EIGEN3)
1796  svdEigen3(w, V);
1797 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
1798  svdOpenCV(w, V);
1799 #elif defined(VISP_HAVE_GSL)
1800  svdGsl(w, V);
1801 #else
1802  (void)w;
1803  (void)V;
1804  throw(vpException(vpException::fatalError, "Cannot compute SVD. Install Lapack, Eigen3, OpenCV or GSL 3rd party"));
1805 #endif
1806 }
1807 
1862 unsigned int vpMatrix::pseudoInverse(vpMatrix &Ap, double svThreshold) const
1863 {
1864 #if defined(VISP_HAVE_LAPACK)
1865  return pseudoInverseLapack(Ap, svThreshold);
1866 #elif defined(VISP_HAVE_EIGEN3)
1867  return pseudoInverseEigen3(Ap, svThreshold);
1868 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
1869  return pseudoInverseOpenCV(Ap, svThreshold);
1870 #elif defined(VISP_HAVE_GSL)
1871  return pseudoInverseGsl(Ap, svThreshold);
1872 #else
1873  (void)Ap;
1874  (void)svThreshold;
1875  throw(vpException(vpException::fatalError, "Cannot compute pseudo-inverse. "
1876  "Install Lapack, Eigen3, OpenCV "
1877  "or GSL 3rd party"));
1878 #endif
1879 }
1880 
1931 vpMatrix vpMatrix::pseudoInverse(double svThreshold) const
1932 {
1933 #if defined(VISP_HAVE_LAPACK)
1934  return pseudoInverseLapack(svThreshold);
1935 #elif defined(VISP_HAVE_EIGEN3)
1936  return pseudoInverseEigen3(svThreshold);
1937 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
1938  return pseudoInverseOpenCV(svThreshold);
1939 #elif defined(VISP_HAVE_GSL)
1940  return pseudoInverseGsl(svThreshold);
1941 #else
1942  (void)w;
1943  (void)V;
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 
3748 vpColVector vpMatrix::getCol(const unsigned int j, const unsigned int i_begin, const unsigned int column_size) const
3749 {
3750  if (i_begin + column_size > getRows() || j >= getCols())
3751  throw(vpException(vpException::dimensionError, "Unable to extract a column vector from the matrix"));
3752  vpColVector c(column_size);
3753  for (unsigned int i = 0; i < column_size; i++)
3754  c[i] = (*this)[i_begin + i][j];
3755  return c;
3756 }
3757 
3797 vpColVector vpMatrix::getCol(const unsigned int j) const
3798 {
3799  if (j >= getCols())
3800  throw(vpException(vpException::dimensionError, "Unable to extract a column vector from the matrix"));
3801  unsigned int nb_rows = getRows();
3802  vpColVector c(nb_rows);
3803  for (unsigned int i = 0; i < nb_rows; i++)
3804  c[i] = (*this)[i][j];
3805  return c;
3806 }
3807 
3843 vpRowVector vpMatrix::getRow(const unsigned int i) const
3844 {
3845  if (i >= getRows())
3846  throw(vpException(vpException::dimensionError, "Unable to extract a row vector from the matrix"));
3847 
3848  vpRowVector r;
3849  r.resize(colNum, false);
3850 
3851  if (r.data != NULL && data != NULL && colNum > 0) {
3852  memcpy(r.data, data + i * colNum, sizeof(double) * colNum);
3853  }
3854 
3855  return r;
3856 }
3857 
3895 vpRowVector vpMatrix::getRow(const unsigned int i, const unsigned int j_begin, const unsigned int row_size) const
3896 {
3897  if (j_begin + row_size > getCols() || i >= getRows())
3898  throw(vpException(vpException::dimensionError, "Unable to extract a row vector from the matrix"));
3899  vpRowVector r(row_size);
3900  for (unsigned int j = 0; j < row_size; j++)
3901  r[j] = (*this)[i][j_begin + i];
3902  return r;
3903 }
3904 
3916 {
3917  vpMatrix C;
3918 
3919  vpMatrix::stack(A, B, C);
3920 
3921  return C;
3922 }
3923 
3935 {
3936  vpMatrix C;
3937 
3938  vpMatrix::stack(A, r, C);
3939 
3940  return C;
3941 }
3942 
3954 void vpMatrix::stack(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
3955 {
3956  unsigned int nra = A.getRows();
3957  unsigned int nrb = B.getRows();
3958 
3959  if (nra != 0) {
3960  if (A.getCols() != B.getCols()) {
3961  throw(vpException(vpException::dimensionError, "Cannot stack (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
3962  A.getCols(), B.getRows(), B.getCols()));
3963  }
3964  }
3965 
3966  if (A.data != NULL && A.data == C.data) {
3967  std::cerr << "A and C must be two different objects!" << std::endl;
3968  return;
3969  }
3970 
3971  if (B.data != NULL && B.data == C.data) {
3972  std::cerr << "B and C must be two different objects!" << std::endl;
3973  return;
3974  }
3975 
3976  C.resize(nra + nrb, B.getCols(), false, false);
3977 
3978  if (C.data != NULL && A.data != NULL && A.size() > 0) {
3979  // Copy A in C
3980  memcpy(C.data, A.data, sizeof(double) * A.size());
3981  }
3982 
3983  if (C.data != NULL && B.data != NULL && B.size() > 0) {
3984  // Copy B in C
3985  memcpy(C.data + A.size(), B.data, sizeof(double) * B.size());
3986  }
3987 }
3988 
4000 void vpMatrix::stack(const vpMatrix &A, const vpRowVector &r, vpMatrix &C)
4001 {
4002  unsigned int nra = A.getRows();
4003 
4004  if (nra != 0) {
4005  if (A.getCols() != r.getCols()) {
4006  throw(vpException(vpException::dimensionError, "Cannot stack (%dx%d) matrix with (1x%d) row vector", A.getRows(),
4007  A.getCols(), r.getCols()));
4008  }
4009  }
4010 
4011  if (A.data != NULL && A.data == C.data) {
4012  std::cerr << "A and C must be two different objects!" << std::endl;
4013  return;
4014  }
4015 
4016  if (r.size() == 0) {
4017  C = A;
4018  return;
4019  }
4020 
4021  C.resize(nra + 1, r.getCols(), false, false);
4022 
4023  if (C.data != NULL && A.data != NULL && A.size() > 0) {
4024  // Copy A in C
4025  memcpy(C.data, A.data, sizeof(double) * A.size());
4026  }
4027 
4028  if (C.data != NULL && r.data != NULL && r.size() > 0) {
4029  // Copy r in C
4030  memcpy(C.data + A.size(), r.data, sizeof(double) * r.size());
4031  }
4032 }
4033 
4046 vpMatrix vpMatrix::insert(const vpMatrix &A, const vpMatrix &B, const unsigned int r, const unsigned int c)
4047 {
4048  vpMatrix C;
4049 
4050  insert(A, B, C, r, c);
4051 
4052  return C;
4053 }
4054 
4068 void vpMatrix::insert(const vpMatrix &A, const vpMatrix &B, vpMatrix &C, const unsigned int r, const unsigned int c)
4069 {
4070  if (((r + B.getRows()) <= A.getRows()) && ((c + B.getCols()) <= A.getCols())) {
4071  C.resize(A.getRows(), A.getCols(), false, false);
4072 
4073  for (unsigned int i = 0; i < A.getRows(); i++) {
4074  for (unsigned int j = 0; j < A.getCols(); j++) {
4075  if (i >= r && i < (r + B.getRows()) && j >= c && j < (c + B.getCols())) {
4076  C[i][j] = B[i - r][j - c];
4077  } else {
4078  C[i][j] = A[i][j];
4079  }
4080  }
4081  }
4082  } else {
4083  throw vpException(vpException::dimensionError, "Cannot insert (%dx%d) matrix in (%dx%d) matrix at position (%d,%d)",
4084  B.getRows(), B.getCols(), A.getCols(), A.getRows(), r, c);
4085  }
4086 }
4087 
4100 {
4101  vpMatrix C;
4102 
4103  juxtaposeMatrices(A, B, C);
4104 
4105  return C;
4106 }
4107 
4121 {
4122  unsigned int nca = A.getCols();
4123  unsigned int ncb = B.getCols();
4124 
4125  if (nca != 0) {
4126  if (A.getRows() != B.getRows()) {
4127  throw(vpException(vpException::dimensionError, "Cannot juxtapose (%dx%d) matrix with (%dx%d) matrix", A.getRows(),
4128  A.getCols(), B.getRows(), B.getCols()));
4129  }
4130  }
4131 
4132  if (B.getRows() == 0 || nca + ncb == 0) {
4133  std::cerr << "B.getRows() == 0 || nca+ncb == 0" << std::endl;
4134  return;
4135  }
4136 
4137  C.resize(B.getRows(), nca + ncb, false, false);
4138 
4139  C.insert(A, 0, 0);
4140  C.insert(B, 0, nca);
4141 }
4142 
4143 //--------------------------------------------------------------------
4144 // Output
4145 //--------------------------------------------------------------------
4146 
4166 int vpMatrix::print(std::ostream &s, unsigned int length, char const *intro) const
4167 {
4168  typedef std::string::size_type size_type;
4169 
4170  unsigned int m = getRows();
4171  unsigned int n = getCols();
4172 
4173  std::vector<std::string> values(m * n);
4174  std::ostringstream oss;
4175  std::ostringstream ossFixed;
4176  std::ios_base::fmtflags original_flags = oss.flags();
4177 
4178  // ossFixed <<std::fixed;
4179  ossFixed.setf(std::ios::fixed, std::ios::floatfield);
4180 
4181  size_type maxBefore = 0; // the length of the integral part
4182  size_type maxAfter = 0; // number of decimals plus
4183  // one place for the decimal point
4184  for (unsigned int i = 0; i < m; ++i) {
4185  for (unsigned int j = 0; j < n; ++j) {
4186  oss.str("");
4187  oss << (*this)[i][j];
4188  if (oss.str().find("e") != std::string::npos) {
4189  ossFixed.str("");
4190  ossFixed << (*this)[i][j];
4191  oss.str(ossFixed.str());
4192  }
4193 
4194  values[i * n + j] = oss.str();
4195  size_type thislen = values[i * n + j].size();
4196  size_type p = values[i * n + j].find('.');
4197 
4198  if (p == std::string::npos) {
4199  maxBefore = vpMath::maximum(maxBefore, thislen);
4200  // maxAfter remains the same
4201  } else {
4202  maxBefore = vpMath::maximum(maxBefore, p);
4203  maxAfter = vpMath::maximum(maxAfter, thislen - p - 1);
4204  }
4205  }
4206  }
4207 
4208  size_type totalLength = length;
4209  // increase totalLength according to maxBefore
4210  totalLength = vpMath::maximum(totalLength, maxBefore);
4211  // decrease maxAfter according to totalLength
4212  maxAfter = (std::min)(maxAfter, totalLength - maxBefore);
4213  if (maxAfter == 1)
4214  maxAfter = 0;
4215 
4216  // the following line is useful for debugging
4217  // std::cerr <<totalLength <<" " <<maxBefore <<" " <<maxAfter <<"\n";
4218 
4219  if (intro)
4220  s << intro;
4221  s << "[" << m << "," << n << "]=\n";
4222 
4223  for (unsigned int i = 0; i < m; i++) {
4224  s << " ";
4225  for (unsigned int j = 0; j < n; j++) {
4226  size_type p = values[i * n + j].find('.');
4227  s.setf(std::ios::right, std::ios::adjustfield);
4228  s.width((std::streamsize)maxBefore);
4229  s << values[i * n + j].substr(0, p).c_str();
4230 
4231  if (maxAfter > 0) {
4232  s.setf(std::ios::left, std::ios::adjustfield);
4233  if (p != std::string::npos) {
4234  s.width((std::streamsize)maxAfter);
4235  s << values[i * n + j].substr(p, maxAfter).c_str();
4236  } else {
4237  assert(maxAfter > 1);
4238  s.width((std::streamsize)maxAfter);
4239  s << ".0";
4240  }
4241  }
4242 
4243  s << ' ';
4244  }
4245  s << std::endl;
4246  }
4247 
4248  s.flags(original_flags); // restore s to standard state
4249 
4250  return (int)(maxBefore + maxAfter);
4251 }
4252 
4289 std::ostream &vpMatrix::matlabPrint(std::ostream &os) const
4290 {
4291  os << "[ ";
4292  for (unsigned int i = 0; i < this->getRows(); ++i) {
4293  for (unsigned int j = 0; j < this->getCols(); ++j) {
4294  os << (*this)[i][j] << ", ";
4295  }
4296  if (this->getRows() != i + 1) {
4297  os << ";" << std::endl;
4298  } else {
4299  os << "]" << std::endl;
4300  }
4301  }
4302  return os;
4303 }
4304 
4333 std::ostream &vpMatrix::maplePrint(std::ostream &os) const
4334 {
4335  os << "([ " << std::endl;
4336  for (unsigned int i = 0; i < this->getRows(); ++i) {
4337  os << "[";
4338  for (unsigned int j = 0; j < this->getCols(); ++j) {
4339  os << (*this)[i][j] << ", ";
4340  }
4341  os << "]," << std::endl;
4342  }
4343  os << "])" << std::endl;
4344  return os;
4345 }
4346 
4374 std::ostream &vpMatrix::csvPrint(std::ostream &os) const
4375 {
4376  for (unsigned int i = 0; i < this->getRows(); ++i) {
4377  for (unsigned int j = 0; j < this->getCols(); ++j) {
4378  os << (*this)[i][j];
4379  if (!(j == (this->getCols() - 1)))
4380  os << ", ";
4381  }
4382  os << std::endl;
4383  }
4384  return os;
4385 }
4386 
4423 std::ostream &vpMatrix::cppPrint(std::ostream &os, const std::string &matrixName, bool octet) const
4424 {
4425  os << "vpMatrix " << matrixName << " (" << this->getRows() << ", " << this->getCols() << "); " << std::endl;
4426 
4427  for (unsigned int i = 0; i < this->getRows(); ++i) {
4428  for (unsigned int j = 0; j < this->getCols(); ++j) {
4429  if (!octet) {
4430  os << matrixName << "[" << i << "][" << j << "] = " << (*this)[i][j] << "; " << std::endl;
4431  } else {
4432  for (unsigned int k = 0; k < sizeof(double); ++k) {
4433  os << "((unsigned char*)&(" << matrixName << "[" << i << "][" << j << "]) )[" << k << "] = 0x" << std::hex
4434  << (unsigned int)((unsigned char *)&((*this)[i][j]))[k] << "; " << std::endl;
4435  }
4436  }
4437  }
4438  os << std::endl;
4439  }
4440  return os;
4441 }
4442 
4448 {
4449  if (rowNum == 0) {
4450  *this = A;
4451  } else if (A.getRows() > 0) {
4452  if (colNum != A.getCols()) {
4453  throw(vpException(vpException::dimensionError, "Cannot stack (%dx%d) matrix with (%dx%d) matrix", rowNum, colNum,
4454  A.getRows(), A.getCols()));
4455  }
4456 
4457  unsigned int rowNumOld = rowNum;
4458  resize(rowNum + A.getRows(), colNum, false, false);
4459  insert(A, rowNumOld, 0);
4460  }
4461 }
4462 
4479 {
4480  if (rowNum == 0) {
4481  *this = r;
4482  } else {
4483  if (colNum != r.getCols()) {
4484  throw(vpException(vpException::dimensionError, "Cannot stack (%dx%d) matrix with (1x%d) row vector", rowNum,
4485  colNum, r.getCols()));
4486  }
4487 
4488  if (r.size() == 0) {
4489  return;
4490  }
4491 
4492  unsigned int oldSize = size();
4493  resize(rowNum + 1, colNum, false, false);
4494 
4495  if (data != NULL && r.data != NULL && r.size() > 0) {
4496  // Copy r in data
4497  memcpy(data + oldSize, r.data, sizeof(double) * r.size());
4498  }
4499  }
4500 }
4501 
4512 void vpMatrix::insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
4513 {
4514  if ((r + A.getRows()) <= rowNum && (c + A.getCols()) <= colNum) {
4515  if (A.colNum == colNum && data != NULL && A.data != NULL && A.size() > 0) {
4516  memcpy(data + r * colNum, A.data, sizeof(double) * A.size());
4517  } else if (data != NULL && A.data != NULL && A.colNum > 0) {
4518  for (unsigned int i = r; i < (r + A.getRows()); i++) {
4519  memcpy(data + i * colNum + c, A.data + (i - r) * A.colNum, sizeof(double) * A.colNum);
4520  }
4521  }
4522  } else {
4523  throw vpException(vpException::dimensionError, "Cannot insert (%dx%d) matrix in (%dx%d) matrix at position (%d,%d)",
4524  A.getRows(), A.getCols(), rowNum, colNum, r, c);
4525  }
4526 }
4527 
4567 {
4568  if (rowNum != colNum) {
4569  throw(vpException(vpException::dimensionError, "Cannot compute eigen values on a non square matrix (%dx%d)", rowNum,
4570  colNum));
4571  }
4572 
4573 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
4574  {
4575  // Check if the matrix is symetric: At - A = 0
4576  vpMatrix At_A = (*this).t() - (*this);
4577  for (unsigned int i = 0; i < rowNum; i++) {
4578  for (unsigned int j = 0; j < rowNum; j++) {
4579  // if (At_A[i][j] != 0) {
4580  if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
4581  throw(vpException(vpException::fatalError, "Cannot compute eigen values on a non symetric matrix"));
4582  }
4583  }
4584  }
4585 
4586  vpColVector evalue(rowNum); // Eigen values
4587 
4588  gsl_vector *eval = gsl_vector_alloc(rowNum);
4589  gsl_matrix *evec = gsl_matrix_alloc(rowNum, colNum);
4590 
4591  gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(rowNum);
4592  gsl_matrix *m = gsl_matrix_alloc(rowNum, colNum);
4593 
4594  unsigned int Atda = (unsigned int)m->tda;
4595  for (unsigned int i = 0; i < rowNum; i++) {
4596  unsigned int k = i * Atda;
4597  for (unsigned int j = 0; j < colNum; j++)
4598  m->data[k + j] = (*this)[i][j];
4599  }
4600  gsl_eigen_symmv(m, eval, evec, w);
4601 
4602  gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_ASC);
4603 
4604  for (unsigned int i = 0; i < rowNum; i++) {
4605  evalue[i] = gsl_vector_get(eval, i);
4606  }
4607 
4608  gsl_eigen_symmv_free(w);
4609  gsl_vector_free(eval);
4610  gsl_matrix_free(m);
4611  gsl_matrix_free(evec);
4612 
4613  return evalue;
4614  }
4615 #else
4616  {
4617  throw(vpException(vpException::functionNotImplementedError, "Eigen values computation is not implemented. You "
4618  "should install GSL rd party"));
4619  }
4620 #endif
4621 }
4622 
4676 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
4677 void vpMatrix::eigenValues(vpColVector &evalue, vpMatrix &evector) const
4678 #else
4679 void vpMatrix::eigenValues(vpColVector & /* evalue */, vpMatrix & /* evector */) const
4680 #endif
4681 {
4682  if (rowNum != colNum) {
4683  throw(vpException(vpException::dimensionError, "Cannot compute eigen values on a non square matrix (%dx%d)", rowNum,
4684  colNum));
4685  }
4686 
4687 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
4688  {
4689  // Check if the matrix is symetric: At - A = 0
4690  vpMatrix At_A = (*this).t() - (*this);
4691  for (unsigned int i = 0; i < rowNum; i++) {
4692  for (unsigned int j = 0; j < rowNum; j++) {
4693  // if (At_A[i][j] != 0) {
4694  if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
4695  throw(vpException(vpException::fatalError, "Cannot compute eigen values on a non symetric matrix"));
4696  }
4697  }
4698  }
4699 
4700  // Resize the output matrices
4701  evalue.resize(rowNum);
4702  evector.resize(rowNum, colNum);
4703 
4704  gsl_vector *eval = gsl_vector_alloc(rowNum);
4705  gsl_matrix *evec = gsl_matrix_alloc(rowNum, colNum);
4706 
4707  gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(rowNum);
4708  gsl_matrix *m = gsl_matrix_alloc(rowNum, colNum);
4709 
4710  unsigned int Atda = (unsigned int)m->tda;
4711  for (unsigned int i = 0; i < rowNum; i++) {
4712  unsigned int k = i * Atda;
4713  for (unsigned int j = 0; j < colNum; j++)
4714  m->data[k + j] = (*this)[i][j];
4715  }
4716  gsl_eigen_symmv(m, eval, evec, w);
4717 
4718  gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_ASC);
4719 
4720  for (unsigned int i = 0; i < rowNum; i++) {
4721  evalue[i] = gsl_vector_get(eval, i);
4722  }
4723  Atda = (unsigned int)evec->tda;
4724  for (unsigned int i = 0; i < rowNum; i++) {
4725  unsigned int k = i * Atda;
4726  for (unsigned int j = 0; j < rowNum; j++) {
4727  evector[i][j] = evec->data[k + j];
4728  }
4729  }
4730 
4731  gsl_eigen_symmv_free(w);
4732  gsl_vector_free(eval);
4733  gsl_matrix_free(m);
4734  gsl_matrix_free(evec);
4735  }
4736 #else
4737  {
4738  throw(vpException(vpException::functionNotImplementedError, "Eigen values computation is not implemented. You "
4739  "should install GSL rd party"));
4740  }
4741 #endif
4742 }
4743 
4763 unsigned int vpMatrix::kernel(vpMatrix &kerAt, double svThreshold) const
4764 {
4765  unsigned int nbline = getRows();
4766  unsigned int nbcol = getCols();
4767 
4768  vpMatrix U; // Copy of the matrix, SVD function is destructive
4769  vpColVector sv(nbcol); // singular values
4770  vpMatrix V(nbcol, nbcol); // V matrix of singular value decomposition
4771 
4772  // Copy and resize matrix to have at least as many rows as columns
4773  // kernel is computed in svd method only if the matrix has more rows than
4774  // columns
4775 
4776  if (nbline < nbcol)
4777  U.resize(nbcol, nbcol);
4778  else
4779  U.resize(nbline, nbcol);
4780 
4781  U.insert(*this, 0, 0);
4782 
4783  U.svd(sv, V);
4784 
4785  // Compute the highest singular value and rank of the matrix
4786  double maxsv = 0;
4787  for (unsigned int i = 0; i < nbcol; i++) {
4788  if (fabs(sv[i]) > maxsv) {
4789  maxsv = fabs(sv[i]);
4790  }
4791  }
4792 
4793  unsigned int rank = 0;
4794  for (unsigned int i = 0; i < nbcol; i++) {
4795  if (fabs(sv[i]) > maxsv * svThreshold) {
4796  rank++;
4797  }
4798  }
4799 
4800  kerAt.resize(nbcol - rank, nbcol);
4801  if (rank != nbcol) {
4802  for (unsigned int j = 0, k = 0; j < nbcol; j++) {
4803  // if( v.col(j) in kernel and non zero )
4804  if ((fabs(sv[j]) <= maxsv * svThreshold) &&
4805  (std::fabs(V.getCol(j).sumSquare()) > std::numeric_limits<double>::epsilon())) {
4806  for (unsigned int i = 0; i < V.getRows(); i++) {
4807  kerAt[k][i] = V[i][j];
4808  }
4809  k++;
4810  }
4811  }
4812  }
4813 
4814  return rank;
4815 }
4816 
4848 double vpMatrix::det(vpDetMethod method) const
4849 {
4850  double det = 0.;
4851 
4852  if (method == LU_DECOMPOSITION) {
4853  det = this->detByLU();
4854  }
4855 
4856  return (det);
4857 }
4858 
4867 {
4868  if (colNum != rowNum) {
4869  throw(vpException(vpException::dimensionError, "Cannot compute the exponential of a non square (%dx%d) matrix",
4870  rowNum, colNum));
4871  } else {
4872 #ifdef VISP_HAVE_GSL
4873  size_t size_ = rowNum * colNum;
4874  double *b = new double[size_];
4875  for (size_t i = 0; i < size_; i++)
4876  b[i] = 0.;
4877  gsl_matrix_view m = gsl_matrix_view_array(this->data, rowNum, colNum);
4878  gsl_matrix_view em = gsl_matrix_view_array(b, rowNum, colNum);
4879  gsl_linalg_exponential_ss(&m.matrix, &em.matrix, 0);
4880  // gsl_matrix_fprintf(stdout, &em.matrix, "%g");
4881  vpMatrix expA(rowNum, colNum);
4882  memcpy(expA.data, b, size_ * sizeof(double));
4883 
4884  delete[] b;
4885  return expA;
4886 #else
4887  vpMatrix _expE(rowNum, colNum);
4888  vpMatrix _expD(rowNum, colNum);
4889  vpMatrix _expX(rowNum, colNum);
4890  vpMatrix _expcX(rowNum, colNum);
4891  vpMatrix _eye(rowNum, colNum);
4892 
4893  _eye.eye();
4894  vpMatrix exp(*this);
4895 
4896  // double f;
4897  int e;
4898  double c = 0.5;
4899  int q = 6;
4900  int p = 1;
4901 
4902  double nA = 0;
4903  for (unsigned int i = 0; i < rowNum; i++) {
4904  double sum = 0;
4905  for (unsigned int j = 0; j < colNum; j++) {
4906  sum += fabs((*this)[i][j]);
4907  }
4908  if (sum > nA || i == 0) {
4909  nA = sum;
4910  }
4911  }
4912 
4913  /* f = */ frexp(nA, &e);
4914  // double s = (0 > e+1)?0:e+1;
4915  double s = e + 1;
4916 
4917  double sca = 1.0 / pow(2.0, s);
4918  exp = sca * exp;
4919  _expX = *this;
4920  _expE = c * exp + _eye;
4921  _expD = -c * exp + _eye;
4922  for (int k = 2; k <= q; k++) {
4923  c = c * ((double)(q - k + 1)) / ((double)(k * (2 * q - k + 1)));
4924  _expcX = exp * _expX;
4925  _expX = _expcX;
4926  _expcX = c * _expX;
4927  _expE = _expE + _expcX;
4928  if (p)
4929  _expD = _expD + _expcX;
4930  else
4931  _expD = _expD - _expcX;
4932  p = !p;
4933  }
4934  _expX = _expD.inverseByLU();
4935  exp = _expX * _expE;
4936  for (int k = 1; k <= s; k++) {
4937  _expE = exp * exp;
4938  exp = _expE;
4939  }
4940  return exp;
4941 #endif
4942  }
4943 }
4944 
4945 /**************************************************************************************************************/
4946 /**************************************************************************************************************/
4947 
4948 // Specific functions
4949 
4950 /*
4951 input:: matrix M(nCols,nRows), nCols > 3, nRows > 3 , nCols == nRows.
4952 
4953 output:: the complement matrix of the element (rowNo,colNo).
4954 This is the matrix obtained from M after elimenating the row rowNo and column
4955 colNo
4956 
4957 example:
4958 1 2 3
4959 M = 4 5 6
4960 7 8 9
4961 1 3
4962 subblock(M, 1, 1) give the matrix 7 9
4963 */
4964 vpMatrix subblock(const vpMatrix &M, unsigned int col, unsigned int row)
4965 {
4966  vpMatrix M_comp(M.getRows() - 1, M.getCols() - 1);
4967 
4968  for (unsigned int i = 0; i < col; i++) {
4969  for (unsigned int j = 0; j < row; j++)
4970  M_comp[i][j] = M[i][j];
4971  for (unsigned int j = row + 1; j < M.getRows(); j++)
4972  M_comp[i][j - 1] = M[i][j];
4973  }
4974  for (unsigned int i = col + 1; i < M.getCols(); i++) {
4975  for (unsigned int j = 0; j < row; j++)
4976  M_comp[i - 1][j] = M[i][j];
4977  for (unsigned int j = row + 1; j < M.getRows(); j++)
4978  M_comp[i - 1][j - 1] = M[i][j];
4979  }
4980  return M_comp;
4981 }
4982 
4987 double vpMatrix::cond() const
4988 {
4989  vpMatrix v;
4990  vpColVector w;
4991 
4992  vpMatrix M;
4993  M = *this;
4994 
4995  M.svd(w, v);
4996  double min = w[0];
4997  double max = w[0];
4998  for (unsigned int i = 0; i < M.getCols(); i++) {
4999  if (min > w[i])
5000  min = w[i];
5001  if (max < w[i])
5002  max = w[i];
5003  }
5004  return max / min;
5005 }
5006 
5013 void vpMatrix::computeHLM(const vpMatrix &H, const double &alpha, vpMatrix &HLM)
5014 {
5015  if (H.getCols() != H.getRows()) {
5016  throw(vpException(vpException::dimensionError, "Cannot compute HLM on a non square matrix (%dx%d)", H.getRows(),
5017  H.getCols()));
5018  }
5019  HLM.resize(H.getRows(), H.getCols(), false, false);
5020 
5021  for (unsigned int i = 0; i < H.getCols(); i++) {
5022  for (unsigned int j = 0; j < H.getCols(); j++) {
5023  HLM[i][j] = H[i][j];
5024  if (i == j)
5025  HLM[i][j] += alpha * H[i][j];
5026  }
5027  }
5028 }
5029 
5039 {
5040  double norm = 0.0;
5041  for (unsigned int i = 0; i < dsize; i++) {
5042  double x = *(data + i);
5043  norm += x * x;
5044  }
5045 
5046  return sqrt(norm);
5047 }
5048 
5060 {
5061  double norm = 0.0;
5062  for (unsigned int i = 0; i < rowNum; i++) {
5063  double x = 0;
5064  for (unsigned int j = 0; j < colNum; j++) {
5065  x += fabs(*(*(rowPtrs + i) + j));
5066  }
5067  if (x > norm) {
5068  norm = x;
5069  }
5070  }
5071  return norm;
5072 }
5073 
5080 double vpMatrix::sumSquare() const
5081 {
5082  double sum_square = 0.0;
5083  double x;
5084 
5085  for (unsigned int i = 0; i < rowNum; i++) {
5086  for (unsigned int j = 0; j < colNum; j++) {
5087  x = rowPtrs[i][j];
5088  sum_square += x * x;
5089  }
5090  }
5091 
5092  return sum_square;
5093 }
5094 
5095 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
5097 {
5098  return (vpMatrix)(vpColVector::stack(A, B));
5099 }
5100 
5102 {
5103  vpColVector::stack(A, B, C);
5104 }
5105 
5107 
5108 void vpMatrix::stackMatrices(const vpMatrix &A, const vpRowVector &B, vpMatrix &C) { vpMatrix::stack(A, B, C); }
5109 
5116 vpRowVector vpMatrix::row(const unsigned int i)
5117 {
5118  vpRowVector c(getCols());
5119 
5120  for (unsigned int j = 0; j < getCols(); j++)
5121  c[j] = (*this)[i - 1][j];
5122  return c;
5123 }
5124 
5132 vpColVector vpMatrix::column(const unsigned int j)
5133 {
5134  vpColVector c(getRows());
5135 
5136  for (unsigned int i = 0; i < getRows(); i++)
5137  c[i] = (*this)[i][j - 1];
5138  return c;
5139 }
5140 
5147 void vpMatrix::setIdentity(const double &val)
5148 {
5149  for (unsigned int i = 0; i < rowNum; i++)
5150  for (unsigned int j = 0; j < colNum; j++)
5151  if (i == j)
5152  (*this)[i][j] = val;
5153  else
5154  (*this)[i][j] = 0;
5155 }
5156 
5157 #endif //#if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
void solveBySVD(const vpColVector &B, vpColVector &x) const
Definition: vpMatrix.cpp:1668
void svd(vpColVector &w, vpMatrix &V)
Definition: vpMatrix.cpp:1791
vpMatrix operator*(const double &x, const vpMatrix &B)
Definition: vpMatrix.cpp:1349
vpMatrix extract(unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols) const
Definition: vpMatrix.cpp:319
double cond() const
Definition: vpMatrix.cpp:4987
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:104
double euclideanNorm() const
Definition: vpMatrix.cpp:5038
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Definition: vpMatrix.cpp:1931
static vpMatrix juxtaposeMatrices(const vpMatrix &A, const vpMatrix &B)
Definition: vpMatrix.cpp:4099
vpRowVector getRow(const unsigned int i) const
Definition: vpMatrix.cpp:3843
vp_deprecated vpRowVector row(const unsigned int i)
Definition: vpMatrix.cpp:5116
double det(vpDetMethod method=LU_DECOMPOSITION) const
Definition: vpMatrix.cpp:4848
void stack(const double &d)
void kron(const vpMatrix &m1, vpMatrix &out) const
Definition: vpMatrix.cpp:1578
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpMatrix operator-() const
Definition: vpMatrix.cpp:1318
Implementation of row vector and the associated operations.
Definition: vpRowVector.h:72
std::ostream & csvPrint(std::ostream &os) const
Definition: vpMatrix.cpp:4374
static void add2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
Definition: vpMatrix.cpp:1112
vpMatrix AtA() const
Definition: vpMatrix.cpp:524
#define vpERROR_TRACE
Definition: vpDebug.h:393
double sum() const
Definition: vpMatrix.cpp:1325
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:1423
void stack(const vpMatrix &A)
Definition: vpMatrix.cpp:4447
vpMatrix inverseByLU() const
vpMatrix & operator/=(double x)
Divide all the element of the matrix by x : Aij = Aij / x.
Definition: vpMatrix.cpp:1433
error that can be emited by ViSP classes.
Definition: vpException.h:71
unsigned int getRows() const
Definition: vpArray2D.h:156
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:678
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:1225
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:158
vpMatrix & operator+=(const vpMatrix &B)
Operation A = A + B.
Definition: vpMatrix.cpp:1259
vpMatrix()
Definition: vpMatrix.h:120
vp_deprecated vpColVector column(const unsigned int j)
Definition: vpMatrix.cpp:5132
double infinityNorm() const
Definition: vpMatrix.cpp:5059
vpMatrix & operator-=(const vpMatrix &B)
Operation A = A - B.
Definition: vpMatrix.cpp:1276
vpMatrix operator+(const vpMatrix &B) const
Definition: vpMatrix.cpp:1170
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.
unsigned int getCols() const
Definition: vpArray2D.h:146
std::ostream & maplePrint(std::ostream &os) const
Definition: vpMatrix.cpp:4333
unsigned int rowNum
Number of rows in the array.
Definition: vpArray2D.h:74
double sumSquare() const
Definition: vpMatrix.cpp:5080
vpMatrix hadamard(const vpMatrix &m) const
Definition: vpMatrix.cpp:1512
vpMatrix t() const
Definition: vpMatrix.cpp:375
void insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
Definition: vpMatrix.cpp:4512
vp_deprecated void setIdentity(const double &val=1.0)
Definition: vpMatrix.cpp:5147
std::ostream & matlabPrint(std::ostream &os) const
Definition: vpMatrix.cpp:4289
unsigned int kernel(vpMatrix &kerAt, double svThreshold=1e-6) const
Definition: vpMatrix.cpp:4763
void diag(const double &val=1.0)
Definition: vpMatrix.cpp:692
vp_deprecated void init()
Definition: vpMatrix.h:673
static void add2WeightedMatrices(const vpMatrix &A, const double &wA, const vpMatrix &B, const double &wB, vpMatrix &C)
Definition: vpMatrix.cpp:1083
VISP_EXPORT bool checkSSE2()
static void multMatrixVector(const vpMatrix &A, const vpColVector &v, vpColVector &w)
Definition: vpMatrix.cpp:764
static void mult2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
Definition: vpMatrix.cpp:805
std::ostream & cppPrint(std::ostream &os, const std::string &matrixName="A", bool octet=false) const
Definition: vpMatrix.cpp:4423
vpColVector eigenValues() const
Definition: vpMatrix.cpp:4566
vpMatrix AAt() const
Definition: vpMatrix.cpp:426
vpMatrix transpose() const
Definition: vpMatrix.cpp:394
unsigned int colNum
Number of columns in the array.
Definition: vpArray2D.h:76
vpMatrix operator/(const double x) const
Cij = Aij / x (A is unchanged)
Definition: vpMatrix.cpp:1379
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpRowVector.h:213
vpMatrix operator*(const vpMatrix &B) const
Definition: vpMatrix.cpp:940
int print(std::ostream &s, unsigned int length, char const *intro=0) const
Definition: vpMatrix.cpp:4166
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
vpRowVector stackRows()
Definition: vpMatrix.cpp:1499
double sumSquare() const
static void createDiagonalMatrix(const vpColVector &A, vpMatrix &DA)
Definition: vpMatrix.cpp:711
vpColVector stackColumns()
Definition: vpMatrix.cpp:1473
unsigned int dsize
Current array size (rowNum * colNum)
Definition: vpArray2D.h:80
double detByLU() const
static void negateMatrix(const vpMatrix &A, vpMatrix &C)
Definition: vpMatrix.cpp:1300
vpColVector getCol(const unsigned int j) const
Definition: vpMatrix.cpp:3797
static void computeHLM(const vpMatrix &H, const double &alpha, vpMatrix &HLM)
Definition: vpMatrix.cpp:5013
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
vpMatrix expm() const
Definition: vpMatrix.cpp:4866
vpMatrix & operator=(const vpArray2D< double > &A)
Definition: vpMatrix.cpp:549
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:241
vpMatrix & operator<<(double *)
Definition: vpMatrix.cpp:606