ViSP  2.7.0
vpMatrix.cpp
1 /****************************************************************************
2 *
3 * $Id: vpMatrix.cpp 4056 2013-01-05 13:04:42Z fspindle $
4 *
5 * This file is part of the ViSP software.
6 * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7 *
8 * This software is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * ("GPL") version 2 as published by the Free Software Foundation.
11 * See the file LICENSE.txt at the root directory of this source
12 * distribution for additional information about the GNU GPL.
13 *
14 * For using ViSP with software that can not be combined with the GNU
15 * GPL, please contact INRIA about acquiring a ViSP Professional
16 * Edition License.
17 *
18 * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19 *
20 * This software was developed at:
21 * INRIA Rennes - Bretagne Atlantique
22 * Campus Universitaire de Beaulieu
23 * 35042 Rennes Cedex
24 * France
25 * http://www.irisa.fr/lagadic
26 *
27 * If you have questions regarding the use of this file, please contact
28 * INRIA at visp@inria.fr
29 *
30 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32 *
33 *
34 * Description:
35 * Matrix manipulation.
36 *
37 * Authors:
38 * Eric Marchand
39 *
40 *****************************************************************************/
41 
42 
43 
49 /*
50 \class vpMatrix
51 
52 \brief Provide simple Matrices computation
53 
54 \author Eric Marchand (Eric.Marchand@irisa.fr) Irisa / Inria Rennes
55 */
56 
57 #include <visp/vpMatrix.h>
58 #include <visp/vpMath.h>
59 #include <visp/vpTranslationVector.h>
60 
61 // Exception
62 #include <visp/vpException.h>
63 #include <visp/vpMatrixException.h>
64 
65 // Debug trace
66 #include <visp/vpDebug.h>
67 
68 #include <stdlib.h>
69 #include <stdio.h>
70 #include <string.h>
71 #include <vector>
72 #include <sstream>
73 #include <algorithm>
74 #include <assert.h>
75 #include <fstream>
76 #include <string>
77 #include <cmath> // std::fabs
78 #include <limits> // numeric_limits
79 
80 #define DEBUG_LEVEL1 0
81 #define DEBUG_LEVEL2 0
82 
83 
84 //Prototypes of specific functions
85 vpMatrix subblock(const vpMatrix &, unsigned int, unsigned int);
86 
92 void
94 {
95 
96  rowNum = 0 ;
97  colNum = 0 ;
98 
99  data = NULL ;
100  rowPtrs = NULL ;
101 
102  dsize = 0 ;
103  trsize =0 ;
104 }
105 
112 {
113  init() ;
114 }
115 
116 
125 vpMatrix::vpMatrix(unsigned int r, unsigned int c)
126 {
127  init() ;
128  resize(r, c);
129 }
130 
135  unsigned int r, unsigned int c,
136  unsigned int nrows, unsigned int ncols)
137 {
138  init() ;
139 
140  if (((r + nrows) > m.rowNum) || ((c + ncols) > m.colNum))
141  {
142  vpERROR_TRACE("\n\t\t SubvpMatrix larger than vpMatrix") ;
144  "\n\t\t SubvpMatrix larger than vpMatrix")) ;
145  }
146 
147  init(m,r,c,nrows,ncols);
148 }
149 
152 {
153  init() ;
154 
155  resize(m.rowNum,m.colNum);
156 
157  memcpy(data,m.data,rowNum*colNum*sizeof(double)) ;
158 }
159 
160 
174 void vpMatrix::resize(const unsigned int nrows, const unsigned int ncols,
175  const bool flagNullify)
176 {
177 
178  if ((nrows == rowNum) && (ncols == colNum))
179  {
180  if (flagNullify)
181  { memset(this->data,0,this->dsize*sizeof(double)) ;}
182  }
183  else
184  {
185  const bool recopyNeeded = (ncols != this ->colNum);
186  double * copyTmp = NULL;
187  unsigned int rowTmp = 0, colTmp=0;
188 
189  vpDEBUG_TRACE (25, "Recopy case per case is required iff number of "
190  "cols has changed (structure of double array is not "
191  "the same in this case.");
192  if (recopyNeeded)
193  {
194  copyTmp = new double[this->dsize];
195  memcpy (copyTmp, this ->data, sizeof(double)*this->dsize);
196  rowTmp=this->rowNum; colTmp=this->colNum;
197  }
198 
199  vpDEBUG_TRACE (25, "Reallocation of this->data array.");
200  this->dsize = nrows*ncols;
201  this->data = (double*)realloc(this->data, this->dsize*sizeof(double));
202  if ((NULL == this->data) && (0 != this->dsize))
203  {
204  vpERROR_TRACE("\n\t\tMemory allocation error when allocating data") ;
206  "\n\t\t Memory allocation error when "
207  "allocating data")) ;
208  }
209 
210  vpDEBUG_TRACE (25, "Reallocation of this->trsize array.");
211  this->trsize = nrows;
212  this->rowPtrs = (double**)realloc (this->rowPtrs, this->trsize*sizeof(double*));
213  if ((NULL == this->rowPtrs) && (0 != this->dsize))
214  {
215  vpERROR_TRACE("\n\t\tMemory allocation error when allocating rowPtrs") ;
217  "\n\t\t Memory allocation error when "
218  "allocating rowPtrs")) ;
219  }
220 
221  vpDEBUG_TRACE (25, "Recomputation this->trsize array values.");
222  {
223  double **t= rowPtrs;
224  for (unsigned int i=0; i<dsize; i+=ncols) { *t++ = this->data + i; }
225  }
226 
227  this->rowNum = nrows; this->colNum = ncols;
228 
229  vpDEBUG_TRACE (25, "Recopy of this->data array values or nullify.");
230  if (flagNullify)
231  { memset(this->data,0,this->dsize*sizeof(double)) ;}
232  else
233  {
234  if (recopyNeeded)
235  {
236  vpDEBUG_TRACE (25, "Recopy...");
237  const unsigned int minRow = (this->rowNum<rowTmp)?this->rowNum:rowTmp;
238  const unsigned int minCol = (this->colNum<colTmp)?this->colNum:colTmp;
239  for (unsigned int i=0; i<this->rowNum; ++i)
240  for (unsigned int j=0; j<this->colNum; ++j)
241  {
242  if ((minRow > i) && (minCol > j))
243  {
244  (*this)[i][j] = copyTmp [i*colTmp+j];
245  vpCDEBUG (25) << i << "x" << j << "<- " << i*colTmp+j
246  << "=" << copyTmp [i*colTmp+j] << std::endl;
247  }
248  else {(*this)[i][j] = 0;}
249  }
250  }
251  else { vpDEBUG_TRACE (25,"Nothing to do: already done by realloc.");}
252  }
253 
254  if (copyTmp != NULL) delete [] copyTmp;
255  }
256 
257 }
258 
259 
260 void
261 vpMatrix::init(const vpMatrix &m,unsigned int r, unsigned int c, unsigned int nrows, unsigned int ncols)
262 {
263  try {
264  resize(nrows, ncols) ;
265  }
266  catch(vpException me)
267  {
268  vpERROR_TRACE("Error caught") ;
269  std::cout << me << std::endl ;
270  throw ;
271  }
272 
273  unsigned int rnrows = r+nrows ;
274  unsigned int cncols = c+ncols ;
275  for (unsigned int i=r ; i < rnrows; i++)
276  for (unsigned int j=c ; j < cncols; j++)
277  (*this)[i-r][j-c] = m[i][j] ;
278 }
279 
283 void
285 {
286  if (data != NULL )
287  {
288  free(data);
289  data=NULL;
290  }
291 
292  if (rowPtrs!=NULL)
293  {
294  free(rowPtrs);
295  rowPtrs=NULL ;
296  }
297 }
302 {
303  kill() ;
304 }
305 
306 
313 vpMatrix &
315 {
316  try {
317  resize(B.rowNum, B.colNum) ;
318  // suppress by em 5/12/06
319  // *this = 0;
320  }
321  catch(vpException me)
322  {
323  vpERROR_TRACE("Error caught") ;
324  std::cout << me << std::endl ;
325  throw ;
326  }
327 
328  memcpy(data,B.data,dsize*sizeof(double)) ;
329 
330  return *this;
331 }
332 
334 vpMatrix &
336 {
337 
338  // double t0,t1;
339  //
340  // t0=vpTime::measureTimeMicros();
341  // for (int i=0;i<dsize;i++)
342  // {
343  // *(data+i) = x;
344  // }
345  // t1=vpTime::measureTimeMicros();
346  // std::cout<< t1-t0<< std::endl;
347 
348  // t0=vpTime::measureTimeMicros();
349  for (unsigned int i=0;i<rowNum;i++)
350  for(unsigned int j=0;j<colNum;j++)
351  rowPtrs[i][j] = x;
352 
353  // t1=vpTime::measureTimeMicros();
354  // std::cout<< t1-t0<<" ";
355 
356 
357 
358  return *this;
359 }
360 
361 
365 vpMatrix &
367 {
368 
369  for (unsigned int i=0; i<rowNum; i++) {
370  for (unsigned int j=0; j<colNum; j++) {
371  rowPtrs[i][j] = *x++;
372  }
373  }
374  return *this;
375 }
376 
377 
378 //---------------------------------
379 // Matrix operations.
380 //---------------------------------
381 
391 void vpMatrix::mult2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
392 {
393  try
394  {
395  if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum)) C.resize(A.rowNum,B.colNum);
396  }
397  catch(vpException me)
398  {
399  vpERROR_TRACE("Error caught") ;
400  std::cout << me << std::endl ;
401  throw ;
402  }
403 
404  if (A.colNum != B.rowNum)
405  {
406  vpERROR_TRACE("\n\t\tvpMatrix mismatch in vpMatrix/vpMatrix multiply") ;
408  "\n\t\tvpMatrix mismatch in "
409  "vpMatrix/vpMatrix multiply")) ;
410  }
411 
412  // 5/12/06 some "very" simple optimization to avoid indexation
413  unsigned int BcolNum = B.colNum;
414  unsigned int BrowNum = B.rowNum;
415  unsigned int i,j,k;
416  double **BrowPtrs = B.rowPtrs;
417  for (i=0;i<A.rowNum;i++)
418  {
419  double *rowptri = A.rowPtrs[i];
420  double *ci = C[i];
421  for (j=0;j<BcolNum;j++)
422  {
423  double s = 0;
424  for (k=0;k<BrowNum;k++) s += rowptri[k] * BrowPtrs[k][j];
425  ci[j] = s;
426  }
427  }
428 }
429 
435 {
436  vpMatrix C;
437 
438  vpMatrix::mult2Matrices(*this,B,C);
439 
440  return C;
441 }
452 void vpMatrix::add2WeightedMatrices(const vpMatrix &A, const double &wA, const vpMatrix &B,const double &wB, vpMatrix &C){
453  try
454  {
455  if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum)) C.resize(A.rowNum,B.colNum);
456  }
457  catch(vpException me)
458  {
459  vpERROR_TRACE("Error caught") ;
460  std::cout << me << std::endl ;
461  throw ;
462  }
463 
464  if ((A.colNum != B.getCols())||(A.rowNum != B.getRows()))
465  {
466  vpERROR_TRACE("\n\t\t vpMatrix mismatch in vpMatrix/vpMatrix addition") ;
468  "\n\t\t vpMatrix mismatch in "
469  "vpMatrix/vpMatrix addition")) ;
470  }
471 
472  double ** ArowPtrs=A.rowPtrs;
473  double ** BrowPtrs=B.rowPtrs;
474  double ** CrowPtrs=C.rowPtrs;
475 
476  for (unsigned int i=0;i<A.rowNum;i++)
477  for(unsigned int j=0;j<A.colNum;j++)
478  CrowPtrs[i][j] = wB*BrowPtrs[i][j]+wA*ArowPtrs[i][j];
479 
480 }
481 
491 void vpMatrix::add2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
492 {
493  try
494  {
495  if ((A.rowNum != C.rowNum) || (B.colNum != C.colNum)) C.resize(A.rowNum,B.colNum);
496  }
497  catch(vpException me)
498  {
499  vpERROR_TRACE("Error caught") ;
500  std::cout << me << std::endl ;
501  throw ;
502  }
503 
504  if ((A.colNum != B.getCols())||(A.rowNum != B.getRows()))
505  {
506  vpERROR_TRACE("\n\t\t vpMatrix mismatch in vpMatrix/vpMatrix addition") ;
508  "\n\t\t vpMatrix mismatch in "
509  "vpMatrix/vpMatrix addition")) ;
510  }
511 
512  double ** ArowPtrs=A.rowPtrs;
513  double ** BrowPtrs=B.rowPtrs;
514  double ** CrowPtrs=C.rowPtrs;
515 
516  // double t0,t1;
517  // t0=vpTime::measureTimeMicros();
518  // for (int i=0;i<A.dsize;i++)
519  // {
520  // *(C.data + i) = *(B.data + i) + *(A.data + i) ;
521  // }
522  // t1=vpTime::measureTimeMicros();
523  // std::cout<< t1-t0<< std::endl;
524 
525  // t0=vpTime::measureTimeMicros();
526  for (unsigned int i=0;i<A.rowNum;i++)
527  for(unsigned int j=0;j<A.colNum;j++)
528  {
529 
530  CrowPtrs[i][j] = BrowPtrs[i][j]+ArowPtrs[i][j];
531  }
532  // t1=vpTime::measureTimeMicros();
533  // std::cout<< t1-t0<<" ";
534 
535 
536 }
537 
543 {
544 
545  vpMatrix C;
546  vpMatrix::add2Matrices(*this,B,C);
547  return C;
548 }
549 
550 
560 void vpMatrix::sub2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
561 {
562  try
563  {
564  if ((A.rowNum != C.rowNum) || (A.colNum != C.colNum)) C.resize(A.rowNum,A.colNum);
565  }
566  catch(vpException me)
567  {
568  vpERROR_TRACE("Error caught") ;
569  std::cout << me << std::endl ;
570  throw ;
571  }
572 
573  if ( (A.colNum != B.getCols())||(A.rowNum != B.getRows()))
574  {
575  vpERROR_TRACE("\n\t\t vpMatrix mismatch in vpMatrix/vpMatrix substraction") ;
577  "\n\t\t vpMatrix mismatch in "
578  "vpMatrix/vpMatrix substraction")) ;
579  }
580 
581 
582 
583  double ** ArowPtrs=A.rowPtrs;
584  double ** BrowPtrs=B.rowPtrs;
585  double ** CrowPtrs=C.rowPtrs;
586 
587  // double t0,t1;
588  //
589  // t0=vpTime::measureTimeMicros();
590  // for (int i=0;i<A.dsize;i++)
591  // {
592  // *(C.data + i) = *(A.data + i) - *(B.data + i) ;
593  // }
594  // t1=vpTime::measureTimeMicros();
595  // std::cout<< t1-t0<< std::endl;
596  //
597  // t0=vpTime::measureTimeMicros();
598  for (unsigned int i=0;i<A.rowNum;i++)
599  for(unsigned int j=0;j<A.colNum;j++)
600  {
601  CrowPtrs[i][j] = ArowPtrs[i][j]-BrowPtrs[i][j];
602  }
603  // t1=vpTime::measureTimeMicros();
604  // std::cout<< t1-t0<<" ";
605 
606 
607 }
608 
614 {
615  vpMatrix C;
616  vpMatrix::sub2Matrices(*this,B,C);
617  return C;
618 }
619 
621 
623 {
624  if ( (colNum != B.getCols())||(rowNum != B.getRows()))
625  {
626  vpERROR_TRACE("\n\t\t vpMatrix mismatch in vpMatrix += addition") ;
628  "\n\t\t vpMatrix mismatch in "
629  "vpMatrix += addition")) ;
630 
631  }
632 
633 
634  double ** BrowPtrs=B.rowPtrs;
635 
636  // double t0,t1;
637  //
638  // t0=vpTime::measureTimeMicros();
639  // for (int i=0;i<dsize;i++)
640  // {
641  // *(data + i) += *(B.data + i) ;
642  // }
643  // t1=vpTime::measureTimeMicros();
644  // std::cout<< t1-t0<< std::endl;
645 
646  // t0=vpTime::measureTimeMicros();
647  for (unsigned int i=0;i<rowNum;i++)
648  for(unsigned int j=0;j<colNum;j++)
649  rowPtrs[i][j] += BrowPtrs[i][j];
650  // t1=vpTime::measureTimeMicros();
651  // std::cout<< t1-t0<<" ";
652 
653 
654 
655 
656 
657  return *this;
658 }
659 
661 
663 {
664  if ( (colNum != B.getCols())||(rowNum != B.getRows()))
665  {
666  vpERROR_TRACE("\n\t\t vpMatrix mismatch in vpMatrix -= substraction") ;
668  "\n\t\t vpMatrix mismatch in "
669  "vpMatrix -= substraction")) ;
670 
671  }
672 
673  double ** BrowPtrs=B.rowPtrs;
674 
675  // double t0,t1;
676 
677  // t0=vpTime::measureTimeMicros();
678  // for (int i=0;i<dsize;i++)
679  // {
680  // *(data + i) -= *(B.data + i) ;
681  // }
682  // t1=vpTime::measureTimeMicros();
683  // std::cout<< t1-t0<< " " ;
684 
685  // t0=vpTime::measureTimeMicros();
686  for (unsigned int i=0;i<rowNum;i++)
687  for(unsigned int j=0;j<colNum;j++)
688  rowPtrs[i][j] -= BrowPtrs[i][j];
689 
690  // t1=vpTime::measureTimeMicros();
691  // std::cout<< t1-t0<<std::endl;
692 
693 
694 
695  return *this;
696 }
697 
708 {
709  try
710  {
711  if ((A.rowNum != C.rowNum) || (A.colNum != C.colNum)) C.resize(A.rowNum,A.colNum);
712  }
713  catch(vpException me)
714  {
715  vpERROR_TRACE("Error caught") ;
716  std::cout << me << std::endl ;
717  throw ;
718  }
719 
720  double ** ArowPtrs=A.rowPtrs;
721  double ** CrowPtrs=C.rowPtrs;
722 
723 
724  // std::cout << "negate" << std::endl;
725  // double t0,t1;
726  //
727  // t0=vpTime::measureTimeMicros();
728  // for (int i=0;i<A.dsize;i++)
729  // {
730  // *(C.data + i) = -*(A.data + i) ;
731  // }
732  // t1=vpTime::measureTimeMicros();
733  // std::cout<< t1-t0<< " ";
734 
735  // t0=vpTime::measureTimeMicros();
736  for (unsigned int i=0;i<A.rowNum;i++)
737  for(unsigned int j=0;j<A.colNum;j++)
738  CrowPtrs[i][j]= -ArowPtrs[i][j];
739  // t1=vpTime::measureTimeMicros();
740  // std::cout<< t1-t0<<std::endl;
741 
742 
743 }
744 
750 {
751  vpMatrix C;
752  vpMatrix::negateMatrix(*this,C);
753  return C;
754 }
755 
757 double
759 {
760  double sum=0.0;
761  double x ;
762 
763  // double t0,t1;
764  //
765  // t0=vpTime::measureTimeMicros();
766  // double *d = data ;
767  // double *n = data+dsize ;
768  // while (d < n )
769  // {
770  // x = *d++ ;
771  // sum += x*x ;
772  // }
773  // t1=vpTime::measureTimeMicros();
774  // std::cout<< t1-t0<<" "<< sum << " ";
775  //
776 
777 
778  // sum= 0.0;
779  // t0=vpTime::measureTimeMicros();
780  for (unsigned int i=0;i<rowNum;i++)
781  for(unsigned int j=0;j<colNum;j++)
782  {
783  x=rowPtrs[i][j];
784  sum+=x*x;
785  }
786  // t1=vpTime::measureTimeMicros();
787  // std::cout<< t1-t0<<" "<< sum << std::endl;
788 
789 
790 
791 
792  return sum;
793 }
794 
795 
796 //---------------------------------
797 // Matrix/vector operations.
798 //---------------------------------
799 
810 {
811  if (A.colNum != b.getRows())
812  {
813  vpERROR_TRACE("vpMatrix mismatch in vpMatrix/vector multiply") ;
815  }
816 
817  try
818  {
819  if (A.rowNum != c.rowNum) c.resize(A.rowNum);
820  }
821  catch(vpException me)
822  {
823  vpERROR_TRACE("Error caught") ;
824  std::cout << me << std::endl ;
825  throw ;
826  }
827 
828  c = 0.0;
829  for (unsigned int j=0;j<A.colNum;j++)
830  {
831  double bj = b[j] ; // optimization em 5/12/2006
832  for (unsigned int i=0;i<A.rowNum;i++)
833  {
834  c[i]+=A.rowPtrs[i][j] * bj;
835  }
836  }
837 }
838 
845 {
846  vpColVector c;
847  vpMatrix::multMatrixVector(*this,b,c);
848  return c;
849 }
850 
854 {
856 
857  if (rowNum != 3 || colNum != 3)
858  {
859  vpERROR_TRACE("vpMatrix mismatch in vpMatrix::operator*(const vpTranslationVector)") ;
861  }
862 
863  for (unsigned int j=0;j<3;j++) c[j]=0 ;
864 
865  for (unsigned int j=0;j<3;j++) {
866  {
867  double bj = b[j] ; // optimization em 5/12/2006
868  for (unsigned int i=0;i<3;i++) {
869  c[i]+=rowPtrs[i][j] * bj;
870  }
871  }
872  }
873  return c ;
874 }
875 
876 //---------------------------------
877 // Matrix/real operations.
878 //---------------------------------
879 
884 vpMatrix operator*(const double &x,const vpMatrix &B)
885 {
886  // Modif EM 13/6/03
887  vpMatrix C ;
888 
889  try {
890  C.resize(B.getRows(),B.getCols());
891  }
892  catch(vpException me)
893  {
894  vpERROR_TRACE("Error caught") ;
895  std::cout << me << std::endl ;
896  throw ;
897  }
898  // double t0,t1;
899 
900  unsigned int Brow = B.getRows() ;
901  unsigned int Bcol = B.getCols() ;
902  // t0=vpTime::measureTimeMicros();
903  //
904  // for (int i=0;i<Brow; i++)
905  // {
906  // double *ci = C[i] ;
907  // double *Bi = B[i] ;
908  // for (int j=0 ; j < Bcol;j++)
909  // ci[j] = Bi[j]*x;
910  // }
911  //
912  // t1=vpTime::measureTimeMicros();
913  // std::cout<< t1-t0<<" ";
914 
915  // t0=vpTime::measureTimeMicros();
916  for (unsigned int i=0;i<Brow;i++)
917  for(unsigned int j=0;j<Bcol;j++)
918  C[i][j]= B[i][j]*x;
919  // t1=vpTime::measureTimeMicros();
920  // std::cout<< t1-t0<<std::endl;
921 
922 
923 
924  return C ;
925 }
926 
929 {
930  vpMatrix C;
931 
932  try {
933  C.resize(rowNum,colNum);
934  }
935  catch(vpException me)
936  {
937  vpERROR_TRACE("Error caught") ;
938  std::cout << me << std::endl ;
939  throw ;
940  }
941  // double t0,t1;
942 
943  double ** CrowPtrs=C.rowPtrs;
944 
945  // t0=vpTime::measureTimeMicros();
946  // for (int i=0;i<dsize;i++)
947  // *(C.data+i) = *(data+i)*x;
948  //
949  // t1=vpTime::measureTimeMicros();
950  // std::cout<< t1-t0<<" ";
951  //
952  // t0=vpTime::measureTimeMicros();
953  for (unsigned int i=0;i<rowNum;i++)
954  for(unsigned int j=0;j<colNum;j++)
955  CrowPtrs[i][j]= rowPtrs[i][j]*x;
956  // t1=vpTime::measureTimeMicros();
957  // std::cout<< t1-t0<<std::endl;
958 
959  return C;
960 }
961 
964 {
965  vpMatrix C;
966 
967  try {
968  C.resize(rowNum,colNum);
969  }
970  catch(vpException me)
971  {
972  vpERROR_TRACE("Error caught") ;
973  vpCERROR << me << std::endl ;
974  throw ;
975  }
976 
977  //if (x == 0) {
978  if (std::fabs(x) <= std::numeric_limits<double>::epsilon()) {
979  vpERROR_TRACE("Divide by zero in method /(double x)") ;
980  throw vpMatrixException(vpMatrixException::divideByZeroError, "Divide by zero in method /(double x)");
981  }
982 
983  double xinv = 1/x ;
984 
985 
986  // double t0,t1;
987  //
988  // t0=vpTime::measureTimeMicros();
989  // for (int i=0;i<dsize;i++)
990  // *(C.data+i) = *(data+i)*xinv ;
991  //
992  // t1=vpTime::measureTimeMicros();
993  // std::cout<< t1-t0<<" ";
994  //
995  // t0=vpTime::measureTimeMicros();
996  for (unsigned int i=0;i<rowNum;i++)
997  for(unsigned int j=0;j<colNum;j++)
998  C[i][j]=rowPtrs[i][j]*xinv;
999  // t1=vpTime::measureTimeMicros();
1000  // std::cout<< t1-t0<<std::endl;
1001 
1002  return C;
1003 
1004 }
1005 
1006 
1009 {
1010 
1011  // double t0,t1;
1012  //
1013  // t0=vpTime::measureTimeMicros();
1014  // for (int i=0;i<dsize;i++)
1015  // *(data+i) += x;
1016  //
1017  // t1=vpTime::measureTimeMicros();
1018  // std::cout<< t1-t0<<" ";
1019  //
1020  // t0=vpTime::measureTimeMicros();
1021  for (unsigned int i=0;i<rowNum;i++)
1022  for(unsigned int j=0;j<colNum;j++)
1023  rowPtrs[i][j]+=x;
1024  // t1=vpTime::measureTimeMicros();
1025  // std::cout<< t1-t0<<std::endl;
1026 
1027  return *this;
1028 }
1029 
1030 
1033 {
1034 
1035 
1036  // double t0,t1;
1037  //
1038  // t0=vpTime::measureTimeMicros();
1039  // for (int i=0;i<dsize;i++)
1040  // *(data+i) -= x;
1041  //
1042  // t1=vpTime::measureTimeMicros();
1043  // std::cout<< t1-t0<<" ";
1044  //
1045  // t0=vpTime::measureTimeMicros();
1046  for (unsigned int i=0;i<rowNum;i++)
1047  for(unsigned int j=0;j<colNum;j++)
1048  rowPtrs[i][j]-=x;
1049  // t1=vpTime::measureTimeMicros();
1050  // std::cout<< t1-t0<<std::endl;
1051 
1052  return *this;
1053 }
1054 
1057 {
1058 
1059 
1060  // for (int i=0;i<dsize;i++)
1061  // *(data+i) *= x;
1062 
1063  for (unsigned int i=0;i<rowNum;i++)
1064  for(unsigned int j=0;j<colNum;j++)
1065  rowPtrs[i][j]*=x;
1066 
1067  return *this;
1068 }
1069 
1072 {
1073  //if (x == 0)
1074  if (std::fabs(x) <= std::numeric_limits<double>::epsilon())
1075  throw vpMatrixException(vpMatrixException::divideByZeroError, "Divide by zero in method /=(double x)");
1076 
1077  double xinv = 1/x ;
1078 
1079  // double t0,t1;
1080  //
1081  // t0=vpTime::measureTimeMicros();
1082  // for (int i=0;i<dsize;i++)
1083  // *(data+i) *= xinv;
1084  //
1085  // t1=vpTime::measureTimeMicros();
1086  // std::cout<< t1-t0<<" ";
1087 
1088  // t0=vpTime::measureTimeMicros();
1089  for (unsigned int i=0;i<rowNum;i++)
1090  for(unsigned int j=0;j<colNum;j++)
1091  rowPtrs[i][j]*=xinv;
1092  // t1=vpTime::measureTimeMicros();
1093  // std::cout<< t1-t0<<std::endl;
1094 
1095  return *this;
1096 }
1097 
1098 //----------------------------------------------------------------
1099 // Matrix Operation
1100 //----------------------------------------------------------------
1101 
1102 
1107 void
1108 vpMatrix::setIdentity(const double & val)
1109 {
1110  if (rowNum != colNum)
1111  {
1112  vpERROR_TRACE("non square matrix") ;
1114  }
1115 
1116  unsigned int i,j;
1117  for (i=0;i<rowNum;i++)
1118  for (j=0;j<colNum;j++)
1119  if (i==j) (*this)[i][j] = val ; else (*this)[i][j] = 0;
1120 }
1121 
1129 void
1130 vpMatrix::eye(unsigned int n)
1131 {
1132  try {
1133  eye(n,n) ;
1134  }
1135  catch(vpException me)
1136  {
1137  vpERROR_TRACE("Error caught") ;
1138  vpCERROR << me << std::endl ;
1139  throw ;
1140  }
1141 }
1149 void
1150 vpMatrix::eye(unsigned int m, unsigned int n)
1151 {
1152  try {
1153  resize(m,n) ;
1154  }
1155  catch(vpException me)
1156  {
1157  vpERROR_TRACE("Error caught") ;
1158  vpCERROR << me << std::endl ;
1159  throw ;
1160  }
1161 
1162 
1163  for (unsigned int i=0; i<rowNum; i++)
1164  for (unsigned int j=0; j<colNum; j++)
1165  if (i == j) (*this)[i][j] = 1;
1166  else (*this)[i][j] = 0;
1167 
1168 }
1169 
1170 
1175 {
1176  vpMatrix At ;
1177 
1178  try {
1179  At.resize(colNum,rowNum);
1180  }
1181  catch(vpException me)
1182  {
1183  vpERROR_TRACE("Error caught") ;
1184  vpCERROR << me << std::endl ;
1185  throw ;
1186  }
1187 
1188  unsigned int i,j;
1189  for (i=0;i<rowNum;i++)
1190  {
1191  double *coli = (*this)[i] ;
1192  for (j=0;j<colNum;j++)
1193  At[j][i] = coli[j];
1194  }
1195  return At;
1196 }
1197 
1198 
1205 {
1206  vpMatrix At ;
1207  transpose(At);
1208  return At;
1209 }
1210 
1217 
1218  try {
1219  At.resize(colNum,rowNum);
1220  }
1221  catch(vpException me)
1222  {
1223  vpERROR_TRACE("Error caught") ;
1224  vpCERROR << me << std::endl ;
1225  throw ;
1226  }
1227 
1228  size_t A_step = colNum;
1229  double ** AtRowPtrs = At.rowPtrs;
1230 
1231  for( unsigned int i = 0; i < colNum; i++ )
1232  {
1233  double * row = AtRowPtrs[i];
1234  double * col = rowPtrs[0]+i;
1235  for( unsigned int j = 0; j < rowNum; j++, col+=A_step )
1236  *(row++)=*col;
1237  }
1238 }
1239 
1240 
1247 {
1248  vpMatrix B;
1249 
1250  AAt(B);
1251 
1252  return B;
1253 }
1254 
1266 void vpMatrix::AAt(vpMatrix &B)const {
1267 
1268  try {
1269  if ((B.rowNum != rowNum) || (B.colNum != rowNum)) B.resize(rowNum,rowNum);
1270  }
1271  catch(vpException me)
1272  {
1273  vpERROR_TRACE("Error caught") ;
1274  vpCERROR << me << std::endl ;
1275  throw ;
1276  }
1277 
1278  // compute A*A^T
1279  for(unsigned int i=0;i<rowNum;i++){
1280  for(unsigned int j=i;j<rowNum;j++){
1281  double *pi = rowPtrs[i];// row i
1282  double *pj = rowPtrs[j];// row j
1283 
1284  // sum (row i .* row j)
1285  double ssum=0;
1286  for(unsigned int k=0; k < colNum ;k++)
1287  ssum += *(pi++)* *(pj++);
1288 
1289  B[i][j]=ssum; //upper triangle
1290  if(i!=j)
1291  B[j][i]=ssum; //lower triangle
1292  }
1293  }
1294 }
1295 
1296 
1297 
1309 void vpMatrix::AtA(vpMatrix &B) const
1310 {
1311  try {
1312  if ((B.rowNum != colNum) || (B.colNum != colNum)) B.resize(colNum,colNum);
1313  }
1314  catch(vpException me)
1315  {
1316  vpERROR_TRACE("Error caught") ;
1317  vpCERROR << me << std::endl ;
1318  throw ;
1319  }
1320 
1321  unsigned int i,j,k;
1322  double s;
1323  double *ptr;
1324  double *Bi;
1325  for (i=0;i<colNum;i++)
1326  {
1327  Bi = B[i] ;
1328  for (j=0;j<i;j++)
1329  {
1330  ptr=data;
1331  s = 0 ;
1332  for (k=0;k<rowNum;k++)
1333  {
1334  s +=(*(ptr+i)) * (*(ptr+j));
1335  ptr+=colNum;
1336  }
1337  *Bi++ = s ;
1338  B[j][i] = s;
1339  }
1340  ptr=data;
1341  s = 0 ;
1342  for (k=0;k<rowNum;k++)
1343  {
1344  s +=(*(ptr+i)) * (*(ptr+i));
1345  ptr+=colNum;
1346  }
1347  *Bi = s;
1348  }
1349 }
1350 
1351 
1358 {
1359  vpMatrix B;
1360 
1361  AtA(B);
1362 
1363  return B;
1364 }
1365 
1366 
1372 
1373  try {
1374  if ((out.rowNum != colNum*rowNum) || (out.colNum != 1)) out.resize(rowNum);
1375  }
1376  catch(vpException me)
1377  {
1378  vpERROR_TRACE("Error caught") ;
1379  vpCERROR << me << std::endl ;
1380  throw ;
1381  }
1382 
1383  double *optr=out.data;
1384  for(unsigned int j =0;j<colNum ; j++){
1385  for(unsigned int i =0;i<rowNum ; i++){
1386  *(optr++)=rowPtrs[i][j];
1387  }
1388  }
1389 }
1390 
1396 
1397  vpColVector out(colNum*rowNum);
1398  stackColumns(out);
1399  return out;
1400 }
1401 
1407 
1408  try {
1409  if ((out.rowNum != 1) || (out.colNum != colNum*rowNum)) out.resize(rowNum);
1410  }
1411  catch(vpException me)
1412  {
1413  vpERROR_TRACE("Error caught") ;
1414  vpCERROR << me << std::endl ;
1415  throw ;
1416  }
1417 
1418  double *mdata=data;
1419  double *optr=out.data;
1420  for(unsigned int i =0;i<dsize ; i++){
1421  *(optr++)=*(mdata++);
1422  }
1423 }
1429 
1430  vpRowVector out(colNum*rowNum);
1431  stackRows(out );
1432  return out;
1433 }
1434 
1441 void vpMatrix::kron(const vpMatrix &m1, const vpMatrix &m2 , vpMatrix &out){
1442  unsigned int r1= m1.getRows();
1443  unsigned int c1= m1.getCols();
1444  unsigned int r2= m2.getRows();
1445  unsigned int c2= m2.getCols();
1446 
1447 
1448  if (r1*r2 !=out.rowNum || c1*c2!= out.colNum )
1449  {
1450  vpERROR_TRACE("Kronecker prodect bad dimension of output vpMatrix") ;
1451  throw(vpMatrixException(vpMatrixException::incorrectMatrixSizeError,"Kronecker prodect bad dimension of output vpMatrix"));
1452  }
1453 
1454  for(unsigned int r =0;r<r1 ; r++){
1455  for(unsigned int c =0;c<c1 ; c++){
1456  double alpha = m1[r][c];
1457  double *m2ptr = m2[0];
1458  unsigned int roffset= r*r2;
1459  unsigned int coffset= c*c2;
1460  for(unsigned int rr =0;rr<r2 ; rr++){
1461  for(unsigned int cc =0;cc<c2 ;cc++){
1462  out[roffset+rr][coffset+cc]= alpha* *(m2ptr++);
1463  }
1464  }
1465  }
1466  }
1467 
1468 }
1469 
1475 void vpMatrix::kron(const vpMatrix &m , vpMatrix &out){
1476  kron(*this,m,out);
1477 }
1478 
1485 vpMatrix vpMatrix::kron(const vpMatrix &m1, const vpMatrix &m2 ){
1486 
1487  unsigned int r1= m1.getRows();
1488  unsigned int c1= m1.getCols();
1489  unsigned int r2= m2.getRows();
1490  unsigned int c2= m2.getCols();
1491 
1492  vpMatrix out(r1*r2,c1*c2);
1493 
1494  for(unsigned int r =0;r<r1 ; r++){
1495  for(unsigned int c =0;c<c1 ; c++){
1496  double alpha = m1[r][c];
1497  double *m2ptr = m2[0];
1498  unsigned int roffset= r*r2;
1499  unsigned int coffset= c*c2;
1500  for(unsigned int rr =0;rr<r2 ; rr++){
1501  for(unsigned int cc =0;cc<c2 ;cc++){
1502  out[roffset+rr ][coffset+cc]= alpha* *(m2ptr++);
1503  }
1504  }
1505  }
1506  }
1507  return out;
1508 }
1509 
1510 
1517  return kron(*this,m);
1518 }
1519 
1570 void
1572 {
1573  x = pseudoInverse(1e-6)*b ;
1574 }
1575 
1576 
1627 {
1628  vpColVector X(colNum);
1629 
1630  solveBySVD(B, X);
1631  return X;
1632 }
1633 
1634 
1699 void
1701 {
1702 #if (DEBUG_LEVEL1 == 0) /* no verification */
1703  {
1704  w.resize( this->getCols() );
1705  v.resize( this->getCols(), this->getCols() );
1706 
1707 #if defined (VISP_HAVE_LAPACK)
1708  svdLapack(w,v);
1709 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
1710  svdOpenCV(w,v);
1711 #elif defined (VISP_HAVE_GSL) /* be careful of the copy below */
1712  svdGsl(w,v) ;
1713 #else
1714  svdNr(w,v) ;
1715 #endif
1716 
1717  //svdNr(w,v) ;
1718  }
1719 #else /* verification of the SVD */
1720  {
1721  int pb = 0;
1722  unsigned int i,j,k,nrows,ncols;
1723  vpMatrix A, Asvd;
1724 
1725  A = (*this); /* copy because svd is destructive */
1726 
1727  w.resize( this->getCols() );
1728  v.resize( this->getCols(), this->getCols() );
1729 #ifdef VISP_HAVE_GSL /* be careful of the copy above */
1730  svdGsl(w,v) ;
1731 #else
1732  svdNr(w,v) ;
1733 #endif
1734  //svdNr(w,v) ;
1735 
1736  nrows = A.getRows();
1737  ncols = A.getCols();
1738  Asvd.resize(nrows,ncols);
1739 
1740  for (i = 0 ; i < nrows ; i++)
1741  {
1742  for (j = 0 ; j < ncols ; j++)
1743  {
1744  Asvd[i][j] = 0.0;
1745  for (k=0 ; k < ncols ; k++) Asvd[i][j] += (*this)[i][k]*w[k]*v[j][k];
1746  }
1747  }
1748  for (i=0;i<nrows;i++)
1749  {
1750  for (j=0;j<ncols;j++) if (fabs(A[i][j]-Asvd[i][j]) > 1e-6) pb = 1;
1751  }
1752  if (pb == 1)
1753  {
1754  printf("pb in SVD\n");
1755  std::cout << " A : " << std::endl << A << std::endl;
1756  std::cout << " Asvd : " << std::endl << Asvd << std::endl;
1757  }
1758  // else printf("SVD ok ;-)\n"); /* It's so good... */
1759  }
1760 #endif
1761 }
1769 unsigned int
1770 vpMatrix::pseudoInverse(vpMatrix &Ap, double svThreshold) const
1771 {
1772  vpColVector sv ;
1773  return pseudoInverse(Ap, sv, svThreshold) ;
1774 }
1775 
1809 vpMatrix
1810 vpMatrix::pseudoInverse(double svThreshold) const
1811 {
1812  vpMatrix Ap ;
1813  vpColVector sv ;
1814  pseudoInverse(Ap, sv, svThreshold) ;
1815  return Ap ;
1816 }
1817 
1825 unsigned int
1826 vpMatrix::pseudoInverse(vpMatrix &Ap, vpColVector &sv, double svThreshold) const
1827 {
1828  vpMatrix imA, imAt ;
1829  return pseudoInverse(Ap, sv, svThreshold, imA, imAt) ;
1830 }
1831 
1864 unsigned int
1866  vpColVector &sv, double svThreshold,
1867  vpMatrix &imA,
1868  vpMatrix &imAt) const
1869 {
1870 
1871  unsigned int i, j, k ;
1872 
1873  unsigned int nrows, ncols;
1874  unsigned int nrows_orig = getRows() ;
1875  unsigned int ncols_orig = getCols() ;
1876  Ap.resize(ncols_orig,nrows_orig) ;
1877 
1878  if (nrows_orig >= ncols_orig)
1879  {
1880  nrows = nrows_orig;
1881  ncols = ncols_orig;
1882  }
1883  else
1884  {
1885  nrows = ncols_orig;
1886  ncols = nrows_orig;
1887  }
1888 
1889  vpMatrix a(nrows,ncols) ;
1890  vpMatrix a1(ncols,nrows);
1891  vpMatrix v(ncols,ncols) ;
1892  sv.resize(ncols) ;
1893 
1894  if (nrows_orig >= ncols_orig) a = *this;
1895  else a = (*this).t();
1896 
1897  a.svd(sv,v);
1898 
1899  // compute the highest singular value and the rank of h
1900  double maxsv = 0 ;
1901  for (i=0 ; i < ncols ; i++)
1902  if (fabs(sv[i]) > maxsv) maxsv = fabs(sv[i]) ;
1903 
1904  unsigned int rank = 0 ;
1905  for (i=0 ; i < ncols ; i++)
1906  if (fabs(sv[i]) > maxsv*svThreshold) rank++ ;
1907 
1908 
1909 
1910  /*------------------------------------------------------- */
1911  for (i = 0 ; i < ncols ; i++)
1912  {
1913  for (j = 0 ; j < nrows ; j++)
1914  {
1915  a1[i][j] = 0.0;
1916 
1917  for (k=0 ; k < ncols ; k++)
1918  if (fabs(sv[k]) > maxsv*svThreshold)
1919  {
1920  a1[i][j] += v[i][k]*a[j][k]/sv[k];
1921  }
1922  }
1923  }
1924  if (nrows_orig >= ncols_orig) Ap = a1;
1925  else Ap = a1.t();
1926 
1927  if (nrows_orig >= ncols_orig)
1928  {
1929  // compute dim At
1930  imAt.resize(ncols_orig,rank) ;
1931  for (i=0 ; i < ncols_orig ; i++)
1932  for (j=0 ; j < rank ; j++)
1933  imAt[i][j] = v[i][j] ;
1934 
1935  // compute dim A
1936  imA.resize(nrows_orig,rank) ;
1937  for (i=0 ; i < nrows_orig ; i++)
1938  for (j=0 ; j < rank ; j++)
1939  imA[i][j] = a[i][j] ;
1940  }
1941  else
1942  {
1943  // compute dim At
1944  imAt.resize(ncols_orig,rank) ;
1945  for (i=0 ; i < ncols_orig ; i++)
1946  for (j=0 ; j < rank ; j++)
1947  imAt[i][j] = a[i][j] ;
1948 
1949  imA.resize(nrows_orig,rank) ;
1950  for (i=0 ; i < nrows_orig ; i++)
1951  for (j=0 ; j < rank ; j++)
1952  imA[i][j] = v[i][j] ;
1953 
1954  }
1955 
1956 #if (DEBUG_LEVEL1)
1957  {
1958  int pb = 0;
1959  vpMatrix A, ApA, AAp, AApA, ApAAp ;
1960 
1961  nrows = nrows_orig;
1962  ncols = ncols_orig;
1963 
1964  A.resize(nrows,ncols) ;
1965  A = *this ;
1966 
1967  ApA = Ap * A;
1968  AApA = A * ApA;
1969  ApAAp = ApA * Ap;
1970  AAp = A * Ap;
1971 
1972  for (i=0;i<nrows;i++)
1973  {
1974  for (j=0;j<ncols;j++) if (fabs(AApA[i][j]-A[i][j]) > 1e-6) pb = 1;
1975  }
1976  for (i=0;i<ncols;i++)
1977  {
1978  for (j=0;j<nrows;j++) if (fabs(ApAAp[i][j]-Ap[i][j]) > 1e-6) pb = 1;
1979  }
1980  for (i=0;i<nrows;i++)
1981  {
1982  for (j=0;j<nrows;j++) if (fabs(AAp[i][j]-AAp[j][i]) > 1e-6) pb = 1;
1983  }
1984  for (i=0;i<ncols;i++)
1985  {
1986  for (j=0;j<ncols;j++) if (fabs(ApA[i][j]-ApA[j][i]) > 1e-6) pb = 1;
1987  }
1988  if (pb == 1)
1989  {
1990  printf("pb in pseudo inverse\n");
1991  std::cout << " A : " << std::endl << A << std::endl;
1992  std::cout << " Ap : " << std::endl << Ap << std::endl;
1993  std::cout << " A - AApA : " << std::endl << A - AApA << std::endl;
1994  std::cout << " Ap - ApAAp : " << std::endl << Ap - ApAAp << std::endl;
1995  std::cout << " AAp - (AAp)^T : " << std::endl << AAp - AAp.t() << std::endl;
1996  std::cout << " ApA - (ApA)^T : " << std::endl << ApA - ApA.t() << std::endl;
1997  }
1998  // else printf("Ap OK ;-) \n");
1999 
2000  }
2001 #endif
2002 
2003  // std::cout << v << std::endl ;
2004  return rank ;
2005 }
2006 
2007 
2008 
2042 unsigned int
2044  vpColVector &sv, double svThreshold,
2045  vpMatrix &imA,
2046  vpMatrix &imAt,
2047  vpMatrix &kerA) const
2048 {
2049 
2050  unsigned int i, j, k ;
2051 
2052  unsigned int nrows, ncols;
2053  unsigned int nrows_orig = getRows() ;
2054  unsigned int ncols_orig = getCols() ;
2055  Ap.resize(ncols_orig,nrows_orig) ;
2056 
2057  if (nrows_orig >= ncols_orig)
2058  {
2059  nrows = nrows_orig;
2060  ncols = ncols_orig;
2061  }
2062  else
2063  {
2064  nrows = ncols_orig;
2065  ncols = nrows_orig;
2066  }
2067 
2068  vpMatrix a(nrows,ncols) ;
2069  vpMatrix a1(ncols,nrows);
2070  vpMatrix v(ncols,ncols) ;
2071  sv.resize(ncols) ;
2072 
2073  if (nrows_orig >= ncols_orig) a = *this;
2074  else a = (*this).t();
2075 
2076  a.svd(sv,v);
2077 
2078  // compute the highest singular value and the rank of h
2079  double maxsv = 0 ;
2080  for (i=0 ; i < ncols ; i++)
2081  if (fabs(sv[i]) > maxsv) maxsv = fabs(sv[i]) ;
2082 
2083  unsigned int rank = 0 ;
2084  for (i=0 ; i < ncols ; i++)
2085  if (fabs(sv[i]) > maxsv*svThreshold) rank++ ;
2086 
2087 
2088 
2089  /*------------------------------------------------------- */
2090  for (i = 0 ; i < ncols ; i++)
2091  {
2092  for (j = 0 ; j < nrows ; j++)
2093  {
2094  a1[i][j] = 0.0;
2095 
2096  for (k=0 ; k < ncols ; k++)
2097  if (fabs(sv[k]) > maxsv*svThreshold)
2098  {
2099  a1[i][j] += v[i][k]*a[j][k]/sv[k];
2100  }
2101  }
2102  }
2103  if (nrows_orig >= ncols_orig) Ap = a1;
2104  else Ap = a1.t();
2105 
2106  if (nrows_orig >= ncols_orig)
2107  {
2108  // compute dim At
2109  imAt.resize(ncols_orig,rank) ;
2110  for (i=0 ; i < ncols_orig ; i++)
2111  for (j=0 ; j < rank ; j++)
2112  imAt[i][j] = v[i][j] ;
2113 
2114  // compute dim A
2115  imA.resize(nrows_orig,rank) ;
2116  for (i=0 ; i < nrows_orig ; i++)
2117  for (j=0 ; j < rank ; j++)
2118  imA[i][j] = a[i][j] ;
2119  }
2120  else
2121  {
2122  // compute dim At
2123  imAt.resize(ncols_orig,rank) ;
2124  for (i=0 ; i < ncols_orig ; i++)
2125  for (j=0 ; j < rank ; j++)
2126  imAt[i][j] = a[i][j] ;
2127 
2128  imA.resize(nrows_orig,rank) ;
2129  for (i=0 ; i < nrows_orig ; i++)
2130  for (j=0 ; j < rank ; j++)
2131  imA[i][j] = v[i][j] ;
2132 
2133  }
2134 
2135  vpMatrix cons(ncols_orig, ncols_orig);
2136  cons = 0;
2137 
2138  for (j = 0; j < ncols_orig; j++)
2139  {
2140  for (i = 0; i < ncols_orig; i++)
2141  {
2142  if (fabs(sv[i]) <= maxsv*svThreshold)
2143  {
2144  cons[i][j] = v[j][i];
2145  }
2146  }
2147  }
2148 
2149  vpMatrix Ker (ncols_orig-rank, ncols_orig);
2150  k = 0;
2151  for (j = 0; j < ncols_orig ; j++)
2152  {
2153  //if ( cons.row(j+1).sumSquare() != 0)
2154  if ( std::fabs(cons.row(j+1).sumSquare()) > std::numeric_limits<double>::epsilon())
2155  {
2156  for (i = 0; i < cons.getCols(); i++)
2157  Ker[k][i] = cons[j][i];
2158 
2159  k++;
2160  }
2161  }
2162  kerA = Ker;
2163 
2164 #if (DEBUG_LEVEL1)
2165  {
2166  int pb = 0;
2167  vpMatrix A, ApA, AAp, AApA, ApAAp ;
2168 
2169  nrows = nrows_orig;
2170  ncols = ncols_orig;
2171 
2172  A.resize(nrows,ncols) ;
2173  A = *this ;
2174 
2175  ApA = Ap * A;
2176  AApA = A * ApA;
2177  ApAAp = ApA * Ap;
2178  AAp = A * Ap;
2179 
2180  for (i=0;i<nrows;i++)
2181  {
2182  for (j=0;j<ncols;j++) if (fabs(AApA[i][j]-A[i][j]) > 1e-6) pb = 1;
2183  }
2184  for (i=0;i<ncols;i++)
2185  {
2186  for (j=0;j<nrows;j++) if (fabs(ApAAp[i][j]-Ap[i][j]) > 1e-6) pb = 1;
2187  }
2188  for (i=0;i<nrows;i++)
2189  {
2190  for (j=0;j<nrows;j++) if (fabs(AAp[i][j]-AAp[j][i]) > 1e-6) pb = 1;
2191  }
2192  for (i=0;i<ncols;i++)
2193  {
2194  for (j=0;j<ncols;j++) if (fabs(ApA[i][j]-ApA[j][i]) > 1e-6) pb = 1;
2195  }
2196  if (pb == 1)
2197  {
2198  printf("pb in pseudo inverse\n");
2199  std::cout << " A : " << std::endl << A << std::endl;
2200  std::cout << " Ap : " << std::endl << Ap << std::endl;
2201  std::cout << " A - AApA : " << std::endl << A - AApA << std::endl;
2202  std::cout << " Ap - ApAAp : " << std::endl << Ap - ApAAp << std::endl;
2203  std::cout << " AAp - (AAp)^T : " << std::endl << AAp - AAp.t() << std::endl;
2204  std::cout << " ApA - (ApA)^T : " << std::endl << ApA - ApA.t() << std::endl;
2205  std::cout << " KerA : " << std::endl << kerA << std::endl;
2206  }
2207  // else printf("Ap OK ;-) \n");
2208 
2209  }
2210 #endif
2211 
2212  // std::cout << v << std::endl ;
2213  return rank ;
2214 }
2215 
2216 
2223 vpMatrix::row(const unsigned int j)
2224 {
2225  vpRowVector c(getCols()) ;
2226 
2227  for (unsigned int i =0 ; i < getCols() ; i++) c[i] = (*this)[j-1][i] ;
2228  return c ;
2229 }
2230 
2231 
2238 vpMatrix::column(const unsigned int j)
2239 {
2240  vpColVector c(getRows()) ;
2241 
2242  for (unsigned int i =0 ; i < getRows() ; i++) c[i] = (*this)[i][j-1] ;
2243  return c ;
2244 }
2245 
2246 
2247 
2248 
2260 vpMatrix
2262 {
2263  vpMatrix C ;
2264 
2265  try{
2266  stackMatrices(A,B, C) ;
2267  }
2268  catch(vpMatrixException me)
2269  {
2270  vpCERROR << me << std::endl;
2271  throw ;
2272  }
2273 
2274  return C ;
2275 }
2276 
2289 void
2291 {
2292  unsigned int nra = A.getRows() ;
2293  unsigned int nrb = B.getRows() ;
2294 
2295  if (nra !=0)
2296  if (A.getCols() != B.getCols())
2297  {
2298  vpERROR_TRACE("\n\t\t incorrect matrices size") ;
2300  "\n\t\t incorrect matrices size")) ;
2301  }
2302 
2303  try {
2304  C.resize(nra+nrb,B.getCols() ) ;
2305  }
2306  catch(vpException me)
2307  {
2308  vpERROR_TRACE("Error caught") ;
2309  vpCERROR << me << std::endl ;
2310  throw ;
2311  }
2312 
2313  unsigned int i,j ;
2314  for (i=0 ; i < nra ; i++)
2315  for (j=0 ; j < A.getCols() ; j++)
2316  C[i][j] = A[i][j] ;
2317 
2318 
2319  for (i=0 ; i < nrb ; i++)
2320  for (j=0 ; j < B.getCols() ; j++)
2321  {
2322  C[i+nra][j] = B[i][j] ;
2323 
2324  }
2325 
2326 
2327 }
2328 
2329 
2330 
2331 
2332 
2345 vpMatrix
2346 vpMatrix::insert(const vpMatrix &A, const vpMatrix &B,
2347  const unsigned int r, const unsigned int c)
2348 {
2349  vpMatrix C ;
2350 
2351  try{
2352  insert(A,B, C, r, c) ;
2353  }
2354  catch(vpMatrixException me)
2355  {
2356  vpCERROR << me << std::endl;
2357  throw me;
2358  }
2359 
2360  return C ;
2361 }
2362 
2376 void
2377 vpMatrix::insert(const vpMatrix &A, const vpMatrix &B, vpMatrix &C,
2378  const unsigned int r, const unsigned int c)
2379 {
2380  if( ( (r + B.getRows()) <= A.getRows() ) &&
2381  ( (c + B.getCols()) <= A.getRows() ) ){
2382  try {
2383  C.resize(A.getRows(),A.getCols() ) ;
2384  }
2385  catch(vpException me)
2386  {
2387  vpERROR_TRACE("Error caught") ;
2388  vpCERROR << me << std::endl ;
2389  throw ;
2390  }
2391  for(unsigned int i=0; i<A.getRows(); i++){
2392  for(unsigned int j=0; j<A.getCols(); j++){
2393  if(i >= r && i < (r + B.getRows()) && j >= c && j < (c+B.getCols())){
2394  C[i][j] = B[i-r][j-c];
2395  }
2396  else{
2397  C[i][j] = A[i][j];
2398  }
2399  }
2400  }
2401  }
2402  else{
2404  "\n\t\tIncorrect size of the matrix to insert data.");
2405  }
2406 }
2407 
2419 vpMatrix
2421 {
2422  vpMatrix C ;
2423 
2424  try{
2425  juxtaposeMatrices(A,B, C) ;
2426  }
2427  catch(vpMatrixException me)
2428  {
2429  vpCERROR << me << std::endl ;
2430  throw ;
2431  }
2432 
2433  return C ;
2434 }
2435 
2448 void
2450 {
2451  unsigned int nca = A.getCols() ;
2452  unsigned int ncb = B.getCols() ;
2453 
2454  if (nca !=0)
2455  if (A.getRows() != B.getRows())
2456  {
2457  vpERROR_TRACE("\n\t\t incorrect matrices size") ;
2459  "\n\t\t incorrect matrices size")) ;
2460  }
2461 
2462  try {
2463  C.resize(B.getRows(),nca+ncb) ;
2464  }
2465  catch(vpException me)
2466  {
2467  vpERROR_TRACE("Error caught") ;
2468  vpCERROR << me << std::endl ;
2469  throw ;
2470  }
2471 
2472  unsigned int i,j ;
2473  for (i=0 ; i < C.getRows(); i++)
2474  for (j=0 ; j < nca ; j++)
2475  C[i][j] = A[i][j] ;
2476 
2477 
2478  for (i=0 ; i < C.getRows() ; i++)
2479  for (j=0 ; j < ncb ; j++)
2480  {
2481  C[i][nca+j] = B[i][j] ;
2482  }
2483 }
2484 
2520 void
2522 {
2523  unsigned int rows = A.getRows() ;
2524  try {
2525  this->resize(rows,rows) ;
2526  }
2527  catch(vpException me)
2528  {
2529  vpERROR_TRACE("Error caught") ;
2530  vpCERROR << me << std::endl ;
2531  throw ;
2532  }
2533  (*this) = 0 ;
2534  for (unsigned int i=0 ; i< rows ; i++ )
2535  (* this)[i][i] = A[i] ;
2536 }
2548 void
2550 {
2551  unsigned int rows = A.getRows() ;
2552  try {
2553  DA.resize(rows,rows) ;
2554  }
2555  catch(vpException me)
2556  {
2557  vpERROR_TRACE("Error caught") ;
2558  vpCERROR << me << std::endl ;
2559  throw ;
2560  }
2561  DA =0 ;
2562  for (unsigned int i=0 ; i< rows ; i++ )
2563  DA[i][i] = A[i] ;
2564 }
2565 
2566 //--------------------------------------------------------------------
2567 // Output
2568 //--------------------------------------------------------------------
2569 
2570 
2574 std::ostream &operator <<(std::ostream &s,const vpMatrix &m)
2575 {
2576  s.precision(10) ;
2577  for (unsigned int i=0;i<m.getRows();i++) {
2578  for (unsigned int j=0;j<m.getCols();j++){
2579  s << m[i][j] << " ";
2580  }
2581  // We don't add a \n char on the end of the last matrix line
2582  if (i < m.getRows()-1)
2583  s << std::endl;
2584  }
2585 
2586  return s;
2587 }
2588 
2612 int
2613 vpMatrix::print(std::ostream& s, unsigned int length, char const* intro)
2614 {
2615  typedef std::string::size_type size_type;
2616 
2617  unsigned int m = getRows();
2618  unsigned int n = getCols();
2619 
2620  std::vector<std::string> values(m*n);
2621  std::ostringstream oss;
2622  std::ostringstream ossFixed;
2623  // ossFixed <<std::fixed;
2624  ossFixed.setf ( std::ios::fixed, std::ios::floatfield );
2625 
2626  size_type maxBefore=0; // the length of the integral part
2627  size_type maxAfter=0; // number of decimals plus
2628  // one place for the decimal point
2629  for (unsigned int i=0;i<m;++i) {
2630  for (unsigned int j=0;j<n;++j){
2631  oss.str("");
2632  oss << (*this)[i][j];
2633  if (oss.str().find("e")!=std::string::npos){
2634  ossFixed.str("");
2635  ossFixed << (*this)[i][j];
2636  oss.str(ossFixed.str());
2637  }
2638 
2639  values[i*n+j]=oss.str();
2640  size_type thislen=values[i*n+j].size();
2641  size_type p=values[i*n+j].find('.');
2642 
2643  if (p==std::string::npos){
2644  maxBefore=vpMath::maximum(maxBefore, thislen);
2645  // maxAfter remains the same
2646  } else{
2647  maxBefore=vpMath::maximum(maxBefore, p);
2648  maxAfter=vpMath::maximum(maxAfter, thislen-p-1);
2649  }
2650  }
2651  }
2652 
2653  size_type totalLength=length;
2654  // increase totalLength according to maxBefore
2655  totalLength=vpMath::maximum(totalLength,maxBefore);
2656  // decrease maxAfter according to totalLength
2657  maxAfter=std::min(maxAfter, totalLength-maxBefore);
2658  if (maxAfter==1) maxAfter=0;
2659 
2660  // the following line is useful for debugging
2661  std::cerr <<totalLength <<" " <<maxBefore <<" " <<maxAfter <<"\n";
2662 
2663  if (intro) s <<intro;
2664  s <<"["<<m<<","<<n<<"]=\n";
2665 
2666  for (unsigned int i=0;i<m;i++) {
2667  s <<" ";
2668  for (unsigned int j=0;j<n;j++){
2669  size_type p=values[i*n+j].find('.');
2670  s.setf(std::ios::right, std::ios::adjustfield);
2671  s.width((std::streamsize)maxBefore);
2672  s <<values[i*n+j].substr(0,p).c_str();
2673 
2674  if (maxAfter>0){
2675  s.setf(std::ios::left, std::ios::adjustfield);
2676  if (p!=std::string::npos){
2677  s.width((std::streamsize)maxAfter);
2678  s <<values[i*n+j].substr(p,maxAfter).c_str();
2679  } else{
2680  assert(maxAfter>1);
2681  s.width((std::streamsize)maxAfter);
2682  s <<".0";
2683  }
2684  }
2685 
2686  s <<' ';
2687  }
2688  s <<std::endl;
2689  }
2690 
2691  return (int)(maxBefore+maxAfter);
2692 }
2693 
2694 
2703 std::ostream & vpMatrix::
2704 matlabPrint(std::ostream & os)
2705 {
2706 
2707  unsigned int i,j;
2708 
2709  os << "[ ";
2710  for (i=0; i < this->getRows(); ++ i)
2711  {
2712  for (j=0; j < this ->getCols(); ++ j)
2713  {
2714  os << (*this)[i][j] << ", ";
2715  }
2716  if (this ->getRows() != i+1) { os << ";" << std::endl; }
2717  else { os << "]" << std::endl; }
2718  }
2719  return os;
2720 };
2721 
2732 std::ostream & vpMatrix::
2733 maplePrint(std::ostream & os)
2734 {
2735  unsigned int i,j;
2736 
2737  os << "([ " << std::endl;
2738  for (i=0; i < this->getRows(); ++ i)
2739  { os << "[";
2740  for (j=0; j < this->getCols(); ++ j)
2741  {
2742  os << (*this)[i][j] << ", ";
2743  }
2744  os << "]," << std::endl;
2745  }
2746  os << "])" << std::endl;
2747  return os;
2748 };
2749 
2750 
2765 std::ostream & vpMatrix::
2766 cppPrint(std::ostream & os, const char * matrixName, bool octet)
2767 {
2768 
2769  unsigned int i,j;
2770  const char defaultName [] = "A";
2771  if (NULL == matrixName)
2772  {
2773  matrixName = defaultName;
2774  }
2775  os << "vpMatrix " << defaultName
2776  << " (" << this ->getRows ()
2777  << ", " << this ->getCols () << "); " <<std::endl;
2778 
2779  for (i=0; i < this->getRows(); ++ i)
2780  {
2781  for (j=0; j < this ->getCols(); ++ j)
2782  {
2783  if (! octet)
2784  {
2785  os << defaultName << "[" << i << "][" << j
2786  << "] = " << (*this)[i][j] << "; " << std::endl;
2787  }
2788  else
2789  {
2790  for (unsigned int k = 0; k < sizeof(double); ++ k)
2791  {
2792  os << "((unsigned char*)&(" << defaultName
2793  << "[" << i << "][" << j << "]) )[" << k
2794  <<"] = 0x" <<std::hex<<
2795  (unsigned int)((unsigned char*)& ((*this)[i][j])) [k]
2796  << "; " << std::endl;
2797  }
2798  }
2799  }
2800  os << std::endl;
2801  }
2802  return os;
2803 };
2804 
2805 
2813 double
2815 {
2816  double norm=0.0;
2817  double x ;
2818  for (unsigned int i=0;i<dsize;i++) {
2819  x = *(data +i); norm += x*x;
2820  }
2821 
2822  return sqrt(norm);
2823 }
2824 
2825 
2826 
2837 double
2839 {
2840  double norm=0.0;
2841  double x ;
2842  for (unsigned int i=0;i<rowNum;i++){
2843  x = 0;
2844  for (unsigned int j=0; j<colNum;j++){
2845  x += fabs (*(*(rowPtrs + i)+j)) ;
2846  }
2847  if (x > norm) {
2848  norm = x;
2849  }
2850  }
2851  return norm;
2852 }
2853 
2862 double vpMatrix::detByLU() const
2863 {
2864  double det(0);
2865 
2866  // Test wether the matrix is squred
2867  if (rowNum == colNum)
2868  {
2869  // create a temporary matrix that will be modified by LUDcmp
2870  vpMatrix tmp(*this);
2871 
2872  // using th LUdcmp based on NR codes
2873  // it modified the tmp matrix in a special structure of type :
2874  // b11 b12 b13 b14
2875  // a21 b22 b23 b24
2876  // a21 a32 b33 b34
2877  // a31 a42 a43 b44
2878 
2879  unsigned int * perm = new unsigned int[rowNum]; // stores the permutations
2880  int d; // +- 1 fi the number of column interchange is even or odd
2881  tmp.LUDcmp(perm, d);
2882  delete[]perm;
2883 
2884  // compute the determinant that is the product of the eigen values
2885  det = (double) d;
2886  for(unsigned int i=0;i<rowNum;i++)
2887  {
2888  det*=tmp[i][i];
2889  }
2890  }
2891 
2892  else {
2893  vpERROR_TRACE("Determinant Computation : ERR Matrix not squared") ;
2895  "\n\t\tDeterminant Computation : ERR Matrix not squared")) ;
2896 
2897 
2898  }
2899  return det ;
2900 }
2901 
2902 
2903 
2919 {
2920  if(rowNum == 0)
2921  *this = A;
2922  else
2923  *this = vpMatrix::stackMatrices(*this, A);
2924 }
2925 
2926 
2937 void vpMatrix::insert(const vpMatrix&A, const unsigned int r,
2938  const unsigned int c)
2939 {
2940  if( (r + A.getRows() ) <= rowNum && (c + A.getCols() ) <= colNum ){
2941  // recopy matrix A in the current one, does not call static function to avoid initialisation and recopy of matrix
2942  for(unsigned int i=r; i<(r+A.getRows()); i++){
2943  for(unsigned int j=c; j<(c+A.getCols()); j++){
2944  (*this)[i][j] = A[i-r][j-c];
2945  }
2946  }
2947  }
2948  else{
2950  "\n\t\tIncorrect size of the matrix to insert data.");
2951  }
2952 }
2953 
2954 
2995 {
2996  if (rowNum != colNum) {
2997  vpERROR_TRACE("Eigen values computation: ERR Matrix not square") ;
2999  "\n\t\tEigen values computation: ERR Matrix not square")) ;
3000  }
3001 
3002 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
3003  {
3004  // Check if the matrix is symetric: At - A = 0
3005  vpMatrix At_A = (*this).t() - (*this);
3006  for (unsigned int i=0; i < rowNum; i++) {
3007  for (unsigned int j=0; j < rowNum; j++) {
3008  //if (At_A[i][j] != 0) {
3009  if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
3010  vpERROR_TRACE("Eigen values computation: ERR Matrix not symmetric") ;
3012  "\n\t\tEigen values computation: "
3013  "ERR Matrix not symmetric")) ;
3014  }
3015  }
3016  }
3017 
3018 
3019  vpColVector evalue(rowNum); // Eigen values
3020 
3021  gsl_vector *eval = gsl_vector_alloc (rowNum);
3022  gsl_matrix *evec = gsl_matrix_alloc (rowNum, colNum);
3023 
3024  gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc (rowNum);
3025  gsl_matrix *m = gsl_matrix_alloc(rowNum, colNum);
3026 
3027  unsigned int Atda = m->tda ;
3028  for (unsigned int i=0 ; i < rowNum ; i++){
3029  unsigned int k = i*Atda ;
3030  for (unsigned int j=0 ; j < colNum ; j++)
3031  m->data[k+j] = (*this)[i][j] ;
3032  }
3033  gsl_eigen_symmv (m, eval, evec, w);
3034 
3035  gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_ABS_ASC);
3036 
3037  for (unsigned int i=0; i < rowNum; i++) {
3038  evalue[i] = gsl_vector_get (eval, i);
3039  }
3040 
3041  gsl_eigen_symmv_free (w);
3042  gsl_vector_free (eval);
3043  gsl_matrix_free (m);
3044  gsl_matrix_free (evec);
3045 
3046  return evalue;
3047  }
3048 #else
3049  {
3050  vpERROR_TRACE("Not implemented since the GSL library is not detected.") ;
3052  "\n\t\tEigen values Computation: Not implemented "
3053  "since the GSL library is not detected")) ;
3054  }
3055 #endif
3056 }
3057 
3112 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
3114 #else
3115 void vpMatrix::eigenValues(vpColVector & /* evalue */, vpMatrix & /* evector */)
3116 #endif
3117 {
3118  if (rowNum != colNum) {
3119  vpERROR_TRACE("Eigen values computation: ERR Matrix not square") ;
3121  "\n\t\tEigen values computation: ERR Matrix not square")) ;
3122  }
3123 
3124 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
3125  {
3126  // Check if the matrix is symetric: At - A = 0
3127  vpMatrix At_A = (*this).t() - (*this);
3128  for (unsigned int i=0; i < rowNum; i++) {
3129  for (unsigned int j=0; j < rowNum; j++) {
3130  //if (At_A[i][j] != 0) {
3131  if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
3132  vpERROR_TRACE("Eigen values computation: ERR Matrix not symmetric") ;
3134  "\n\t\tEigen values computation: "
3135  "ERR Matrix not symmetric")) ;
3136  }
3137  }
3138  }
3139 
3140  // Resize the output matrices
3141  evalue.resize(rowNum);
3142  evector.resize(rowNum, colNum);
3143 
3144  gsl_vector *eval = gsl_vector_alloc (rowNum);
3145  gsl_matrix *evec = gsl_matrix_alloc (rowNum, colNum);
3146 
3147  gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc (rowNum);
3148  gsl_matrix *m = gsl_matrix_alloc(rowNum, colNum);
3149 
3150  unsigned int Atda = m->tda ;
3151  for (unsigned int i=0 ; i < rowNum ; i++){
3152  unsigned int k = i*Atda ;
3153  for (unsigned int j=0 ; j < colNum ; j++)
3154  m->data[k+j] = (*this)[i][j] ;
3155  }
3156  gsl_eigen_symmv (m, eval, evec, w);
3157 
3158  gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_ABS_ASC);
3159 
3160  for (unsigned int i=0; i < rowNum; i++) {
3161  evalue[i] = gsl_vector_get (eval, i);
3162  }
3163  Atda = evec->tda ;
3164  for (unsigned int i=0; i < rowNum; i++) {
3165  unsigned int k = i*Atda ;
3166  for (unsigned int j=0; j < rowNum; j++) {
3167  evector[i][j] = evec->data[k+j];
3168  }
3169  }
3170 
3171 
3172  // {
3173  // int i;
3174 
3175  // for (i = 0; i < rowNum; i++)
3176  // {
3177  // double eval_i
3178  // = gsl_vector_get (eval, i);
3179  // gsl_vector_view evec_i
3180  // = gsl_matrix_column (evec, i);
3181 
3182  // printf ("eigenvalue = %g\n", eval_i);
3183  // printf ("eigenvector = \n");
3184  // gsl_vector_fprintf (stdout,
3185  // &evec_i.vector, "%g");
3186  // }
3187  // }
3188 
3189  gsl_eigen_symmv_free (w);
3190  gsl_vector_free (eval);
3191  gsl_matrix_free (m);
3192  gsl_matrix_free (evec);
3193  }
3194 #else
3195  {
3196  vpERROR_TRACE("Not implemented since the GSL library is not detected.") ;
3198  "\n\t\tEigen values Computation: Not implemented "
3199  "since the GSL library is not detected")) ;
3200  }
3201 #endif
3202 }
3203 
3204 
3214 unsigned int
3215 vpMatrix::kernel(vpMatrix &kerA, double svThreshold)
3216 {
3217 #if (DEBUG_LEVEL1)
3218  std::cout << "begin Kernel" << std::endl ;
3219 #endif
3220  unsigned int i, j ;
3221  unsigned int ncaptor = getRows() ;
3222  unsigned int ddl = getCols() ;
3223  vpMatrix C ;
3224 
3225  if (ncaptor == 0)
3226  std::cout << "Erreur Matrice non initialise" << std::endl ;
3227 
3228 #if (DEBUG_LEVEL2)
3229  {
3230  std::cout << "Interaction matrix L" << std::endl ;
3231  std::cout << *this ;
3232  std::cout << "signaux capteurs : " << ncaptor << std::endl ;
3233  }
3234 #endif
3235 
3236  C.resize(ddl,ncaptor) ;
3237  unsigned int min ;
3238 
3239  if (ncaptor > ddl) min = ddl ; else min = ncaptor ;
3240 
3241  // ! the SVDcmp function inthe matrix lib is destructive
3242 
3243  vpMatrix a1 ;
3244  vpMatrix a2 ;
3245 
3246  vpColVector sv(ddl) ; // singular values
3247  vpMatrix v(ddl,ddl) ;
3248 
3249  if (ncaptor < ddl)
3250  {
3251  a1.resize(ddl,ddl) ;
3252  }
3253  else
3254  {
3255  a1.resize(ncaptor,ddl) ;
3256  }
3257 
3258  a2.resize(ncaptor,ddl) ;
3259 
3260  for (i=0 ; i < ncaptor ; i++)
3261  for (j=0 ; j < ddl ; j++)
3262  {
3263  a1[i][j] = (*this)[i][j] ;
3264  a2[i][j] = (*this)[i][j] ;
3265  }
3266 
3267 
3268  if (ncaptor < ddl)
3269  {
3270  for (i=ncaptor ; i < ddl ; i++)
3271  for (j=0 ; j < ddl ; j++)
3272  {
3273  a1[i][j] = 0 ;
3274  }
3275  a1.svd(sv,v);
3276  }
3277  else
3278  {
3279  a1.svd(sv,v);
3280  }
3281 
3282  // compute the highest singular value and the rank of h
3283 
3284  double maxsv = 0 ;
3285  for (i=0 ; i < ddl ; i++)
3286  if (fabs(sv[i]) > maxsv) maxsv = fabs(sv[i]) ;
3287 
3288 #if (DEBUG_LEVEL2)
3289  {
3290  std::cout << "Singular Value : (" ;
3291  for (i=0 ; i < ddl ; i++) std::cout << sv[i] << " , " ;
3292  std::cout << ")" << std::endl ;
3293  }
3294 #endif
3295 
3296  unsigned int rank = 0 ;
3297  for (i=0 ; i < ddl ; i++)
3298  if (fabs(sv[i]) > maxsv*svThreshold) rank++ ;
3299 
3300 #if (DEBUG_LEVEL2)
3301  {
3302 
3303  for (i = 0 ; i < ddl ; i++)
3304  {
3305  for (j = 0 ; j < ncaptor ; j++)
3306  {
3307  unsigned int k=0 ;
3308  C[i][j] = 0.0;
3309 
3310  // modif le 25 janvier 1999 0.001 <-- maxsv*1.e-ndof
3311  // sinon on peut observer une perte de range de la matrice
3312  // ( d'ou venait ce 0.001 ??? )
3313  for (k=0 ; k < ddl ; k++) if (fabs(sv[k]) > maxsv*svThreshold)
3314  {
3315  C[i][j] += v[i][k]*a1[j][k]/sv[k];
3316  }
3317  }
3318  }
3319 
3320  // cout << v << endl ;
3321  std::cout << C << std::endl ;
3322  }
3323 #endif
3324  /*------------------------------------------------------- */
3325  if (rank != ddl)
3326  {
3327  // Compute the kernel if wanted
3328  if (min < ddl)
3329  {
3330  vpMatrix ch(ddl,ddl) ;
3331  ch = C*a2 ;
3332  ch.svd(sv,v) ;
3333 
3334  }
3335  // if (noyau == 1)
3336  {
3337  double maxsv = 0 ;
3338  for (i=0 ; i < ddl ; i++)
3339  if (fabs(sv[i]) > maxsv) maxsv = fabs(sv[i]) ;
3340  unsigned int rank = 0 ;
3341  for (i=0 ; i < ddl ; i++)
3342  if (fabs(sv[i]) > maxsv*svThreshold) rank++ ;
3343  vpMatrix cons(ddl,ddl) ;
3344 
3345  cons =0 ;
3346  for (j = 0 ; j < ddl ; j++)
3347  {
3348  for (i = 0 ; i < ddl ; i++)
3349  // Change Nicolas Mansard 23/4/04
3350  // was if (fabs(sv[i]) < maxsv*seuilvp)
3351  if (fabs(sv[i]) <= maxsv*svThreshold)
3352  {
3353  cons[i][j] = v[j][i];
3354  }
3355  }
3356 
3357  vpMatrix Ker(ddl-rank,ddl) ;
3358  unsigned int k =0 ;
3359  for (j = 0 ; j < ddl ; j++)
3360  {
3361  // cout << cons.Row(j+1) << " = " << cons.Row(j+1).SumSquare() << endl ;
3362 
3363  //if (cons.row(j+1).sumSquare() !=0)
3364  if (std::fabs(cons.row(j+1).sumSquare()) > std::numeric_limits<double>::epsilon())
3365  {
3366  for (i=0 ; i < cons.getCols() ; i++)
3367  Ker[k][i] = cons[j][i] ;
3368  // Ker.Row(k+1) = cons.Row(j+1) ;
3369  k++;
3370  }
3371  }
3372  kerA = Ker ;
3373  }
3374  }
3375 #if (DEBUG_LEVEL1)
3376  std::cout << "end Kernel" << std::endl ;
3377 #endif
3378  return rank ;
3379 }
3380 
3411 double vpMatrix::det(vpDetMethod method) const
3412 {
3413  double det = 0;
3414 
3415  if ( method == LU_DECOMPOSITION )
3416  {
3417  det = this->detByLU();
3418  }
3419 
3420  return (det);
3421 }
3422 
3423 
3437 bool
3438 vpMatrix::saveMatrix(const char *filename, const vpMatrix &M,
3439  const bool binary, const char *Header)
3440 {
3441  std::fstream file;
3442 
3443  if (!binary)
3444  file.open(filename, std::fstream::out);
3445  else
3446  file.open(filename, std::fstream::out|std::fstream::binary);
3447 
3448  if(!file)
3449  {
3450  file.close();
3451  return false;
3452  }
3453 
3454  else
3455  {
3456  if (!binary)
3457  {
3458  unsigned int i = 0;
3459  file << "# ";
3460  while (Header[i] != '\0')
3461  {
3462  file << Header[i];
3463  if (Header[i] == '\n')
3464  file << "# ";
3465  i++;
3466  }
3467  file << '\0';
3468  file << std::endl;
3469  file << M.getRows() << "\t" << M.getCols() << std::endl;
3470  file << M << std::endl;
3471  }
3472  else
3473  {
3474  int headerSize = 0;
3475  while (Header[headerSize] != '\0') headerSize++;
3476  file.write(Header,headerSize+1);
3477  unsigned int matrixSize;
3478  matrixSize = M.getRows();
3479  file.write((char*)&matrixSize,sizeof(int));
3480  matrixSize = M.getCols();
3481  file.write((char*)&matrixSize,sizeof(int));
3482  double value;
3483  for(unsigned int i = 0; i < M.getRows(); i++)
3484  {
3485  for(unsigned int j = 0; j < M.getCols(); j++)
3486  {
3487  value = M[i][j];
3488  file.write((char*)&value,sizeof(double));
3489  }
3490  }
3491  }
3492  }
3493 
3494  file.close();
3495  return true;
3496 }
3497 
3498 
3510 bool
3511 vpMatrix::loadMatrix(const char *filename, vpMatrix &M, const bool binary,
3512  char *Header)
3513 {
3514  std::fstream file;
3515 
3516  if (!binary)
3517  file.open(filename, std::fstream::in);
3518  else
3519  file.open(filename, std::fstream::in|std::fstream::binary);
3520 
3521  if(!file)
3522  {
3523  file.close();
3524  return false;
3525  }
3526 
3527  else
3528  {
3529  if (!binary)
3530  {
3531  char c='0';
3532  std::string h;
3533  while ((c != '\0') && (c != '\n'))
3534  {
3535  file.read(&c,1);
3536  h+=c;
3537  }
3538  if (Header != NULL)
3539  strncpy(Header, h.c_str(), h.size() + 1);
3540 
3541  unsigned int rows, cols;
3542  file >> rows;
3543  file >> cols;
3544  M.resize(rows,cols);
3545 
3546  double value;
3547  for(unsigned int i = 0; i < rows; i++)
3548  {
3549  for(unsigned int j = 0; j < cols; j++)
3550  {
3551  file >> value;
3552  M[i][j] = value;
3553  }
3554  }
3555  }
3556  else
3557  {
3558  char c='0';
3559  std::string h;
3560  while ((c != '\0') && (c != '\n'))
3561  {
3562  file.read(&c,1);
3563  h+=c;
3564  }
3565  if (Header != NULL)
3566  strncpy(Header, h.c_str(), h.size() + 1);
3567 
3568  unsigned int rows, cols;
3569  file.read((char*)&rows,sizeof(unsigned int));
3570  file.read((char*)&cols,sizeof(unsigned int));
3571  M.resize(rows,cols);
3572 
3573  double value;
3574  for(unsigned int i = 0; i < rows; i++)
3575  {
3576  for(unsigned int j = 0; j < cols; j++)
3577  {
3578  file.read((char*)&value,sizeof(double));
3579  M[i][j] = value;
3580  }
3581  }
3582  }
3583  }
3584 
3585  file.close();
3586  return true;
3587 }
3588 
3589 
3597 vpMatrix
3599 {
3600  if(colNum != rowNum)
3601  {
3602  vpTRACE("The matrix must be square");
3604  "The matrix must be square" ));
3605  }
3606  else
3607  {
3608  vpMatrix _expE(rowNum, colNum);
3609  vpMatrix _expD(rowNum, colNum);
3610  vpMatrix _expX(rowNum, colNum);
3611  vpMatrix _expcX(rowNum, colNum);
3612  vpMatrix _eye(rowNum, colNum);
3613 
3614  _eye.setIdentity();
3615  vpMatrix exp(*this);
3616 
3617  // double f;
3618  int e;
3619  double c = 0.5;
3620  int q = 6;
3621  int p = 1;
3622 
3623  double nA = 0;
3624  for (unsigned int i = 0; i < rowNum;i++)
3625  {
3626  double sum = 0;
3627  for (unsigned int j=0; j < colNum; j++)
3628  {
3629  sum += fabs((*this)[i][j]);
3630  }
3631  if (sum>nA||i==0)
3632  {
3633  nA=sum;
3634  }
3635  }
3636 
3637  /* f = */ frexp(nA, &e);
3638  //double s = (0 > e+1)?0:e+1;
3639  double s = e+1;
3640 
3641  double sca = 1.0 / pow(2.0,s);
3642  exp=sca*exp;
3643  _expX=*this;
3644  _expE=c*exp+_eye;
3645  _expD=-c*exp+_eye;
3646  for (int k=2;k<=q;k++)
3647  {
3648  c = c * ((double)(q-k+1)) / ((double)(k*(2*q-k+1)));
3649  _expcX=exp*_expX;
3650  _expX=_expcX;
3651  _expcX=c*_expX;
3652  _expE=_expE+_expcX;
3653  if (p) _expD=_expD+_expcX;
3654  else _expD=_expD- _expcX;
3655  p = !p;
3656  }
3657  _expX=_expD.inverseByLU();
3658  exp=_expX*_expE;
3659  for (int k=1;k<=s;k++)
3660  {
3661  _expE=exp*exp;
3662  exp=_expE;
3663  }
3664  return exp;
3665  }
3666 }
3667 
3668 double
3670 {
3671  double *dataptr = data;
3672  double min = *dataptr;
3673  dataptr++;
3674  for (unsigned int i = 0; i < dsize-1; i++)
3675  {
3676  if (*dataptr < min) min = *dataptr;
3677  dataptr++;
3678  }
3679  return min;
3680 }
3681 
3682 double
3684 {
3685  double *dataptr = data;
3686  double max = *dataptr;
3687  dataptr++;
3688  for (unsigned int i = 0; i < dsize-1; i++)
3689  {
3690  if (*dataptr > max) max = *dataptr;
3691  dataptr++;
3692  }
3693  return max;
3694 }
3695 
3696 
3697 /**************************************************************************************************************/
3698 /**************************************************************************************************************/
3699 
3700 
3701 //Specific functions
3702 
3703 /*
3704 input:: matrix M(nCols,nRows), nCols > 3, nRows > 3 , nCols == nRows.
3705 
3706 output:: the complement matrix of the element (rowNo,colNo).
3707 This is the matrix obtained from M after elimenating the row rowNo and column colNo
3708 
3709 example:
3710 1 2 3
3711 M = 4 5 6
3712 7 8 9
3713 1 3
3714 subblock(M, 1, 1) give the matrix 7 9
3715 */
3716 vpMatrix subblock(const vpMatrix &M, unsigned int col, unsigned int row)
3717 {
3718  vpMatrix M_comp(M.getRows()-1,M.getCols()-1);
3719 
3720  for ( unsigned int i = 0 ; i < col ; i++)
3721  {
3722  for ( unsigned int j = 0 ; j < row ; j++)
3723  M_comp[i][j]=M[i][j];
3724  for ( unsigned int j = row+1 ; j < M.getRows() ; j++)
3725  M_comp[i][j-1]=M[i][j];
3726  }
3727  for ( unsigned int i = col+1 ; i < M.getCols(); i++)
3728  {
3729  for ( unsigned int j = 0 ; j < row ; j++)
3730  M_comp[i-1][j]=M[i][j];
3731  for ( unsigned int j = row+1 ; j < M.getRows() ; j++)
3732  M_comp[i-1][j-1]=M[i][j];
3733  }
3734  return M_comp;
3735 }
3736 
3737 #undef DEBUG_LEVEL1
3738 #undef DEBUG_LEVEL2
3739 
3740 /*
3741 * Local variables:
3742 * c-basic-offset: 2
3743 * End:
3744 */
vpMatrix operator*(const double &x, const vpMatrix &B)
Definition: vpMatrix.cpp:884
friend VISP_EXPORT std::ostream & operator<<(std::ostream &s, const vpMatrix &m)
std::cout a matrix
Definition: vpMatrix.cpp:2574
#define vpDEBUG_TRACE
Definition: vpDebug.h:454
Definition of the vpMatrix class.
Definition: vpMatrix.h:96
unsigned int kernel(vpMatrix &KerA, double svThreshold=1e-6)
Definition: vpMatrix.cpp:3215
static vpMatrix juxtaposeMatrices(const vpMatrix &A, const vpMatrix &B)
Definition: vpMatrix.cpp:2420
void resize(const unsigned int nrows, const unsigned int ncols, const bool nullify=true)
Definition: vpMatrix.cpp:174
vpRowVector row(const unsigned int i)
Row extraction.
Definition: vpMatrix.cpp:2223
double infinityNorm() const
Definition: vpMatrix.cpp:2838
void init()
Initialization of the object matrix.
Definition: vpMatrix.cpp:93
#define vpERROR_TRACE
Definition: vpDebug.h:379
#define vpTRACE
Definition: vpDebug.h:401
Definition of the row vector class.
Definition: vpRowVector.h:73
static bool saveMatrix(const char *filename, const vpMatrix &M, const bool binary=false, const char *Header="")
Definition: vpMatrix.cpp:3438
static void add2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
Definition: vpMatrix.cpp:491
#define vpCERROR
Definition: vpDebug.h:354
double getMinValue() const
Definition: vpMatrix.cpp:3669
vpMatrix & operator*=(const double x)
Multiply all the element of the matrix by x : Aij = Aij * x.
Definition: vpMatrix.cpp:1056
vpMatrix & operator/=(double x)
Divide all the element of the matrix by x : Aij = Aij / x.
Definition: vpMatrix.cpp:1071
error that can be emited by ViSP classes.
Definition: vpException.h:75
static void sub2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
Definition: vpMatrix.cpp:560
vpMatrix & operator+=(const vpMatrix &B)
Operation A = A + B.
Definition: vpMatrix.cpp:622
double sumSquare() const
return sum of the Aij^2 (for all i, for all j)
Definition: vpMatrix.cpp:758
vpMatrix()
Basic constructor.
Definition: vpMatrix.cpp:111
int print(std::ostream &s, unsigned int length, char const *intro=0)
Definition: vpMatrix.cpp:2613
vpColVector column(const unsigned int j)
Column extraction.
Definition: vpMatrix.cpp:2238
vpMatrix & operator-=(const vpMatrix &B)
Operation A = A - B.
Definition: vpMatrix.cpp:662
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
double * data
address of the first element of the data array
Definition: vpMatrix.h:116
std::ostream & cppPrint(std::ostream &os, const char *matrixName=NULL, bool octet=false)
Print to be used as part of a C++ code later.
Definition: vpMatrix.cpp:2766
unsigned int trsize
Total row space.
Definition: vpMatrix.h:124
vpColVector eigenValues()
Definition: vpMatrix.cpp:2994
void insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
Definition: vpMatrix.cpp:2937
void solveBySVD(const vpColVector &B, vpColVector &x) const
Definition: vpMatrix.cpp:1571
void setIdentity(const double &val=1.0)
Definition: vpMatrix.cpp:1108
double ** rowPtrs
address of the first element of each rows
Definition: vpMatrix.h:119
void svd(vpColVector &w, vpMatrix &v)
Definition: vpMatrix.cpp:1700
vpMatrix & operator=(const vpMatrix &B)
Copy operator. Allow operation such as A = B.
Definition: vpMatrix.cpp:314
vpMatrix AtA() const
Definition: vpMatrix.cpp:1357
static void multMatrixVector(const vpMatrix &A, const vpColVector &b, vpColVector &c)
Definition: vpMatrix.cpp:809
vpMatrix AAt() const
Definition: vpMatrix.cpp:1246
static bool loadMatrix(const char *filename, vpMatrix &M, const bool binary=false, char *Header=NULL)
Definition: vpMatrix.cpp:3511
static void add2WeightedMatrices(const vpMatrix &A, const double &wA, const vpMatrix &B, const double &wB, vpMatrix &C)
Definition: vpMatrix.cpp:452
static void mult2Matrices(const vpMatrix &A, const vpMatrix &B, vpMatrix &C)
Definition: vpMatrix.cpp:391
vpMatrix operator+(const vpMatrix &B) const
Definition: vpMatrix.cpp:542
vpMatrix transpose() const
Definition: vpMatrix.cpp:1204
void kill()
Destruction of the matrix (Memory de-allocation)
Definition: vpMatrix.cpp:284
#define vpCDEBUG(niv)
Definition: vpDebug.h:478
double det(vpDetMethod method=LU_DECOMPOSITION) const
Definition: vpMatrix.cpp:3411
VISP_EXPORT std::ostream & operator<<(std::ostream &os, const vpImagePoint &ip)
Definition: vpImagePoint.h:529
static vpMatrix stackMatrices(const vpMatrix &A, const vpMatrix &B)
Stack two Matrices C = [ A B ]^T.
Definition: vpMatrix.cpp:2261
void diag(const vpColVector &A)
Definition: vpMatrix.cpp:2521
unsigned int rowNum
number of rows
Definition: vpMatrix.h:110
void eye(unsigned int n)
Definition: vpMatrix.cpp:1130
vpMatrix t() const
Definition: vpMatrix.cpp:1174
double getMaxValue() const
Definition: vpMatrix.cpp:3683
void resize(unsigned int i)
Set the size of the Row vector.
Definition: vpRowVector.h:91
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
double euclideanNorm() const
Definition: vpMatrix.cpp:2814
vpMatrix inverseByLU() const
unsigned int getCols() const
Return the number of columns of the matrix.
Definition: vpMatrix.h:159
vpRowVector stackRows()
Definition: vpMatrix.cpp:1428
vpMatrix operator/(const double x) const
Cij = Aij / x (A is unchanged)
Definition: vpMatrix.cpp:963
static void createDiagonalMatrix(const vpColVector &A, vpMatrix &DA)
Definition: vpMatrix.cpp:2549
vpMatrix operator*(const vpMatrix &B) const
Definition: vpMatrix.cpp:434
error that can be emited by the vpMatrix class and its derivates
vpColVector stackColumns()
Definition: vpMatrix.cpp:1395
vpMatrix operator-() const
Definition: vpMatrix.cpp:749
std::ostream & maplePrint(std::ostream &os)
Print using MAPLE matrix input format.
Definition: vpMatrix.cpp:2733
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1810
unsigned int dsize
Current size (rowNum * colNum)
Definition: vpMatrix.h:122
void kron(const vpMatrix &m1, vpMatrix &out)
Definition: vpMatrix.cpp:1475
unsigned int colNum
number of columns
Definition: vpMatrix.h:112
unsigned int getRows() const
Return the number of rows of the matrix.
Definition: vpMatrix.h:157
static void negateMatrix(const vpMatrix &A, vpMatrix &C)
Definition: vpMatrix.cpp:707
vpMatrix expm()
Definition: vpMatrix.cpp:3598
Class that consider the case of a translation vector.
virtual ~vpMatrix()
Destructor (Memory de-allocation)
Definition: vpMatrix.cpp:301
std::ostream & matlabPrint(std::ostream &os)
Print using matlab syntax, to be put in matlab later.
Definition: vpMatrix.cpp:2704
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:94