core/vnl/vnl_sym_matrix.h
Go to the documentation of this file.
00001 // This is core/vnl/vnl_sym_matrix.h
00002 #ifndef vnl_sym_matrix_h_
00003 #define vnl_sym_matrix_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Contains class for symmetric matrices
00010 // \author Ian Scott (Manchester ISBE)
00011 // \date   6 Dec 2001
00012 
00013 #include <vcl_cassert.h>
00014 #include <vcl_iosfwd.h>
00015 #include <vnl/vnl_vector.h>
00016 #include <vnl/vnl_matrix.h>
00017 #include <vnl/vnl_c_vector.h>
00018 
00019 //: stores a symmetric matrix as just the diagonal and lower triangular part
00020 //  vnl_sym_matrix stores a symmetric matrix for time and space efficiency.
00021 //  Specifically, only the diagonal and lower triangular elements are stored.
00022 
00023 export
00024 template <class T>
00025 class vnl_sym_matrix
00026 {
00027  public:
00028   //: Construct an empty symmetric matrix.
00029   vnl_sym_matrix(): data_(0), index_(0), nn_(0) {}
00030 
00031   //: Construct a symmetric matrix of size nn by nn.
00032   explicit vnl_sym_matrix(unsigned nn):
00033   data_(vnl_c_vector<T>::allocate_T(nn * (nn + 1) / 2)),
00034   index_(vnl_c_vector<T>::allocate_Tptr(nn)),
00035   nn_(nn) { setup_index(); }
00036 
00037   //: Construct a symmetric matrix with elements equal to data
00038   // Value should be stored row-wise, and contain the
00039   // n*(n+1)/2 diagonal and lower triangular elements
00040   inline vnl_sym_matrix(T const * data, unsigned nn);
00041 
00042   //: Construct a symmetric matrix with all elements equal to value
00043   inline vnl_sym_matrix(unsigned nn, const T & value);
00044 
00045   //: Construct a symmetric matrix from a full matrix.
00046   // If NDEBUG is set, the symmetry of the matrix will be asserted.
00047   inline explicit vnl_sym_matrix(vnl_matrix<T> const& that);
00048 
00049   //: Copy constructor
00050   inline vnl_sym_matrix(vnl_sym_matrix<T> const& that);
00051 
00052   ~vnl_sym_matrix()
00053   { vnl_c_vector<T>::deallocate(data_, size());
00054     vnl_c_vector<T>::deallocate(index_, nn_);}
00055 
00056   vnl_sym_matrix<T>& operator=(vnl_sym_matrix<T> const& that);
00057 
00058   // Operations----------------------------------------------------------------
00059 
00060   //: In-place arithmetic operations
00061   vnl_sym_matrix<T>& operator*=(T v) { vnl_c_vector<T>::scale(data_, data_, size(), v); return *this; }
00062   //: In-place arithmetic operations
00063   vnl_sym_matrix<T>& operator/=(T v) { vnl_c_vector<T>::scale(data_, data_, size(), ((T)1)/v); return *this; }
00064 
00065 
00066   // Data Access---------------------------------------------------------------
00067 
00068   T operator () (unsigned i, unsigned j) const {
00069     return (i > j) ? index_[i][j] : index_[j][i];
00070   }
00071 
00072   T& operator () (unsigned i, unsigned j) {
00073     return (i > j) ? index_[i][j] : index_[j][i];
00074   }
00075 
00076   //: Access a half-row of data.
00077   // Only the first i+1 values from this pointer are valid.
00078   const T* operator [] (unsigned i) const {
00079     assert (i < nn_);
00080     return index_[i];
00081   }
00082 
00083   //: fast access, however i >= j
00084   T fast (unsigned i, unsigned j) const {
00085     assert (i >= j);
00086     return index_[i][j];
00087   }
00088 
00089   //: fast access, however i >= j
00090   T& fast (unsigned i, unsigned j) {
00091     assert (i >= j);
00092     return index_[i][j];
00093   }
00094 
00095   // iterators
00096 
00097   typedef T* iterator;
00098   inline iterator begin() { return data_; }
00099   inline iterator end() { return data_ + size(); }
00100   typedef const T* const_iterator;
00101   inline const_iterator begin() const { return data_; }
00102   inline const_iterator end() const { return data_ + size(); }
00103 
00104   unsigned long size() const { return nn_ * (nn_ + 1) / 2; }
00105   unsigned rows() const { return nn_; }
00106   unsigned cols() const { return nn_; }
00107   unsigned columns() const { return nn_; }
00108 
00109   // Need this until we add a vnl_sym_matrix ctor to vnl_matrix;
00110   inline vnl_matrix<T> as_matrix() const;
00111 
00112   //: Resize matrix to n by n.
00113   // You will loose any existing data.
00114   inline void set_size(int n);
00115 
00116 
00117   //: Return pointer to the lower triangular elements as a contiguous 1D C array;
00118   T*       data_block()       { return data_; }
00119   //: Return pointer to the lower triangular elements as a contiguous 1D C array;
00120   T const* data_block() const { return data_; }
00121 
00122   //: Set the first i values of row i
00123   // or the top i values of column i
00124   void set_half_row (const vnl_vector<T> &half_row, unsigned i);
00125 
00126   //: Replaces the symmetric submatrix of THIS matrix with the elements of matrix m.
00127   // Starting at top left corner. Complexity is $O(m^2)$.
00128   vnl_sym_matrix<T>& update (vnl_sym_matrix<T> const& m, unsigned diag_start=0);
00129 
00130   //: Swap contents of m with THIS
00131   void swap(vnl_sym_matrix &m);
00132 
00133  protected:
00134 //: Set up the index array
00135   inline void setup_index() {
00136     T * data = data_;
00137     for (unsigned i=0; i< nn_; ++i) { index_[i] = data; data += i+1; }
00138   }
00139 
00140   T* data_;
00141   T** index_;
00142   unsigned nn_;
00143 };
00144 
00145 //:
00146 // \relatesalso vnl_sym_matrix
00147 template <class T> vcl_ostream& operator<< (vcl_ostream&, vnl_sym_matrix<T> const&);
00148 
00149 
00150 template <class T>
00151 inline vnl_sym_matrix<T>::vnl_sym_matrix(T const * data, unsigned nn):
00152   data_(vnl_c_vector<T>::allocate_T(nn * (nn + 1) / 2)),
00153   index_(vnl_c_vector<T>::allocate_Tptr(nn)),
00154   nn_(nn)
00155 {
00156   setup_index();
00157   for (unsigned i = 0; i < nn_; ++i)
00158     for (unsigned j = 0; j <= i; ++j)
00159       fast(i,j) = *(data++);
00160 }
00161 
00162 template <class T>
00163 inline vnl_sym_matrix<T>::vnl_sym_matrix(unsigned nn, const T & value):
00164   data_(vnl_c_vector<T>::allocate_T(nn * (nn + 1) / 2)),
00165   index_(vnl_c_vector<T>::allocate_Tptr(nn)),
00166   nn_(nn)
00167 {
00168   setup_index();
00169   vnl_c_vector<T>::fill(data_, size(), value);
00170 }
00171 
00172 
00173 template <class T>
00174 inline vnl_sym_matrix<T>::vnl_sym_matrix(vnl_matrix<T> const& that):
00175   data_(vnl_c_vector<T>::allocate_T(that.rows() * (that.rows() + 1) / 2)),
00176   index_(vnl_c_vector<T>::allocate_Tptr(that.rows())),
00177   nn_(that.rows())
00178 {
00179   setup_index();
00180   assert (nn_ == that.cols());
00181   for (unsigned i = 0; i < nn_; ++i)
00182     for (unsigned j = 0; j <= i; ++j)
00183     {
00184       assert( that(i,j) == that(j,i) );
00185       fast(i,j) = that(i,j);
00186     }
00187 }
00188 
00189 template <class T>
00190 inline vnl_sym_matrix<T>::vnl_sym_matrix(vnl_sym_matrix<T> const& that):
00191   data_(0), index_(0), nn_(0)
00192 {
00193   set_size(that.rows());
00194   update(that);
00195 }
00196 
00197 //: Convert a vnl_sym_matrix to a vnl_matrix.
00198 template <class T>
00199 inline vnl_matrix<T> vnl_sym_matrix<T>::as_matrix() const
00200 {
00201   vnl_matrix<T> ret(nn_, nn_);
00202   for (unsigned i = 0; i < nn_; ++i)
00203     for (unsigned j = 0; j <= i; ++j)
00204       ret(i,j) = ret(j,i) = fast(i,j);
00205   return ret;
00206 }
00207 
00208 
00209 template <class T>
00210 inline void vnl_sym_matrix<T>::set_size(int n)
00211 {
00212   if (n == (int)nn_) return;
00213 
00214   vnl_c_vector<T>::deallocate(data_, size());
00215   vnl_c_vector<T>::deallocate(index_, nn_);
00216 
00217   nn_ = n;
00218   data_ = vnl_c_vector<T>::allocate_T(size());
00219   index_ = vnl_c_vector<T>::allocate_Tptr(n);
00220 
00221   setup_index();
00222 }
00223 
00224 template <class T>
00225 bool operator==(const vnl_sym_matrix<T> &a, const vnl_sym_matrix<T> &b);
00226 
00227 template <class T>
00228 bool operator==(const vnl_sym_matrix<T> &a, const vnl_matrix<T> &b);
00229 
00230 template <class T>
00231 bool operator==(const vnl_matrix<T> &a, const vnl_sym_matrix<T> &b);
00232 
00233 //: Swap the contents of a and b.
00234 // \relatesalso vnl_sym_matrix
00235 template <class T>
00236 void swap(vnl_sym_matrix<T> &a, vnl_sym_matrix<T> &b)
00237 { a.swap(b); }
00238 
00239 
00240 #endif // vnl_sym_matrix_h_