ViSP  2.6.2
vpMatrix.cpp
1 /****************************************************************************
2 *
3 * $Id: vpMatrix.cpp 3735 2012-05-17 15:58:40Z fspindle $
4 *
5 * This file is part of the ViSP software.
6 * Copyright (C) 2005 - 2012 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 >= 0x020100) // Require opencv >= 2.1.0
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 
2736 std::ostream & vpMatrix::
2737 cppPrint(std::ostream & os, const char * matrixName, bool octet)
2738 {
2739 
2740  unsigned int i,j;
2741  const char defaultName [] = "A";
2742  if (NULL == matrixName)
2743  {
2744  matrixName = defaultName;
2745  }
2746  os << "vpMatrix " << defaultName
2747  << " (" << this ->getRows ()
2748  << ", " << this ->getCols () << "); " <<std::endl;
2749 
2750  for (i=0; i < this->getRows(); ++ i)
2751  {
2752  for (j=0; j < this ->getCols(); ++ j)
2753  {
2754  if (! octet)
2755  {
2756  os << defaultName << "[" << i << "][" << j
2757  << "] = " << (*this)[i][j] << "; " << std::endl;
2758  }
2759  else
2760  {
2761  for (unsigned int k = 0; k < sizeof(double); ++ k)
2762  {
2763  os << "((unsigned char*)&(" << defaultName
2764  << "[" << i << "][" << j << "]) )[" << k
2765  <<"] = 0x" <<std::hex<<
2766  (unsigned int)((unsigned char*)& ((*this)[i][j])) [k]
2767  << "; " << std::endl;
2768  }
2769  }
2770  }
2771  os << std::endl;
2772  }
2773  return os;
2774 };
2775 
2776 
2784 double
2786 {
2787  double norm=0.0;
2788  double x ;
2789  for (unsigned int i=0;i<dsize;i++) {
2790  x = *(data +i); norm += x*x;
2791  }
2792 
2793  return sqrt(norm);
2794 }
2795 
2796 
2797 
2808 double
2810 {
2811  double norm=0.0;
2812  double x ;
2813  for (unsigned int i=0;i<rowNum;i++){
2814  x = 0;
2815  for (unsigned int j=0; j<colNum;j++){
2816  x += fabs (*(*(rowPtrs + i)+j)) ;
2817  }
2818  if (x > norm) {
2819  norm = x;
2820  }
2821  }
2822  return norm;
2823 }
2824 
2833 double vpMatrix::detByLU() const
2834 {
2835  double det(0);
2836 
2837  // Test wether the matrix is squred
2838  if (rowNum == colNum)
2839  {
2840  // create a temporary matrix that will be modified by LUDcmp
2841  vpMatrix tmp(*this);
2842 
2843  // using th LUdcmp based on NR codes
2844  // it modified the tmp matrix in a special structure of type :
2845  // b11 b12 b13 b14
2846  // a21 b22 b23 b24
2847  // a21 a32 b33 b34
2848  // a31 a42 a43 b44
2849 
2850  unsigned int * perm = new unsigned int[rowNum]; // stores the permutations
2851  int d; // +- 1 fi the number of column interchange is even or odd
2852  tmp.LUDcmp(perm, d);
2853  delete[]perm;
2854 
2855  // compute the determinant that is the product of the eigen values
2856  det = (double) d;
2857  for(unsigned int i=0;i<rowNum;i++)
2858  {
2859  det*=tmp[i][i];
2860  }
2861  }
2862 
2863  else {
2864  vpERROR_TRACE("Determinant Computation : ERR Matrix not squared") ;
2866  "\n\t\tDeterminant Computation : ERR Matrix not squared")) ;
2867 
2868 
2869  }
2870  return det ;
2871 }
2872 
2873 
2874 
2890 {
2891  if(rowNum == 0)
2892  *this = A;
2893  else
2894  *this = vpMatrix::stackMatrices(*this, A);
2895 }
2896 
2897 
2908 void vpMatrix::insert(const vpMatrix&A, const unsigned int r,
2909  const unsigned int c)
2910 {
2911  if( (r + A.getRows() ) <= rowNum && (c + A.getCols() ) <= colNum ){
2912  // recopy matrix A in the current one, does not call static function to avoid initialisation and recopy of matrix
2913  for(unsigned int i=r; i<(r+A.getRows()); i++){
2914  for(unsigned int j=c; j<(c+A.getCols()); j++){
2915  (*this)[i][j] = A[i-r][j-c];
2916  }
2917  }
2918  }
2919  else{
2921  "\n\t\tIncorrect size of the matrix to insert data.");
2922  }
2923 }
2924 
2925 
2966 {
2967  if (rowNum != colNum) {
2968  vpERROR_TRACE("Eigen values computation: ERR Matrix not square") ;
2970  "\n\t\tEigen values computation: ERR Matrix not square")) ;
2971  }
2972 
2973 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
2974  {
2975  // Check if the matrix is symetric: At - A = 0
2976  vpMatrix At_A = (*this).t() - (*this);
2977  for (unsigned int i=0; i < rowNum; i++) {
2978  for (unsigned int j=0; j < rowNum; j++) {
2979  //if (At_A[i][j] != 0) {
2980  if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
2981  vpERROR_TRACE("Eigen values computation: ERR Matrix not symmetric") ;
2983  "\n\t\tEigen values computation: "
2984  "ERR Matrix not symmetric")) ;
2985  }
2986  }
2987  }
2988 
2989 
2990  vpColVector evalue(rowNum); // Eigen values
2991 
2992  gsl_vector *eval = gsl_vector_alloc (rowNum);
2993  gsl_matrix *evec = gsl_matrix_alloc (rowNum, colNum);
2994 
2995  gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc (rowNum);
2996  gsl_matrix *m = gsl_matrix_alloc(rowNum, colNum);
2997 
2998  unsigned int Atda = m->tda ;
2999  for (unsigned int i=0 ; i < rowNum ; i++){
3000  unsigned int k = i*Atda ;
3001  for (unsigned int j=0 ; j < colNum ; j++)
3002  m->data[k+j] = (*this)[i][j] ;
3003  }
3004  gsl_eigen_symmv (m, eval, evec, w);
3005 
3006  gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_ABS_ASC);
3007 
3008  for (unsigned int i=0; i < rowNum; i++) {
3009  evalue[i] = gsl_vector_get (eval, i);
3010  }
3011 
3012  gsl_eigen_symmv_free (w);
3013  gsl_vector_free (eval);
3014  gsl_matrix_free (m);
3015  gsl_matrix_free (evec);
3016 
3017  return evalue;
3018  }
3019 #else
3020  {
3021  vpERROR_TRACE("Not implemented since the GSL library is not detected.") ;
3023  "\n\t\tEigen values Computation: Not implemented "
3024  "since the GSL library is not detected")) ;
3025  }
3026 #endif
3027 }
3028 
3083 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
3085 #else
3086 void vpMatrix::eigenValues(vpColVector & /* evalue */, vpMatrix & /* evector */)
3087 #endif
3088 {
3089  if (rowNum != colNum) {
3090  vpERROR_TRACE("Eigen values computation: ERR Matrix not square") ;
3092  "\n\t\tEigen values computation: ERR Matrix not square")) ;
3093  }
3094 
3095 #ifdef VISP_HAVE_GSL /* be careful of the copy below */
3096  {
3097  // Check if the matrix is symetric: At - A = 0
3098  vpMatrix At_A = (*this).t() - (*this);
3099  for (unsigned int i=0; i < rowNum; i++) {
3100  for (unsigned int j=0; j < rowNum; j++) {
3101  //if (At_A[i][j] != 0) {
3102  if (std::fabs(At_A[i][j]) > std::numeric_limits<double>::epsilon()) {
3103  vpERROR_TRACE("Eigen values computation: ERR Matrix not symmetric") ;
3105  "\n\t\tEigen values computation: "
3106  "ERR Matrix not symmetric")) ;
3107  }
3108  }
3109  }
3110 
3111  // Resize the output matrices
3112  evalue.resize(rowNum);
3113  evector.resize(rowNum, colNum);
3114 
3115  gsl_vector *eval = gsl_vector_alloc (rowNum);
3116  gsl_matrix *evec = gsl_matrix_alloc (rowNum, colNum);
3117 
3118  gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc (rowNum);
3119  gsl_matrix *m = gsl_matrix_alloc(rowNum, colNum);
3120 
3121  unsigned int Atda = m->tda ;
3122  for (unsigned int i=0 ; i < rowNum ; i++){
3123  unsigned int k = i*Atda ;
3124  for (unsigned int j=0 ; j < colNum ; j++)
3125  m->data[k+j] = (*this)[i][j] ;
3126  }
3127  gsl_eigen_symmv (m, eval, evec, w);
3128 
3129  gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_ABS_ASC);
3130 
3131  for (unsigned int i=0; i < rowNum; i++) {
3132  evalue[i] = gsl_vector_get (eval, i);
3133  }
3134  Atda = evec->tda ;
3135  for (unsigned int i=0; i < rowNum; i++) {
3136  unsigned int k = i*Atda ;
3137  for (unsigned int j=0; j < rowNum; j++) {
3138  evector[i][j] = evec->data[k+j];
3139  }
3140  }
3141 
3142 
3143  // {
3144  // int i;
3145 
3146  // for (i = 0; i < rowNum; i++)
3147  // {
3148  // double eval_i
3149  // = gsl_vector_get (eval, i);
3150  // gsl_vector_view evec_i
3151  // = gsl_matrix_column (evec, i);
3152 
3153  // printf ("eigenvalue = %g\n", eval_i);
3154  // printf ("eigenvector = \n");
3155  // gsl_vector_fprintf (stdout,
3156  // &evec_i.vector, "%g");
3157  // }
3158  // }
3159 
3160  gsl_eigen_symmv_free (w);
3161  gsl_vector_free (eval);
3162  gsl_matrix_free (m);
3163  gsl_matrix_free (evec);
3164  }
3165 #else
3166  {
3167  vpERROR_TRACE("Not implemented since the GSL library is not detected.") ;
3169  "\n\t\tEigen values Computation: Not implemented "
3170  "since the GSL library is not detected")) ;
3171  }
3172 #endif
3173 }
3174 
3175 
3185 unsigned int
3186 vpMatrix::kernel(vpMatrix &kerA, double svThreshold)
3187 {
3188 #if (DEBUG_LEVEL1)
3189  std::cout << "begin Kernel" << std::endl ;
3190 #endif
3191  unsigned int i, j ;
3192  unsigned int ncaptor = getRows() ;
3193  unsigned int ddl = getCols() ;
3194  vpMatrix C ;
3195 
3196  if (ncaptor == 0)
3197  std::cout << "Erreur Matrice non initialise" << std::endl ;
3198 
3199 #if (DEBUG_LEVEL2)
3200  {
3201  std::cout << "Interaction matrix L" << std::endl ;
3202  std::cout << *this ;
3203  std::cout << "signaux capteurs : " << ncaptor << std::endl ;
3204  }
3205 #endif
3206 
3207  C.resize(ddl,ncaptor) ;
3208  unsigned int min ;
3209 
3210  if (ncaptor > ddl) min = ddl ; else min = ncaptor ;
3211 
3212  // ! the SVDcmp function inthe matrix lib is destructive
3213 
3214  vpMatrix a1 ;
3215  vpMatrix a2 ;
3216 
3217  vpColVector sv(ddl) ; // singular values
3218  vpMatrix v(ddl,ddl) ;
3219 
3220  if (ncaptor < ddl)
3221  {
3222  a1.resize(ddl,ddl) ;
3223  }
3224  else
3225  {
3226  a1.resize(ncaptor,ddl) ;
3227  }
3228 
3229  a2.resize(ncaptor,ddl) ;
3230 
3231  for (i=0 ; i < ncaptor ; i++)
3232  for (j=0 ; j < ddl ; j++)
3233  {
3234  a1[i][j] = (*this)[i][j] ;
3235  a2[i][j] = (*this)[i][j] ;
3236  }
3237 
3238 
3239  if (ncaptor < ddl)
3240  {
3241  for (i=ncaptor ; i < ddl ; i++)
3242  for (j=0 ; j < ddl ; j++)
3243  {
3244  a1[i][j] = 0 ;
3245  }
3246  a1.svd(sv,v);
3247  }
3248  else
3249  {
3250  a1.svd(sv,v);
3251  }
3252 
3253  // compute the highest singular value and the rank of h
3254 
3255  double maxsv = 0 ;
3256  for (i=0 ; i < ddl ; i++)
3257  if (fabs(sv[i]) > maxsv) maxsv = fabs(sv[i]) ;
3258 
3259 #if (DEBUG_LEVEL2)
3260  {
3261  std::cout << "Singular Value : (" ;
3262  for (i=0 ; i < ddl ; i++) std::cout << sv[i] << " , " ;
3263  std::cout << ")" << std::endl ;
3264  }
3265 #endif
3266 
3267  unsigned int rank = 0 ;
3268  for (i=0 ; i < ddl ; i++)
3269  if (fabs(sv[i]) > maxsv*svThreshold) rank++ ;
3270 
3271 #if (DEBUG_LEVEL2)
3272  {
3273 
3274  for (i = 0 ; i < ddl ; i++)
3275  {
3276  for (j = 0 ; j < ncaptor ; j++)
3277  {
3278  unsigned int k=0 ;
3279  C[i][j] = 0.0;
3280 
3281  // modif le 25 janvier 1999 0.001 <-- maxsv*1.e-ndof
3282  // sinon on peut observer une perte de range de la matrice
3283  // ( d'ou venait ce 0.001 ??? )
3284  for (k=0 ; k < ddl ; k++) if (fabs(sv[k]) > maxsv*svThreshold)
3285  {
3286  C[i][j] += v[i][k]*a1[j][k]/sv[k];
3287  }
3288  }
3289  }
3290 
3291  // cout << v << endl ;
3292  std::cout << C << std::endl ;
3293  }
3294 #endif
3295  /*------------------------------------------------------- */
3296  if (rank != ddl)
3297  {
3298  // Compute the kernel if wanted
3299  if (min < ddl)
3300  {
3301  vpMatrix ch(ddl,ddl) ;
3302  ch = C*a2 ;
3303  ch.svd(sv,v) ;
3304 
3305  }
3306  // if (noyau == 1)
3307  {
3308  double maxsv = 0 ;
3309  for (i=0 ; i < ddl ; i++)
3310  if (fabs(sv[i]) > maxsv) maxsv = fabs(sv[i]) ;
3311  unsigned int rank = 0 ;
3312  for (i=0 ; i < ddl ; i++)
3313  if (fabs(sv[i]) > maxsv*svThreshold) rank++ ;
3314  vpMatrix cons(ddl,ddl) ;
3315 
3316  cons =0 ;
3317  for (j = 0 ; j < ddl ; j++)
3318  {
3319  for (i = 0 ; i < ddl ; i++)
3320  // Change Nicolas Mansard 23/4/04
3321  // was if (fabs(sv[i]) < maxsv*seuilvp)
3322  if (fabs(sv[i]) <= maxsv*svThreshold)
3323  {
3324  cons[i][j] = v[j][i];
3325  }
3326  }
3327 
3328  vpMatrix Ker(ddl-rank,ddl) ;
3329  unsigned int k =0 ;
3330  for (j = 0 ; j < ddl ; j++)
3331  {
3332  // cout << cons.Row(j+1) << " = " << cons.Row(j+1).SumSquare() << endl ;
3333 
3334  //if (cons.row(j+1).sumSquare() !=0)
3335  if (std::fabs(cons.row(j+1).sumSquare()) > std::numeric_limits<double>::epsilon())
3336  {
3337  for (i=0 ; i < cons.getCols() ; i++)
3338  Ker[k][i] = cons[j][i] ;
3339  // Ker.Row(k+1) = cons.Row(j+1) ;
3340  k++;
3341  }
3342  }
3343  kerA = Ker ;
3344  }
3345  }
3346 #if (DEBUG_LEVEL1)
3347  std::cout << "end Kernel" << std::endl ;
3348 #endif
3349  return rank ;
3350 }
3351 
3382 double vpMatrix::det(vpDetMethod method) const
3383 {
3384  double det = 0;
3385 
3386  if ( method == LU_DECOMPOSITION )
3387  {
3388  det = this->detByLU();
3389  }
3390 
3391  return (det);
3392 }
3393 
3394 
3408 bool
3409 vpMatrix::saveMatrix(const char *filename, const vpMatrix &M,
3410  const bool binary, const char *Header)
3411 {
3412  std::fstream file;
3413 
3414  if (!binary)
3415  file.open(filename, std::fstream::out);
3416  else
3417  file.open(filename, std::fstream::out|std::fstream::binary);
3418 
3419  if(!file)
3420  {
3421  file.close();
3422  return false;
3423  }
3424 
3425  else
3426  {
3427  if (!binary)
3428  {
3429  unsigned int i = 0;
3430  file << "# ";
3431  while (Header[i] != '\0')
3432  {
3433  file << Header[i];
3434  if (Header[i] == '\n')
3435  file << "# ";
3436  i++;
3437  }
3438  file << '\0';
3439  file << std::endl;
3440  file << M.getRows() << "\t" << M.getCols() << std::endl;
3441  file << M << std::endl;
3442  }
3443  else
3444  {
3445  int headerSize = 0;
3446  while (Header[headerSize] != '\0') headerSize++;
3447  file.write(Header,headerSize+1);
3448  unsigned int matrixSize;
3449  matrixSize = M.getRows();
3450  file.write((char*)&matrixSize,sizeof(int));
3451  matrixSize = M.getCols();
3452  file.write((char*)&matrixSize,sizeof(int));
3453  double value;
3454  for(unsigned int i = 0; i < M.getRows(); i++)
3455  {
3456  for(unsigned int j = 0; j < M.getCols(); j++)
3457  {
3458  value = M[i][j];
3459  file.write((char*)&value,sizeof(double));
3460  }
3461  }
3462  }
3463  }
3464 
3465  file.close();
3466  return true;
3467 }
3468 
3469 
3481 bool
3482 vpMatrix::loadMatrix(const char *filename, vpMatrix &M, const bool binary,
3483  char *Header)
3484 {
3485  std::fstream file;
3486 
3487  if (!binary)
3488  file.open(filename, std::fstream::in);
3489  else
3490  file.open(filename, std::fstream::in|std::fstream::binary);
3491 
3492  if(!file)
3493  {
3494  file.close();
3495  return false;
3496  }
3497 
3498  else
3499  {
3500  if (!binary)
3501  {
3502  char c='0';
3503  std::string h;
3504  while ((c != '\0') && (c != '\n'))
3505  {
3506  file.read(&c,1);
3507  h+=c;
3508  }
3509  if (Header != NULL)
3510  strncpy(Header, h.c_str(), h.size() + 1);
3511 
3512  unsigned int rows, cols;
3513  file >> rows;
3514  file >> cols;
3515  M.resize(rows,cols);
3516 
3517  double value;
3518  for(unsigned int i = 0; i < rows; i++)
3519  {
3520  for(unsigned int j = 0; j < cols; j++)
3521  {
3522  file >> value;
3523  M[i][j] = value;
3524  }
3525  }
3526  }
3527  else
3528  {
3529  char c='0';
3530  std::string h;
3531  while ((c != '\0') && (c != '\n'))
3532  {
3533  file.read(&c,1);
3534  h+=c;
3535  }
3536  if (Header != NULL)
3537  strncpy(Header, h.c_str(), h.size() + 1);
3538 
3539  unsigned int rows, cols;
3540  file.read((char*)&rows,sizeof(unsigned int));
3541  file.read((char*)&cols,sizeof(unsigned int));
3542  M.resize(rows,cols);
3543 
3544  double value;
3545  for(unsigned int i = 0; i < rows; i++)
3546  {
3547  for(unsigned int j = 0; j < cols; j++)
3548  {
3549  file.read((char*)&value,sizeof(double));
3550  M[i][j] = value;
3551  }
3552  }
3553  }
3554  }
3555 
3556  file.close();
3557  return true;
3558 }
3559 
3560 
3568 vpMatrix
3570 {
3571  if(colNum != rowNum)
3572  {
3573  vpTRACE("The matrix must be square");
3575  "The matrix must be square" ));
3576  }
3577  else
3578  {
3579  vpMatrix _expE(rowNum, colNum);
3580  vpMatrix _expD(rowNum, colNum);
3581  vpMatrix _expX(rowNum, colNum);
3582  vpMatrix _expcX(rowNum, colNum);
3583  vpMatrix _eye(rowNum, colNum);
3584 
3585  _eye.setIdentity();
3586  vpMatrix exp(*this);
3587 
3588  // double f;
3589  int e;
3590  double c = 0.5;
3591  int q = 6;
3592  int p = 1;
3593 
3594  double nA = 0;
3595  for (unsigned int i = 0; i < rowNum;i++)
3596  {
3597  double sum = 0;
3598  for (unsigned int j=0; j < colNum; j++)
3599  {
3600  sum += fabs((*this)[i][j]);
3601  }
3602  if (sum>nA||i==0)
3603  {
3604  nA=sum;
3605  }
3606  }
3607 
3608  /* f = */ frexp(nA, &e);
3609  //double s = (0 > e+1)?0:e+1;
3610  double s = e+1;
3611 
3612  double sca = 1.0 / pow(2.0,s);
3613  exp=sca*exp;
3614  _expX=*this;
3615  _expE=c*exp+_eye;
3616  _expD=-c*exp+_eye;
3617  for (int k=2;k<=q;k++)
3618  {
3619  c = c * ((double)(q-k+1)) / ((double)(k*(2*q-k+1)));
3620  _expcX=exp*_expX;
3621  _expX=_expcX;
3622  _expcX=c*_expX;
3623  _expE=_expE+_expcX;
3624  if (p) _expD=_expD+_expcX;
3625  else _expD=_expD- _expcX;
3626  p = !p;
3627  }
3628  _expX=_expD.inverseByLU();
3629  exp=_expX*_expE;
3630  for (int k=1;k<=s;k++)
3631  {
3632  _expE=exp*exp;
3633  exp=_expE;
3634  }
3635  return exp;
3636  }
3637 }
3638 
3639 double
3641 {
3642  double *dataptr = data;
3643  double min = *dataptr;
3644  dataptr++;
3645  for (unsigned int i = 0; i < dsize-1; i++)
3646  {
3647  if (*dataptr < min) min = *dataptr;
3648  dataptr++;
3649  }
3650  return min;
3651 }
3652 
3653 double
3655 {
3656  double *dataptr = data;
3657  double max = *dataptr;
3658  dataptr++;
3659  for (unsigned int i = 0; i < dsize-1; i++)
3660  {
3661  if (*dataptr > max) max = *dataptr;
3662  dataptr++;
3663  }
3664  return max;
3665 }
3666 
3667 
3668 /**************************************************************************************************************/
3669 /**************************************************************************************************************/
3670 
3671 
3672 //Specific functions
3673 
3674 /*
3675 input:: matrix M(nCols,nRows), nCols > 3, nRows > 3 , nCols == nRows.
3676 
3677 output:: the complement matrix of the element (rowNo,colNo).
3678 This is the matrix obtained from M after elimenating the row rowNo and column colNo
3679 
3680 example:
3681 1 2 3
3682 M = 4 5 6
3683 7 8 9
3684 1 3
3685 subblock(M, 1, 1) give the matrix 7 9
3686 */
3687 vpMatrix subblock(const vpMatrix &M, unsigned int col, unsigned int row)
3688 {
3689  vpMatrix M_comp(M.getRows()-1,M.getCols()-1);
3690 
3691  for ( unsigned int i = 0 ; i < col ; i++)
3692  {
3693  for ( unsigned int j = 0 ; j < row ; j++)
3694  M_comp[i][j]=M[i][j];
3695  for ( unsigned int j = row+1 ; j < M.getRows() ; j++)
3696  M_comp[i][j-1]=M[i][j];
3697  }
3698  for ( unsigned int i = col+1 ; i < M.getCols(); i++)
3699  {
3700  for ( unsigned int j = 0 ; j < row ; j++)
3701  M_comp[i-1][j]=M[i][j];
3702  for ( unsigned int j = row+1 ; j < M.getRows() ; j++)
3703  M_comp[i-1][j-1]=M[i][j];
3704  }
3705  return M_comp;
3706 }
3707 
3708 #undef DEBUG_LEVEL1
3709 #undef DEBUG_LEVEL2
3710 
3711 /*
3712 * Local variables:
3713 * c-basic-offset: 2
3714 * End:
3715 */
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:3186
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:2809
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:3409
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:3640
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
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:2737
unsigned int trsize
Total row space.
Definition: vpMatrix.h:124
vpColVector eigenValues()
Definition: vpMatrix.cpp:2965
void insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
Definition: vpMatrix.cpp:2908
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:3482
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:3382
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:3654
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:2785
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
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:3569
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