core/vnl/vnl_matrix.txx

Go to the documentation of this file.
00001 // This is core/vnl/vnl_matrix.txx
00002 #ifndef vnl_matrix_txx_
00003 #define vnl_matrix_txx_
00004 //:
00005 // \file
00006 //
00007 // Copyright (C) 1991 Texas Instruments Incorporated.
00008 // Copyright (C) 1992 General Electric Company.
00009 //
00010 // Permission is granted to any individual or institution to use, copy, modify,
00011 // and distribute this software, provided that this complete copyright and
00012 // permission notice is maintained, intact, in all copies and supporting
00013 // documentation.
00014 //
00015 // Texas Instruments Incorporated, General Electric Company,
00016 // provides this software "as is" without express or implied warranty.
00017 //
00018 // Created: MBN Apr 21, 1989 Initial design and implementation
00019 // Updated: MBN Jun 22, 1989 Removed non-destructive methods
00020 // Updated: LGO Aug 09, 1989 Inherit from Generic
00021 // Updated: MBN Aug 20, 1989 Changed template usage to reflect new syntax
00022 // Updated: MBN Sep 11, 1989 Added conditional exception handling and base class
00023 // Updated: LGO Oct 05, 1989 Don't re-allocate data in operator= when same size
00024 // Updated: LGO Oct 19, 1989 Add extra parameter to varargs constructor
00025 // Updated: MBN Oct 19, 1989 Added optional argument to set_compare method
00026 // Updated: LGO Dec 08, 1989 Allocate column data in one chunk
00027 // Updated: LGO Dec 08, 1989 Clean-up get and put, add const everywhere.
00028 // Updated: LGO Dec 19, 1989 Remove the map and reduce methods
00029 // Updated: MBN Feb 22, 1990 Changed size arguments from int to unsigned int
00030 // Updated: MJF Jun 30, 1990 Added base class name to constructor initializer
00031 // Updated: VDN Feb 21, 1992 New lite version
00032 // Updated: VDN May 05, 1992 Use envelope to avoid unnecessary copying
00033 // Updated: VDN Sep 30, 1992 Matrix inversion with singular value decomposition
00034 // Updated: AWF Aug 21, 1996 set_identity, normalize_rows, scale_row.
00035 // Updated: AWF Sep 30, 1996 set_row/column methods. Const-correct data_block().
00036 // Updated: AWF 14 Feb 1997  get_n_rows, get_n_columns.
00037 // Updated: PVR 20 Mar 1997  get_row, get_column.
00038 //
00039 // The parameterized vnl_matrix<T> class implements two dimensional arithmetic
00040 // matrices of a user specified type. The only constraint placed on the type is
00041 // that it must overload the following operators: +, -,  *,  and /. Thus, it
00042 // will be possible to have a vnl_matrix over vcl_complex<T>. The vnl_matrix<T>
00043 // class is static in size, that is once a vnl_matrix<T> of a particular size
00044 // has been created, there is no dynamic growth method available. You can
00045 // resize the matrix, with the loss of any existing data using set_size().
00046 //
00047 // Each matrix contains  a protected  data section  that has a T** slot that
00048 // points to the  physical memory allocated  for the two  dimensional array. In
00049 // addition, two integers  specify   the number  of  rows  and columns  for the
00050 // matrix.  These values  are provided in the  constructors. A single protected
00051 // slot  contains a pointer  to a compare  function  to   be used  in  equality
00052 // operations. The default function used is the built-in == operator.
00053 //
00054 // Four  different constructors are provided.  The  first constructor takes two
00055 // integer arguments  specifying the  row  and column  size.   Enough memory is
00056 // allocated to hold row*column elements  of type Type.  The second constructor
00057 // takes the  same two  first arguments, but  also accepts  an additional third
00058 // argument that is  a reference to  an  object of  the appropriate  type whose
00059 // value is used as an initial fill value.  The third constructor is similar to
00060 // the third, except that it accepts a variable number of initialization values
00061 // for the Matrix.  If there are  fewer values than elements,  the rest are set
00062 // to zero. Finally, the last constructor takes a single argument consisting of
00063 // a reference to a Matrix and duplicates its size and element values.
00064 //
00065 // Methods   are  provided   for destructive   scalar   and Matrix    addition,
00066 // multiplication, check for equality  and inequality, fill, reduce, and access
00067 // and set individual elements.  Finally, both  the  input and output operators
00068 // are overloaded to allow for formatted input and output of matrix elements.
00069 //
00070 // Good matrix inversion is needed. We choose singular value decomposition,
00071 // since it is general and works great for nearly singular cases. Singular
00072 // value decomposition is preferred to LU decomposition, since the accuracy
00073 // of the pivots is independent from the left->right top->down elimination.
00074 // LU decomposition also does not give eigenvectors and eigenvalues when
00075 // the matrix is symmetric.
00076 //
00077 // Several different constructors are provided. See .h file for brief descriptions.
00078 
00079 //--------------------------------------------------------------------------------
00080 
00081 #include "vnl_matrix.h"
00082 
00083 #include <vcl_cassert.h>
00084 #include <vcl_cstdio.h>   // EOF
00085 #include <vcl_cstdlib.h>  // abort()
00086 #include <vcl_cctype.h>   // isspace()
00087 #include <vcl_iostream.h>
00088 #include <vcl_vector.h>
00089 #include <vcl_algorithm.h>
00090 
00091 #include <vnl/vnl_math.h>
00092 #include <vnl/vnl_vector.h>
00093 #include <vnl/vnl_c_vector.h>
00094 #include <vnl/vnl_numeric_traits.h>
00095 //--------------------------------------------------------------------------------
00096 
00097 #if VCL_HAS_SLICED_DESTRUCTOR_BUG
00098 // vnl_matrix owns its data by default.
00099 # define vnl_matrix_construct_hack() vnl_matrix_own_data = 1
00100 #else
00101 # define vnl_matrix_construct_hack()
00102 #endif
00103 
00104 // This macro allocates and initializes the dynamic storage used by a vnl_matrix.
00105 #define vnl_matrix_alloc_blah(rowz_, colz_) \
00106 do { \
00107   this->num_rows = (rowz_); \
00108   this->num_cols = (colz_); \
00109   if (this->num_rows && this->num_cols) { \
00110     /* Allocate memory to hold the row pointers */ \
00111     this->data = vnl_c_vector<T>::allocate_Tptr(this->num_rows); \
00112     /* Allocate memory to hold the elements of the matrix */ \
00113     T* elmns = vnl_c_vector<T>::allocate_T(this->num_rows * this->num_cols); \
00114     /* Fill in the array of row pointers */ \
00115     for (unsigned int i = 0; i < this->num_rows; ++ i) \
00116       this->data[i] = elmns + i*this->num_cols; \
00117   } \
00118   else { \
00119    /* This is to make sure .begin() and .end() work for 0xN matrices: */ \
00120    (this->data = vnl_c_vector<T>::allocate_Tptr(1))[0] = 0; \
00121   } \
00122 } while (false)
00123 
00124 // This macro releases the dynamic storage used by a vnl_matrix.
00125 #define vnl_matrix_free_blah \
00126 do { \
00127   if (this->data) { \
00128     if (this->num_cols && this->num_rows) { \
00129       vnl_c_vector<T>::deallocate(this->data[0], this->num_cols * this->num_rows); \
00130       vnl_c_vector<T>::deallocate(this->data, this->num_rows); \
00131     } else { \
00132       vnl_c_vector<T>::deallocate(this->data, 1); \
00133     } \
00134   } \
00135 } while (false)
00136 
00137 //: Creates a matrix with given number of rows and columns.
00138 // Elements are not initialized. O(m*n).
00139 
00140 template<class T>
00141 vnl_matrix<T>::vnl_matrix (unsigned rowz, unsigned colz)
00142 {
00143   vnl_matrix_construct_hack();
00144   vnl_matrix_alloc_blah(rowz, colz);
00145 }
00146 
00147 //: Creates a matrix with given number of rows and columns, and initialize all elements to value. O(m*n).
00148 
00149 template<class T>
00150 vnl_matrix<T>::vnl_matrix (unsigned rowz, unsigned colz, T const& value)
00151 {
00152   vnl_matrix_construct_hack();
00153   vnl_matrix_alloc_blah(rowz, colz);
00154   for (unsigned int i = 0; i < rowz; ++ i)
00155     for (unsigned int j = 0; j < colz; ++ j)
00156       this->data[i][j] = value;
00157 }
00158 
00159 //: r rows, c cols, special type.  Currently implements "identity" and "null".
00160 template <class T>
00161 vnl_matrix<T>::vnl_matrix(unsigned r, unsigned c, vnl_matrix_type t)
00162 {
00163   vnl_matrix_construct_hack();
00164   vnl_matrix_alloc_blah(r, c);
00165   switch (t) {
00166    case vnl_matrix_identity:
00167     assert(r == c);
00168     for (unsigned int i = 0; i < r; ++ i)
00169       for (unsigned int j = 0; j < c; ++ j)
00170         this->data[i][j] = (i==j) ? T(1) : T(0);
00171     break;
00172    case vnl_matrix_null:
00173     for (unsigned int i = 0; i < r; ++ i)
00174       for (unsigned int j = 0; j < c; ++ j)
00175         this->data[i][j] = T(0);
00176     break;
00177    default:
00178     assert(false);
00179     break;
00180   }
00181 }
00182 
00183 #if 1 // fsm: who uses this?
00184 //: Creates a matrix with given dimension (rows, cols) and initialize first n elements, row-wise, to values. O(m*n).
00185 
00186 template<class T>
00187 vnl_matrix<T>::vnl_matrix (unsigned rowz, unsigned colz, unsigned n, T const values[])
00188 {
00189   vnl_matrix_construct_hack();
00190   vnl_matrix_alloc_blah(rowz, colz);
00191   if (n > rowz*colz)
00192     n = rowz*colz;
00193   T *dst = this->data[0];
00194   for (unsigned k=0; k<n; ++k)
00195     dst[k] = values[k];
00196 }
00197 #endif
00198 
00199 //: Creates a matrix from a block array of data, stored row-wise.
00200 // O(m*n).
00201 
00202 template<class T>
00203 vnl_matrix<T>::vnl_matrix (T const* datablck, unsigned rowz, unsigned colz)
00204 {
00205   vnl_matrix_construct_hack();
00206   vnl_matrix_alloc_blah(rowz, colz);
00207   unsigned int n = rowz*colz;
00208   T *dst = this->data[0];
00209   for (unsigned int k=0; k<n; ++k)
00210     dst[k] = datablck[k];
00211 }
00212 
00213 
00214 //: Creates a new matrix and copies all the elements.
00215 // O(m*n).
00216 
00217 template<class T>
00218 vnl_matrix<T>::vnl_matrix (vnl_matrix<T> const& from)
00219 {
00220   vnl_matrix_construct_hack();
00221   if (from.data) {
00222     vnl_matrix_alloc_blah(from.num_rows, from.num_cols);
00223     unsigned int n = this->num_rows * this->num_cols;
00224     T *dst = this->data[0];
00225     T const *src = from.data[0];
00226     for (unsigned int k=0; k<n; ++k)
00227       dst[k] = src[k];
00228   }
00229   else {
00230     num_rows = 0;
00231     num_cols = 0;
00232     data = 0;
00233   }
00234 }
00235 
00236 //------------------------------------------------------------
00237 
00238 template<class T>
00239 vnl_matrix<T>::vnl_matrix (vnl_matrix<T> const &A, vnl_matrix<T> const &B, vnl_tag_add)
00240 {
00241 #ifndef NDEBUG
00242   if (A.num_rows != B.num_rows || A.num_cols != B.num_cols)
00243     vnl_error_matrix_dimension ("vnl_tag_add", A.num_rows, A.num_cols, B.num_rows, B.num_cols);
00244 #endif
00245 
00246   vnl_matrix_construct_hack();
00247   vnl_matrix_alloc_blah(A.num_rows, A.num_cols);
00248 
00249   unsigned int n = A.num_rows * A.num_cols;
00250   T const *a = A.data[0];
00251   T const *b = B.data[0];
00252   T *dst = this->data[0];
00253 
00254   for (unsigned int i=0; i<n; ++i)
00255     dst[i] = T(a[i] + b[i]);
00256 }
00257 
00258 template<class T>
00259 vnl_matrix<T>::vnl_matrix (vnl_matrix<T> const &A, vnl_matrix<T> const &B, vnl_tag_sub)
00260 {
00261 #ifndef NDEBUG
00262   if (A.num_rows != B.num_rows || A.num_cols != B.num_cols)
00263     vnl_error_matrix_dimension ("vnl_tag_sub", A.num_rows, A.num_cols, B.num_rows, B.num_cols);
00264 #endif
00265 
00266   vnl_matrix_construct_hack();
00267   vnl_matrix_alloc_blah(A.num_rows, A.num_cols);
00268 
00269   unsigned int n = A.num_rows * A.num_cols;
00270   T const *a = A.data[0];
00271   T const *b = B.data[0];
00272   T *dst = this->data[0];
00273 
00274   for (unsigned int i=0; i<n; ++i)
00275     dst[i] = T(a[i] - b[i]);
00276 }
00277 
00278 template<class T>
00279 vnl_matrix<T>::vnl_matrix (vnl_matrix<T> const &M, T s, vnl_tag_mul)
00280 {
00281   vnl_matrix_construct_hack();
00282   vnl_matrix_alloc_blah(M.num_rows, M.num_cols);
00283 
00284   unsigned int n = M.num_rows * M.num_cols;
00285   T const *m = M.data[0];
00286   T *dst = this->data[0];
00287 
00288   for (unsigned int i=0; i<n; ++i)
00289     dst[i] = T(m[i] * s);
00290 }
00291 
00292 template<class T>
00293 vnl_matrix<T>::vnl_matrix (vnl_matrix<T> const &M, T s, vnl_tag_div)
00294 {
00295   vnl_matrix_construct_hack();
00296   vnl_matrix_alloc_blah(M.num_rows, M.num_cols);
00297 
00298   unsigned int n = M.num_rows * M.num_cols;
00299   T const *m = M.data[0];
00300   T *dst = this->data[0];
00301 
00302   for (unsigned int i=0; i<n; ++i)
00303     dst[i] = T(m[i] / s);
00304 }
00305 
00306 template<class T>
00307 vnl_matrix<T>::vnl_matrix (vnl_matrix<T> const &M, T s, vnl_tag_add)
00308 {
00309   vnl_matrix_construct_hack();
00310   vnl_matrix_alloc_blah(M.num_rows, M.num_cols);
00311 
00312   unsigned int n = M.num_rows * M.num_cols;
00313   T const *m = M.data[0];
00314   T *dst = this->data[0];
00315 
00316   for (unsigned int i=0; i<n; ++i)
00317     dst[i] = T(m[i] + s);
00318 }
00319 
00320 template<class T>
00321 vnl_matrix<T>::vnl_matrix (vnl_matrix<T> const &M, T s, vnl_tag_sub)
00322 {
00323   vnl_matrix_construct_hack();
00324   vnl_matrix_alloc_blah(M.num_rows, M.num_cols);
00325 
00326   unsigned int n = M.num_rows * M.num_cols;
00327   T const *m = M.data[0];
00328   T *dst = this->data[0];
00329 
00330   for (unsigned int i=0; i<n; ++i)
00331     dst[i] = T(m[i] - s);
00332 }
00333 
00334 template<class T>
00335 vnl_matrix<T>::vnl_matrix (vnl_matrix<T> const &A, vnl_matrix<T> const &B, vnl_tag_mul)
00336 {
00337 #ifndef NDEBUG
00338   if (A.num_cols != B.num_rows)
00339     vnl_error_matrix_dimension("vnl_tag_mul", A.num_rows, A.num_cols, B.num_rows, B.num_cols);
00340 #endif
00341 
00342   unsigned int l = A.num_rows;
00343   unsigned int m = A.num_cols; // == B.num_rows
00344   unsigned int n = B.num_cols;
00345 
00346   vnl_matrix_construct_hack();
00347   vnl_matrix_alloc_blah(l, n);
00348 
00349   for (unsigned int i=0; i<l; ++i) {
00350     for (unsigned int k=0; k<n; ++k) {
00351       T sum(0);
00352       for (unsigned int j=0; j<m; ++j)
00353         sum += T(A.data[i][j] * B.data[j][k]);
00354       this->data[i][k] = sum;
00355     }
00356   }
00357 }
00358 
00359 //------------------------------------------------------------
00360 
00361 template<class T>
00362 vnl_matrix<T>::~vnl_matrix()
00363 {
00364   // save some fcalls if data is 0 (i.e. in matrix_fixed)
00365 #if VCL_HAS_SLICED_DESTRUCTOR_BUG
00366   if (data && vnl_matrix_own_data) destroy();
00367 #else
00368   if (data) destroy();
00369 #endif
00370 }
00371 
00372 //: Frees up the dynamic storage used by matrix.
00373 // O(m*n).
00374 
00375 template<class T>
00376 void vnl_matrix<T>::destroy()
00377 {
00378   vnl_matrix_free_blah;
00379 }
00380 
00381 template<class T>
00382 void vnl_matrix<T>::clear()
00383 {
00384   if (data) {
00385     destroy();
00386     num_rows = 0;
00387     num_cols = 0;
00388     data = 0;
00389   }
00390 }
00391 
00392 // Resizes the data arrays of THIS matrix to (rows x cols). O(m*n).
00393 // Elements are not initialized, existing data is not preserved.
00394 // Returns true if size is changed.
00395 
00396 template<class T>
00397 bool vnl_matrix<T>::set_size (unsigned rowz, unsigned colz)
00398 {
00399   if (this->data) {
00400     // if no change in size, do not reallocate.
00401     if (this->num_rows == rowz && this->num_cols == colz)
00402       return false;
00403 
00404     // else, simply release old storage and allocate new.
00405     vnl_matrix_free_blah;
00406     vnl_matrix_alloc_blah(rowz, colz);
00407   }
00408   else {
00409     // This happens if the matrix is default constructed.
00410     vnl_matrix_alloc_blah(rowz, colz);
00411   }
00412 
00413   return true;
00414 }
00415 
00416 #undef vnl_matrix_alloc_blah
00417 #undef vnl_matrix_free_blah
00418 
00419 //------------------------------------------------------------
00420 
00421 //: Sets all elements of matrix to specified value. O(m*n).
00422 
00423 template<class T>
00424 void vnl_matrix<T>::fill (T const& value)
00425 {
00426   for (unsigned int i = 0; i < this->num_rows; i++)
00427     for (unsigned int j = 0; j < this->num_cols; j++)
00428       this->data[i][j] = value;
00429 }
00430 
00431 //: Sets all diagonal elements of matrix to specified value. O(n).
00432 
00433 template<class T>
00434 void vnl_matrix<T>::fill_diagonal (T const& value)
00435 {
00436   for (unsigned int i = 0; i < this->num_rows && i < this->num_cols; i++)
00437     this->data[i][i] = value;
00438 }
00439 
00440 #if 0
00441 //: Assigns value to all elements of a matrix. O(m*n).
00442 
00443 template<class T>
00444 vnl_matrix<T>& vnl_matrix<T>::operator= (T const& value)
00445 {
00446   for (unsigned i = 0; i < this->num_rows; i++)    // For each row in Matrix
00447     for (unsigned j = 0; j < this->num_cols; j++)  // For each column in Matrix
00448       this->data[i][j] = value;                 // Assign value
00449   return *this;                                 // Return Matrix reference
00450 }
00451 #endif // 0
00452 
00453 //: Copies all elements of rhs matrix into lhs matrix. O(m*n).
00454 // If needed, the arrays in lhs matrix are freed up, and new arrays are
00455 // allocated to match the dimensions of the rhs matrix.
00456 
00457 template<class T>
00458 vnl_matrix<T>& vnl_matrix<T>::operator= (vnl_matrix<T> const& rhs)
00459 {
00460   if (this != &rhs) { // make sure *this != m
00461     if (rhs.data) {
00462       this->set_size(rhs.num_rows, rhs.num_cols);
00463       for (unsigned int i = 0; i < this->num_rows; i++)
00464         for (unsigned int j = 0; j < this->num_cols; j++)
00465           this->data[i][j] = rhs.data[i][j];
00466     }
00467     else {
00468       // rhs is default-constructed.
00469       clear();
00470     }
00471   }
00472   return *this;
00473 }
00474 
00475 template<class T>
00476 void vnl_matrix<T>::print(vcl_ostream& os) const
00477 {
00478   for (unsigned int i = 0; i < this->rows(); i++) {
00479     for (unsigned int j = 0; j < this->columns(); j++)
00480       os << this->data[i][j] << ' ';
00481     os << '\n';
00482   }
00483 }
00484 
00485 //: Prints the 2D array of elements of a matrix out to a stream.
00486 // O(m*n).
00487 
00488 template<class T>
00489 vcl_ostream& operator<< (vcl_ostream& os, vnl_matrix<T> const& m)
00490 {
00491   for (unsigned int i = 0; i < m.rows(); ++i) {
00492     for (unsigned int j = 0; j < m.columns(); ++j)
00493       os << m(i, j) << ' ';
00494     os << '\n';
00495   }
00496   return os;
00497 }
00498 
00499 //: Read an vnl_matrix from an ascii vcl_istream.
00500 // Automatically determines file size if the input matrix has zero size.
00501 template<class T>
00502 vcl_istream& operator>>(vcl_istream& s, vnl_matrix<T>& M)
00503 {
00504   M.read_ascii(s);
00505   return s;
00506 }
00507 
00508 template<class T>
00509 void vnl_matrix<T>::inline_function_tickler()
00510 {
00511   vnl_matrix<T> M;
00512   // fsm: hack to get 2.96 to instantiate the inline function.
00513   M = T(1) + T(3) * M;
00514 }
00515 
00516 template<class T>
00517 vnl_matrix<T>& vnl_matrix<T>::operator+= (T value)
00518 {
00519   for (unsigned int i = 0; i < this->num_rows; i++)
00520     for (unsigned int j = 0; j < this->num_cols; j++)
00521       this->data[i][j] += value;
00522   return *this;
00523 }
00524 
00525 template<class T>
00526 vnl_matrix<T>& vnl_matrix<T>::operator-= (T value)
00527 {
00528   for (unsigned int i = 0; i < this->num_rows; i++)
00529     for (unsigned int j = 0; j < this->num_cols; j++)
00530       this->data[i][j] -= value;
00531   return *this;
00532 }
00533 
00534 template<class T>
00535 vnl_matrix<T>& vnl_matrix<T>::operator*= (T value)
00536 {
00537   for (unsigned int i = 0; i < this->num_rows; i++)
00538     for (unsigned int j = 0; j < this->num_cols; j++)
00539       this->data[i][j] *= value;
00540   return *this;
00541 }
00542 
00543 template<class T>
00544 vnl_matrix<T>& vnl_matrix<T>::operator/= (T value)
00545 {
00546   for (unsigned int i = 0; i < this->num_rows; i++)
00547     for (unsigned int j = 0; j < this->num_cols; j++)
00548       this->data[i][j] /= value;
00549   return *this;
00550 }
00551 
00552 
00553 //: Adds lhs matrix with rhs matrix, and stores in place in lhs matrix.
00554 // O(m*n). The dimensions of the two matrices must be identical.
00555 
00556 template<class T>
00557 vnl_matrix<T>& vnl_matrix<T>::operator+= (vnl_matrix<T> const& rhs)
00558 {
00559 #ifndef NDEBUG
00560   if (this->num_rows != rhs.num_rows ||
00561       this->num_cols != rhs.num_cols)           // Size match?
00562     vnl_error_matrix_dimension ("operator+=",
00563                                 this->num_rows, this->num_cols,
00564                                 rhs.num_rows, rhs.num_cols);
00565 #endif
00566   for (unsigned int i = 0; i < this->num_rows; i++)    // For each row
00567     for (unsigned int j = 0; j < this->num_cols; j++)  // For each element in column
00568       this->data[i][j] += rhs.data[i][j];       // Add elements
00569   return *this;
00570 }
00571 
00572 
00573 //: Subtract lhs matrix with rhs matrix and store in place in lhs matrix.
00574 // O(m*n).
00575 // The dimensions of the two matrices must be identical.
00576 
00577 template<class T>
00578 vnl_matrix<T>& vnl_matrix<T>::operator-= (vnl_matrix<T> const& rhs)
00579 {
00580 #ifndef NDEBUG
00581   if (this->num_rows != rhs.num_rows ||
00582       this->num_cols != rhs.num_cols) // Size?
00583     vnl_error_matrix_dimension ("operator-=",
00584                                 this->num_rows, this->num_cols,
00585                                 rhs.num_rows, rhs.num_cols);
00586 #endif
00587   for (unsigned int i = 0; i < this->num_rows; i++)
00588     for (unsigned int j = 0; j < this->num_cols; j++)
00589       this->data[i][j] -= rhs.data[i][j];
00590   return *this;
00591 }
00592 
00593 
00594 template<class T>
00595 vnl_matrix<T> operator- (T const& value, vnl_matrix<T> const& m)
00596 {
00597   vnl_matrix<T> result(m.rows(),m.columns());
00598   for (unsigned int i = 0; i < m.rows(); i++)  // For each row
00599     for (unsigned int j = 0; j < m.columns(); j++) // For each element in column
00600       result.put(i,j, T(value - m.get(i,j)) );    // subtract from value element.
00601   return result;
00602 }
00603 
00604 
00605 #if 0 // commented out
00606 //: Returns new matrix which is the product of m1 with m2, m1 * m2.
00607 // O(n^3). Number of columns of first matrix must match number of rows
00608 // of second matrix.
00609 
00610 template<class T>
00611 vnl_matrix<T> vnl_matrix<T>::operator* (vnl_matrix<T> const& rhs) const
00612 {
00613 #ifndef NDEBUG
00614   if (this->num_cols != rhs.num_rows)           // dimensions do not match?
00615     vnl_error_matrix_dimension("operator*",
00616                                this->num_rows, this->num_cols,
00617                                rhs.num_rows, rhs.num_cols);
00618 #endif
00619   vnl_matrix<T> result(this->num_rows, rhs.num_cols); // Temp to store product
00620   for (unsigned i = 0; i < this->num_rows; i++) {  // For each row
00621     for (unsigned j = 0; j < rhs.num_cols; j++) {  // For each element in column
00622       T sum = 0;
00623       for (unsigned k = 0; k < this->num_cols; k++) // Loop over column values
00624         sum += (this->data[i][k] * rhs.data[k][j]);     // Multiply
00625       result(i,j) = sum;
00626     }
00627   }
00628   return result;
00629 }
00630 #endif
00631 
00632 //: Returns new matrix which is the negation of THIS matrix.
00633 // O(m*n).
00634 
00635 template<class T>
00636 vnl_matrix<T> vnl_matrix<T>::operator- () const
00637 {
00638   vnl_matrix<T> result(this->num_rows, this->num_cols);
00639   for (unsigned int i = 0; i < this->num_rows; i++)
00640     for (unsigned int j = 0; j < this->num_cols; j++)
00641       result.data[i][j] = - this->data[i][j];
00642   return result;
00643 }
00644 
00645 #if 0 // commented out
00646 //: Returns new matrix with elements of lhs matrix added with value.
00647 // O(m*n).
00648 
00649 template<class T>
00650 vnl_matrix<T> vnl_matrix<T>::operator+ (T const& value) const
00651 {
00652   vnl_matrix<T> result(this->num_rows, this->num_cols);
00653   for (unsigned i = 0; i < this->num_rows; i++)    // For each row
00654     for (unsigned j = 0; j < this->num_cols; j++)  // For each element in column
00655       result.data[i][j] = (this->data[i][j] + value);   // Add scalar
00656   return result;
00657 }
00658 
00659 
00660 //: Returns new matrix with elements of lhs matrix multiplied with value.
00661 // O(m*n).
00662 
00663 template<class T>
00664 vnl_matrix<T> vnl_matrix<T>::operator* (T const& value) const
00665 {
00666   vnl_matrix<T> result(this->num_rows, this->num_cols);
00667   for (unsigned i = 0; i < this->num_rows; i++)    // For each row
00668     for (unsigned j = 0; j < this->num_cols; j++)  // For each element in column
00669       result.data[i][j] = (this->data[i][j] * value);   // Multiply
00670   return result;
00671 }
00672 
00673 
00674 //: Returns new matrix with elements of lhs matrix divided by value. O(m*n).
00675 template<class T>
00676 vnl_matrix<T> vnl_matrix<T>::operator/ (T const& value) const
00677 {
00678   vnl_matrix<T> result(this->num_rows, this->num_cols);
00679   for (unsigned i = 0; i < this->num_rows; i++)    // For each row
00680     for (unsigned j = 0; j < this->num_cols; j++)  // For each element in column
00681       result.data[i][j] = (this->data[i][j] / value);   // Divide
00682   return result;
00683 }
00684 #endif
00685 
00686 //: Return the matrix made by applying "f" to each element.
00687 template <class T>
00688 vnl_matrix<T> vnl_matrix<T>::apply(T (*f)(T const&)) const
00689 {
00690   vnl_matrix<T> ret(num_rows, num_cols);
00691   vnl_c_vector<T>::apply(this->data[0], num_rows * num_cols, f, ret.data_block());
00692   return ret;
00693 }
00694 
00695 //: Return the matrix made by applying "f" to each element.
00696 template <class T>
00697 vnl_matrix<T> vnl_matrix<T>::apply(T (*f)(T)) const
00698 {
00699   vnl_matrix<T> ret(num_rows, num_cols);
00700   vnl_c_vector<T>::apply(this->data[0], num_rows * num_cols, f, ret.data_block());
00701   return ret;
00702 }
00703 
00704 ////--------------------------- Additions------------------------------------
00705 
00706 //: Returns new matrix with rows and columns transposed.
00707 // O(m*n).
00708 
00709 template<class T>
00710 vnl_matrix<T> vnl_matrix<T>::transpose() const
00711 {
00712   vnl_matrix<T> result(this->num_cols, this->num_rows);
00713   for (unsigned int i = 0; i < this->num_cols; i++)
00714     for (unsigned int j = 0; j < this->num_rows; j++)
00715       result.data[i][j] = this->data[j][i];
00716   return result;
00717 }
00718 
00719 // adjoint/hermitian transpose
00720 
00721 template<class T>
00722 vnl_matrix<T> vnl_matrix<T>::conjugate_transpose() const
00723 {
00724   vnl_matrix<T> result(transpose());
00725   vnl_c_vector<T>::conjugate(result.begin(),  // src
00726                              result.begin(),  // dst
00727                              result.size());  // size of block
00728   return result;
00729 }
00730 
00731 //: Replaces the submatrix of THIS matrix, starting at top left corner, by the elements of matrix m. O(m*n).
00732 // This is the reverse of extract().
00733 
00734 template<class T>
00735 vnl_matrix<T>& vnl_matrix<T>::update (vnl_matrix<T> const& m,
00736                                       unsigned top, unsigned left)
00737 {
00738   unsigned int bottom = top + m.num_rows;
00739   unsigned int right = left + m.num_cols;
00740 #ifndef NDEBUG
00741   if (this->num_rows < bottom || this->num_cols < right)
00742     vnl_error_matrix_dimension ("update",
00743                                 bottom, right, m.num_rows, m.num_cols);
00744 #endif
00745   for (unsigned int i = top; i < bottom; i++)
00746     for (unsigned int j = left; j < right; j++)
00747       this->data[i][j] = m.data[i-top][j-left];
00748   return *this;
00749 }
00750 
00751 
00752 //: Returns a copy of submatrix of THIS matrix, specified by the top-left corner and size in rows, cols. O(m*n).
00753 // Use update() to copy new values of this submatrix back into THIS matrix.
00754 
00755 template<class T>
00756 vnl_matrix<T> vnl_matrix<T>::extract (unsigned rowz, unsigned colz,
00757                                       unsigned top, unsigned left) const {
00758   vnl_matrix<T> result(rowz, colz);
00759   this->extract( result, top, left );
00760   return result;
00761 }
00762 
00763 template<class T>
00764 void vnl_matrix<T>::extract( vnl_matrix<T>& submatrix,
00765                              unsigned top, unsigned left) const {
00766   unsigned const rowz = submatrix.rows();
00767   unsigned const colz = submatrix.cols();
00768 #ifndef NDEBUG
00769   unsigned int bottom = top + rowz;
00770   unsigned int right = left + colz;
00771   if ((this->num_rows < bottom) || (this->num_cols < right))
00772     vnl_error_matrix_dimension ("extract",
00773                                 this->num_rows, this->num_cols, bottom, right);
00774 #endif
00775   for (unsigned int i = 0; i < rowz; i++)      // actual copy of all elements
00776     for (unsigned int j = 0; j < colz; j++)    // in submatrix
00777       submatrix.data[i][j] = data[top+i][left+j];
00778 }
00779 
00780 //: Returns the dot product of the two matrices. O(m*n).
00781 // This is the sum of all pairwise products of the elements m1[i,j]*m2[i,j].
00782 
00783 template<class T>
00784 T dot_product (vnl_matrix<T> const& m1, vnl_matrix<T> const& m2)
00785 {
00786 #ifndef NDEBUG
00787   if (m1.rows() != m2.rows() || m1.columns() != m2.columns()) // Size?
00788     vnl_error_matrix_dimension ("dot_product",
00789                                 m1.rows(), m1.columns(),
00790                                 m2.rows(), m2.columns());
00791 #endif
00792   return vnl_c_vector<T>::dot_product(m1.begin(), m2.begin(), m1.rows()*m1.cols());
00793 }
00794 
00795 //: Hermitian inner product.
00796 // O(mn).
00797 
00798 template<class T>
00799 T inner_product (vnl_matrix<T> const& m1, vnl_matrix<T> const& m2)
00800 {
00801 #ifndef NDEBUG
00802   if (m1.rows() != m2.rows() || m1.columns() != m2.columns()) // Size?
00803     vnl_error_matrix_dimension ("inner_product",
00804                                 m1.rows(), m1.columns(),
00805                                 m2.rows(), m2.columns());
00806 #endif
00807   return vnl_c_vector<T>::inner_product(m1.begin(), m2.begin(), m1.rows()*m1.cols());
00808 }
00809 
00810 // cos_angle. O(mn).
00811 
00812 template<class T>
00813 T cos_angle (vnl_matrix<T> const& a, vnl_matrix<T> const& b)
00814 {
00815   typedef typename vnl_numeric_traits<T>::abs_t Abs_t;
00816   typedef typename vnl_numeric_traits<Abs_t>::real_t abs_r;
00817 
00818   T ab = inner_product(a,b);
00819   Abs_t a_b = (Abs_t)vcl_sqrt( (abs_r)vnl_math_abs(inner_product(a,a) * inner_product(b,b)) );
00820 
00821   return T( ab / a_b);
00822 }
00823 
00824 //: Returns new matrix whose elements are the products m1[ij]*m2[ij].
00825 // O(m*n).
00826 
00827 template<class T>
00828 vnl_matrix<T> element_product (vnl_matrix<T> const& m1,
00829                                vnl_matrix<T> const& m2)
00830 {
00831 #ifndef NDEBUG
00832   if (m1.rows() != m2.rows() || m1.columns() != m2.columns()) // Size?
00833     vnl_error_matrix_dimension ("element_product",
00834                                 m1.rows(), m1.columns(), m2.rows(), m2.columns());
00835 #endif
00836   vnl_matrix<T> result(m1.rows(), m1.columns());
00837   for (unsigned int i = 0; i < m1.rows(); i++)
00838     for (unsigned int j = 0; j < m1.columns(); j++)
00839       result.put(i,j, T(m1.get(i,j) * m2.get(i,j)) );
00840   return result;
00841 }
00842 
00843 //: Returns new matrix whose elements are the quotients m1[ij]/m2[ij].
00844 // O(m*n).
00845 
00846 template<class T>
00847 vnl_matrix<T> element_quotient (vnl_matrix<T> const& m1,
00848                                 vnl_matrix<T> const& m2)
00849 {
00850 #ifndef NDEBUG
00851   if (m1.rows() != m2.rows() || m1.columns() != m2.columns()) // Size?
00852     vnl_error_matrix_dimension("element_quotient",
00853                                m1.rows(), m1.columns(), m2.rows(), m2.columns());
00854 #endif
00855   vnl_matrix<T> result(m1.rows(), m1.columns());
00856   for (unsigned int i = 0; i < m1.rows(); i++)
00857     for (unsigned int j = 0; j < m1.columns(); j++)
00858       result.put(i,j, T(m1.get(i,j) / m2.get(i,j)) );
00859   return result;
00860 }
00861 
00862 //: Fill this matrix with the given data.
00863 //  We assume that p points to a contiguous rows*cols array, stored rowwise.
00864 template<class T>
00865 void vnl_matrix<T>::copy_in(T const *p)
00866 {
00867   T* dp = this->data[0];
00868   unsigned int n = this->num_rows * this->num_cols;
00869   while (n--)
00870     *dp++ = *p++;
00871 }
00872 
00873 //: Fill the given array with this matrix.
00874 //  We assume that p points to a contiguous rows*cols array, stored rowwise.
00875 template<class T>
00876 void vnl_matrix<T>::copy_out(T *p) const
00877 {
00878   T* dp = this->data[0];
00879   unsigned int n = this->num_rows * this->num_cols;
00880   while (n--)
00881     *p++ = *dp++;
00882 }
00883 
00884 //: Fill this matrix with a row*row identity matrix.
00885 template<class T>
00886 void vnl_matrix<T>::set_identity()
00887 {
00888 #ifndef NDEBUG
00889   if (this->num_rows != this->num_cols) // Size?
00890     vnl_error_matrix_nonsquare ("set_identity");
00891 #endif
00892   for (unsigned int i = 0; i < this->num_rows; i++)    // For each row in the Matrix
00893     for (unsigned int j = 0; j < this->num_cols; j++)  // For each element in column
00894       if (i == j)
00895         this->data[i][j] = T(1);
00896       else
00897         this->data[i][j] = T(0);
00898 }
00899 
00900 //: Make each row of the matrix have unit norm.
00901 // All-zero rows are ignored.
00902 template<class T>
00903 void vnl_matrix<T>::normalize_rows()
00904 {
00905   typedef typename vnl_numeric_traits<T>::abs_t Abs_t;
00906   typedef typename vnl_numeric_traits<T>::real_t Real_t;
00907   typedef typename vnl_numeric_traits<Real_t>::abs_t abs_real_t;
00908   for (unsigned int i = 0; i < this->num_rows; i++) {  // For each row in the Matrix
00909     Abs_t norm(0); // double will not do for all types.
00910     for (unsigned int j = 0; j < this->num_cols; j++)  // For each element in row
00911       norm += vnl_math_squared_magnitude(this->data[i][j]);
00912 
00913     if (norm != 0) {
00914       abs_real_t scale = abs_real_t(1)/(vcl_sqrt((abs_real_t)norm));
00915       for (unsigned int j = 0; j < this->num_cols; j++)
00916         this->data[i][j] = T(Real_t(this->data[i][j]) * scale);
00917     }
00918   }
00919 }
00920 
00921 //: Make each column of the matrix have unit norm.
00922 // All-zero columns are ignored.
00923 template<class T>
00924 void vnl_matrix<T>::normalize_columns()
00925 {
00926   typedef typename vnl_numeric_traits<T>::abs_t Abs_t;
00927   typedef typename vnl_numeric_traits<T>::real_t Real_t;
00928   typedef typename vnl_numeric_traits<Real_t>::abs_t abs_real_t;
00929   for (unsigned int j = 0; j < this->num_cols; j++) {  // For each column in the Matrix
00930     Abs_t norm(0); // double will not do for all types.
00931     for (unsigned int i = 0; i < this->num_rows; i++)
00932       norm += vnl_math_squared_magnitude(this->data[i][j]);
00933 
00934     if (norm != 0) {
00935       abs_real_t scale = abs_real_t(1)/(vcl_sqrt((abs_real_t)norm));
00936       for (unsigned int i = 0; i < this->num_rows; i++)
00937         this->data[i][j] = T(Real_t(this->data[i][j]) * scale);
00938     }
00939   }
00940 }
00941 
00942 //: Multiply row[row_index] by value
00943 template<class T>
00944 void vnl_matrix<T>::scale_row(unsigned row_index, T value)
00945 {
00946 #ifndef NDEBUG
00947   if (row_index >= this->num_rows)
00948     vnl_error_matrix_row_index("scale_row", row_index);
00949 #endif
00950   for (unsigned int j = 0; j < this->num_cols; j++)    // For each element in row
00951     this->data[row_index][j] *= value;
00952 }
00953 
00954 //: Multiply column[column_index] by value
00955 template<class T>
00956 void vnl_matrix<T>::scale_column(unsigned column_index, T value)
00957 {
00958 #ifndef NDEBUG
00959   if (column_index >= this->num_cols)
00960     vnl_error_matrix_col_index("scale_column", column_index);
00961 #endif
00962   for (unsigned int j = 0; j < this->num_rows; j++)    // For each element in column
00963     this->data[j][column_index] *= value;
00964 }
00965 
00966 //: Returns a copy of n rows, starting from "row"
00967 template<class T>
00968 vnl_matrix<T> vnl_matrix<T>::get_n_rows (unsigned row, unsigned n) const
00969 {
00970 #ifndef NDEBUG
00971   if (row + n > this->num_rows)
00972     vnl_error_matrix_row_index ("get_n_rows", row);
00973 #endif
00974 
00975   // Extract data rowwise.
00976   return vnl_matrix<T>(data[row], n, this->num_cols);
00977 }
00978 
00979 //: Returns a copy of n columns, starting from "column".
00980 template<class T>
00981 vnl_matrix<T> vnl_matrix<T>::get_n_columns (unsigned column, unsigned n) const
00982 {
00983 #ifndef NDEBUG
00984   if (column + n > this->num_cols)
00985     vnl_error_matrix_col_index ("get_n_columns", column);
00986 #endif
00987 
00988   vnl_matrix<T> result(this->num_rows, n);
00989   for (unsigned int c = 0; c < n; ++c)
00990     for (unsigned int r = 0; r < this->num_rows; ++r)
00991       result(r, c) = data[r][column + c];
00992   return result;
00993 }
00994 
00995 //: Create a vector out of row[row_index].
00996 template<class T>
00997 vnl_vector<T> vnl_matrix<T>::get_row(unsigned row_index) const
00998 {
00999 #ifdef ERROR_CHECKING
01000   if (row_index >= this->num_rows)
01001     vnl_error_matrix_row_index ("get_row", row_index);
01002 #endif
01003 
01004   vnl_vector<T> v(this->num_cols);
01005   for (unsigned int j = 0; j < this->num_cols; j++)    // For each element in row
01006     v[j] = this->data[row_index][j];
01007   return v;
01008 }
01009 
01010 //: Create a vector out of column[column_index].
01011 template<class T>
01012 vnl_vector<T> vnl_matrix<T>::get_column(unsigned column_index) const
01013 {
01014 #ifdef ERROR_CHECKING
01015   if (column_index >= this->num_cols)
01016     vnl_error_matrix_col_index ("get_column", column_index);
01017 #endif
01018 
01019   vnl_vector<T> v(this->num_rows);
01020   for (unsigned int j = 0; j < this->num_rows; j++)    // For each element in row
01021     v[j] = this->data[j][column_index];
01022   return v;
01023 }
01024 
01025 //--------------------------------------------------------------------------------
01026 
01027 //: Set row[row_index] to data at given address. No bounds check.
01028 template<class T>
01029 void vnl_matrix<T>::set_row(unsigned row_index, T const *v)
01030 {
01031   for (unsigned int j = 0; j < this->num_cols; j++)    // For each element in row
01032     this->data[row_index][j] = v[j];
01033 }
01034 
01035 //: Set row[row_index] to given vector.
01036 template<class T>
01037 void vnl_matrix<T>::set_row(unsigned row_index, vnl_vector<T> const &v)
01038 {
01039 #ifndef NDEBUG
01040   if (v.size() != this->num_cols)
01041     vnl_error_vector_dimension ("vnl_matrix::set_row", v.size(), this->num_cols);
01042 #endif
01043   set_row(row_index,v.data_block());
01044 }
01045 
01046 //: Set row[row_index] to given value.
01047 template<class T>
01048 void vnl_matrix<T>::set_row(unsigned row_index, T v)
01049 {
01050   for (unsigned int j = 0; j < this->num_cols; j++)    // For each element in row
01051     this->data[row_index][j] = v;
01052 }
01053 
01054 //--------------------------------------------------------------------------------
01055 
01056 //: Set column[column_index] to data at given address.
01057 template<class T>
01058 void vnl_matrix<T>::set_column(unsigned column_index, T const *v)
01059 {
01060   for (unsigned int i = 0; i < this->num_rows; i++)    // For each element in row
01061     this->data[i][column_index] = v[i];
01062 }
01063 
01064 //: Set column[column_index] to given vector.
01065 template<class T>
01066 void vnl_matrix<T>::set_column(unsigned column_index, vnl_vector<T> const &v)
01067 {
01068 #ifndef NDEBUG
01069   if (v.size() != this->num_rows)
01070     vnl_error_vector_dimension ("vnl_matrix::set_column", v.size(), this->num_rows);
01071 #endif
01072   set_column(column_index,v.data_block());
01073 }
01074 
01075 //: Set column[column_index] to given value.
01076 template<class T>
01077 void vnl_matrix<T>::set_column(unsigned column_index, T v)
01078 {
01079   for (unsigned int j = 0; j < this->num_rows; j++)    // For each element in row
01080     this->data[j][column_index] = v;
01081 }
01082 
01083 
01084 //: Set columns starting at starting_column to given matrix
01085 template<class T>
01086 void vnl_matrix<T>::set_columns(unsigned starting_column, vnl_matrix<T> const& m)
01087 {
01088 #ifndef NDEBUG
01089   if (this->num_rows != m.num_rows ||
01090       this->num_cols < m.num_cols + starting_column)           // Size match?
01091     vnl_error_matrix_dimension ("set_columns",
01092                                 this->num_rows, this->num_cols,
01093                                 m.num_rows, m.num_cols);
01094 #endif
01095 
01096   for (unsigned int j = 0; j < m.num_cols; ++j)
01097     for (unsigned int i = 0; i < this->num_rows; i++)    // For each element in row
01098       this->data[i][starting_column + j] = m.data[i][j];
01099 }
01100 
01101 //--------------------------------------------------------------------------------
01102 
01103 //: Two matrices are equal if and only if they have the same dimensions and the same values.
01104 // O(m*n).
01105 // Elements are compared with operator== as default.
01106 // Change this default with set_compare() at run time or by specializing
01107 // vnl_matrix_compare at compile time.
01108 
01109 template<class T>
01110 bool vnl_matrix<T>::operator_eq(vnl_matrix<T> const& rhs) const
01111 {
01112   if (this == &rhs)                                      // same object => equal.
01113     return true;
01114 
01115   if (this->num_rows != rhs.num_rows || this->num_cols != rhs.num_cols)
01116     return false;                                        // different sizes => not equal.
01117 
01118   for (unsigned int i = 0; i < this->num_rows; i++)     // For each row
01119     for (unsigned int j = 0; j < this->num_cols; j++)   // For each columne
01120       if (!(this->data[i][j] == rhs.data[i][j]))            // different element ?
01121         return false;                                    // Then not equal.
01122 
01123   return true;                                           // Else same; return true
01124 }
01125 
01126 template <class T>
01127 bool vnl_matrix<T>::is_identity() const
01128 {
01129   T const zero(0);
01130   T const one(1);
01131   for (unsigned int i = 0; i < this->rows(); ++i)
01132     for (unsigned int j = 0; j < this->columns(); ++j) {
01133       T xm = (*this)(i,j);
01134       if ( !((i == j) ? (xm == one) : (xm == zero)) )
01135         return false;
01136     }
01137   return true;
01138 }
01139 
01140 //: Return true if maximum absolute deviation of M from identity is <= tol.
01141 template <class T>
01142 bool vnl_matrix<T>::is_identity(double tol) const
01143 {
01144   T one(1);
01145   for (unsigned int i = 0; i < this->rows(); ++i)
01146     for (unsigned int j = 0; j < this->columns(); ++j) {
01147       T xm = (*this)(i,j);
01148       abs_t absdev = (i == j) ? vnl_math_abs(xm - one) : vnl_math_abs(xm);
01149       if (absdev > tol)
01150         return false;
01151     }
01152   return true;
01153 }
01154 
01155 template <class T>
01156 bool vnl_matrix<T>::is_zero() const
01157 {
01158   T const zero(0);
01159   for (unsigned int i = 0; i < this->rows(); ++i)
01160     for (unsigned int j = 0; j < this->columns(); ++j)
01161       if ( !( (*this)(i, j) == zero) )
01162         return false;
01163 
01164   return true;
01165 }
01166 
01167 //: Return true if max(abs((*this))) <= tol.
01168 template <class T>
01169 bool vnl_matrix<T>::is_zero(double tol) const
01170 {
01171   for (unsigned int i = 0; i < this->rows(); ++i)
01172     for (unsigned int j = 0; j < this->columns(); ++j)
01173       if (vnl_math_abs((*this)(i,j)) > tol)
01174         return false;
01175 
01176   return true;
01177 }
01178 
01179 //: Return true if any element of (*this) is nan
01180 template <class T>
01181 bool vnl_matrix<T>::has_nans() const
01182 {
01183   for (unsigned int i = 0; i < this->rows(); ++i)
01184     for (unsigned int j = 0; j < this->columns(); ++j)
01185       if (vnl_math_isnan((*this)(i,j)))
01186         return true;
01187 
01188   return false;
01189 }
01190 
01191 //: Return false if any element of (*this) is inf or nan
01192 template <class T>
01193 bool vnl_matrix<T>::is_finite() const
01194 {
01195   for (unsigned int i = 0; i < this->rows(); ++i)
01196     for (unsigned int j = 0; j < this->columns(); ++j)
01197       if (!vnl_math_isfinite((*this)(i,j)))
01198         return false;
01199 
01200   return true;
01201 }
01202 
01203 //: Abort if any element of M is inf or nan
01204 template <class T>
01205 void vnl_matrix<T>::assert_finite_internal() const
01206 {
01207   if (is_finite())
01208     return;
01209 
01210   vcl_cerr << "\n\n" __FILE__ ": " << __LINE__ << ": matrix has non-finite elements\n";
01211 
01212   if (rows() <= 20 && cols() <= 20) {
01213     vcl_cerr << __FILE__ ": here it is:\n" << *this;
01214   }
01215   else {
01216     vcl_cerr << __FILE__ ": it is quite big (" << rows() << 'x' << cols() << ")\n"
01217              << __FILE__ ": in the following picture '-' means finite and '*' means non-finite:\n";
01218 
01219     for (unsigned int i=0; i<rows(); ++i) {
01220       for (unsigned int j=0; j<cols(); ++j)
01221         vcl_cerr << char(vnl_math_isfinite((*this)(i, j)) ? '-' : '*');
01222       vcl_cerr << '\n';
01223     }
01224   }
01225   vcl_cerr << __FILE__ ": calling abort()\n";
01226   vcl_abort();
01227 }
01228 
01229 //: Abort unless M has the given size.
01230 template <class T>
01231 void vnl_matrix<T>::assert_size_internal(unsigned rs,unsigned cs) const
01232 {
01233   if (this->rows()!=rs || this->cols()!=cs) {
01234     vcl_cerr << __FILE__ ": size is " << this->rows() << 'x' << this->cols()
01235              << ". should be " << rs << 'x' << cs << vcl_endl;
01236     vcl_abort();
01237   }
01238 }
01239 
01240 //: Read a vnl_matrix from an ascii vcl_istream.
01241 // Automatically determines file size if the input matrix has zero size.
01242 template <class T>
01243 bool vnl_matrix<T>::read_ascii(vcl_istream& s)
01244 {
01245   if (!s.good()) {
01246     vcl_cerr << __FILE__ ": vnl_matrix<T>::read_ascii: Called with bad stream\n";
01247     return false;
01248   }
01249 
01250   bool size_known = (this->rows() != 0);
01251 
01252   if (size_known) {
01253     for (unsigned int i = 0; i < this->rows(); ++i)
01254       for (unsigned int j = 0; j < this->columns(); ++j)
01255         s >> this->data[i][j];
01256 
01257     return s.good() || s.eof();
01258   }
01259 
01260   bool debug = false;
01261 
01262   vcl_vector<T> first_row_vals;
01263   if (debug)
01264     vcl_cerr << __FILE__ ": vnl_matrix<T>::read_ascii: Determining file dimensions: ";
01265 
01266   for (;;) {
01267     // Clear whitespace, looking for a newline
01268     while (true)
01269     {
01270       int c = s.get();
01271       if (c == EOF)
01272         goto loademup;
01273       if (!vcl_isspace(c)) {
01274         if (!s.putback(char(c)).good())
01275           vcl_cerr << "vnl_matrix<T>::read_ascii: Could not push back '" << c << "'\n";
01276 
01277         goto readfloat;
01278       }
01279       // First newline after first number tells us the column dimension
01280       if (c == '\n' && first_row_vals.size() > 0) {
01281         goto loademup;
01282       }
01283     }
01284   readfloat:
01285     T val;
01286     s >> val;
01287     if (!s.fail())
01288       first_row_vals.push_back(val);
01289     if (s.eof())
01290       goto loademup;
01291   }
01292  loademup:
01293   vcl_size_t colz = first_row_vals.size();
01294 
01295   if (debug) vcl_cerr << colz << " cols, ";
01296 
01297   if (colz == 0)
01298     return false;
01299 
01300   // need to be careful with resizing here as will often be reading humungous files
01301   // So let's just build an array of row pointers
01302   vcl_vector<T*> row_vals;
01303   row_vals.reserve(1000);
01304   {
01305     // Copy first row.  Can't use first_row_vals, as may be a vector of bool...
01306     T* row = vnl_c_vector<T>::allocate_T(colz);
01307     for (unsigned int k = 0; k < colz; ++k)
01308       row[k] = first_row_vals[k];
01309     row_vals.push_back(row);
01310   }
01311 
01312   while (true)
01313   {
01314     T* row = vnl_c_vector<T>::allocate_T(colz);
01315     if (row == 0) {
01316       vcl_cerr << "vnl_matrix<T>::read_ascii: Error, Out of memory on row "
01317                << row_vals.size() << vcl_endl;
01318       return false;
01319     }
01320     s >> row[0];
01321     if (!s.good())
01322     {
01323       vnl_c_vector<T>::deallocate(row, colz);
01324       break;
01325     }
01326     for (unsigned int k = 1; k < colz; ++k) {
01327       if (s.eof()) {
01328         vcl_cerr << "vnl_matrix<T>::read_ascii: Error, EOF on row "
01329                  << row_vals.size() << ", column " << k << vcl_endl;
01330 
01331         return false;
01332       }
01333       s >> row[k];
01334       if (s.fail()) {
01335         vcl_cerr << "vnl_matrix<T>::read_ascii: Error, row "
01336                  << row_vals.size() << " failed on column " << k << vcl_endl;
01337         return false;
01338       }
01339     }
01340     row_vals.push_back(row);
01341   }
01342 
01343   vcl_size_t rowz = row_vals.size();
01344 
01345   if (debug)
01346     vcl_cerr << rowz << " rows.\n";
01347 
01348   set_size(rowz, colz);
01349 
01350   T* p = this->data[0];
01351   for (unsigned int i = 0; i < rowz; ++i) {
01352     for (unsigned int j = 0; j < colz; ++j)
01353       *p++ = row_vals[i][j];
01354     /*if (i>0)*/ vnl_c_vector<T>::deallocate(row_vals[i], colz);
01355   }
01356 
01357   return true;
01358 }
01359 
01360 //: Read a vnl_matrix from an ascii vcl_istream.
01361 // Automatically determines file size if the input matrix has zero size.
01362 // This is a static method so you can type
01363 // <verb>
01364 // vnl_matrix<float> M = vnl_matrix<float>::read(cin);
01365 // </verb>
01366 // which many people prefer to the ">>" alternative.
01367 template <class T>
01368 vnl_matrix<T> vnl_matrix<T>::read(vcl_istream& s)
01369 {
01370   vnl_matrix<T> M;
01371   s >> M;
01372   return M;
01373 }
01374 
01375 template <class T>
01376 void vnl_matrix<T>::swap(vnl_matrix<T> &that)
01377 {
01378   vcl_swap(this->num_rows, that.num_rows);
01379   vcl_swap(this->num_cols, that.num_cols);
01380   vcl_swap(this->data, that.data);
01381 }
01382 
01383 //: Reverse order of rows.  Name is from Matlab, meaning "flip upside down".
01384 template <class T>
01385 void vnl_matrix<T>::flipud()
01386 {
01387   unsigned int n = this->rows();
01388   unsigned int colz = this->columns();
01389 
01390   unsigned int m = n / 2;
01391   for (unsigned int r = 0; r < m; ++r) {
01392     unsigned int r1 = r;
01393     unsigned int r2 = n - 1 - r;
01394     for (unsigned int c = 0; c < colz; ++c) {
01395       T tmp = (*this)(r1, c);
01396       (*this)(r1, c) = (*this)(r2, c);
01397       (*this)(r2, c) = tmp;
01398     }
01399   }
01400 }
01401 
01402 //: Reverse order of columns.
01403 template <class T>
01404 void vnl_matrix<T>::fliplr()
01405 {
01406   unsigned int n = this->cols();
01407   unsigned int rowz = this->rows();
01408 
01409   unsigned int m = n / 2;
01410   for (unsigned int c = 0; c < m; ++c) {
01411     unsigned int c1 = c;
01412     unsigned int c2 = n - 1 - c;
01413     for (unsigned int r = 0; r < rowz; ++r) {
01414       T tmp = (*this)(r, c1);
01415       (*this)(r, c1) = (*this)(r, c2);
01416       (*this)(r, c2) = tmp;
01417     }
01418   }
01419 }
01420 
01421 // || M ||  = \max \sum | M   |
01422 //        1     j    i     ij
01423 template <class T>
01424 typename vnl_matrix<T>::abs_t vnl_matrix<T>::operator_one_norm() const
01425 {
01426   abs_t max = 0;
01427   for (unsigned int j=0; j<this->num_cols; ++j) {
01428     abs_t tmp = 0;
01429     for (unsigned int i=0; i<this->num_rows; ++i)
01430       tmp += vnl_math_abs(this->data[i][j]);
01431     if (tmp > max)
01432       max = tmp;
01433   }
01434   return max;
01435 }
01436 
01437 // || M ||   = \max \sum | M   |
01438 //        oo     i    j     ij
01439 template <class T>
01440 typename vnl_matrix<T>::abs_t vnl_matrix<T>::operator_inf_norm() const
01441 {
01442   abs_t max = 0;
01443   for (unsigned int i=0; i<this->num_rows; ++i) {
01444     abs_t tmp = 0;
01445     for (unsigned int j=0; j<this->num_cols; ++j)
01446       tmp += vnl_math_abs(this->data[i][j]);
01447     if (tmp > max)
01448       max = tmp;
01449   }
01450   return max;
01451 }
01452 
01453 template <class doublereal>              // ideally, char* should be bool* - PVr
01454 int vnl_inplace_transpose(doublereal *a, unsigned m, unsigned n, char* move, unsigned iwrk)
01455 {
01456   doublereal b, c;
01457   int k = m * n - 1;
01458   int iter, i1, i2, im, i1c, i2c, ncount, max_;
01459 
01460 // *****
01461 //  ALGORITHM 380 - REVISED
01462 // *****
01463 //  A IS A ONE-DIMENSIONAL ARRAY OF LENGTH MN=M*N, WHICH
01464 //  CONTAINS THE MXN MATRIX TO BE TRANSPOSED (STORED
01465 //  COLUMNWISE). MOVE IS A ONE-DIMENSIONAL ARRAY OF LENGTH IWRK
01466 //  USED TO STORE INFORMATION TO SPEED UP THE PROCESS.  THE
01467 //  VALUE IWRK=(M+N)/2 IS RECOMMENDED. IOK INDICATES THE
01468 //  SUCCESS OR FAILURE OF THE ROUTINE.
01469 //  NORMAL RETURN  IOK=0
01470 //  ERRORS         IOK=-2 ,IWRK NEGATIVE OR ZERO
01471 //                 IOK.GT.0, (SHOULD NEVER OCCUR),IN THIS CASE
01472 //  WE SET IOK EQUAL TO THE FINAL VALUE OF ITER WHEN THE SEARCH
01473 //  IS COMPLETED BUT SOME LOOPS HAVE NOT BEEN MOVED
01474 //  NOTE * MOVE(I) WILL STAY ZERO FOR FIXED POINTS
01475 
01476   if (m < 2 || n < 2)
01477     return 0; // JUST RETURN IF MATRIX IS SINGLE ROW OR COLUMN
01478   if (iwrk < 1)
01479     return -2; // ERROR RETURN
01480   if (m == n) {
01481     // IF MATRIX IS SQUARE, EXCHANGE ELEMENTS A(I,J) AND A(J,I).
01482     for (unsigned i = 0; i < n; ++i)
01483     for (unsigned j = i+1; j < n; ++j) {
01484       i1 = i + j * n;
01485       i2 = j + i * m;
01486       b = a[i1];
01487       a[i1] = a[i2];
01488       a[i2] = b;
01489     }
01490     return 0; // NORMAL RETURN
01491   }
01492   ncount = 2;
01493   for (unsigned i = 0; i < iwrk; ++i)
01494     move[i] = char(0); // false;
01495   if (m > 2 && n > 2) {
01496     // CALCULATE THE NUMBER OF FIXED POINTS, EUCLIDS ALGORITHM FOR GCD(M-1,N-1).
01497     int ir2 = m - 1;
01498     int ir1 = n - 1;
01499     int ir0 = ir2 % ir1;
01500     while (ir0 != 0) {
01501       ir2 = ir1;
01502       ir1 = ir0;
01503       ir0 = ir2 % ir1;
01504     }
01505     ncount += ir1 - 1;
01506   }
01507 // SET INITIAL VALUES FOR SEARCH
01508   iter = 1;
01509   im = m;
01510 // AT LEAST ONE LOOP MUST BE RE-ARRANGED
01511   goto L80;
01512 // SEARCH FOR LOOPS TO REARRANGE
01513 L40:
01514   max_ = k - iter;
01515   ++iter;
01516   if (iter > max_)
01517     return iter; // error return
01518   im += m;
01519   if (im > k)
01520     im -= k;
01521   i2 = im;
01522   if (iter == i2)
01523     goto L40;
01524   if (iter <= (int)iwrk) {
01525     if (move[iter-1])
01526       goto L40;
01527     else
01528       goto L80;
01529   }
01530   while (i2 > iter && i2 < max_) {
01531     i1 = i2;
01532     i2 = m * i1 - k * (i1 / n);
01533   }
01534   if (i2 != iter)
01535     goto L40;
01536 // REARRANGE THE ELEMENTS OF A LOOP AND ITS COMPANION LOOP
01537 L80:
01538   i1 = iter;
01539   b = a[i1];
01540   i1c = k - iter;
01541   c = a[i1c];
01542   while (true) {
01543     i2 = m * i1 - k * (i1 / n);
01544     i2c = k - i2;
01545     if (i1 <= (int)iwrk)
01546       move[i1-1] = '1'; // true;
01547     if (i1c <= (int)iwrk)
01548       move[i1c-1] = '1'; // true;
01549     ncount += 2;
01550     if (i2 == iter)
01551       break;
01552     if (i2+iter == k) {
01553       doublereal d = b; b = c; c = d; // interchange b and c
01554       break;
01555     }
01556     a[i1] = a[i2];
01557     a[i1c] = a[i2c];
01558     i1 = i2;
01559     i1c = i2c;
01560   }
01561 // FINAL STORE AND TEST FOR FINISHED
01562   a[i1] = b;
01563   a[i1c] = c;
01564   if (ncount > k)
01565     return 0; // NORMAL RETURN
01566   goto L40;
01567 } /* dtrans_ */
01568 
01569 
01570 //: Transpose matrix M in place.
01571 //  Works for rectangular matrices using an enormously clever algorithm from ACM TOMS.
01572 template <class T>
01573 void vnl_matrix<T>::inplace_transpose()
01574 {
01575   unsigned m = rows();
01576   unsigned n = columns();
01577   unsigned iwrk = (m+n)/2;
01578   vcl_vector<char> move(iwrk);
01579 
01580   int iok = ::vnl_inplace_transpose(data_block(), n, m, &move[0], iwrk);
01581   if (iok != 0)
01582     vcl_cerr << __FILE__ " : inplace_transpose() -- iok = " << iok << vcl_endl;
01583 
01584   this->num_rows = n;
01585   this->num_cols = m;
01586 
01587   // row pointers. we have to reallocate even when n<=m because
01588   // vnl_c_vector<T>::deallocate needs to know n_when_allocatod.
01589   {
01590     T *tmp = data[0];
01591     vnl_c_vector<T>::deallocate(data, m);
01592     data = vnl_c_vector<T>::allocate_Tptr(n);
01593     for (unsigned i=0; i<n; ++i)
01594       data[i] = tmp + i * m;
01595   }
01596 }
01597 
01598 //------------------------------------------------------------------------------
01599 
01600 #define VNL_MATRIX_INSTANTIATE(T) \
01601 template class vnl_matrix<T >; \
01602 template vnl_matrix<T > operator-(T const &, vnl_matrix<T > const &); \
01603 VCL_INSTANTIATE_INLINE(vnl_matrix<T > operator+(T const &, vnl_matrix<T > const &)); \
01604 VCL_INSTANTIATE_INLINE(vnl_matrix<T > operator*(T const &, vnl_matrix<T > const &)); \
01605 template T dot_product(vnl_matrix<T > const &, vnl_matrix<T > const &); \
01606 template T inner_product(vnl_matrix<T > const &, vnl_matrix<T > const &); \
01607 template T cos_angle(vnl_matrix<T > const &, vnl_matrix<T > const &); \
01608 template vnl_matrix<T > element_product(vnl_matrix<T > const &, vnl_matrix<T > const &); \
01609 template vnl_matrix<T > element_quotient(vnl_matrix<T > const &, vnl_matrix<T > const &); \
01610 template int vnl_inplace_transpose(T*, unsigned, unsigned, char*, unsigned); \
01611 template vcl_ostream & operator<<(vcl_ostream &, vnl_matrix<T > const &); \
01612 template vcl_istream & operator>>(vcl_istream &, vnl_matrix<T >       &)
01613 
01614 #endif // vnl_matrix_txx_

Generated on Mon Mar 8 05:06:45 2010 for core/vnl by  doxygen 1.5.1