core/vnl/vnl_matrix_fixed_ref.h

Go to the documentation of this file.
00001 // This is core/vnl/vnl_matrix_fixed_ref.h
00002 #ifndef vnl_matrix_fixed_ref_h_
00003 #define vnl_matrix_fixed_ref_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 //  \file
00009 //  \brief Fixed size stack-stored vnl_matrix
00010 //
00011 //  > > From: Amitha Perera [mailto:perera@cs.rpi.edu]
00012 //  > > Sent: Monday, October 07, 2002 3:18 PM
00013 //  > > Subject: vnl_vector_fixed_ref
00014 //  > >
00015 //  > > I'm working on separating vnl_vector and vnl_vector_fixed in the VXL
00016 //  > > tree, as I mailed a while ago to the vxl-maintainers list. I noticed
00017 //  > > that you'd committed a vnl_vector_fixed_ref class which doesn't seem
00018 //  > > to provide any additional functionality over vnl_vector_ref. May I
00019 //  > > remove it, or is there some use for it?
00020 //  > >
00021 //  > > FYI, the author is listed as "Paul P. Smyth, Vicon Motion
00022 //  > > Systems Ltd."
00023 //  > > and the comment is dated 02 May 2001.
00024 //
00025 //  Paul Smyth <paul.smyth@vicon.com> writes:
00026 //  > The rationale behind it was that I had some (fast) algorithms for
00027 //  > matrix/vector operations that made use of compile-time knowledge of the
00028 //  > vector and matrix sizes.
00029 //  > This was typically appropriate when trying to interpret a fixed-size
00030 //  > subvector within a large vector of parameters as e.g. a translation.
00031 //  >
00032 //  > As I saw it, the various types of vector possible were: (with their current
00033 //  > names)
00034 //  > - pointer to memory, plus compile-time knowledge of vector size ( T*, and enum{size}) = vnl_vector_fixed_ref
00035 //  > - ownership of memory, plus compile-time size = vnl_vector_fixed
00036 //  > - pointer to memory, plus run-time only knowledge of size (T* and size()) = vnl_vector_ref
00037 //  > - ownership of memory, variably sized = vnl_vector
00038 //  >
00039 //  > I had a conversation with Andrew Fitzgibbon, where he reckoned that the best
00040 //  > thing to do with vnl vectors etc. was to create entirely separate types, and
00041 //  > routines for conversion between them (possibly implicitly), rather that
00042 //  > trying to establish a class hierarchy, which may add too many burdens in
00043 //  > terms of object size for small vectors/matrices.
00044 //  >
00045 //  > Sorry - I've now found the debate on the maintaners list!
00046 //  >
00047 //  > Anyway, I believe that vector_fixed_ref is very necessary, and that you
00048 //  > should be able to convert from a vector_fixed to a vector_fixed_ref - say
00049 //  > using an as_ref() member on vector_fixed or standalone function.
00050 //  > And I believe that for the restructured classes, vector_fixed_ref and
00051 //  > vector_fixed should not be related by inheritance, as that would place an
00052 //  > excessive burden on the size of vector_fixed.
00053 //  >
00054 //  > ------
00055 //  > Another issue - do you have a mechanism for dealing with const data safely?
00056 //  > {
00057 //  >   template<typename T, int n>
00058 //  >   vnl_vector_fixed_ref(T* i_Data);
00059 //  >
00060 //  >   void MyFunction(const vnl_vector<double> & Input)
00061 //  >   {
00062 //  >     // take a reference to the first 3 elements of Input
00063 //  >     vnl_vector_fixed_ref<double,3> ref(Input.begin());
00064 //  >     // compiler error - as making vector_fixed_ref from const
00065 //  > double *
00066 //  >   }
00067 //  > }
00068 //  >
00069 //  > The options appear to be
00070 //  > 1) Make a separate class vnl_vector_fixed_ref_const
00071 //  > 2) Make vnl_vector_fixed_ref so it can be instantiated with
00072 //  > vnl_vector_fixed_ref<double,n> AND vnl_vector_fixed_ref<const double,n>, and
00073 //  > gives appropriate behaviour - would probably require a to_const function
00074 //  > which generates vnl_vector_fixed_ref<const T,n> from
00075 //  > vnl_vector_fixed_ref<T,n>
00076 //  >
00077 //  > ------
00078 //  > Another note is that a number of routines that use vector_fixed currently
00079 //  > (e.g. cross_3d) should really use vector_fixed_ref as an input, because they
00080 //  > should be able to operate on fixed vector references as well as fixed
00081 //  > vectors.
00082 //  >
00083 //  > While I'm at it, has it been decided that the vnl_vector and vnl_vector_ref
00084 //  > classes are to remain unchanged? Because having vnl_vector as the base, and
00085 //  > vnl_vector_ref derived from it is a real pain in the backside. A vector
00086 //  > which may or may not own its own memory is a more general type than one
00087 //  > which does own it's own memory, and having vnl_vector as the base means that
00088 //  > all sorts of nastinesses can happen. Simply, a vector_ref Is-not a type of
00089 //  > vector.
00090 //  > If anything, it should be the other way round.
00091 //  >
00092 //  > void DoAssign(vnl_vector<double> & RefToMemoryIDontOwn, const vnl_vector<double> & NewContents)
00093 //  > {
00094 //  >   RefToMemoryIDontOwn = NewContents;
00095 //  > }
00096 //  >
00097 //  > void DeleteTwice()
00098 //  > {
00099 //  >   vnl_vector<double> vec1(3, 0); // size 3 - news 3*double
00100 //  >   vnl_vector<double> vec2(4,1); // size 4 news 4 * double
00101 //  >   vnl_vector_ref<double> ref_to_1(3,vec1.begin()); // copies pointer
00102 //  >   DoAssign(ref_to_1, vec2); // deletes memory owned by 1, news 4 * double
00103 //  >   // vec1 now points to deleted memory, and will crash when goes out of scope
00104 //  > }
00105 //  >
00106 //  > Maybe that issue isn't on your agenda - but it's a bit of a disaster. I know
00107 //  > that fixing this might break some code.
00108 //  >
00109 //  > ---------
00110 //  > Sorry for rolling all these things into one - I'd be interested to know what
00111 //  > you think. But please don't kill my vnl_vector_ref!
00112 //  >
00113 //  > Paul.
00114 //
00115 //    vnl_matrix_fixed_ref is a fixed-size vnl_matrix for which the data space
00116 //    has been supplied externally.  This is useful for two main tasks:
00117 //
00118 //    (a) Treating some row-based "C" matrix as a vnl_matrix in order to
00119 //    perform vnl_matrix operations on it.
00120 //
00121 //    (b) Declaring a vnl_matrix that uses entirely stack-based storage for the
00122 //    matrix.
00123 //
00124 //    The big warning is that returning a vnl_matrix_fixed_ref pointer will free
00125 //    non-heap memory if deleted through a vnl_matrix pointer.  This should be
00126 //    very difficult though, as vnl_matrix_fixed_ref objects may not be constructed
00127 //    using operator new.  This in turn is plausible as the point is to avoid
00128 //    such calls.
00129 //
00130 // \author Andrew W. Fitzgibbon, Oxford RRG
00131 // \date   04 Aug 1996
00132 //
00133 // \verbatim
00134 //  Modifications:
00135 //   27-Nov-1996 Peter Vanroose - added default constructor which allocates matrix storage
00136 //    4-Jul-2003 Paul Smyth - general cleanup and rewrite; interface now as vnl_matrix_fixed
00137 //   15-Aug-2003 Peter Vanroose - removed "duplicate" operator=(vnl_matrix_fixed<T,n> const&)
00138 //    8-Dec-2006 Markus Moll - changed operator>> signature (to const& argument)
00139 //   30-Mar-2009 Peter Vanroose - added arg_min() and arg_max()
00140 // \endverbatim
00141 //
00142 //-----------------------------------------------------------------------------
00143 
00144 #include <vcl_cassert.h>
00145 #include <vcl_iosfwd.h>
00146 #include <vcl_cstring.h> // memcpy()
00147 #include <vnl/vnl_matrix_fixed.h>
00148 #include <vnl/vnl_vector_fixed.h>
00149 #include <vnl/vnl_vector_fixed_ref.h>
00150 #include <vnl/vnl_c_vector.h>
00151 
00152 //: Fixed size stack-stored vnl_matrix
00153 // vnl_matrix_fixed_ref is a fixed-size vnl_matrix for which the data space
00154 // has been supplied externally.  This is useful for two main tasks:
00155 //
00156 // (a) Treating some row-based "C" matrix as a vnl_matrix in order to
00157 // perform vnl_matrix operations on it.
00158 //
00159 // (b) Declaring a vnl_matrix that uses entirely stack-based storage for the
00160 // matrix.
00161 //
00162 // The big warning is that returning a vnl_matrix_fixed_ref pointer will free
00163 // non-heap memory if deleted through a vnl_matrix pointer.  This should be
00164 // very difficult though, as vnl_matrix_fixed_ref objects may not be constructed
00165 // using operator new.  This in turn is plausible as the point is to avoid
00166 // such calls.
00167 //
00168 
00169 template <class T, unsigned num_rows, unsigned num_cols>
00170 class vnl_matrix_fixed_ref_const
00171 {
00172  protected:
00173   const T* data_;
00174  public:
00175   vnl_matrix_fixed_ref_const(const vnl_matrix_fixed<T,num_rows,num_cols>& rhs)
00176     : data_(rhs.data_block())
00177   {
00178   }
00179   explicit vnl_matrix_fixed_ref_const(const T * dataptr)
00180     : data_(dataptr)
00181   {
00182   }
00183   vnl_matrix_fixed_ref_const(const vnl_matrix_fixed_ref_const<T,num_rows,num_cols> & rhs)
00184     : data_(rhs.data_)
00185   {
00186   }
00187   //: Get j-th row
00188   vnl_vector_fixed<T,num_rows> get_row(unsigned row_index) const
00189   {
00190     vnl_vector<T> v(num_cols);
00191     for (unsigned int j = 0; j < num_cols; j++)    // For each element in row
00192       v[j] = (*this)(row_index,j);
00193     return v;
00194   }
00195 
00196   //: Get j-th column
00197   vnl_vector_fixed<T,num_cols> get_column(unsigned column_index) const
00198   {
00199     vnl_vector<T> v(num_rows);
00200     for (unsigned int j = 0; j < num_rows; j++)
00201       v[j] = (*this)(j,column_index);
00202     return v;
00203   }
00204   const T * data_block() const { return data_; }
00205 
00206   //: Const iterators
00207   typedef T const *const_iterator;
00208   //: Iterator pointing to start of data
00209   const_iterator begin() const { return data_; }
00210   //: Iterator pointing to element beyond end of data
00211   const_iterator end() const { return begin() + this->size(); }
00212 
00213   //: Type defs for iterators
00214   typedef const T element_type;
00215   //: Type defs for iterators
00216   typedef const T       *iterator;
00217 
00218   T const & operator() (unsigned r, unsigned c) const
00219   {
00220 #if VNL_CONFIG_CHECK_BOUNDS  && (!defined NDEBUG)
00221     assert(r<num_rows);   // Check the row index is valid
00222     assert(c<num_cols);   // Check the column index is valid
00223 #endif
00224     return *(data_ + num_cols * r + c);
00225   }
00226 
00227   //: return pointer to given row
00228   // No boundary checking here.
00229   T const * operator[] (unsigned r) const { return data_ + num_cols * r; }
00230 
00231   //: Return number of rows
00232   unsigned rows()    const { return num_rows; }
00233 
00234   //: Return number of columns
00235   // A synonym for cols()
00236   unsigned columns()  const { return num_cols; }
00237 
00238   //: Return number of columns
00239   // A synonym for columns()
00240   unsigned cols()    const { return num_cols; }
00241 
00242   //: Return number of elements
00243   // This equals rows() * cols()
00244   unsigned size()    const { return num_rows*num_cols; }
00245 
00246   //: Print matrix to os in some hopefully sensible format
00247   void print(vcl_ostream& os) const;
00248 
00249   void copy_out(T *) const;
00250 
00251   ////--------------------------- Additions ----------------------------
00252 
00253   //: Make a new matrix by applying function to each element.
00254   vnl_matrix_fixed<T,num_rows,num_cols> apply(T (*f)(T)) const;
00255 
00256   //: Make a new matrix by applying function to each element.
00257   vnl_matrix_fixed<T,num_rows,num_cols> apply(T (*f)(T const&)) const;
00258 
00259   //: Return transpose
00260   vnl_matrix_fixed<T,num_cols,num_rows> transpose () const;
00261 
00262   //: Return conjugate transpose
00263   vnl_matrix_fixed<T,num_cols,num_rows> conjugate_transpose () const;
00264 
00265   //: Extract a sub-matrix of size rows x cols, starting at (top,left)
00266   //  Thus it contains elements  [top,top+rows-1][left,left+cols-1]
00267   vnl_matrix<T> extract (unsigned rowz,  unsigned colz,
00268                          unsigned top=0, unsigned left=0) const;
00269 
00270   //: Get n rows beginning at rowstart
00271   vnl_matrix<T> get_n_rows   (unsigned rowstart, unsigned n) const;
00272 
00273   //: Get n columns beginning at colstart
00274   vnl_matrix<T> get_n_columns(unsigned colstart, unsigned n) const;
00275 
00276   //: Type def for norms.
00277   typedef typename vnl_c_vector<T>::abs_t abs_t;
00278 
00279   //: Return sum of absolute values of elements
00280   abs_t array_one_norm() const { return vnl_c_vector<T>::one_norm(begin(), size()); }
00281 
00282   //: Return square root of sum of squared absolute element values
00283   abs_t array_two_norm() const { return vnl_c_vector<T>::two_norm(begin(), size()); }
00284 
00285   //: Return largest absolute element value
00286   abs_t array_inf_norm() const { return vnl_c_vector<T>::inf_norm(begin(), size()); }
00287 
00288   //: Return sum of absolute values of elements
00289   abs_t absolute_value_sum() const { return array_one_norm(); }
00290 
00291   //: Return largest absolute value
00292   abs_t absolute_value_max() const { return array_inf_norm(); }
00293 
00294   // $ || M ||_1 := \max_j \sum_i | M_{ij} | $
00295   abs_t operator_one_norm() const;
00296 
00297   // $ || M ||_\inf := \max_i \sum_j | M_{ij} | $
00298   abs_t operator_inf_norm() const;
00299 
00300   //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements)
00301   abs_t frobenius_norm() const { return vnl_c_vector<T>::two_norm(begin(), size()); }
00302 
00303   //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements)
00304   abs_t fro_norm() const { return frobenius_norm(); }
00305 
00306   //: Return RMS of all elements
00307   abs_t rms() const { return vnl_c_vector<T>::rms_norm(begin(), size()); }
00308 
00309   //: Return minimum value of elements
00310   T min_value() const { return vnl_c_vector<T>::min_value(begin(), size()); }
00311 
00312   //: Return maximum value of elements
00313   T max_value() const { return vnl_c_vector<T>::max_value(begin(), size()); }
00314 
00315   //: Return location of minimum value of elements
00316   unsigned arg_min() const { return vnl_c_vector<T>::arg_min(begin(), size()); }
00317 
00318   //: Return location of maximum value of elements
00319   unsigned arg_max() const { return vnl_c_vector<T>::arg_max(begin(), size()); }
00320 
00321   //: Return mean of all matrix elements
00322   T mean() const { return vnl_c_vector<T>::mean(begin(), size()); }
00323 
00324   // predicates
00325 
00326   //: Return true iff the size is zero.
00327   bool empty() const { return num_rows==0 && num_cols==0; }
00328 
00329   //:  Return true if all elements equal to identity.
00330   bool is_identity() const;
00331 
00332   //:  Return true if all elements equal to identity, within given tolerance
00333   bool is_identity(double tol) const;
00334 
00335   //: Return true if all elements equal to zero.
00336   bool is_zero() const;
00337 
00338   //: Return true if all elements equal to zero, within given tolerance
00339   bool is_zero(double tol) const;
00340 
00341   //: Return true if finite
00342   bool is_finite() const;
00343 
00344   //: Return true if matrix contains NaNs
00345   bool has_nans() const;
00346 
00347   //: abort if size is not as expected
00348   // This function does or tests nothing if NDEBUG is defined
00349   void assert_size(unsigned rowz, unsigned colz) const
00350   {
00351 #ifndef NDEBUG
00352     assert_size_internal(rowz, colz);
00353 #endif
00354   }
00355   //: abort if matrix contains any INFs or NANs.
00356   // This function does or tests nothing if NDEBUG is defined
00357   void assert_finite() const
00358   {
00359 #ifndef NDEBUG
00360     assert_finite_internal();
00361 #endif
00362   }
00363 
00364   static void add( const T* a, const T* b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::add(a,b,r); }
00365   static void add( const T* a, T b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::add(a,b,r); }
00366   static void sub( const T* a, const T* b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::sub(a,b,r); }
00367   static void sub( const T* a, T b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::sub(a,b,r); }
00368   static void sub( T a, const T* b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::sub(a,b,r); }
00369   static void mul( const T* a, const T* b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::mul(a,b,r); }
00370   static void mul( const T* a, T b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::mul(a,b,r); }
00371   static void div( const T* a, const T* b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::div(a,b,r); }
00372   static void div( const T* a, T b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::div(a,b,r); }
00373 
00374   static bool equal( const T* a, const T* b ) { return vnl_matrix_fixed<T,num_rows,num_cols>::equal(a,b); }
00375 
00376  private:
00377   const vnl_matrix_fixed_ref_const<T,num_rows,num_cols> & operator=(const vnl_matrix_fixed_ref_const<T,num_rows,num_cols>& ) const
00378   {
00379     assert(!"Assignment is illegal for a vnl_matrix_fixed_ref_const");
00380     return *this;
00381   }
00382 
00383   void assert_finite_internal() const;
00384 
00385   void assert_size_internal(unsigned, unsigned) const;
00386 };
00387 
00388 
00389 template <class T, unsigned num_rows, unsigned num_cols>
00390 class vnl_matrix_fixed_ref : public vnl_matrix_fixed_ref_const<T,num_rows,num_cols>
00391 {
00392   typedef vnl_matrix_fixed_ref_const<T,num_rows,num_cols> base;
00393 
00394  public:
00395   // this is the only point where the const_cast happens
00396   // the base class is used to store the pointer, so that conversion is not necessary
00397   T * data_block() const {
00398     return const_cast<T*>(this->data_);
00399   }
00400   vnl_matrix_fixed_ref(vnl_matrix_fixed<T,num_rows,num_cols>& rhs)
00401     : base(rhs.data_block())
00402   {
00403   }
00404   explicit vnl_matrix_fixed_ref(T * dataptr)
00405     : base(dataptr)
00406   {
00407   }
00408 
00409   //: Copy another vnl_matrix_fixed<T,m,n> into this.
00410   vnl_matrix_fixed_ref const & operator=(const vnl_matrix_fixed_ref_const<T,num_rows,num_cols>& rhs) const
00411   {
00412     vcl_memcpy(data_block(), rhs.data_block(), num_rows*num_cols*sizeof(T));
00413     return *this;
00414   }
00415 
00416   // Basic 2D-Array functionality-------------------------------------------
00417 
00418   //: set element
00419   void put (unsigned r, unsigned c, T const& v) { (*this)(r,c) = v; }
00420 
00421   //: get element
00422   T    get (unsigned r, unsigned c) const { return (*this)(r,c); }
00423 
00424   //: return pointer to given row
00425   // No boundary checking here.
00426   T  * operator[] (unsigned r) const { return data_block() + num_cols * r; }
00427 
00428   //: Access an element for reading or writing
00429   // There are assert style boundary checks - #define NDEBUG to turn them off.
00430   T       & operator() (unsigned r, unsigned c) const
00431   {
00432 #if VNL_CONFIG_CHECK_BOUNDS  && (!defined NDEBUG)
00433     assert(r<num_rows);   // Check the row index is valid
00434     assert(c<num_cols);   // Check the column index is valid
00435 #endif
00436     return *(this->data_block() + num_cols * r + c);
00437   }
00438 
00439   // Filling and copying------------------------------------------------
00440 
00441   //: Set all elements of matrix to specified value.
00442   // Complexity $O(r.c)$
00443   void fill (T) const;
00444 
00445   //: Set all diagonal elements of matrix to specified value.
00446   // Complexity $O(\min(r,c))$
00447   void fill_diagonal (T) const;
00448 
00449   //: Fill (laminate) this matrix with the given data.
00450   // We assume that p points to a contiguous rows*cols array, stored rowwise.
00451   void copy_in(T const *) const;
00452 
00453   //: Fill (laminate) this matrix with the given data.
00454   // A synonym for copy_in()
00455   void set(T const *d) const { copy_in(d); }
00456 
00457   //: Fill the given array with this matrix.
00458   // We assume that p points to a contiguous rows*cols array, stored rowwise.
00459   // No bounds checking on the array
00460 
00461   //: Transpose this matrix efficiently, if it is a square matrix
00462   void inplace_transpose() const;
00463 
00464   // Arithmetic ----------------------------------------------------
00465   // note that these functions should not pass scalar as a const&.
00466   // Look what would happen to A /= A(0,0).
00467 
00468   //: Add \a s to each element of lhs matrix in situ
00469   vnl_matrix_fixed_ref const& operator+= (T s) const
00470   {
00471     base::add( data_block(), s, data_block() ); return *this;
00472   }
00473 
00474   //: Subtract \a s from each element of lhs matrix in situ
00475   vnl_matrix_fixed_ref const& operator-= (T s) const
00476   {
00477     base::sub( data_block(), s, data_block() ); return *this;
00478   }
00479 
00480   //:
00481   vnl_matrix_fixed_ref const& operator*= (T s) const
00482   {
00483     base::mul( data_block(), s, data_block() ); return *this;
00484   }
00485 
00486   //:
00487   vnl_matrix_fixed_ref const& operator/= (T s) const
00488   {
00489     base::div( data_block(), s, data_block() ); return *this;
00490   }
00491 
00492   //:
00493   vnl_matrix_fixed_ref const & operator+= (vnl_matrix_fixed_ref_const<T,num_rows,num_cols> const& m) const
00494   {
00495     base::add( data_block(), m.data_block(), data_block() ); return *this;
00496   }
00497 
00498   //:
00499   vnl_matrix_fixed_ref const& operator+= (vnl_matrix<T> const& m) const
00500   {
00501     assert( m.rows() == num_rows && m.cols() == num_cols );
00502     base::add( data_block(), m.data_block(), data_block() ); return *this;
00503   }
00504 
00505   //:
00506   vnl_matrix_fixed_ref const& operator-= (vnl_matrix_fixed_ref_const<T,num_rows,num_cols> const& m) const
00507   {
00508     base::sub( data_block(), m.data_block(), data_block() ); return *this;
00509   }
00510 
00511   //:
00512   vnl_matrix_fixed_ref const& operator-= (vnl_matrix<T> const& m) const
00513   {
00514     assert( m.rows() == num_rows && m.cols() == num_cols );
00515     base::sub( data_block(), m.data_block(), data_block() ); return *this;
00516   }
00517 
00518   //: Negate all elements of matrix
00519   vnl_matrix_fixed<T,num_rows,num_cols> operator- () const
00520   {
00521     vnl_matrix_fixed<T,num_rows,num_cols> r;
00522     base::sub( T(0), data_block(), r.data_block() );
00523     return r;
00524   }
00525 
00526   //:
00527   vnl_matrix_fixed_ref const& operator*= (vnl_matrix_fixed_ref_const<T,num_cols,num_cols> const& s) const
00528   {
00529     vnl_matrix_fixed<T, num_rows, num_cols> out;
00530     for (unsigned i = 0; i < num_rows; ++i)
00531       for (unsigned j = 0; j < num_cols; ++j)
00532       {
00533         T accum = this->operator()(i,0) * s(0,j);
00534         for (unsigned k = 1; k < num_cols; ++k)
00535           accum += this->operator()(i,k) * s(k,j);
00536         out(i,j) = accum;
00537       }
00538     *this = out;
00539     return *this;
00540   }
00541 
00542 #ifdef VCL_VC_6
00543   template<unsigned o>
00544   vnl_matrix_fixed<T,num_rows,o> operator*( vnl_matrix_fixed_fake_base<o,num_cols,T> const& mat ) const
00545   {
00546     vnl_matrix_fixed<T,num_cols,o> const& b = static_cast<vnl_matrix_fixed<T,num_cols,o> const&>(mat);
00547     return vnl_matrix_fixed_mat_mat_mult<T,num_rows,num_cols,o>( *this, b );
00548   }
00549   vnl_vector_fixed<T, num_rows> operator*( vnl_vector_fixed_ref_const<T, num_cols> const& b) const
00550   {
00551     return vnl_matrix_fixed_mat_vec_mult<T,num_rows,num_cols>(*this,b);
00552   }
00553 #endif
00554 
00555   //: Set values of this matrix to those of M, starting at [top,left]
00556   vnl_matrix_fixed_ref const & update (vnl_matrix<T> const&, unsigned top=0, unsigned left=0) const;
00557 
00558   //: Set the elements of the i'th column to v[j]  (No bounds checking)
00559   void set_column(unsigned i, T const * v) const;
00560 
00561   //: Set the elements of the i'th column to value
00562   void set_column(unsigned i, T value ) const;
00563 
00564   //: Set j-th column to v
00565   void set_column(unsigned j, vnl_vector<T> const& v) const;
00566 
00567   //: Set columns to those in M, starting at starting_column
00568   void set_columns(unsigned starting_column, vnl_matrix<T> const& M) const;
00569 
00570   //: Set the elements of the i'th row to v[j]  (No bounds checking)
00571   void set_row   (unsigned i, T const * v) const;
00572 
00573   //: Set the elements of the i'th row to value
00574   void set_row   (unsigned i, T value ) const;
00575 
00576   //: Set the i-th row
00577   void set_row   (unsigned i, vnl_vector<T> const&) const;
00578 
00579   // ==== mutators ====
00580 
00581   //: Set this matrix to an identity matrix
00582   //  Abort if the matrix is not square
00583   void set_identity() const;
00584 
00585   //: Reverse order of rows.
00586   void flipud() const;
00587 
00588   //: Reverse order of columns.
00589   void fliplr() const;
00590 
00591   //: Normalize each row so it is a unit vector
00592   //  Zero rows are ignored
00593   void normalize_rows() const;
00594 
00595   //: Normalize each column so it is a unit vector
00596   //  Zero columns are ignored
00597   void normalize_columns() const;
00598 
00599   //: Scale elements in given row by a factor of T
00600   void scale_row   (unsigned row, T value) const;
00601 
00602   //: Scale elements in given column by a factor of T
00603   void scale_column(unsigned col, T value) const;
00604 
00605   ////----------------------- Input/Output ----------------------------
00606 
00607   // : Read a vnl_matrix from an ascii vcl_istream, automatically determining file size if the input matrix has zero size.
00608   bool read_ascii(vcl_istream& s) const;
00609 
00610   //----------------------------------------------------------------------
00611   // Conversion to vnl_matrix_ref.
00612 
00613   // The const version of as_ref should return a const vnl_matrix_ref
00614   // so that the vnl_matrix_ref::non_const() cannot be used on
00615   // it. This prevents a const vnl_matrix_fixed from being cast into a
00616   // non-const vnl_matrix reference, giving a slight increase in type safety.
00617 
00618   //: Explicit conversion to a vnl_matrix_ref.
00619   // This is a cheap conversion for those functions that have an interface
00620   // for vnl_matrix_ref but not for vnl_matrix_fixed_ref. There is also a
00621   // conversion operator that should work most of the time.
00622   // \sa vnl_matrix_ref::non_const
00623   vnl_matrix_ref<T> as_ref() { return vnl_matrix_ref<T>( num_rows, num_cols, data_block() ); }
00624 
00625   //: Explicit conversion to a vnl_matrix_ref.
00626   // This is a cheap conversion for those functions that have an interface
00627   // for vnl_matrix_ref but not for vnl_matrix_fixed_ref. There is also a
00628   // conversion operator that should work most of the time.
00629   // \sa vnl_matrix_ref::non_const
00630   const vnl_matrix_ref<T> as_ref() const { return vnl_matrix_ref<T>( num_rows, num_cols, const_cast<T*>(data_block()) ); }
00631 
00632   //: Cheap conversion to vnl_matrix_ref
00633   // Sometimes, such as with templated functions, the compiler cannot
00634   // use this user-defined conversion. For those cases, use the
00635   // explicit as_ref() method instead.
00636   operator const vnl_matrix_ref<T>() const { return vnl_matrix_ref<T>( num_rows, num_cols, const_cast<T*>(data_block()) ); }
00637 
00638   //: Convert to a vnl_matrix.
00639   const vnl_matrix<T> as_matrix() const { return vnl_matrix<T>(const_cast<T*>(data_block()),num_rows,num_cols); }
00640 
00641   //----------------------------------------------------------------------
00642 
00643   typedef T element_type;
00644 
00645   //: Iterators
00646   typedef T       *iterator;
00647   //: Iterator pointing to start of data
00648   iterator       begin() const { return data_block(); }
00649   //: Iterator pointing to element beyond end of data
00650   iterator       end() const { return begin() + this->size(); }
00651   //--------------------------------------------------------------------------------
00652 
00653   //: Return true if *this == rhs
00654   bool operator_eq (vnl_matrix_fixed_ref_const<T,num_rows,num_cols> const & rhs) const
00655   {
00656     return equal( this->data_block(), rhs.data_block() );
00657   }
00658 
00659   //: Equality operator
00660   bool operator==(vnl_matrix_fixed_ref_const<T,num_rows,num_cols> const &that) const { return  this->operator_eq(that); }
00661 
00662   //: Inequality operator
00663   bool operator!=(vnl_matrix_fixed_ref_const<T,num_rows,num_cols> const &that) const { return !this->operator_eq(that); }
00664 
00665 //--------------------------------------------------------------------------------
00666 };
00667 
00668 #undef VNL_MATRIX_FIXED_VCL60_WORKAROUND
00669 
00670   // Helper routines for arithmetic. These routines know the size from
00671   // the template parameters. The vector-vector operations are
00672   // element-wise.
00673 
00674 // Make the operators below inline because (1) they are small and
00675 // (2) we then have less explicit instantiation trouble.
00676 
00677 // --- Matrix-scalar -------------------------------------------------------------
00678 
00679 template<class T, unsigned m, unsigned n>
00680 inline
00681 vnl_matrix_fixed<T,m,n> operator+( const vnl_matrix_fixed_ref_const<T,m,n>& mat1, const vnl_matrix_fixed_ref_const<T,m,n>& mat2 )
00682 {
00683   vnl_matrix_fixed<T,m,n> r;
00684   vnl_matrix_fixed<T,m,n>::add( mat1.data_block(), mat2.data_block(), r.data_block() );
00685   return r;
00686 }
00687 
00688 template<class T, unsigned m, unsigned n>
00689 inline
00690 vnl_matrix_fixed<T,m,n> operator+( const vnl_matrix_fixed_ref_const<T,m,n>& mat, T s )
00691 {
00692   vnl_matrix_fixed<T,m,n> r;
00693   vnl_matrix_fixed<T,m,n>::add( mat.data_block(), s, r.data_block() );
00694   return r;
00695 }
00696 
00697 template<class T, unsigned m, unsigned n>
00698 inline
00699 vnl_matrix_fixed<T,m,n> operator+( T s, const vnl_matrix_fixed_ref_const<T,m,n>& mat )
00700 {
00701   vnl_matrix_fixed<T,m,n> r;
00702   vnl_matrix_fixed<T,m,n>::add( mat.data_block(), s, r.data_block() );
00703   return r;
00704 }
00705 
00706 template<class T, unsigned m, unsigned n>
00707 inline
00708 vnl_matrix_fixed<T,m,n> operator-( const vnl_matrix_fixed_ref_const<T,m,n>& mat1, const vnl_matrix_fixed_ref_const<T,m,n>& mat2 )
00709 {
00710   vnl_matrix_fixed<T,m,n> r;
00711   vnl_matrix_fixed<T,m,n>::sub( mat1.data_block(), mat2.data_block(), r.data_block() );
00712   return r;
00713 }
00714 
00715 template<class T, unsigned m, unsigned n>
00716 inline
00717 vnl_matrix_fixed<T,m,n> operator-( const vnl_matrix_fixed_ref_const<T,m,n>& mat, T s )
00718 {
00719   vnl_matrix_fixed<T,m,n> r;
00720   vnl_matrix_fixed<T,m,n>::sub( mat.data_block(), s, r.data_block() );
00721   return r;
00722 }
00723 
00724 template<class T, unsigned m, unsigned n>
00725 inline
00726 vnl_matrix_fixed<T,m,n> operator-( T s, const vnl_matrix_fixed_ref_const<T,m,n>& mat )
00727 {
00728   vnl_matrix_fixed<T,m,n> r;
00729   vnl_matrix_fixed<T,m,n>::sub( s, mat.data_block(), r.data_block() );
00730   return r;
00731 }
00732 
00733 template<class T, unsigned m, unsigned n>
00734 inline
00735 vnl_matrix_fixed<T,m,n> operator*( const vnl_matrix_fixed_ref_const<T,m,n>& mat, T s )
00736 {
00737   vnl_matrix_fixed<T,m,n> r;
00738   vnl_matrix_fixed<T,m,n>::mul( mat.data_block(), s, r.data_block() );
00739   return r;
00740 }
00741 
00742 template<class T, unsigned m, unsigned n>
00743 inline
00744 vnl_matrix_fixed<T,m,n> operator*( T s, const vnl_matrix_fixed_ref_const<T,m,n>& mat )
00745 {
00746   vnl_matrix_fixed<T,m,n> r;
00747   vnl_matrix_fixed<T,m,n>::mul( mat.data_block(), s, r.data_block() );
00748   return r;
00749 }
00750 
00751 template<class T, unsigned m, unsigned n>
00752 inline
00753 vnl_matrix_fixed<T,m,n> operator/( const vnl_matrix_fixed_ref_const<T,m,n>& mat, T s )
00754 {
00755   vnl_matrix_fixed<T,m,n> r;
00756   vnl_matrix_fixed<T,m,n>::div( mat.data_block(), s, r.data_block() );
00757   return r;
00758 }
00759 
00760 
00761 template<class T, unsigned m, unsigned n>
00762 inline
00763 vnl_matrix_fixed<T,m,n> element_product( const vnl_matrix_fixed_ref_const<T,m,n>& mat1,
00764                                          const vnl_matrix_fixed_ref_const<T,m,n>& mat2 )
00765 {
00766   vnl_matrix_fixed<T,m,n> r;
00767   vnl_matrix_fixed<T,m,n>::mul( mat1.data_block(), mat2.data_block(), r.data_block() );
00768   return r;
00769 }
00770 
00771 
00772 template<class T, unsigned m, unsigned n>
00773 inline
00774 vnl_matrix_fixed<T,m,n> element_quotient( const vnl_matrix_fixed_ref_const<T,m,n>& mat1,
00775                                           const vnl_matrix_fixed_ref_const<T,m,n>& mat2)
00776 {
00777   vnl_matrix_fixed<T,m,n> r;
00778   vnl_matrix_fixed<T,m,n>::div( mat1.data_block(), mat2.data_block(), r.data_block() );
00779   return r;
00780 }
00781 
00782 
00783 // The following two functions are helper functions that keep the
00784 // matrix-matrix and matrix-vector multiplication code in one place,
00785 // so that bug fixes, etc, can be localized.
00786 template <class T, unsigned M, unsigned N>
00787 inline
00788 vnl_vector_fixed<T, M>
00789 vnl_matrix_fixed_mat_vec_mult(const vnl_matrix_fixed_ref_const<T, M, N>& a,
00790                               const vnl_vector_fixed_ref_const<T, N>& b)
00791 {
00792   vnl_vector_fixed<T, M> out;
00793   for (unsigned i = 0; i < M; ++i)
00794   {
00795     T accum = a(i,0) * b(0);
00796     for (unsigned k = 1; k < N; ++k)
00797       accum += a(i,k) * b(k);
00798     out(i) = accum;
00799   }
00800   return out;
00801 }
00802 
00803 // see comment above
00804 template <class T, unsigned M, unsigned N, unsigned O>
00805 inline
00806 vnl_matrix_fixed<T, M, O>
00807 vnl_matrix_fixed_mat_mat_mult(const vnl_matrix_fixed_ref_const<T, M, N>& a,
00808                               const vnl_matrix_fixed_ref_const<T, N, O>& b)
00809 {
00810   vnl_matrix_fixed<T, M, O> out;
00811   for (unsigned i = 0; i < M; ++i)
00812     for (unsigned j = 0; j < O; ++j)
00813     {
00814       T accum = a(i,0) * b(0,j);
00815       for (unsigned k = 1; k < N; ++k)
00816         accum += a(i,k) * b(k,j);
00817       out(i,j) = accum;
00818     }
00819   return out;
00820 }
00821 
00822 #ifndef VCL_VC_6
00823 // The version for correct compilers
00824 
00825 //: Multiply  conformant vnl_matrix_fixed (M x N) and vector_fixed (N)
00826 // \relatesalso vnl_vector_fixed
00827 // \relatesalso vnl_matrix_fixed
00828 template <class T, unsigned M, unsigned N>
00829 inline
00830 vnl_vector_fixed<T, M> operator*(const vnl_matrix_fixed_ref_const<T, M, N>& a, const vnl_vector_fixed_ref_const<T, N>& b)
00831 {
00832   return vnl_matrix_fixed_mat_vec_mult(a,b);
00833 }
00834 
00835 //: Multiply two conformant vnl_matrix_fixed (M x N) times (N x O)
00836 // \relatesalso vnl_matrix_fixed
00837 template <class T, unsigned M, unsigned N, unsigned O>
00838 inline
00839 vnl_matrix_fixed<T, M, O> operator*(const vnl_matrix_fixed_ref_const<T, M, N>& a, const vnl_matrix_fixed_ref_const<T, N, O>& b)
00840 {
00841   return vnl_matrix_fixed_mat_mat_mult(a,b);
00842 }
00843 #endif // ! VCL_VC_6
00844 
00845 
00846 // These overloads for the common case of mixing a fixed with a
00847 // non-fixed. Because the operator* are templated, the fixed will not
00848 // be automatically converted to a non-fixed-ref. These do it for you.
00849 
00850 template<class T, unsigned m, unsigned n>
00851 inline vnl_matrix<T> operator+( const vnl_matrix_fixed_ref_const<T,m,n>& a, const vnl_matrix<T>& b )
00852 {
00853   return a.as_ref() + b;
00854 }
00855 
00856 template<class T, unsigned m, unsigned n>
00857 inline vnl_matrix<T> operator+( const vnl_matrix<T>& a, const vnl_matrix_fixed_ref_const<T,m,n>& b )
00858 {
00859   return a + b.as_ref();
00860 }
00861 
00862 template<class T, unsigned m, unsigned n>
00863 inline vnl_matrix<T> operator-( const vnl_matrix_fixed_ref_const<T,m,n>& a, const vnl_matrix<T>& b )
00864 {
00865   return a.as_ref() - b;
00866 }
00867 
00868 template<class T, unsigned m, unsigned n>
00869 inline vnl_matrix<T> operator-( const vnl_matrix<T>& a, const vnl_matrix_fixed_ref_const<T,m,n>& b )
00870 {
00871   return a - b.as_ref();
00872 }
00873 
00874 template<class T, unsigned m, unsigned n>
00875 inline vnl_matrix<T> operator*( const vnl_matrix_fixed_ref_const<T,m,n>& a, const vnl_matrix<T>& b )
00876 {
00877   return a.as_ref() * b;
00878 }
00879 
00880 template<class T, unsigned m, unsigned n>
00881 inline vnl_matrix<T> operator*( const vnl_matrix<T>& a, const vnl_matrix_fixed_ref_const<T,m,n>& b )
00882 {
00883   return a * b.as_ref();
00884 }
00885 
00886 template<class T, unsigned m, unsigned n>
00887 inline vnl_vector<T> operator*( const vnl_matrix_fixed_ref_const<T,m,n>& a, const vnl_vector<T>& b )
00888 {
00889   return a.as_ref() * b;
00890 }
00891 
00892 template<class T, unsigned n>
00893 inline vnl_vector<T> operator*( const vnl_matrix<T>& a, const vnl_vector_fixed_ref_const<T,n>& b )
00894 {
00895   return a * b.as_ref();
00896 }
00897 
00898 
00899 // --- I/O operations ------------------------------------------------------------
00900 
00901 template<class T, unsigned m, unsigned n>
00902 inline
00903 vcl_ostream& operator<< (vcl_ostream& os, vnl_matrix_fixed_ref_const<T,m,n> const& mat)
00904 {
00905   mat.print(os);
00906   return os;
00907 }
00908 
00909 template<class T, unsigned m, unsigned n>
00910 inline
00911 vcl_istream& operator>> (vcl_istream& is, vnl_matrix_fixed_ref<T,m,n> const& mat)
00912 {
00913   mat.read_ascii(is);
00914   return is;
00915 }
00916 
00917 
00918 #endif // vnl_matrix_fixed_ref_h_

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