core/vnl/vnl_matrix_fixed.h

Go to the documentation of this file.
00001 // This is core/vnl/vnl_matrix_fixed.h
00002 #ifndef vnl_matrix_fixed_h_
00003 #define vnl_matrix_fixed_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief fixed size matrix
00010 //
00011 // \author Andrew W. Fitzgibbon, Oxford RRG
00012 // \date   04 Aug 96
00013 //
00014 // \verbatim
00015 //  Modifications
00016 //   Peter Vanroose, 23 Nov 1996:  added explicit copy constructor
00017 //   LSB (Manchester) 15/03/2001:  added Binary I/O and tidied up the documentation
00018 //   Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
00019 //   Oct.2002 - Amitha Perera  - separated vnl_matrix and vnl_matrix_fixed,
00020 //                               removed necessity for vnl_matrix_fixed_ref
00021 //   Oct.2002 - Peter Vanroose - added inplace_transpose() method
00022 //   Jul.2003 - Paul Smyth     - fixed end() bug, made op*=() more general
00023 //   Mar.2009 - Peter Vanroose - added arg_min() and arg_max()
00024 // \endverbatim
00025 //-----------------------------------------------------------------------------
00026 
00027 #include <vcl_cstring.h> // memcpy()
00028 #include <vcl_cassert.h>
00029 #include <vcl_iosfwd.h>
00030 
00031 #include "vnl_matrix.h"
00032 #include "vnl_matrix_ref.h"
00033 #include <vnl/vnl_vector.h>
00034 #include <vnl/vnl_c_vector.h>
00035 #include <vnl/vnl_config.h> // for VNL_CONFIG_CHECK_BOUNDS
00036 
00037 export template <class T, unsigned int n> class vnl_vector_fixed;
00038 export template <class T, unsigned int num_rows, unsigned int num_cols> class vnl_matrix_fixed;
00039 
00040 // This mess is for a MSVC6 workaround.
00041 //
00042 // The problem: the matrix-matrix operator* should be written as a
00043 // non-member function since vxl (currently) forbits the use of member
00044 // templates. However, when declared as
00045 //
00046 //     template <class T, unsigned m, unsigned n, unsigned o>
00047 //     matrix<T,m,o> operator*( matrix<T,m,n>, matrix<T,n,o> );
00048 //
00049 // MSVC6 does not find it. A solution is to declare it as a member
00050 // template. However, the obvious
00051 //
00052 //     template <unsigned o>
00053 //     matrix<T,num_rows,o> operator*( matrix<T,num_cols,o> );
00054 //
00055 // causes an internal compiler error. It turns out that if the new
00056 // template parameter "o" comes _first_, then all is okay. Now, we
00057 // can't change the signature of vnl_matrix_fixed to <unsigned num_cols,
00058 // unsigned num_rows, type>, so we use a "hidden" helper matrix. Except
00059 // that user defined conversion operators and conversion constructors
00060 // are not called for templated functions. So we have to use a helper
00061 // base class. The base class is empty, which means that there is no
00062 // loss in space or time efficiency. Finally, we have:
00063 //
00064 //   template <unsigned num_cols, unsigned num_rows, class T>
00065 //   class fake_base { };
00066 //
00067 //   template <class T, unsigned num_rows, unsigned num_cols>
00068 //   class matrix : public fake_base<num_cols,num_rows,T>
00069 //   {
00070 //      template <unsigned o>
00071 //      matrix<T,num_rows,o>  operator*( fake_base<o,num_cols,T> );
00072 //   };
00073 //
00074 // Notice how "o" is first in the list of template parameters. Since
00075 // base class conversions _are_ performed during template matching,
00076 // matrix<T,m,n> is matched as fake_base<n,m,T>, and all is good. For
00077 // some values of good.
00078 //
00079 // Of course, all this trickery is pre-processed away for conforming
00080 // compilers.
00081 //
00082 template <class T, unsigned int num_rows, unsigned int num_cols>
00083 class vnl_matrix_fixed;
00084 template <class T, unsigned M, unsigned N>
00085 inline
00086 vnl_vector_fixed<T, M> vnl_matrix_fixed_mat_vec_mult(const vnl_matrix_fixed<T, M, N>& a, const vnl_vector_fixed<T, N>& b);
00087 template <class T, unsigned M, unsigned N, unsigned O>
00088 inline
00089 vnl_matrix_fixed<T, M, O> vnl_matrix_fixed_mat_mat_mult(const vnl_matrix_fixed<T, M, N>& a, const vnl_matrix_fixed<T, N, O>& b);
00090 #ifdef VCL_VC_6
00091 template <unsigned num_cols, unsigned num_rows, class T>
00092 class vnl_matrix_fixed_fake_base
00093 {
00094 };
00095 
00096 #define VNL_MATRIX_FIXED_VCL60_WORKAROUND : public vnl_matrix_fixed_fake_base<num_cols,num_rows,T>
00097 #else
00098 #define VNL_MATRIX_FIXED_VCL60_WORKAROUND /* no workaround. Phew. */
00099 #endif
00100 
00101 //: Fixed size, stack-stored, space-efficient matrix.
00102 // vnl_matrix_fixed is a fixed-length, stack storage vector. It has
00103 // the same storage size as a C-style array. It is not related via
00104 // inheritance to vnl_matrix. However, it can be converted cheaply to
00105 // a vnl_matrix_ref.
00106 //
00107 // Read the overview documentation of vnl_vector_fixed. The text there
00108 // applies here.
00109 template <class T, unsigned int num_rows, unsigned int num_cols>
00110 class vnl_matrix_fixed  VNL_MATRIX_FIXED_VCL60_WORKAROUND
00111 {
00112  public:
00113   typedef vnl_matrix_fixed<T,num_rows,num_cols> self;
00114   typedef unsigned int size_type;
00115 
00116  private:
00117   T data_[num_rows][num_cols]; // Local storage
00118 
00119  public:
00120 
00121   //: Construct an empty num_rows*num_cols matrix
00122   vnl_matrix_fixed() {}
00123 
00124   //: Construct an empty num_rows*num_cols matrix
00125   //
00126   // The sole purpose of this constructor is to match the interface of
00127   // vnl_matrix, so that algorithms can template over the matrix type
00128   // itself.  It is illegal to call this constructor without
00129   // <tt>n==num_rows</tt> and <tt>m==num_cols</tt>.
00130   vnl_matrix_fixed( unsigned n, unsigned m )
00131   {
00132     assert( n == num_rows && m == num_cols );
00133   }
00134 
00135   //: Construct an m*n matrix and fill with value
00136   explicit vnl_matrix_fixed(T value)
00137   {
00138     T* p = data_[0];
00139     unsigned int n = num_rows * num_cols;
00140     while (n--)
00141       *p++ = value;
00142   }
00143 
00144   //: Construct an m*n Matrix and copy data into it row-wise.
00145   explicit vnl_matrix_fixed(const T* datablck)
00146   {
00147     vcl_memcpy(data_[0], datablck, num_rows*num_cols*sizeof(T));
00148   }
00149 
00150   //: Construct an m*n Matrix and copy rhs into it.
00151   //  Abort if rhs is not the same size.
00152   vnl_matrix_fixed(const vnl_matrix_fixed& rhs)
00153   {
00154     vcl_memcpy(data_[0], rhs.data_block(), num_rows*num_cols*sizeof(T));
00155   }
00156 
00157   //: Construct an m*n Matrix and copy rhs into it.
00158   //  Abort if rhs is not the same size.
00159   vnl_matrix_fixed(const vnl_matrix<T>& rhs)
00160   {
00161     assert(rhs.rows() == num_rows && rhs.columns() == num_cols);
00162     vcl_memcpy(data_[0], rhs.data_block(), num_rows*num_cols*sizeof(T));
00163   }
00164 
00165   //  Destruct the m*n matrix.
00166   // An explicit destructor seems to be necessary, at least for gcc 3.0.0,
00167   // to avoid the compiler generating multiple versions of it.
00168   // (This way, a weak symbol is generated; otherwise not.  A bug of gcc 3.0.)
00169   ~vnl_matrix_fixed() {}
00170 
00171   //: Set all elements to value v
00172   // Complexity $O(r.c)$
00173   vnl_matrix_fixed& operator= (T const&v) { fill(v); return *this; }
00174 
00175   //: Copy a vnl_matrix into this.
00176   //  Abort if rhs is not the same size.
00177   vnl_matrix_fixed& operator=(const vnl_matrix<T>& rhs)
00178   {
00179     assert(rhs.rows() == num_rows && rhs.columns() == num_cols);
00180     vcl_memcpy(data_[0], rhs.data_block(), num_rows*num_cols*sizeof(T));
00181     return *this;
00182   }
00183 
00184   //: Copy another vnl_matrix_fixed<T,m,n> into this.
00185   vnl_matrix_fixed& operator=(const vnl_matrix_fixed& rhs)
00186   {
00187     vcl_memcpy(data_[0], rhs.data_block(), num_rows*num_cols*sizeof(T));
00188     return *this;
00189   }
00190 
00191 // Basic 2D-Array functionality-------------------------------------------
00192 
00193   //: Return number of rows
00194   unsigned rows()    const { return num_rows; }
00195 
00196   //: Return number of columns
00197   // A synonym for cols()
00198   unsigned columns()  const { return num_cols; }
00199 
00200   //: Return number of columns
00201   // A synonym for columns()
00202   unsigned cols()    const { return num_cols; }
00203 
00204   //: Return number of elements
00205   // This equals rows() * cols()
00206   unsigned size()    const { return num_rows*num_cols; }
00207 
00208   //: set element
00209   void put (unsigned r, unsigned c, T const& v) { (*this)(r,c) = v; }
00210 
00211   //: get element
00212   T    get (unsigned r, unsigned c) const { return (*this)(r,c); }
00213 
00214   //: return pointer to given row
00215   // No boundary checking here.
00216   T       * operator[] (unsigned r) { return data_[r]; }
00217 
00218   //: return pointer to given row
00219   // No boundary checking here.
00220   T const * operator[] (unsigned r) const { return data_[r]; }
00221 
00222   //: Access an element for reading or writing
00223   // There are assert style boundary checks - #define NDEBUG to turn them off.
00224   T       & operator() (unsigned r, unsigned c)
00225   {
00226 #if VNL_CONFIG_CHECK_BOUNDS  && (!defined NDEBUG)
00227     assert(r<rows());   // Check the row index is valid
00228     assert(c<cols());   // Check the column index is valid
00229 #endif
00230     return this->data_[r][c];
00231   }
00232 
00233   //: Access an element for reading
00234   // There are assert style boundary checks - #define NDEBUG to turn them off.
00235   T const & operator() (unsigned r, unsigned c) const
00236   {
00237 #if VNL_CONFIG_CHECK_BOUNDS  && (!defined NDEBUG)
00238     assert(r<rows());   // Check the row index is valid
00239     assert(c<cols());   // Check the column index is valid
00240 #endif
00241     return this->data_[r][c];
00242   }
00243 
00244 // Filling and copying------------------------------------------------
00245 
00246   //: Set all elements of matrix to specified value.
00247   // Complexity $O(r.c)$
00248   void fill (T);
00249 
00250   //: Set all diagonal elements of matrix to specified value.
00251   // Complexity $O(\min(r,c))$
00252   void fill_diagonal (T);
00253 
00254   //: Fill (laminate) this matrix with the given data.
00255   // We assume that p points to a contiguous rows*cols array, stored rowwise.
00256   void copy_in(T const *);
00257 
00258   //: Fill (laminate) this matrix with the given data.
00259   // A synonym for copy_in()
00260   void set(T const *d) { copy_in(d); }
00261 
00262   //: Fill the given array with this matrix.
00263   // We assume that p points to
00264   // a contiguous rows*cols array, stored rowwise.
00265   // No bounds checking on the array
00266   void copy_out(T *) const;
00267 
00268   //: Transpose this matrix efficiently, if it is a square matrix
00269   void inplace_transpose();
00270 
00271 
00272 // Arithmetic ----------------------------------------------------
00273   // note that these functions should not pass scalar as a const&.
00274   // Look what would happen to A /= A(0,0).
00275 
00276   //: Add \a s to each element of lhs matrix in situ
00277   vnl_matrix_fixed& operator+= (T s)
00278   {
00279     self::add( data_block(), s, data_block() ); return *this;
00280   }
00281 
00282   //: Subtract \a s from each element of lhs matrix in situ
00283   vnl_matrix_fixed& operator-= (T s)
00284   {
00285     self::sub( data_block(), s, data_block() ); return *this;
00286   }
00287 
00288   //:
00289   vnl_matrix_fixed& operator*= (T s)
00290   {
00291     self::mul( data_block(), s, data_block() ); return *this;
00292   }
00293 
00294   //:
00295   vnl_matrix_fixed& operator/= (T s)
00296   {
00297     self::div( data_block(), s, data_block() ); return *this;
00298   }
00299 
00300   //:
00301   vnl_matrix_fixed& operator+= (vnl_matrix_fixed const& m)
00302   {
00303     self::add( data_block(), m.data_block(), data_block() ); return *this;
00304   }
00305 
00306   //:
00307   vnl_matrix_fixed& operator+= (vnl_matrix<T> const& m)
00308   {
00309     assert( m.rows() == rows() && m.cols() == cols() );
00310     self::add( data_block(), m.data_block(), data_block() ); return *this;
00311   }
00312 
00313   //:
00314   vnl_matrix_fixed& operator-= (vnl_matrix_fixed const& m)
00315   {
00316     self::sub( data_block(), m.data_block(), data_block() ); return *this;
00317   }
00318 
00319   //:
00320   vnl_matrix_fixed& operator-= (vnl_matrix<T> const& m)
00321   {
00322     assert( m.rows() == rows() && m.cols() == cols() );
00323     self::sub( data_block(), m.data_block(), data_block() );
00324     return *this;
00325   }
00326 
00327   //: Negate all elements of matrix
00328   vnl_matrix_fixed operator- () const
00329   {
00330     vnl_matrix_fixed r;
00331     self::sub( T(0), data_block(), r.data_block() );
00332     return r;
00333   }
00334 
00335   //:
00336   vnl_matrix_fixed& operator*= (vnl_matrix_fixed<T,num_cols,num_cols> const& s)
00337   {
00338     vnl_matrix_fixed<T, num_rows, num_cols> out;
00339     for (unsigned i = 0; i < num_rows; ++i)
00340       for (unsigned j = 0; j < num_cols; ++j)
00341       {
00342         T accum = this->data_[i][0] * s(0,j);
00343         for (unsigned k = 1; k < num_cols; ++k)
00344           accum += this->data_[i][k] * s(k,j);
00345         out(i,j) = accum;
00346       }
00347     return *this = out;
00348   }
00349 
00350 #ifdef VCL_VC_6
00351   template <unsigned o>
00352   vnl_matrix_fixed<T,num_rows,o> operator*( vnl_matrix_fixed_fake_base<o,num_cols,T> const& mat ) const
00353   {
00354     vnl_matrix_fixed<T,num_cols,o> const& b = static_cast<vnl_matrix_fixed<T,num_cols,o> const&>(mat);
00355     return vnl_matrix_fixed_mat_mat_mult<T,num_rows,num_cols,o>( *this, b );
00356   }
00357   vnl_vector_fixed<T, num_rows> operator*( vnl_vector_fixed<T, num_cols> const& b) const
00358   {
00359     return vnl_matrix_fixed_mat_vec_mult<T,num_rows,num_cols>(*this,b);
00360   }
00361 #endif
00362 
00363   ////--------------------------- Additions ----------------------------
00364 
00365   //: Make a new matrix by applying function to each element.
00366   vnl_matrix_fixed apply(T (*f)(T)) const;
00367 
00368   //: Make a new matrix by applying function to each element.
00369   vnl_matrix_fixed apply(T (*f)(T const&)) const;
00370 
00371   //: Return transpose
00372   vnl_matrix_fixed<T,num_cols,num_rows> transpose () const;
00373 
00374   //: Return conjugate transpose
00375   vnl_matrix_fixed<T,num_cols,num_rows> conjugate_transpose () const;
00376 
00377   //: Set values of this matrix to those of M, starting at [top,left]
00378   vnl_matrix_fixed& update (vnl_matrix<T> const&, unsigned top=0, unsigned left=0);
00379 
00380   //: Set the elements of the i'th column to v[j]  (No bounds checking)
00381   void set_column(unsigned i, T const * v);
00382 
00383   //: Set the elements of the i'th column to value
00384   void set_column(unsigned i, T value );
00385 
00386   //: Set j-th column to v
00387   void set_column(unsigned j, vnl_vector<T> const& v);
00388 
00389   //: Set j-th column to v
00390   void set_column(unsigned j, vnl_vector_fixed<T,num_rows> const& v);
00391 
00392   //: Set columns to those in M, starting at starting_column
00393   void set_columns(unsigned starting_column, vnl_matrix<T> const& M);
00394 
00395   //: Set the elements of the i'th row to v[j]  (No bounds checking)
00396   void set_row   (unsigned i, T const * v);
00397 
00398   //: Set the elements of the i'th row to value
00399   void set_row   (unsigned i, T value );
00400 
00401   //: Set the i-th row
00402   void set_row   (unsigned i, vnl_vector<T> const&);
00403 
00404   //: Set the i-th row
00405   void set_row   (unsigned i, vnl_vector_fixed<T,num_cols> const&);
00406 
00407   //: Extract a sub-matrix of size r x c, starting at (top,left)
00408   //  Thus it contains elements  [top,top+r-1][left,left+c-1]
00409   vnl_matrix<T> extract (unsigned r,  unsigned c,
00410                          unsigned top=0, unsigned left=0) const;
00411 
00412   //: Extract a sub-matrix starting at (top,left)
00413   //
00414   //  The output is stored in \a sub_matrix, and it should have the
00415   //  required size on entry.  Thus the result will contain elements
00416   //  [top,top+sub_matrix.rows()-1][left,left+sub_matrix.cols()-1]
00417   void extract ( vnl_matrix<T>& sub_matrix,
00418                  unsigned top=0, unsigned left=0) const;
00419 
00420   //: Get a vector equal to the given row
00421   vnl_vector_fixed<T,num_cols> get_row   (unsigned row) const;
00422 
00423   //: Get a vector equal to the given column
00424   vnl_vector_fixed<T,num_rows> get_column(unsigned col) const;
00425 
00426   //: Get n rows beginning at rowstart
00427   vnl_matrix<T> get_n_rows   (unsigned rowstart, unsigned n) const;
00428 
00429   //: Get n columns beginning at colstart
00430   vnl_matrix<T> get_n_columns(unsigned colstart, unsigned n) const;
00431 
00432 
00433   // mutators
00434 
00435   //: Set this matrix to an identity matrix
00436   //  Abort if the matrix is not square
00437   void set_identity();
00438 
00439   //: Reverse order of rows.
00440   void flipud();
00441 
00442   //: Reverse order of columns.
00443   void fliplr();
00444 
00445   //: Normalize each row so it is a unit vector
00446   //  Zero rows are ignored
00447   void normalize_rows();
00448 
00449   //: Normalize each column so it is a unit vector
00450   //  Zero columns are ignored
00451   void normalize_columns();
00452 
00453   //: Scale elements in given row by a factor of T
00454   void scale_row   (unsigned row, T value);
00455 
00456   //: Scale elements in given column by a factor of T
00457   void scale_column(unsigned col, T value);
00458 
00459   //: Type def for norms.
00460   typedef typename vnl_c_vector<T>::abs_t abs_t;
00461 
00462   //: Return sum of absolute values of elements
00463   abs_t array_one_norm() const { return vnl_c_vector<T>::one_norm(begin(), size()); }
00464 
00465   //: Return square root of sum of squared absolute element values
00466   abs_t array_two_norm() const { return vnl_c_vector<T>::two_norm(begin(), size()); }
00467 
00468   //: Return largest absolute element value
00469   abs_t array_inf_norm() const { return vnl_c_vector<T>::inf_norm(begin(), size()); }
00470 
00471   //: Return sum of absolute values of elements
00472   abs_t absolute_value_sum() const { return array_one_norm(); }
00473 
00474   //: Return largest absolute value
00475   abs_t absolute_value_max() const { return array_inf_norm(); }
00476 
00477   // $ || M ||_1 := \max_j \sum_i | M_{ij} | $
00478   abs_t operator_one_norm() const;
00479 
00480   // $ || M ||_\inf := \max_i \sum_j | M_{ij} | $
00481   abs_t operator_inf_norm() const;
00482 
00483   //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements)
00484   abs_t frobenius_norm() const { return vnl_c_vector<T>::two_norm(begin(), size()); }
00485 
00486   //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements)
00487   abs_t fro_norm() const { return frobenius_norm(); }
00488 
00489   //: Return RMS of all elements
00490   abs_t rms() const { return vnl_c_vector<T>::rms_norm(begin(), size()); }
00491 
00492   //: Return minimum value of elements
00493   T min_value() const { return vnl_c_vector<T>::min_value(begin(), size()); }
00494 
00495   //: Return maximum value of elements
00496   T max_value() const { return vnl_c_vector<T>::max_value(begin(), size()); }
00497 
00498   //: Return location of minimum value of elements
00499   unsigned arg_min() const { return vnl_c_vector<T>::arg_min(begin(), size()); }
00500 
00501   //: Return location of maximum value of elements
00502   unsigned arg_max() const { return vnl_c_vector<T>::arg_max(begin(), size()); }
00503 
00504   //: Return mean of all matrix elements
00505   T mean() const { return vnl_c_vector<T>::mean(begin(), size()); }
00506 
00507   // predicates
00508 
00509   //: Return true iff the size is zero.
00510   bool empty() const { return num_rows==0 && num_cols==0; }
00511 
00512   //:  Return true if all elements equal to identity.
00513   bool is_identity() const;
00514 
00515   //:  Return true if all elements equal to identity, within given tolerance
00516   bool is_identity(double tol) const;
00517 
00518   //: Return true if all elements equal to zero.
00519   bool is_zero() const;
00520 
00521   //: Return true if all elements equal to zero, within given tolerance
00522   bool is_zero(double tol) const;
00523 
00524   //: Return true if finite
00525   bool is_finite() const;
00526 
00527   //: Return true if matrix contains NaNs
00528   bool has_nans() const;
00529 
00530   //: abort if size is not as expected
00531   // This function does or tests nothing if NDEBUG is defined
00532   void assert_size(unsigned nr_rows, unsigned nr_cols) const
00533   {
00534 #ifndef NDEBUG
00535     assert_size_internal(nr_rows, nr_cols);
00536 #endif
00537   }
00538 
00539   //: abort if matrix contains any INFs or NANs.
00540   // This function does or tests nothing if NDEBUG is defined
00541   void assert_finite() const
00542   {
00543 #ifndef NDEBUG
00544     assert_finite_internal();
00545 #endif
00546   }
00547 
00548   ////----------------------- Input/Output ----------------------------
00549 
00550   // : Read a vnl_matrix from an ascii vcl_istream, automatically determining file size if the input matrix has zero size.
00551   bool read_ascii(vcl_istream& s);
00552 
00553   //--------------------------------------------------------------------------------
00554 
00555   //: Access the contiguous block storing the elements in the matrix row-wise. O(1).
00556   // 1d array, row-major order.
00557   T const* data_block () const { return data_[0]; }
00558 
00559   //: Access the contiguous block storing the elements in the matrix row-wise. O(1).
00560   // 1d array, row-major order.
00561   T      * data_block () { return data_[0]; }
00562 
00563 
00564   //----------------------------------------------------------------------
00565   // Conversion to vnl_matrix_ref.
00566 
00567   // The const version of as_ref should return a const vnl_matrix_ref
00568   // so that the vnl_matrix_ref::non_const() cannot be used on
00569   // it. This prevents a const vnl_matrix_fixed from being cast into a
00570   // non-const vnl_matrix reference, giving a slight increase in type safety.
00571 
00572   //: Explicit conversion to a vnl_matrix_ref.
00573   // This is a cheap conversion for those functions that have an interface
00574   // for vnl_matrix but not for vnl_matrix_fixed. There is also a
00575   // conversion operator that should work most of the time.
00576   // \sa vnl_matrix_ref::non_const
00577   vnl_matrix_ref<T> as_ref() { return vnl_matrix_ref<T>( num_rows, num_cols, data_block() ); }
00578 
00579   //: Explicit conversion to a vnl_matrix_ref.
00580   // This is a cheap conversion for those functions that have an interface
00581   // for vnl_matrix but not for vnl_matrix_fixed. There is also a
00582   // conversion operator that should work most of the time.
00583   // \sa vnl_matrix_ref::non_const
00584   const vnl_matrix_ref<T> as_ref() const { return vnl_matrix_ref<T>( num_rows, num_cols, const_cast<T*>(data_block()) ); }
00585 
00586   //: Cheap conversion to vnl_matrix_ref
00587   // Sometimes, such as with templated functions, the compiler cannot
00588   // use this user-defined conversion. For those cases, use the
00589   // explicit as_ref() method instead.
00590   operator const vnl_matrix_ref<T>() const { return vnl_matrix_ref<T>( num_rows, num_cols, const_cast<T*>(data_block()) ); }
00591 
00592   //: Convert to a vnl_matrix.
00593   const vnl_matrix<T> as_matrix() const { return vnl_matrix<T>(const_cast<T*>(data_block()),num_rows,num_cols); }
00594 
00595   //----------------------------------------------------------------------
00596 
00597   typedef T element_type;
00598 
00599   //: Iterators
00600   typedef T       *iterator;
00601   //: Iterator pointing to start of data
00602   iterator       begin() { return data_[0]; }
00603   //: Iterator pointing to element beyond end of data
00604   iterator       end() { return begin() + size(); }
00605 
00606   //: Const iterators
00607   typedef T const *const_iterator;
00608   //: Iterator pointing to start of data
00609   const_iterator begin() const { return data_[0]; }
00610   //: Iterator pointing to element beyond end of data
00611   const_iterator end() const { return begin() + size(); }
00612 
00613   //--------------------------------------------------------------------------------
00614 
00615   //: Return true if *this == rhs
00616   bool operator_eq (vnl_matrix_fixed const & rhs) const
00617   {
00618     return equal( this->data_block(), rhs.data_block() );
00619   }
00620 
00621   //: Equality operator
00622   bool operator==(vnl_matrix<T> const &that) const { return  this->operator_eq(that); }
00623 
00624   //: Inequality operator
00625   bool operator!=(vnl_matrix<T> const &that) const { return !this->operator_eq(that); }
00626 
00627   //: Print matrix to os in some hopefully sensible format
00628   void print(vcl_ostream& os) const;
00629 
00630 //--------------------------------------------------------------------------------
00631 
00632 
00633   // Helper routines for arithmetic. These routines know the size from
00634   // the template parameters. The vector-vector operations are
00635   // element-wise.
00636 
00637   static void add( const T* a, const T* b, T* r );
00638   static void add( const T* a, T b, T* r );
00639   static void sub( const T* a, const T* b, T* r );
00640   static void sub( const T* a, T b, T* r );
00641   static void sub( T a, const T* b, T* r );
00642   static void mul( const T* a, const T* b, T* r );
00643   static void mul( const T* a, T b, T* r );
00644   static void div( const T* a, const T* b, T* r );
00645   static void div( const T* a, T b, T* r );
00646 
00647   static bool equal( const T* a, const T* b );
00648 
00649  private:
00650   void assert_finite_internal() const;
00651 
00652   void assert_size_internal(unsigned, unsigned) const;
00653 };
00654 
00655 #undef VNL_MATRIX_FIXED_VCL60_WORKAROUND
00656 
00657 
00658 // Make the operators below inline because (1) they are small and
00659 // (2) we then have less explicit instantiation trouble.
00660 
00661 
00662 // --- Matrix-scalar -------------------------------------------------------------
00663 
00664 template <class T, unsigned m, unsigned n>
00665 inline
00666 vnl_matrix_fixed<T,m,n> operator+( const vnl_matrix_fixed<T,m,n>& mat1, const vnl_matrix_fixed<T,m,n>& mat2 )
00667 {
00668   vnl_matrix_fixed<T,m,n> r;
00669   vnl_matrix_fixed<T,m,n>::add( mat1.data_block(), mat2.data_block(), r.data_block() );
00670   return r;
00671 }
00672 
00673 template <class T, unsigned m, unsigned n>
00674 inline
00675 vnl_matrix_fixed<T,m,n> operator+( const vnl_matrix_fixed<T,m,n>& mat, T s )
00676 {
00677   vnl_matrix_fixed<T,m,n> r;
00678   vnl_matrix_fixed<T,m,n>::add( mat.data_block(), s, r.data_block() );
00679   return r;
00680 }
00681 
00682 template <class T, unsigned m, unsigned n>
00683 inline
00684 vnl_matrix_fixed<T,m,n> operator+( const T& s,
00685                                    const vnl_matrix_fixed<T,m,n>& mat )
00686 {
00687   vnl_matrix_fixed<T,m,n> r;
00688   vnl_matrix_fixed<T,m,n>::add( mat.data_block(), s, r.data_block() );
00689   return r;
00690 }
00691 
00692 template <class T, unsigned m, unsigned n>
00693 inline
00694 vnl_matrix_fixed<T,m,n> operator-( const vnl_matrix_fixed<T,m,n>& mat1, const vnl_matrix_fixed<T,m,n>& mat2 )
00695 {
00696   vnl_matrix_fixed<T,m,n> r;
00697   vnl_matrix_fixed<T,m,n>::sub( mat1.data_block(), mat2.data_block(), r.data_block() );
00698   return r;
00699 }
00700 
00701 template <class T, unsigned m, unsigned n>
00702 inline
00703 vnl_matrix_fixed<T,m,n> operator-( const vnl_matrix_fixed<T,m,n>& mat, T s )
00704 {
00705   vnl_matrix_fixed<T,m,n> r;
00706   vnl_matrix_fixed<T,m,n>::sub( mat.data_block(), s, r.data_block() );
00707   return r;
00708 }
00709 
00710 template <class T, unsigned m, unsigned n>
00711 inline
00712 vnl_matrix_fixed<T,m,n> operator-( const T& s,
00713                                    const vnl_matrix_fixed<T,m,n>& mat )
00714 {
00715   vnl_matrix_fixed<T,m,n> r;
00716   vnl_matrix_fixed<T,m,n>::sub( s, mat.data_block(), r.data_block() );
00717   return r;
00718 }
00719 
00720 template <class T, unsigned m, unsigned n>
00721 inline
00722 vnl_matrix_fixed<T,m,n> operator*( const vnl_matrix_fixed<T,m,n>& mat, T s )
00723 {
00724   vnl_matrix_fixed<T,m,n> r;
00725   vnl_matrix_fixed<T,m,n>::mul( mat.data_block(), s, r.data_block() );
00726   return r;
00727 }
00728 
00729 template <class T, unsigned m, unsigned n>
00730 inline
00731 vnl_matrix_fixed<T,m,n> operator*( const T& s,
00732                                    const vnl_matrix_fixed<T,m,n>& mat )
00733 {
00734   vnl_matrix_fixed<T,m,n> r;
00735   vnl_matrix_fixed<T,m,n>::mul( mat.data_block(), s, r.data_block() );
00736   return r;
00737 }
00738 
00739 template <class T, unsigned m, unsigned n>
00740 inline
00741 vnl_matrix_fixed<T,m,n> operator/( const vnl_matrix_fixed<T,m,n>& mat, T s )
00742 {
00743   vnl_matrix_fixed<T,m,n> r;
00744   vnl_matrix_fixed<T,m,n>::div( mat.data_block(), s, r.data_block() );
00745   return r;
00746 }
00747 
00748 
00749 template <class T, unsigned m, unsigned n>
00750 inline
00751 vnl_matrix_fixed<T,m,n> element_product( const vnl_matrix_fixed<T,m,n>& mat1,
00752                                          const vnl_matrix_fixed<T,m,n>& mat2 )
00753 {
00754   vnl_matrix_fixed<T,m,n> r;
00755   vnl_matrix_fixed<T,m,n>::mul( mat1.data_block(), mat2.data_block(), r.data_block() );
00756   return r;
00757 }
00758 
00759 
00760 template <class T, unsigned m, unsigned n>
00761 inline
00762 vnl_matrix_fixed<T,m,n> element_quotient( const vnl_matrix_fixed<T,m,n>& mat1,
00763                                           const vnl_matrix_fixed<T,m,n>& mat2)
00764 {
00765   vnl_matrix_fixed<T,m,n> r;
00766   vnl_matrix_fixed<T,m,n>::div( mat1.data_block(), mat2.data_block(), r.data_block() );
00767   return r;
00768 }
00769 
00770 
00771 // The following two functions are helper functions keep the
00772 // matrix-matrix and matrix-vector multiplication code in one place,
00773 // so that bug fixes, etc, can be localized.
00774 template <class T, unsigned M, unsigned N>
00775 inline
00776 vnl_vector_fixed<T, M>
00777 vnl_matrix_fixed_mat_vec_mult(const vnl_matrix_fixed<T, M, N>& a,
00778                               const vnl_vector_fixed<T, N>& b)
00779 {
00780   vnl_vector_fixed<T, M> out;
00781   for (unsigned i = 0; i < M; ++i)
00782   {
00783     T accum = a(i,0) * b(0);
00784     for (unsigned k = 1; k < N; ++k)
00785       accum += a(i,k) * b(k);
00786     out(i) = accum;
00787   }
00788   return out;
00789 }
00790 
00791 template <class T, unsigned M, unsigned N>
00792 inline
00793 vnl_vector_fixed<T, N>
00794 vnl_matrix_fixed_vec_mat_mult(const vnl_vector_fixed<T, M>& a,
00795                               const vnl_matrix_fixed<T, M, N>& b)
00796 {
00797   vnl_vector_fixed<T, N> out;
00798   for (unsigned i = 0; i < N; ++i)
00799   {
00800     T accum = a(0) * b(0,i);
00801     for (unsigned k = 1; k < M; ++k)
00802       accum += a(k) * b(k,i);
00803     out(i) = accum;
00804   }
00805   return out;
00806 }
00807 
00808 // see comment above
00809 template <class T, unsigned M, unsigned N, unsigned O>
00810 inline
00811 vnl_matrix_fixed<T, M, O>
00812 vnl_matrix_fixed_mat_mat_mult(const vnl_matrix_fixed<T, M, N>& a,
00813                               const vnl_matrix_fixed<T, N, O>& b)
00814 {
00815   vnl_matrix_fixed<T, M, O> out;
00816   for (unsigned i = 0; i < M; ++i)
00817     for (unsigned j = 0; j < O; ++j)
00818     {
00819       T accum = a(i,0) * b(0,j);
00820       for (unsigned k = 1; k < N; ++k)
00821         accum += a(i,k) * b(k,j);
00822       out(i,j) = accum;
00823     }
00824   return out;
00825 }
00826 
00827 #ifndef VCL_VC_6
00828 // The version for correct compilers
00829 
00830 //: Multiply  conformant vnl_matrix_fixed (M x N) and vector_fixed (N)
00831 // \relatesalso vnl_vector_fixed
00832 // \relatesalso vnl_matrix_fixed
00833 template <class T, unsigned M, unsigned N>
00834 inline
00835 vnl_vector_fixed<T, M> operator*(const vnl_matrix_fixed<T, M, N>& a, const vnl_vector_fixed<T, N>& b)
00836 {
00837   return vnl_matrix_fixed_mat_vec_mult(a, b);
00838 }
00839 
00840 //: Multiply  conformant vector_fixed (M) and vnl_matrix_fixed (M x N)
00841 // \relatesalso vnl_vector_fixed
00842 // \relatesalso vnl_matrix_fixed
00843 template <class T, unsigned M, unsigned N>
00844 inline
00845 vnl_vector_fixed<T, N> operator*(const vnl_vector_fixed<T, M>& a, const vnl_matrix_fixed<T, M, N>& b)
00846 {
00847   return vnl_matrix_fixed_vec_mat_mult(a, b);
00848 }
00849 
00850 //: Multiply two conformant vnl_matrix_fixed (M x N) times (N x O)
00851 // \relatesalso vnl_matrix_fixed
00852 template <class T, unsigned M, unsigned N, unsigned O>
00853 inline
00854 vnl_matrix_fixed<T, M, O> operator*(const vnl_matrix_fixed<T, M, N>& a, const vnl_matrix_fixed<T, N, O>& b)
00855 {
00856   return vnl_matrix_fixed_mat_mat_mult(a, b);
00857 }
00858 #endif // VCL_VC_6
00859 
00860 
00861 // These overloads for the common case of mixing a fixed with a
00862 // non-fixed. Because the operator* are templated, the fixed will not
00863 // be automatically converted to a non-fixed-ref. These do it for you.
00864 
00865 template <class T, unsigned m, unsigned n>
00866 inline vnl_matrix<T> operator+( const vnl_matrix_fixed<T,m,n>& a, const vnl_matrix<T>& b )
00867 {
00868   return a.as_ref() + b;
00869 }
00870 
00871 template <class T, unsigned m, unsigned n>
00872 inline vnl_matrix<T> operator+( const vnl_matrix<T>& a, const vnl_matrix_fixed<T,m,n>& b )
00873 {
00874   return a + b.as_ref();
00875 }
00876 
00877 template <class T, unsigned m, unsigned n>
00878 inline vnl_matrix<T> operator-( const vnl_matrix_fixed<T,m,n>& a, const vnl_matrix<T>& b )
00879 {
00880   return a.as_ref() - b;
00881 }
00882 
00883 template <class T, unsigned m, unsigned n>
00884 inline vnl_matrix<T> operator-( const vnl_matrix<T>& a, const vnl_matrix_fixed<T,m,n>& b )
00885 {
00886   return a - b.as_ref();
00887 }
00888 
00889 template <class T, unsigned m, unsigned n>
00890 inline vnl_matrix<T> operator*( const vnl_matrix_fixed<T,m,n>& a, const vnl_matrix<T>& b )
00891 {
00892   return a.as_ref() * b;
00893 }
00894 
00895 template <class T, unsigned m, unsigned n>
00896 inline vnl_matrix<T> operator*( const vnl_matrix<T>& a, const vnl_matrix_fixed<T,m,n>& b )
00897 {
00898   return a * b.as_ref();
00899 }
00900 
00901 template <class T, unsigned m, unsigned n>
00902 inline vnl_vector<T> operator*( const vnl_matrix_fixed<T,m,n>& a, const vnl_vector<T>& b )
00903 {
00904   return a.as_ref() * b;
00905 }
00906 
00907 template <class T, unsigned n>
00908 inline vnl_vector<T> operator*( const vnl_matrix<T>& a, const vnl_vector_fixed<T,n>& b )
00909 {
00910   return a * b.as_ref();
00911 }
00912 
00913 
00914 // --- I/O operations ------------------------------------------------------------
00915 
00916 template <class T, unsigned m, unsigned n>
00917 inline
00918 vcl_ostream& operator<< (vcl_ostream& os, vnl_matrix_fixed<T,m,n> const& mat)
00919 {
00920   mat.print(os);
00921   return os;
00922 }
00923 
00924 template <class T, unsigned m, unsigned n>
00925 inline
00926 vcl_istream& operator>> (vcl_istream& is, vnl_matrix_fixed<T,m,n>& mat)
00927 {
00928   mat.read_ascii(is);
00929   return is;
00930 }
00931 
00932 // More workarounds for Visual C++ 6.0. The problem is that VC6 cannot
00933 // automatically determine the m of the second parameter, for some
00934 // reason. Also, VC6 can't figure out that vector_fixed::SIZE is a
00935 // compile time constant when used in the return parameter. So, we
00936 // have to introduce a helper class to do it.
00937 //
00938 #if defined(VCL_VC_6) && !defined(__GCCXML__)
00939 
00940 template<class T, unsigned m, class FixedVector>
00941 struct outer_product_fixed_type_helper
00942 {
00943   typedef vnl_matrix_fixed<T,m,FixedVector::SIZE> result_matrix;
00944 };
00945 
00946 template<class V1, class V2, class RM>
00947 struct outer_product_fixed_calc_helper
00948 {
00949   static RM calc( V1 const& a, V2 const& b );
00950 };
00951 
00952 template <class T, unsigned m, class SecondFixedVector>
00953 outer_product_fixed_type_helper<T,m,SecondFixedVector>::result_matrix
00954 outer_product(vnl_vector_fixed<T,m> const& a, SecondFixedVector const& b)
00955 {
00956   typedef vnl_vector_fixed<T,m> VecA;
00957   typedef vnl_vector_fixed<T,SecondFixedVector::SIZE> VecB;
00958   typedef outer_product_fixed_type_helper<T,m,SecondFixedVector>::result_matrix ResultMat;
00959   return outer_product_fixed_calc_helper<VecA,VecB,ResultMat>::calc(a,b);
00960 }
00961 
00962 #else // no need for VC6 workaround for outer_product
00963 
00964 //:
00965 // \relatesalso vnl_vector_fixed
00966 template <class T, unsigned m, unsigned n>
00967 vnl_matrix_fixed<T,m,n> outer_product(vnl_vector_fixed<T,m> const& a, vnl_vector_fixed<T,n> const& b);
00968 
00969 #endif // VC6 workaround for outer_product
00970 
00971 #define VNL_MATRIX_FIXED_INSTANTIATE(T, M, N) \
00972 extern "please include vnl/vnl_matrix_fixed.txx instead"
00973 
00974 #endif // vnl_matrix_fixed_h_

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