core/vnl/vnl_diag_matrix_fixed.h
Go to the documentation of this file.
00001 // This is core/vnl/vnl_diag_matrix_fixed.h
00002 #ifndef vnl_diag_matrix_fixed_h_
00003 #define vnl_diag_matrix_fixed_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Contains class for diagonal matrices
00010 // \author Andrew W. Fitzgibbon (Oxford RRG)
00011 // \date   5 Aug 1996
00012 //
00013 // \verbatim
00014 //  Modifications
00015 //   IMS (Manchester) 16 Mar 2001: Tidied up the documentation + added binary_io
00016 //   Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
00017 //   Sep.2002 - Peter Vanroose - Added operator+, operator-, operator*
00018 //   Mar.2004 - Peter Vanroose - removed deprecated resize()
00019 //   Oct.2010 - Peter Vanroose - mutators and setters now return *this
00020 //   Jan.2011 - Peter Vanroose - added methods set_diagonal() & get_diagonal()
00021 // \endverbatim
00022 
00023 #include <vcl_cassert.h>
00024 #include <vcl_iosfwd.h>
00025 #include <vnl/vnl_vector_fixed.h>
00026 #include <vnl/vnl_matrix_fixed.h>
00027 
00028 // forward declarations
00029 template <class T, unsigned int N> class vnl_diag_matrix_fixed;
00030 template <class T, unsigned int N> vnl_vector_fixed<T,N> operator*(vnl_diag_matrix_fixed<T,N> const&, vnl_vector_fixed<T,N> const&);
00031 
00032 //: stores a diagonal matrix as a single vector.
00033 //  vnl_diag_matrix_fixed stores a diagonal matrix for time and space efficiency.
00034 //  Specifically, only the diagonal elements are stored, and some matrix
00035 //  operations (currently *, + and -) are overloaded to use more efficient
00036 //  algorithms.
00037 
00038 export
00039 template <class T, unsigned int N>
00040 class vnl_diag_matrix_fixed
00041 {
00042   vnl_vector_fixed<T,N> diagonal_;
00043 
00044  public:
00045   vnl_diag_matrix_fixed() : diagonal_() {}
00046 
00047 
00048   //: Construct a diagonal matrix with diagonal elements equal to value.
00049   vnl_diag_matrix_fixed(T const& value) : diagonal_(N, value) {}
00050 
00051   //: Construct a diagonal matrix from a vnl_vector_fixed.
00052   //  The vector elements become the diagonal elements.
00053   explicit vnl_diag_matrix_fixed(vnl_vector_fixed<T,N> const& that): diagonal_(that) {}
00054  ~vnl_diag_matrix_fixed() {}
00055 
00056   inline vnl_diag_matrix_fixed& operator=(vnl_diag_matrix_fixed<T,N> const& that) {
00057     this->diagonal_ = that.diagonal_;
00058     return *this;
00059   }
00060 
00061   // Operations----------------------------------------------------------------
00062 
00063   //: In-place arithmetic operation
00064   inline vnl_diag_matrix_fixed<T,N>& operator*=(T v) { diagonal_ *= v; return *this; }
00065   //: In-place arithmetic operation
00066   inline vnl_diag_matrix_fixed<T,N>& operator/=(T v) { diagonal_ /= v; return *this; }
00067 
00068   // Computations--------------------------------------------------------------
00069 
00070   inline vnl_diag_matrix_fixed& invert_in_place();
00071   T determinant() const;
00072   vnl_vector_fixed<T,N> solve(vnl_vector_fixed<T,N> const& b) const;
00073   void solve(vnl_vector_fixed<T,N> const& b, vnl_vector_fixed<T,N>* out) const;
00074 
00075   // Data Access---------------------------------------------------------------
00076 
00077   inline T operator () (unsigned i, unsigned j) const {
00078     return (i != j) ? T(0) : diagonal_[i];
00079   }
00080 
00081   inline T& operator () (unsigned i, unsigned j) {
00082     assert(i == j);
00083     return diagonal_[i];
00084   }
00085   inline T& operator() (unsigned i) { return diagonal_[i]; }
00086   inline T const& operator() (unsigned i) const { return diagonal_[i]; }
00087 
00088   inline T& operator[] (unsigned i) { return diagonal_[i]; }
00089   inline T const& operator[] (unsigned i) const { return diagonal_[i]; }
00090 
00091   //: set element with boundary checks.
00092   inline void put (unsigned r, unsigned c, T const& v) {
00093     assert(r == c); assert (r<size()); diagonal_[r] = v;
00094   }
00095 
00096   //: get element with boundary checks.
00097   inline T get (unsigned r, unsigned c) const {
00098     assert(r == c); assert (r<size()); return diagonal_[r];
00099   }
00100 
00101   //: Return a vector (copy) with the content of the (main) diagonal
00102   inline vnl_vector_fixed<T,N> get_diagonal() const { return diagonal_; }
00103 
00104   //: Return diagonal elements as a vector
00105   inline vnl_vector_fixed<T,N> const& diagonal() const { return diagonal_; }
00106 
00107   //: Set all diagonal elements of matrix to specified value.
00108   inline vnl_diag_matrix_fixed& fill_diagonal (T const& v) { diagonal_.fill(v); return *this; }
00109 
00110   //: Sets the diagonal elements of this matrix to the specified list of values.
00111   inline vnl_diag_matrix_fixed& set_diagonal(vnl_vector_fixed<T,N> const& v) { diagonal_ = v; return *this; }
00112 
00113   // iterators
00114 
00115   typedef typename vnl_vector_fixed<T,N>::iterator iterator;
00116   inline iterator begin() { return diagonal_.begin(); }
00117   inline iterator end() { return diagonal_.end(); }
00118   typedef typename vnl_vector_fixed<T,N>::const_iterator const_iterator;
00119   inline const_iterator begin() const { return diagonal_.begin(); }
00120   inline const_iterator end() const { return diagonal_.end(); }
00121 
00122   inline unsigned size() const { return diagonal_.size(); }
00123   inline unsigned rows() const { return diagonal_.size(); }
00124   inline unsigned cols() const { return diagonal_.size(); }
00125   inline unsigned columns() const { return diagonal_.size(); }
00126 
00127   // Need this until we add a vnl_diag_matrix_fixed ctor to vnl_matrix;
00128   inline vnl_matrix_fixed<T,N,N> as_matrix_fixed() const;
00129 
00130   inline vnl_matrix_fixed<T,N,N> as_ref() const { return as_matrix_fixed(); }
00131 
00132   // This is as good as a vnl_diag_matrix_fixed ctor for vnl_matrix_fixed:
00133   inline operator vnl_matrix_fixed<T,N,N> () const { return as_matrix_fixed(); }
00134 
00135   inline vnl_diag_matrix_fixed& fill(T const &x) { diagonal_.fill(x); return *this; }
00136 
00137   //: Return pointer to the diagonal elements as a contiguous 1D C array;
00138   inline T*       data_block()       { return diagonal_.data_block(); }
00139   inline T const* data_block() const { return diagonal_.data_block(); }
00140 
00141   //: Set diagonal elements using vector, then return *this
00142   inline vnl_diag_matrix_fixed& set(vnl_vector_fixed<T,N> const& v)  { diagonal_=v; return *this; }
00143 
00144  private:
00145   #if VCL_NEED_FRIEND_FOR_TEMPLATE_OVERLOAD
00146   friend vnl_vector_fixed<T,N> operator*(vnl_diag_matrix_fixed<T,N> const&,vnl_vector_fixed<T,N> const&);
00147   #endif
00148 };
00149 
00150 //:
00151 // \relatesalso vnl_diag_matrix_fixed
00152 template <class T, unsigned int N>
00153 vcl_ostream& operator<< (vcl_ostream&, vnl_diag_matrix_fixed<T,N> const&);
00154 
00155 //: Convert a vnl_diag_matrix_fixed to a Matrix.
00156 template <class T, unsigned int N>
00157 inline vnl_matrix_fixed<T,N,N> vnl_diag_matrix_fixed<T,N>::as_matrix_fixed() const
00158 {
00159   vnl_matrix_fixed<T,N,N> ret;
00160   for (unsigned i = 0; i < N; ++i)
00161   {
00162     unsigned j;
00163     for (j = 0; j < i; ++j)
00164       ret(i,j) = T(0);
00165     for (j = i+1; j < N; ++j)
00166       ret(i,j) = T(0);
00167     ret(i,i) = diagonal_[i];
00168   }
00169   return ret;
00170 }
00171 
00172 //: Invert a vnl_diag_matrix_fixed in-situ, then returns *this.
00173 // Just replaces each element with its reciprocal.
00174 template <class T, unsigned int N>
00175 inline vnl_diag_matrix_fixed<T,N>& vnl_diag_matrix_fixed<T,N>::invert_in_place()
00176 {
00177   T* d = data_block();
00178   T one = T(1);
00179   for (unsigned i = 0; i < N; ++i)
00180     d[i] = one / d[i];
00181   return *this;
00182 }
00183 
00184 //: Return determinant as product of diagonal values.
00185 template <class T, unsigned int N>
00186 inline T vnl_diag_matrix_fixed<T,N>::determinant() const
00187 {
00188   T det = T(1);
00189   T const* d = data_block();
00190   for (unsigned i = 0; i < N; ++i)
00191     det *= d[i];
00192   return det;
00193 }
00194 
00195 //: Multiply two vnl_diag_matrices.  Just multiply the diag elements - n flops
00196 // \relatesalso vnl_diag_matrix_fixed
00197 template <class T, unsigned int N>
00198 inline vnl_diag_matrix_fixed<T,N> operator* (vnl_diag_matrix_fixed<T,N> const& A, vnl_diag_matrix_fixed<T,N> const& B)
00199 {
00200   vnl_diag_matrix_fixed<T,N> ret = A;
00201   for (unsigned i = 0; i < N; ++i)
00202     ret(i,i) *= B(i,i);
00203   return ret;
00204 }
00205 
00206 //: Multiply a vnl_matrix by a vnl_diag_matrix_fixed.  Just scales the columns - mn flops
00207 // \relatesalso vnl_diag_matrix_fixed
00208 // \relatesalso vnl_matrix
00209 template <class T, unsigned int R, unsigned int C>
00210 inline vnl_matrix_fixed<T,R,C> operator* (vnl_matrix_fixed<T,R,C> const& A, vnl_diag_matrix_fixed<T,C> const& D)
00211 {
00212   vnl_matrix_fixed<T,R,C> ret;
00213   for (unsigned i = 0; i < R; ++i)
00214     for (unsigned j = 0; j < C; ++j)
00215       ret(i,j) = A(i,j) * D(j,j);
00216   return ret;
00217 }
00218 
00219 //: Multiply a vnl_diag_matrix_fixed by a vnl_matrix.  Just scales the rows - mn flops
00220 // \relatesalso vnl_diag_matrix_fixed
00221 // \relatesalso vnl_matrix
00222 template <class T, unsigned int R, unsigned int C>
00223 inline vnl_matrix_fixed<T,R,C> operator* (vnl_diag_matrix_fixed<T,R> const& D, vnl_matrix_fixed<T,R,C> const& A)
00224 {
00225   vnl_matrix_fixed<T,R,C> ret;
00226   T const* d = D.data_block();
00227   for (unsigned i = 0; i < R; ++i)
00228     for (unsigned j = 0; j < C; ++j)
00229       ret(i,j) = A(i,j) * d[i];
00230   return ret;
00231 }
00232 
00233 //: Add two vnl_diag_matrices.  Just add the diag elements - n flops
00234 // \relatesalso vnl_diag_matrix_fixed
00235 template <class T, unsigned int N>
00236 inline vnl_diag_matrix_fixed<T,N> operator+ (vnl_diag_matrix_fixed<T,N> const& A, vnl_diag_matrix_fixed<T,N> const& B)
00237 {
00238   vnl_diag_matrix_fixed<T,N> ret = A;
00239   for (unsigned i = 0; i < N; ++i)
00240     ret(i,i) += B(i,i);
00241   return ret;
00242 }
00243 
00244 //: Add a vnl_diag_matrix_fixed to a vnl_matrix.  n adds, mn copies.
00245 // \relatesalso vnl_diag_matrix_fixed
00246 // \relatesalso vnl_matrix
00247 template <class T, unsigned int N>
00248 inline vnl_matrix_fixed<T,N,N> operator+ (vnl_matrix_fixed<T,N,N> const& A, vnl_diag_matrix_fixed<T,N> const& D)
00249 {
00250   vnl_matrix_fixed<T,N,N> ret(A);
00251   T const* d = D.data_block();
00252   for (unsigned j = 0; j < N; ++j)
00253     ret(j,j) += d[j];
00254   return ret;
00255 }
00256 
00257 //: Add a vnl_matrix to a vnl_diag_matrix_fixed.  n adds, mn copies.
00258 // \relatesalso vnl_diag_matrix_fixed
00259 // \relatesalso vnl_matrix
00260 template <class T, unsigned int N>
00261 inline vnl_matrix_fixed<T,N,N> operator+ (vnl_diag_matrix_fixed<T,N> const& D, vnl_matrix_fixed<T,N,N> const& A)
00262 {
00263   return A + D;
00264 }
00265 
00266 //: Subtract two vnl_diag_matrices.  Just subtract the diag elements - n flops
00267 // \relatesalso vnl_diag_matrix_fixed
00268 template <class T, unsigned int N>
00269 inline vnl_diag_matrix_fixed<T,N> operator- (vnl_diag_matrix_fixed<T,N> const& A, vnl_diag_matrix_fixed<T,N> const& B)
00270 {
00271   vnl_diag_matrix_fixed<T,N> ret(A);
00272   for (unsigned i = 0; i < N; ++i)
00273     ret(i,i) -= B(i,i);
00274   return ret;
00275 }
00276 
00277 //: Subtract a vnl_diag_matrix_fixed from a vnl_matrix.  n adds, mn copies.
00278 // \relatesalso vnl_diag_matrix_fixed
00279 // \relatesalso vnl_matrix
00280 template <class T, unsigned int N>
00281 inline vnl_matrix_fixed<T,N,N> operator- (vnl_matrix_fixed<T,N,N> const& A, vnl_diag_matrix_fixed<T,N> const& D)
00282 {
00283   vnl_matrix_fixed<T,N,N> ret(A);
00284   T const* d = D.data_block();
00285   for (unsigned j = 0; j < N; ++j)
00286     ret(j,j) -= d[j];
00287   return ret;
00288 }
00289 
00290 //: Subtract a vnl_matrix from a vnl_diag_matrix_fixed.  n adds, mn copies.
00291 // \relatesalso vnl_diag_matrix_fixed
00292 // \relatesalso vnl_matrix
00293 template <class T, unsigned int N>
00294 inline vnl_matrix_fixed<T,N,N> operator- (vnl_diag_matrix_fixed<T,N> const& D, vnl_matrix_fixed<T,N,N> const& A)
00295 {
00296   vnl_matrix_fixed<T,N,N> ret;
00297   T const* d = D.data_block();
00298   for (unsigned i = 0; i < N; ++i)
00299   {
00300     for (unsigned j = 0; j < i; ++j)
00301       ret(i,j) = -A(i,j);
00302     for (unsigned j = i+1; j < N; ++j)
00303       ret(i,j) = -A(i,j);
00304     ret(i,i) = d[i] - A(i,i);
00305   }
00306   return ret;
00307 }
00308 
00309 //: Multiply a vnl_diag_matrix_fixed by a vnl_vector_fixed.  n flops.
00310 // \relatesalso vnl_diag_matrix_fixed
00311 // \relatesalso vnl_vector_fixed
00312 template <class T, unsigned int N>
00313 inline vnl_vector_fixed<T,N> operator* (vnl_diag_matrix_fixed<T,N> const& D, vnl_vector_fixed<T,N> const& A)
00314 {
00315   return element_product(D.diagonal(), A);
00316 }
00317 
00318 //: Multiply a vnl_vector_fixed by a vnl_diag_matrix_fixed.  n flops.
00319 // \relatesalso vnl_diag_matrix_fixed
00320 // \relatesalso vnl_vector_fixed
00321 template <class T, unsigned int N>
00322 inline vnl_vector_fixed<T,N> operator* (vnl_vector_fixed<T,N> const& A, vnl_diag_matrix_fixed<T,N> const& D)
00323 {
00324   return element_product(D.diagonal(), A);
00325 }
00326 
00327 #endif // vnl_diag_matrix_fixed_h_