core/vnl/vnl_diag_matrix.h

Go to the documentation of this file.
00001 // This is core/vnl/vnl_diag_matrix.h
00002 #ifndef vnl_diag_matrix_h_
00003 #define vnl_diag_matrix_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 // \endverbatim
00020 
00021 #include <vcl_cassert.h>
00022 #include <vcl_iosfwd.h>
00023 #include <vnl/vnl_vector.h>
00024 #include <vnl/vnl_matrix.h>
00025 
00026 // forward declarations
00027 template <class T> class vnl_diag_matrix;
00028 template <class T> vnl_vector<T> operator*(vnl_diag_matrix<T> const&, vnl_vector<T> const&);
00029 
00030 //: stores a diagonal matrix as a single vector.
00031 //  vnl_diag_matrix stores a diagonal matrix for time and space efficiency.
00032 //  Specifically, only the diagonal elements are stored, and some matrix
00033 //  operations (currently *, + and -) are overloaded to use more efficient
00034 //  algorithms.
00035 
00036 export
00037 template <class T>
00038 class vnl_diag_matrix
00039 {
00040   vnl_vector<T> diagonal_;
00041 
00042  public:
00043   vnl_diag_matrix() {}
00044 
00045   //: Construct an empty diagonal matrix.
00046   vnl_diag_matrix(unsigned nn) : diagonal_(nn) {}
00047 
00048   //: Construct a diagonal matrix with diagonal elements equal to value.
00049   vnl_diag_matrix(unsigned nn, T const& value) : diagonal_(nn, value) {}
00050 
00051   //: Construct a diagonal matrix from a vnl_vector.
00052   //  The vector elements become the diagonal elements.
00053   vnl_diag_matrix(vnl_vector<T> const& that): diagonal_(that) {}
00054  ~vnl_diag_matrix() {}
00055 
00056   inline vnl_diag_matrix& operator=(vnl_diag_matrix<T> 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<T>& operator*=(T v) { diagonal_ *= v; return *this; }
00065   //: In-place arithmetic operation
00066   inline vnl_diag_matrix<T>& operator/=(T v) { diagonal_ /= v; return *this; }
00067 
00068   // Computations--------------------------------------------------------------
00069 
00070   void invert_in_place();
00071   T determinant() const;
00072   vnl_vector<T> solve(vnl_vector<T> const& b) const;
00073   void solve(vnl_vector<T> const& b, vnl_vector<T>* 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   //: Set all diagonal elements of matrix to specified value.
00102   inline void fill_diagonal (T const& v) { diagonal_.fill(v); }
00103 
00104   // iterators
00105 
00106   typedef typename vnl_vector<T>::iterator iterator;
00107   inline iterator begin() { return diagonal_.begin(); }
00108   inline iterator end() { return diagonal_.end(); }
00109   typedef typename vnl_vector<T>::const_iterator const_iterator;
00110   inline const_iterator begin() const { return diagonal_.begin(); }
00111   inline const_iterator end() const { return diagonal_.end(); }
00112 
00113   inline unsigned size() const { return diagonal_.size(); }
00114   inline unsigned rows() const { return diagonal_.size(); }
00115   inline unsigned cols() const { return diagonal_.size(); }
00116   inline unsigned columns() const { return diagonal_.size(); }
00117 
00118   // Need this until we add a vnl_diag_matrix ctor to vnl_matrix;
00119   inline vnl_matrix<T> asMatrix() const;
00120 
00121   inline vnl_matrix<T> as_ref() const { return asMatrix(); }
00122 
00123   // This is as good as a vnl_diag_matrix ctor for vnl_matrix:
00124   inline operator vnl_matrix<T> () const { return asMatrix(); }
00125 
00126   inline void set_size(int n) { diagonal_.set_size(n); }
00127 
00128   inline void clear() { diagonal_.clear(); }
00129   inline void fill(T const &x) { diagonal_.fill(x); }
00130 
00131   //: Return pointer to the diagonal elements as a contiguous 1D C array;
00132   inline T*       data_block()       { return diagonal_.data_block(); }
00133   inline T const* data_block() const { return diagonal_.data_block(); }
00134 
00135   //: Return diagonal elements as a vector
00136   inline vnl_vector<T> const& diagonal() const { return diagonal_; }
00137 
00138   //: Set diagonal elements using vector
00139   inline void set(vnl_vector<T> const& v)  { diagonal_=v; }
00140 
00141  private:
00142   #if VCL_NEED_FRIEND_FOR_TEMPLATE_OVERLOAD
00143   friend vnl_vector<T> operator*(vnl_diag_matrix<T> const&,vnl_vector<T> const&);
00144   #endif
00145 };
00146 
00147 //:
00148 // \relatesalso vnl_diag_matrix
00149 template <class T>
00150 vcl_ostream& operator<< (vcl_ostream&, vnl_diag_matrix<T> const&);
00151 
00152 //: Convert a vnl_diag_matrix to a Matrix.
00153 template <class T>
00154 inline vnl_matrix<T> vnl_diag_matrix<T>::asMatrix() const
00155 {
00156   unsigned len = diagonal_.size();
00157   vnl_matrix<T> ret(len, len);
00158   for (unsigned i = 0; i < len; ++i)
00159   {
00160     unsigned j;
00161     for (j = 0; j < i; ++j)
00162       ret(i,j) = T(0);
00163     for (j = i+1; j < len; ++j)
00164       ret(i,j) = T(0);
00165     ret(i,i) = diagonal_[i];
00166   }
00167   return ret;
00168 }
00169 
00170 //: Invert a vnl_diag_matrix in-situ.
00171 // Just replaces each element with its reciprocal.
00172 template <class T>
00173 inline void vnl_diag_matrix<T>::invert_in_place()
00174 {
00175   unsigned len = diagonal_.size();
00176   T* d = data_block();
00177   T one = T(1);
00178   for (unsigned i = 0; i < len; ++i)
00179     d[i] = one / d[i];
00180 }
00181 
00182 //: Return determinant as product of diagonal values.
00183 template <class T>
00184 inline T vnl_diag_matrix<T>::determinant() const
00185 {
00186   T det = T(1);
00187   T const* d = data_block();
00188   unsigned len = diagonal_.size();
00189   for (unsigned i = 0; i < len; ++i)
00190     det *= d[i];
00191   return det;
00192 }
00193 
00194 //: Multiply two vnl_diag_matrices.  Just multiply the diag elements - n flops
00195 // \relatesalso vnl_diag_matrix
00196 template <class T>
00197 inline vnl_diag_matrix<T> operator* (vnl_diag_matrix<T> const& A, vnl_diag_matrix<T> const& B)
00198 {
00199   assert(A.size() == B.size());
00200   vnl_diag_matrix<T> ret = A;
00201   for (unsigned i = 0; i < A.size(); ++i)
00202     ret(i,i) *= B(i,i);
00203   return ret;
00204 }
00205 
00206 //: Multiply a vnl_matrix by a vnl_diag_matrix.  Just scales the columns - mn flops
00207 // \relatesalso vnl_diag_matrix
00208 // \relatesalso vnl_matrix
00209 template <class T>
00210 inline vnl_matrix<T> operator* (vnl_matrix<T> const& A, vnl_diag_matrix<T> const& D)
00211 {
00212   assert(A.columns() == D.size());
00213   vnl_matrix<T> ret(A.rows(), A.columns());
00214   for (unsigned i = 0; i < A.rows(); ++i)
00215     for (unsigned j = 0; j < A.columns(); ++j)
00216       ret(i,j) = A(i,j) * D(j,j);
00217   return ret;
00218 }
00219 
00220 //: Multiply a vnl_diag_matrix by a vnl_matrix.  Just scales the rows - mn flops
00221 // \relatesalso vnl_diag_matrix
00222 // \relatesalso vnl_matrix
00223 template <class T>
00224 inline vnl_matrix<T> operator* (vnl_diag_matrix<T> const& D, vnl_matrix<T> const& A)
00225 {
00226   assert(A.rows() == D.size());
00227   vnl_matrix<T> ret(A.rows(), A.columns());
00228   T const* d = D.data_block();
00229   for (unsigned i = 0; i < A.rows(); ++i)
00230     for (unsigned j = 0; j < A.columns(); ++j)
00231       ret(i,j) = A(i,j) * d[i];
00232   return ret;
00233 }
00234 
00235 //: Add two vnl_diag_matrices.  Just add the diag elements - n flops
00236 // \relatesalso vnl_diag_matrix
00237 template <class T>
00238 inline vnl_diag_matrix<T> operator+ (vnl_diag_matrix<T> const& A, vnl_diag_matrix<T> const& B)
00239 {
00240   assert(A.size() == B.size());
00241   vnl_diag_matrix<T> ret = A;
00242   for (unsigned i = 0; i < A.size(); ++i)
00243     ret(i,i) += B(i,i);
00244   return ret;
00245 }
00246 
00247 //: Add a vnl_diag_matrix to a vnl_matrix.  n adds, mn copies.
00248 // \relatesalso vnl_diag_matrix
00249 // \relatesalso vnl_matrix
00250 template <class T>
00251 inline vnl_matrix<T> operator+ (vnl_matrix<T> const& A, vnl_diag_matrix<T> const& D)
00252 {
00253   const unsigned n = D.size();
00254   assert(A.rows() == n); assert(A.columns() == n);
00255   vnl_matrix<T> ret(A);
00256   T const* d = D.data_block();
00257   for (unsigned j = 0; j < n; ++j)
00258     ret(j,j) += d[j];
00259   return ret;
00260 }
00261 
00262 //: Add a vnl_matrix to a vnl_diag_matrix.  n adds, mn copies.
00263 // \relatesalso vnl_diag_matrix
00264 // \relatesalso vnl_matrix
00265 template <class T>
00266 inline vnl_matrix<T> operator+ (vnl_diag_matrix<T> const& D, vnl_matrix<T> const& A)
00267 {
00268   return A + D;
00269 }
00270 
00271 //: Subtract two vnl_diag_matrices.  Just subtract the diag elements - n flops
00272 // \relatesalso vnl_diag_matrix
00273 template <class T>
00274 inline vnl_diag_matrix<T> operator- (vnl_diag_matrix<T> const& A, vnl_diag_matrix<T> const& B)
00275 {
00276   assert(A.size() == B.size());
00277   vnl_diag_matrix<T> ret = A;
00278   for (unsigned i = 0; i < A.size(); ++i)
00279     ret(i,i) -= B(i,i);
00280   return ret;
00281 }
00282 
00283 //: Subtract a vnl_diag_matrix from a vnl_matrix.  n adds, mn copies.
00284 // \relatesalso vnl_diag_matrix
00285 // \relatesalso vnl_matrix
00286 template <class T>
00287 inline vnl_matrix<T> operator- (vnl_matrix<T> const& A, vnl_diag_matrix<T> const& D)
00288 {
00289   const unsigned n = D.size();
00290   assert(A.rows() == n); assert(A.columns() == n);
00291   vnl_matrix<T> ret(A);
00292   T const* d = D.data_block();
00293   for (unsigned j = 0; j < n; ++j)
00294     ret(j,j) -= d[j];
00295   return ret;
00296 }
00297 
00298 //: Subtract a vnl_matrix from a vnl_diag_matrix.  n adds, mn copies.
00299 // \relatesalso vnl_diag_matrix
00300 // \relatesalso vnl_matrix
00301 template <class T>
00302 inline vnl_matrix<T> operator- (vnl_diag_matrix<T> const& D, vnl_matrix<T> const& A)
00303 {
00304   const unsigned n = D.size();
00305   assert(A.rows() == n); assert(A.columns() == n);
00306   vnl_matrix<T> ret(n, n);
00307   T const* d = D.data_block();
00308   for (unsigned i = 0; i < n; ++i)
00309   {
00310     for (unsigned j = 0; j < i; ++j)
00311       ret(i,j) = -A(i,j);
00312     for (unsigned j = i+1; j < n; ++j)
00313       ret(i,j) = -A(i,j);
00314     ret(i,i) = d[i] - A(i,i);
00315   }
00316   return ret;
00317 }
00318 
00319 //: Multiply a vnl_diag_matrix by a vnl_vector.  n flops.
00320 // \relatesalso vnl_diag_matrix
00321 // \relatesalso vnl_vector
00322 template <class T>
00323 inline vnl_vector<T> operator* (vnl_diag_matrix<T> const& D, vnl_vector<T> const& A)
00324 {
00325   assert(A.size() == D.size());
00326   return element_product(D.diagonal(), A);
00327 }
00328 
00329 //: Multiply a vnl_vector by a vnl_diag_matrix.  n flops.
00330 // \relatesalso vnl_diag_matrix
00331 // \relatesalso vnl_vector
00332 template <class T>
00333 inline vnl_vector<T> operator* (vnl_vector<T> const& A, vnl_diag_matrix<T> const& D)
00334 {
00335   assert(A.size() == D.size());
00336   return element_product(D.diagonal(), A);
00337 }
00338 
00339 #endif // vnl_diag_matrix_h_

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