opennurbs_matrix.h
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003 //
00004 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006 // McNeel & Associates.
00007 //
00008 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011 //                              
00012 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013 //
00015 */
00016 
00017 #if !defined(ON_MATRIX_INC_)
00018 #define ON_MATRIX_INC_
00019 
00020 class ON_Xform;
00021 
00022 class ON_CLASS ON_Matrix
00023 {
00024 public:
00025   ON_Matrix();
00026   ON_Matrix( 
00027     int row_count,
00028     int col_count
00029      );
00030   ON_Matrix( // see ON_Matrix::Create(int,int,int,int) for details
00031      int, // first valid row index
00032      int, // last valid row index
00033      int, // first valid column index
00034      int  // last valid column index
00035      );
00036   ON_Matrix( const ON_Xform& );
00037   ON_Matrix( const ON_Matrix& );
00038 
00039   /*
00040   Description:
00041     This constructor is for experts who have storage for a matrix
00042     and need to use it in ON_Matrix form.
00043   Parameters:
00044     row_count - [in]
00045     col_count - [in]
00046     M - [in]
00047     bDestructorFreeM - [in]
00048       If true, ~ON_Matrix will call onfree(M).
00049       If false, caller is managing M's memory.
00050   Remarks:
00051     ON_Matrix functions that increase the value of row_count or col_count
00052     will fail on a matrix created with this constructor.
00053   */
00054   ON_Matrix(
00055     int row_count,
00056     int col_count,
00057     double** M,
00058     bool bDestructorFreeM
00059     );
00060 
00061   virtual ~ON_Matrix();
00062   void EmergencyDestroy(); // call if memory pool used matrix by becomes invalid
00063 
00064   // ON_Matrix[i][j] = value at row i and column j
00065   //           0 <= i < RowCount()
00066   //           0 <= j < ColCount()
00067   double* operator[](int);
00068   const double* operator[](int) const;
00069 
00070   ON_Matrix& operator=(const ON_Matrix&);
00071   ON_Matrix& operator=(const ON_Xform&);
00072 
00073   bool IsValid() const;
00074   int IsSquare() const; // returns 0 for no and m_row_count (= m_col_count) for yes
00075   int RowCount() const;
00076   int ColCount() const;
00077   int MinCount() const; // smallest of row and column count
00078   int MaxCount() const; // largest of row and column count
00079 
00080   void RowScale(int,double); 
00081   void ColScale(int,double);
00082   void RowOp(int,double,int);
00083   void ColOp(int,double,int);
00084 
00085   bool Create(
00086      int, // number of rows
00087      int  // number of columns
00088      );
00089 
00090   bool Create( // E.g., Create(1,5,1,7) creates a 5x7 sized matrix that with
00091                // "top" row = m[1][1],...,m[1][7] and "bottom" row
00092                // = m[5][1],...,m[5][7].  The result of Create(0,m,0,n) is
00093                // identical to the result of Create(m+1,n+1).
00094      int, // first valid row index
00095      int, // last valid row index
00096      int, // first valid column index
00097      int  // last valid column index
00098      );
00099 
00100   /*
00101   Description:
00102     This constructor is for experts who have storage for a matrix
00103     and need to use it in ON_Matrix form.
00104   Parameters:
00105     row_count - [in]
00106     col_count - [in]
00107     M - [in]
00108     bDestructorFreeM - [in]
00109       If true, ~ON_Matrix will call onfree(M).
00110       If false, caller is managing M's memory.
00111   Remarks:
00112     ON_Matrix functions that increase the value of row_count or col_count
00113     will fail on a matrix created with this constructor.
00114   */
00115   bool Create(
00116     int row_count,
00117     int col_count,
00118     double** M,
00119     bool bDestructorFreeM
00120     );
00121 
00122 
00123   void Destroy();
00124 
00125   void Zero();
00126 
00127   void SetDiagonal(double); // sets diagonal value and zeros off diagonal values
00128   void SetDiagonal(const double*); // sets diagonal values and zeros off diagonal values
00129   void SetDiagonal(int, const double*); // sets size to count x count and diagonal values and zeros off diagonal values
00130   void SetDiagonal(const ON_SimpleArray<double>&); // sets size to length X lengthdiagonal values and zeros off diagonal values
00131 
00132   bool Transpose();
00133 
00134   bool SwapRows( int, int ); // ints are row indices to swap
00135   bool SwapCols( int, int ); // ints are col indices to swap
00136   bool Invert( 
00137           double // zero tolerance
00138           );
00139 
00140   /*
00141   Description:
00142     Set this = A*B.
00143   Parameters:
00144     A - [in]
00145       (Can be this)
00146     B - [in]
00147       (Can be this)
00148   Returns:
00149     True when A is an mXk matrix and B is a k X n matrix; in which case
00150     "this" will be an mXn matrix = A*B.
00151     False when A.ColCount() != B.RowCount().
00152   */
00153   bool Multiply( const ON_Matrix& A, const ON_Matrix& B );
00154 
00155   /*
00156   Description:
00157     Set this = A+B.
00158   Parameters:
00159     A - [in]
00160       (Can be this)
00161     B - [in]
00162       (Can be this)
00163   Returns:
00164     True when A and B are mXn matrices; in which case
00165     "this" will be an mXn matrix = A+B.
00166     False when A and B have different sizes.
00167   */
00168   bool Add( const ON_Matrix& A, const ON_Matrix& B );
00169 
00170 
00171   /*
00172   Description:
00173     Set this = s*this.
00174   Parameters:
00175     s - [in]
00176   Returns:
00177     True when A and s are valid.
00178   */
00179   bool Scale( double s );
00180 
00181 
00182   // Description:
00183   //   Row reduce a matrix to calculate rank and determinant.
00184   // Parameters:
00185   //   zero_tolerance - [in] (>=0.0) zero tolerance for pivot test
00186   //       If the absolute value of a pivot is <= zero_tolerance,
00187   //       then the pivot is assumed to be zero.
00188   //   determinant - [out] value of determinant is returned here.
00189   //   pivot - [out] value of the smallest pivot is returned here
00190   // Returns:
00191   //   Rank of the matrix.
00192   // Remarks:
00193   //   The matrix itself is row reduced so that the result is
00194   //   an upper triangular matrix with 1's on the diagonal.
00195   int RowReduce( // returns rank
00196     double,  // zero_tolerance
00197     double&, // determinant
00198     double&  // pivot
00199     ); 
00200 
00201   // Description:
00202   //   Row reduce a matrix as the first step in solving M*X=B where
00203   //   B is a column of values.
00204   // Parameters:
00205   //   zero_tolerance - [in] (>=0.0) zero tolerance for pivot test
00206   //       If the absolute value of a pivot is <= zero_tolerance,
00207   //       then the pivot is assumed to be zero.
00208   //   B - [in/out] an array of m_row_count values that is row reduced
00209   //       with the matrix.
00210   //   determinant - [out] value of determinant is returned here.
00211   //   pivot - [out] If not NULL, then the value of the smallest 
00212   //       pivot is returned here
00213   // Returns:
00214   //   Rank of the matrix.
00215   // Remarks:
00216   //   The matrix itself is row reduced so that the result is
00217   //   an upper triangular matrix with 1's on the diagonal.
00218   // Example:
00219   //   Solve M*X=B;
00220   //   double B[m] = ...;
00221   //   double B[n] = ...;
00222   //   ON_Matrix M(m,n) = ...;
00223   //   M.RowReduce(ON_ZERO_TOLERANCE,B); // modifies M and B
00224   //   M.BackSolve(m,B,X); // solution is in X
00225   // See Also: 
00226   //   ON_Matrix::BackSolve
00227   int RowReduce(
00228     double,        // zero_tolerance
00229     double*,       // B
00230     double* = NULL // pivot
00231     ); 
00232 
00233   // Description:
00234   //   Row reduce a matrix as the first step in solving M*X=B where
00235   //   B is a column of 3d points
00236   // Parameters:
00237   //   zero_tolerance - [in] (>=0.0) zero tolerance for pivot test
00238   //       If the absolute value of a pivot is <= zero_tolerance,
00239   //       then the pivot is assumed to be zero.
00240   //   B - [in/out] an array of m_row_count 3d points that is 
00241   //       row reduced with the matrix.
00242   //   determinant - [out] value of determinant is returned here.
00243   //   pivot - [out] If not NULL, then the value of the smallest 
00244   //       pivot is returned here
00245   // Returns:
00246   //   Rank of the matrix.
00247   // Remarks:
00248   //   The matrix itself is row reduced so that the result is
00249   //   an upper triangular matrix with 1's on the diagonal.
00250   // See Also: 
00251   //   ON_Matrix::BackSolve
00252   int RowReduce(
00253     double,        // zero_tolerance
00254     ON_3dPoint*,   // B
00255     double* = NULL // pivot
00256     ); 
00257 
00258   // Description:
00259   //   Row reduce a matrix as the first step in solving M*X=B where
00260   //   B is a column arbitrary dimension points.
00261   // Parameters:
00262   //   zero_tolerance - [in] (>=0.0) zero tolerance for pivot test
00263   //       If a the absolute value of a pivot is <= zero_tolerance,
00264   //       then the pivoit is assumed to be zero.
00265   //   pt_dim - [in] dimension of points
00266   //   pt_stride - [in] stride between points (>=pt_dim)
00267   //   pt - [in/out] array of m_row_count*pt_stride values.
00268   //        The i-th point is
00269   //        (pt[i*pt_stride],...,pt[i*pt_stride+pt_dim-1]).
00270   //        This array of points is row reduced along with the 
00271   //        matrix.
00272   //   pivot - [out] If not NULL, then the value of the smallest 
00273   //       pivot is returned here
00274   // Returns:
00275   //   Rank of the matrix.
00276   // Remarks:
00277   //   The matrix itself is row reduced so that the result is
00278   //   an upper triangular matrix with 1's on the diagonal.
00279   // See Also: 
00280   //   ON_Matrix::BackSolve
00281   int RowReduce( // returns rank
00282     double,      // zero_tolerance
00283     int,         // pt_dim
00284     int,         // pt_stride
00285     double*,     // pt
00286     double* = NULL // pivot
00287     ); 
00288 
00289   // Description:
00290   //   Solve M*X=B where M is upper triangular with a unit diagonal and
00291   //   B is a column of values.
00292   // Parameters:
00293   //   zero_tolerance - [in] (>=0.0) used to test for "zero" values in B
00294   //       in under determined systems of equations.
00295   //   Bsize - [in] (>=m_row_count) length of B.  The values in
00296   //       B[m_row_count],...,B[Bsize-1] are tested to make sure they are
00297   //       "zero".
00298   //   B - [in] array of length Bsize.
00299   //   X - [out] array of length m_col_count.  Solutions returned here.
00300   // Remarks:
00301   //   Actual values M[i][j] with i <= j are ignored. 
00302   //   M[i][i] is assumed to be one and M[i][j] i<j is assumed to be zero.
00303   //   For square M, B and X can point to the same memory.
00304   // See Also:
00305   //   ON_Matrix::RowReduce
00306   bool BackSolve(
00307     double,        // zero_tolerance
00308     int,           // Bsize
00309     const double*, // B
00310     double*        // X
00311       ) const;
00312 
00313   // Description:
00314   //   Solve M*X=B where M is upper triangular with a unit diagonal and
00315   //   B is a column of 3d points.
00316   // Parameters:
00317   //   zero_tolerance - [in] (>=0.0) used to test for "zero" values in B
00318   //       in under determined systems of equations.
00319   //   Bsize - [in] (>=m_row_count) length of B.  The values in
00320   //       B[m_row_count],...,B[Bsize-1] are tested to make sure they are
00321   //       "zero".
00322   //   B - [in] array of length Bsize.
00323   //   X - [out] array of length m_col_count.  Solutions returned here.
00324   // Remarks:
00325   //   Actual values M[i][j] with i <= j are ignored. 
00326   //   M[i][i] is assumed to be one and M[i][j] i<j is assumed to be zero.
00327   //   For square M, B and X can point to the same memory.
00328   // See Also:
00329   //   ON_Matrix::RowReduce
00330   bool BackSolve(
00331     double,            // zero_tolerance
00332     int,               // Bsize
00333     const ON_3dPoint*, // B
00334     ON_3dPoint*        // X
00335       ) const;
00336 
00337   // Description:
00338   //   Solve M*X=B where M is upper triangular with a unit diagonal and
00339   //   B is a column of points
00340   // Parameters:
00341   //   zero_tolerance - [in] (>=0.0) used to test for "zero" values in B
00342   //       in under determined systems of equations.
00343   //   pt_dim - [in] dimension of points
00344   //   Bsize - [in] (>=m_row_count) number of points in B[].  The points
00345   //       correspoinding to indices m_row_count, ..., (Bsize-1)
00346   //       are tested to make sure they are "zero".
00347   //   Bpt_stride - [in] stride between B points (>=pt_dim)
00348   //   Bpt - [in/out] array of m_row_count*Bpt_stride values.
00349   //        The i-th B point is
00350   //        (Bpt[i*Bpt_stride],...,Bpt[i*Bpt_stride+pt_dim-1]).
00351   //   Xpt_stride - [in] stride between X points (>=pt_dim)
00352   //   Xpt - [out] array of m_col_count*Xpt_stride values.
00353   //        The i-th X point is
00354   //        (Xpt[i*Xpt_stride],...,Xpt[i*Xpt_stride+pt_dim-1]).
00355   // Remarks:
00356   //   Actual values M[i][j] with i <= j are ignored. 
00357   //   M[i][i] is assumed to be one and M[i][j] i<j is assumed to be zero.
00358   //   For square M, B and X can point to the same memory.
00359   // See Also:
00360   //   ON_Matrix::RowReduce
00361   bool BackSolve(
00362     double,       // zero_tolerance
00363     int,          // pt_dim
00364     int,          // Bsize
00365     int,          // Bpt_stride
00366     const double*,// Bpt
00367     int,          // Xpt_stride
00368     double*       // Xpt
00369       ) const;
00370 
00371   bool IsRowOrthoganal() const;
00372   bool IsRowOrthoNormal() const;
00373 
00374   bool IsColOrthoganal() const;
00375   bool IsColOrthoNormal() const;
00376 
00377 
00378   double** m; // m[i][j] = value at row i and column j
00379               //           0 <= i < RowCount()
00380               //           0 <= j < ColCount()
00381 private:
00382   int m_row_count;
00383   int m_col_count;
00384   // m_rowmem[i][j] = row i+m_row_offset and column j+m_col_offset.
00385   ON_SimpleArray<double*> m_rowmem; 
00386         double** m_Mmem; // used by Create(row_count,col_count,user_memory,true);
00387         int   m_row_offset; // = ri0 when sub-matrix constructor is used
00388         int   m_col_offset; // = ci0 when sub-matrix constructor is used
00389   void* m_cmem;
00390   // returns 0 based arrays, even in submatrix case.
00391   double const * const * ThisM() const;
00392   double * * ThisM();
00393 };
00394 
00395 /*
00396 Description:
00397   Calculate the singular value decomposition of a matrix.
00398 
00399 Parameters:
00400   row_count - [in]
00401     number of rows in matrix A
00402   col_count - [in]
00403     number of columns in matrix A
00404   A - [in]
00405     Matrix for which you want the singular value decomposition.
00406     A[0][0] = coefficeint in the first row and first column.
00407     A[row_count-1][col_count-1] = coefficeint in the last row
00408     and last column.
00409   U - [out]
00410     The singular value decomposition of A is U*Diag(W)*Transpose(V),
00411     where U has the same size as A, Diag(W) is a col_count X col_count
00412     diagonal matrix with (W[0],...,W[col_count-1]) on the diagonal
00413     and V is a col_count X col_count matrix.
00414     U and A may be the same pointer.  If the input value of U is
00415     null, heap storage will be allocated using onmalloc()
00416     and the calling function must call onfree(U).  If the input
00417     value of U is not null, U[i] must point to an array of col_count
00418     doubles.  
00419   W - [out]
00420     If the input value W is null, then heap storage will be allocated
00421     using onmalloc() and the calling function must call onfree(W).
00422     If the input value of W is not null, then W must point to
00423     an array of col_count doubles.
00424   V - [out]
00425     If the input value V is null, then heap storage will be allocated
00426     using onmalloc() and the calling function must call onfree(V).
00427     If the input value of V is not null, then V[i] must point
00428     to an array of col_count doubles.
00429 
00430 Example:
00431 
00432           int m = row_count;
00433           int n = col_count;
00434           ON_Matrix A(m,n);
00435           for (i = 0; i < m; i++ ) for ( j = 0; j < n; j++ )
00436           {
00437             A[i][j] = ...;
00438           }
00439           ON_Matrix U(m,n);
00440           double* W = 0; // ON_GetMatrixSVD() will allocate W
00441           ON_Matrix V(n,n);
00442           bool rc = ON_GetMatrixSVD(m,n,A.m,U.m,W,V.m);
00443           ...
00444           onfree(W); // W allocated in ON_GetMatrixSVD()
00445 
00446 Returns:
00447   True if the singular value decomposition was cacluated.
00448   False if the algorithm failed to converge.
00449 */
00450 ON_DECL
00451 bool ON_GetMatrixSVD(
00452   int row_count,
00453   int col_count,
00454   double const * const * A,
00455   double**& U,
00456   double*& W,
00457   double**& V
00458   );
00459 
00460 /*
00461 Description:
00462   Invert the diagonal matrix in a the singular value decomposition.
00463 Parameters:
00464   count - [in] number of elements in W
00465   W - [in]
00466     diagonal values in the singular value decomposition.
00467   invW - [out]
00468     The inverted diagonal is returned here.  invW may be the same
00469     pointer as W.  If the input value of invW is not null, it must
00470     point to an array of count doubles.  If the input value of
00471     invW is null, heap storage will be allocated using onmalloc()
00472     and the calling function must call onfree(invW).
00473 Remarks:
00474   If the singular value decomposition were mathematically perfect, then
00475   this function would be:
00476     for (i = 0; i < count; i++) 
00477       invW[i] = (W[i] != 0.0) ? 1.0/W[i] : 0.0;
00478   Because the double precision arithmetic is not mathematically perfect,
00479   very small values of W[i] may well be zero and this function makes
00480   a reasonable guess as to when W[i] should be treated as zero.  
00481 Returns:
00482   Number of non-zero elements in invW, which, in a mathematically perfect
00483   situation, is the rank of Diag(W).
00484 */
00485 ON_DECL
00486 int ON_InvertSVDW(
00487   int count, 
00488   const double* W,
00489   double*& invW
00490   );
00491 
00492 /*
00493 Description:
00494   Solve a linear system of equations using the singular value decomposition.
00495 Parameters:
00496   row_count - [in]
00497     number of rows in matrix U
00498   col_count - [in]
00499     number of columns in matrix U
00500   U - [in]
00501     row_count X col_count matix.
00502     See the remarks section for the definition of U.
00503   invW - [in]
00504     inverted DVD diagonal.
00505     See the remarks section for the definition of invW.
00506   V - [in]
00507     col_count X col_count matrix.
00508     See the remarks section for the definition of V.
00509   B - [in]
00510     An array of row_count values.
00511   X - [out]
00512     The solution array of col_count values is returned here.
00513     If the input value of X is not null, it must point to an
00514     array of col_count doubles.  If the input value of X is
00515     null, heap storage will be allocated using onmalloc() and
00516     the calling function must call onfree(X).
00517 Remarks:
00518   If A*X = B is an m X n system of equations (m = row_count, n = col_count)
00519   and A = U*Diag(W)*Transpose(V) is the singular value decompostion of A,
00520   then a solution is X = V*Diag(1/W)*Transpose(U).
00521 Example:
00522 
00523           int m = row_count;
00524           int n = col_count;
00525           ON_Matrix A(m,n);
00526           for (i = 0; i < m; i++ ) for ( j = 0; j < n; j++ )
00527           {
00528             A[i][j] = ...;
00529           }
00530           ON_SimpleArray<double> B(m);
00531           for (i = 0; i < m; i++ )
00532           {
00533             B[i] = ...;
00534           }
00535 
00536           ON_SimpleArray<double> X; // solution returned here.
00537           {
00538             double** U = 0;
00539             double* W = 0;
00540             double** V = 0;
00541             if ( ON_GetMatrixSVD(m,n,A.m,U,W,V) )
00542             {
00543               double* invW = 0;
00544               int rankW = ON_InvertSVDW(n,W,W); // save invW into W
00545               X.Reserve(n);
00546               if ( ON_SolveSVD(m,n,U,W,V,B,X.Array()) )
00547                 X.SetCount(n);
00548             }
00549             onfree(U); // U allocated in ON_GetMatrixSVD()
00550             onfree(W); // W allocated in ON_GetMatrixSVD()
00551             onfree(V); // V allocated in ON_GetMatrixSVD()
00552           }
00553 
00554           if ( n == X.Count() )
00555           {
00556             ... use solution
00557           }  
00558 Returns:
00559   True if input is valid and X[] was calculated. 
00560   False if input is not valid.
00561 */
00562 ON_DECL
00563 bool ON_SolveSVD(
00564   int row_count,
00565   int col_count,
00566   double const * const * U,
00567   const double* invW,
00568   double const * const * V,
00569   const double* B,
00570   double*& X
00571   );
00572   
00573 
00574 /*
00575 Description:
00576   Perform simple row reduction on a matrix.  If A is square, positive
00577   definite, and really really nice, then the returned B is the inverse
00578   of A.  If A is not positive definite and really really nice, then it
00579   is probably a waste of time to call this function.
00580 Parameters:
00581   row_count - [in]
00582   col_count - [in]
00583   zero_pivot - [in]
00584     absolute values <= zero_pivot are considered to be zero
00585   A - [in/out]
00586     A row_count X col_count matrix.  Input is the matrix to be
00587     row reduced.  The calculation destroys A, so output A is garbage.
00588   B - [out]
00589     A a row_count X row_count matrix. That records the row reduction.
00590   pivots - [out]
00591     minimum and maximum absolute values of pivots.
00592 Returns:
00593   Rank of A.  If the returned value < min(row_count,col_count),
00594   then a zero pivot was encountered.
00595   If C = input value of A, then B*C = (I,*)
00596 */
00597 ON_DECL
00598 int ON_RowReduce( 
00599           int row_count, 
00600           int col_count,
00601           double zero_pivot,
00602           double** A, 
00603           double** B, 
00604           double pivots[2] 
00605           );
00606 
00607 #endif


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:01