vnl_sym_matrix.h
Go to the documentation of this file.
1 // This is core/vnl/vnl_sym_matrix.h
2 #ifndef vnl_sym_matrix_h_
3 #define vnl_sym_matrix_h_
4 //:
5 // \file
6 // \brief Contains class for symmetric matrices
7 // \author Ian Scott (Manchester ISBE)
8 // \date 6 Dec 2001
9 
10 #include <iosfwd>
11 #include <cassert>
12 #ifdef _MSC_VER
13 # include <vcl_msvc_warnings.h>
14 #endif
15 #include <vnl/vnl_vector.h>
16 #include <vnl/vnl_matrix.h>
17 #include <vnl/vnl_c_vector.h>
18 #include "vnl/vnl_export.h"
19 
20 template <class T> class vnl_sym_matrix;
21 
22 //: stores a symmetric matrix as just the diagonal and lower triangular part
23 // vnl_sym_matrix stores a symmetric matrix for time and space efficiency.
24 // Specifically, only the diagonal and lower triangular elements are stored.
25 
26 template <class T>
27 class VNL_EXPORT vnl_sym_matrix
28 {
29  public:
30  //: Construct an empty symmetric matrix.
31  vnl_sym_matrix(): data_(nullptr), index_(nullptr), nn_(0) {}
32 
33  //: Construct a symmetric matrix of size nn by nn.
34  explicit vnl_sym_matrix(unsigned nn):
35  data_(vnl_c_vector<T>::allocate_T(nn * (nn + 1) / 2)),
36  index_(vnl_c_vector<T>::allocate_Tptr(nn)),
37  nn_(nn) { setup_index(); }
38 
39  //: Construct a symmetric matrix with elements equal to data
40  // Value should be stored row-wise, and contain the
41  // n*(n+1)/2 diagonal and lower triangular elements
42  inline vnl_sym_matrix(T const * data, unsigned nn);
43 
44  //: Construct a symmetric matrix with all elements equal to value
45  inline vnl_sym_matrix(unsigned nn, const T & value);
46 
47  //: Construct a symmetric matrix from a full matrix.
48  // If NDEBUG is set, the symmetry of the matrix will be asserted.
49  inline explicit vnl_sym_matrix(vnl_matrix<T> const& that);
50 
51  //: Copy constructor
52  inline vnl_sym_matrix(vnl_sym_matrix<T> const& that);
53 
54  ~vnl_sym_matrix();
55 
56  vnl_sym_matrix<T>& operator=(vnl_sym_matrix<T> const& that);
57 
58  // Operations----------------------------------------------------------------
59 
60  //: In-place arithmetic operations
61  inline vnl_sym_matrix<T>& operator*=(T v) { vnl_c_vector<T>::scale(data_, data_, size(), v); return *this; }
62  //: In-place arithmetic operations
63  inline vnl_sym_matrix<T>& operator/=(T v) { vnl_c_vector<T>::scale(data_, data_, size(), ((T)1)/v); return *this; }
64 
65 
66  // Data Access---------------------------------------------------------------
67 
68  inline T operator () (unsigned i, unsigned j) const {
69  return (i > j) ? index_[i][j] : index_[j][i];
70  }
71 
72  inline T& operator () (unsigned i, unsigned j) {
73  return (i > j) ? index_[i][j] : index_[j][i];
74  }
75 
76  //: Access a half-row of data.
77  // Only the first i+1 values from this pointer are valid.
78  inline const T* operator [] (unsigned i) const {
79  assert (i < nn_);
80  return index_[i];
81  }
82 
83  //: fast access, however i >= j
84  inline T fast (unsigned i, unsigned j) const {
85  assert (i >= j);
86  return index_[i][j];
87  }
88 
89  //: fast access, however i >= j
90  inline T& fast (unsigned i, unsigned j) {
91  assert (i >= j);
92  return index_[i][j];
93  }
94 
95  // iterators
96 
97  typedef T* iterator;
98  inline iterator begin() { return data_; }
99  inline iterator end() { return data_ + size(); }
100  typedef const T* const_iterator;
101  inline const_iterator begin() const { return data_; }
102  inline const_iterator end() const { return data_ + size(); }
103 
104  //: Return the total number of elements stored by the matrix.
105  // Since vnl_sym_matrix only stores the diagonal and lower
106  // triangular elements and must be square, this returns
107  // n*(n+1)/2, where n == rows() == cols().
108  inline unsigned int size() const { return nn_ * (nn_ + 1) / 2; }
109 
110  //: Return the number of rows.
111  inline unsigned int rows() const { return nn_; }
112 
113  //: Return the number of columns.
114  // A synonym for columns().
115  inline unsigned int cols() const { return nn_; }
116 
117  //: Return the number of columns.
118  // A synonym for cols().
119  inline unsigned int columns() const { return nn_; }
120 
121  //: set element
122  inline void put (unsigned r, unsigned c, T const& v)
123  {
124 #if VNL_CONFIG_CHECK_BOUNDS
125  if (r >= this->nn_) // If invalid size specified
126  vnl_error_matrix_row_index("put", r); // Raise exception
127  if (c >= this->nn_) // If invalid size specified
128  vnl_error_matrix_col_index("put", c); // Raise exception
129 #endif
130  (r > c) ? index_[r][c] = v : index_[c][r] = v;
131  }
132 
133  //: get element
134  inline T get (unsigned r, unsigned c) const
135  {
136 #if VNL_CONFIG_CHECK_BOUNDS
137  if (r >= this->nn_) // If invalid size specified
138  vnl_error_matrix_row_index("get", r); // Raise exception
139  if (c >= this->nn_) // If invalid size specified
140  vnl_error_matrix_col_index("get", c); // Raise exception
141 #endif
142  return (r > c) ? index_[r][c] : index_[c][r];
143  }
144 
145  // Need this until we add a vnl_sym_matrix ctor to vnl_matrix;
146  inline vnl_matrix<T> as_matrix() const;
147 
148  //: Resize matrix to n by n.
149  // You will loose any existing data.
150  inline void set_size(int n);
151 
152 
153  //: Return pointer to the lower triangular elements as a contiguous 1D C array;
154  T* data_block() { return data_; }
155  //: Return pointer to the lower triangular elements as a contiguous 1D C array;
156  T const* data_block() const { return data_; }
157 
158  //: Set the first i values of row i
159  // or the top i values of column i
160  void set_half_row (const vnl_vector<T> &half_row, unsigned i);
161 
162  //: Replaces the symmetric submatrix of THIS matrix with the elements of matrix m.
163  // Starting at top left corner. Complexity is $O(m^2)$.
164  vnl_sym_matrix<T>& update (vnl_sym_matrix<T> const& m, unsigned diag_start=0);
165 
166  //: Swap contents of m with THIS
167  void swap(vnl_sym_matrix &m);
168 
169  protected:
170 //: Set up the index array
171  void setup_index();
172 
173  T* data_;
174  T** index_;
175  unsigned nn_;
176 };
177 
178 //:
179 // \relatesalso vnl_sym_matrix
180 template <class T> VNL_EXPORT std::ostream& operator<< (std::ostream&, vnl_sym_matrix<T> const&);
181 
182 
183 template <class T>
184 inline vnl_sym_matrix<T>::vnl_sym_matrix(T const * data, unsigned nn):
185  data_(vnl_c_vector<T>::allocate_T(nn * (nn + 1) / 2)),
186  index_(vnl_c_vector<T>::allocate_Tptr(nn)),
187  nn_(nn)
188 {
189  setup_index();
190  for (unsigned i = 0; i < nn_; ++i)
191  for (unsigned j = 0; j <= i; ++j)
192  fast(i,j) = *(data++);
193 }
194 
195 template <class T>
196 inline vnl_sym_matrix<T>::vnl_sym_matrix(unsigned nn, const T & value):
197  data_(vnl_c_vector<T>::allocate_T(nn * (nn + 1) / 2)),
198  index_(vnl_c_vector<T>::allocate_Tptr(nn)),
199  nn_(nn)
200 {
201  setup_index();
202  vnl_c_vector<T>::fill(data_, size(), value);
203 }
204 
205 
206 template <class T>
208  data_(vnl_c_vector<T>::allocate_T(that.rows() * (that.rows() + 1) / 2)),
209  index_(vnl_c_vector<T>::allocate_Tptr(that.rows())),
210  nn_(that.rows())
211 {
212  setup_index();
213  assert (nn_ == that.cols());
214  for (unsigned i = 0; i < nn_; ++i)
215  for (unsigned j = 0; j <= i; ++j)
216  {
217  assert( that(i,j) == that(j,i) );
218  fast(i,j) = that(i,j);
219  }
220 }
221 
222 template <class T>
224  data_(nullptr), index_(nullptr), nn_(0)
225 {
226  set_size(that.rows());
227  update(that);
228 }
229 
230 //: Convert a vnl_sym_matrix to a vnl_matrix.
231 template <class T>
233 {
234  vnl_matrix<T> ret(nn_, nn_);
235  for (unsigned i = 0; i < nn_; ++i)
236  for (unsigned j = 0; j <= i; ++j)
237  ret(i,j) = ret(j,i) = fast(i,j);
238  return ret;
239 }
240 
241 
242 template <class T>
243 inline void vnl_sym_matrix<T>::set_size(int n)
244 {
245  if (n == (int)nn_) return;
246 
247  vnl_c_vector<T>::deallocate(data_, static_cast<std::size_t>(size()));
248  vnl_c_vector<T>::deallocate(index_, static_cast<std::size_t>( nn_));
249 
250  nn_ = n;
251  data_ = vnl_c_vector<T>::allocate_T(size());
252  index_ = vnl_c_vector<T>::allocate_Tptr(n);
253 
254  setup_index();
255 }
256 
257 template <class T> VNL_EXPORT
258 bool operator==(const vnl_sym_matrix<T> &a, const vnl_sym_matrix<T> &b);
259 
260 template <class T> VNL_EXPORT
261 bool operator==(const vnl_sym_matrix<T> &a, const vnl_matrix<T> &b);
262 
263 template <class T> VNL_EXPORT
264 bool operator==(const vnl_matrix<T> &a, const vnl_sym_matrix<T> &b);
265 
266 //: Swap the contents of a and b.
267 // \relatesalso vnl_sym_matrix
268 template <class T> void swap(vnl_sym_matrix<T> &a, vnl_sym_matrix<T> &b)
269 { a.swap(b); }
270 
271 #endif // vnl_sym_matrix_h_
static void deallocate(T **, const std::size_t n_when_allocated)
unsigned int cols() const
Return the number of columns.
Definition: vnl_matrix.h:183
const T * const_iterator
const_iterator end() const
An ordinary mathematical matrix.
void swap(vnl_sym_matrix &m)
Swap contents of m with THIS.
vnl_sym_matrix< T > & update(vnl_sym_matrix< T > const &m, unsigned diag_start=0)
Replaces the symmetric submatrix of THIS matrix with the elements of matrix m.
unsigned int columns() const
Return the number of columns.
#define m
Definition: vnl_vector.h:43
T const * data_block() const
Return pointer to the lower triangular elements as a contiguous 1D C array;.
vnl_c_vector interfaces to lowlevel memory-block operations.
Definition: vnl_c_vector.h:39
iterator end()
void vnl_error_matrix_row_index(char const *fcn, int r)
Raise exception for invalid row index.
Definition: vnl_error.cxx:51
T fast(unsigned i, unsigned j) const
fast access, however i >= j.
void vnl_error_matrix_col_index(char const *fcn, int c)
Raise exception for invalid col index.
Definition: vnl_error.cxx:61
T get(unsigned r, unsigned c) const
get element.
unsigned int cols() const
Return the number of columns.
std::ostream & operator<<(std::ostream &s, vnl_decnum const &r)
decimal output.
Definition: vnl_decnum.h:393
#define v
Definition: vnl_vector.h:42
const_iterator begin() const
vnl_sym_matrix(unsigned nn)
Construct a symmetric matrix of size nn by nn.
unsigned int rows() const
Return the number of rows.
iterator begin()
T & fast(unsigned i, unsigned j)
fast access, however i >= j.
void put(unsigned r, unsigned c, T const &v)
set element.
bool operator==(int r1, vnl_finite_int< N > const &r2)
Definition: vnl_finite.h:385
static void fill(T *x, unsigned, T const &v)
x[i] = v.
unsigned int size() const
Return the total number of elements stored by the matrix.
static T * allocate_T(const std::size_t n)
An ordinary mathematical matrix.
Definition: vnl_adjugate.h:22
static T ** allocate_Tptr(const std::size_t n)
Memory allocation.
void swap(vnl_matrix< T > &A, vnl_matrix< T > &B)
Swap two matrices.
Definition: vnl_matrix.h:733
Mathematical vector class, templated by type of element.
Definition: vnl_fwd.h:16
void swap(vnl_sym_matrix< T > &a, vnl_sym_matrix< T > &b)
Swap the contents of a and b.
void set_size(int n)
Resize matrix to n by n.
T * data_block()
Return pointer to the lower triangular elements as a contiguous 1D C array;.
void setup_index()
Set up the index array.
vnl_sym_matrix< T > & operator/=(T v)
In-place arithmetic operations.
Math on blocks of memory.
vnl_sym_matrix()
Construct an empty symmetric matrix.
stores a symmetric matrix as just the diagonal and lower triangular part.
static void scale(T const *x, T *y, unsigned, T const &)
y[i] = a*x[i].
vnl_matrix< T > as_matrix() const
Convert a vnl_sym_matrix to a vnl_matrix.