vnl_diag_matrix.h
Go to the documentation of this file.
1 // This is core/vnl/vnl_diag_matrix.h
2 #ifndef vnl_diag_matrix_h_
3 #define vnl_diag_matrix_h_
4 //:
5 // \file
6 // \brief Contains class for diagonal matrices
7 // \author Andrew W. Fitzgibbon (Oxford RRG)
8 // \date 5 Aug 1996
9 //
10 // \verbatim
11 // Modifications
12 // IMS (Manchester) 16 Mar 2001: Tidied up the documentation + added binary_io
13 // Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
14 // Sep.2002 - Peter Vanroose - Added operator+, operator-, operator*
15 // Mar.2004 - Peter Vanroose - removed deprecated resize()
16 // Oct.2010 - Peter Vanroose - mutators and setters now return *this
17 // Jan.2011 - Peter Vanroose - added methods set_diagonal() & get_diagonal()
18 // \endverbatim
19 
20 #include <iosfwd>
21 #include <cassert>
22 #ifdef _MSC_VER
23 # include <vcl_msvc_warnings.h>
24 #endif
25 #include <vnl/vnl_vector.h>
26 #include <vnl/vnl_matrix.h>
27 #include "vnl/vnl_export.h"
28 
29 // forward declarations
30 template <class T> class vnl_diag_matrix;
31 template <class T> VNL_EXPORT vnl_vector<T> operator*(vnl_diag_matrix<T> const&, vnl_vector<T> const&);
32 
33 //: stores a diagonal matrix as a single vector.
34 // vnl_diag_matrix stores a diagonal matrix for time and space efficiency.
35 // Specifically, only the diagonal elements are stored, and some matrix
36 // operations (currently *, + and -) are overloaded to use more efficient
37 // algorithms.
38 
39 template <class T>
40 class VNL_EXPORT vnl_diag_matrix
41 {
43 
44  public:
45  vnl_diag_matrix() : diagonal_() {}
46 
47  //: Construct an empty diagonal matrix.
48  vnl_diag_matrix(unsigned nn) : diagonal_(nn) {}
49 
50  //: Construct a diagonal matrix with diagonal elements equal to value.
51  vnl_diag_matrix(unsigned nn, T const& value) : diagonal_(nn, value) {}
52 
53  //: Construct a diagonal matrix from a vnl_vector.
54  // The vector elements become the diagonal elements.
55  vnl_diag_matrix(vnl_vector<T> const& that): diagonal_(that) {}
56  ~vnl_diag_matrix() = default;
57 
59  this->diagonal_ = that.diagonal_;
60  return *this;
61  }
62 
63  // Operations----------------------------------------------------------------
64 
65  //: In-place arithmetic operation
66  inline vnl_diag_matrix<T>& operator*=(T v) { diagonal_ *= v; return *this; }
67  //: In-place arithmetic operation
68  inline vnl_diag_matrix<T>& operator/=(T v) { diagonal_ /= v; return *this; }
69 
70  // Computations--------------------------------------------------------------
71 
72  vnl_diag_matrix& invert_in_place();
73  T determinant() const;
74  vnl_vector<T> solve(vnl_vector<T> const& b) const;
75  void solve(vnl_vector<T> const& b, vnl_vector<T>* out) const;
76 
77  // Data Access---------------------------------------------------------------
78 
79  inline T operator () (unsigned i, unsigned j) const {
80  return (i != j) ? T(0) : diagonal_[i];
81  }
82 
83  inline T& operator () (unsigned i, unsigned j) {
84  assert(i == j); (void)j;
85  return diagonal_[i];
86  }
87  inline T& operator() (unsigned i) { return diagonal_[i]; }
88  inline T const& operator() (unsigned i) const { return diagonal_[i]; }
89 
90  inline T& operator[] (unsigned i) { return diagonal_[i]; }
91  inline T const& operator[] (unsigned i) const { return diagonal_[i]; }
92 
93  //: Return a vector (copy) with the content of the (main) diagonal
94  inline vnl_vector<T> get_diagonal() const { return diagonal_; }
95 
96  //: Return diagonal elements as a vector
97  inline vnl_vector<T> const& diagonal() const { return diagonal_; }
98 
99  //: Set all diagonal elements of matrix to specified value.
100  inline vnl_diag_matrix& fill_diagonal (T const& v) { diagonal_.fill(v); return *this; }
101 
102  //: Sets the diagonal elements of this matrix to the specified list of values.
103  inline vnl_diag_matrix& set_diagonal(vnl_vector<T> const& v) { diagonal_ = v; return *this; }
104 
105  // iterators
106 
108  inline iterator begin() { return diagonal_.begin(); }
109  inline iterator end() { return diagonal_.end(); }
111  inline const_iterator begin() const { return diagonal_.begin(); }
112  inline const_iterator end() const { return diagonal_.end(); }
113 
114  //: Return the total number of elements stored by the matrix.
115  // Since vnl_diag_matrix only stores values on the diagonal
116  // and must be square, size() == rows() == cols().
117  inline unsigned int size() const { return diagonal_.size(); }
118 
119  //: Return the number of rows.
120  inline unsigned int rows() const { return diagonal_.size(); }
121 
122  //: Return the number of columns.
123  // A synonym for columns().
124  inline unsigned int cols() const { return diagonal_.size(); }
125 
126  //: Return the number of columns.
127  // A synonym for cols().
128  inline unsigned int columns() const { return diagonal_.size(); }
129 
130  //: set element with boundary checks.
131  inline void put (unsigned r, unsigned c, T const& v) {
132  assert(r == c);
133  (void)c;
134 #if VNL_CONFIG_CHECK_BOUNDS
135  if (r >= this->size()) // If invalid size specified
136  vnl_error_matrix_row_index("get", r); // Raise exception
137 #endif
138  diagonal_[r] = v;
139  }
140 
141  //: get element with boundary checks.
142  inline T get (unsigned r, unsigned c) const {
143  assert(r == c);
144  (void)c;
145 #if VNL_CONFIG_CHECK_BOUNDS
146  if (r >= this->size()) // If invalid size specified
147  vnl_error_matrix_row_index("get", r); // Raise exception
148 #endif
149  return diagonal_[r];
150  }
151 
152  // Need this until we add a vnl_diag_matrix ctor to vnl_matrix;
153  inline vnl_matrix<T> asMatrix() const;
154 
155  inline vnl_matrix<T> as_ref() const { return asMatrix(); }
156 
157  // This is as good as a vnl_diag_matrix ctor for vnl_matrix:
158  inline operator vnl_matrix<T> () const { return asMatrix(); }
159 
160  inline void set_size(int n) { diagonal_.set_size(n); }
161 
162  inline void clear() { diagonal_.clear(); }
163  inline vnl_diag_matrix& fill(T const &x) { diagonal_.fill(x); return *this; }
164 
165  //: Return pointer to the diagonal elements as a contiguous 1D C array;
166  inline T* data_block() { return diagonal_.data_block(); }
167  inline T const* data_block() const { return diagonal_.data_block(); }
168 
169  //: Set diagonal elements using vector
170  inline vnl_diag_matrix& set(vnl_vector<T> const& v) { diagonal_=v; return *this; }
171 
172  private:
173 };
174 
175 //:
176 // \relatesalso vnl_diag_matrix
177 template <class T> VNL_EXPORT
178 std::ostream& operator<< (std::ostream&, vnl_diag_matrix<T> const&);
179 
180 //: Convert a vnl_diag_matrix to a Matrix.
181 template <class T>
183 {
184  unsigned len = diagonal_.size();
185  vnl_matrix<T> ret(len, len);
186  for (unsigned i = 0; i < len; ++i)
187  {
188  unsigned j;
189  for (j = 0; j < i; ++j)
190  ret(i,j) = T(0);
191  for (j = i+1; j < len; ++j)
192  ret(i,j) = T(0);
193  ret(i,i) = diagonal_[i];
194  }
195  return ret;
196 }
197 
198 //: Invert a vnl_diag_matrix in-situ.
199 // Just replaces each element with its reciprocal.
200 template <class T>
202 {
203  unsigned len = diagonal_.size();
204  T* d = data_block();
205  T one = T(1);
206  for (unsigned i = 0; i < len; ++i)
207  d[i] = one / d[i];
208  return *this;
209 }
210 
211 //: Return determinant as product of diagonal values.
212 template <class T>
214 {
215  T det = T(1);
216  T const* d = data_block();
217  unsigned len = diagonal_.size();
218  for (unsigned i = 0; i < len; ++i)
219  det *= d[i];
220  return det;
221 }
222 
223 //: Multiply two vnl_diag_matrices. Just multiply the diag elements - n flops
224 // \relatesalso vnl_diag_matrix
225 template <class T>
227 {
228  assert(A.size() == B.size());
229  vnl_diag_matrix<T> ret = A;
230  for (unsigned i = 0; i < A.size(); ++i)
231  ret(i,i) *= B(i,i);
232  return ret;
233 }
234 
235 //: Multiply a vnl_matrix by a vnl_diag_matrix. Just scales the columns - mn flops
236 // \relatesalso vnl_diag_matrix
237 // \relatesalso vnl_matrix
238 template <class T>
240 {
241  assert(A.columns() == D.size());
242  vnl_matrix<T> ret(A.rows(), A.columns());
243  for (unsigned i = 0; i < A.rows(); ++i)
244  for (unsigned j = 0; j < A.columns(); ++j)
245  ret(i,j) = A(i,j) * D(j,j);
246  return ret;
247 }
248 
249 //: Multiply a vnl_diag_matrix by a vnl_matrix. Just scales the rows - mn flops
250 // \relatesalso vnl_diag_matrix
251 // \relatesalso vnl_matrix
252 template <class T>
254 {
255  assert(A.rows() == D.size());
256  vnl_matrix<T> ret(A.rows(), A.columns());
257  T const* d = D.data_block();
258  for (unsigned i = 0; i < A.rows(); ++i)
259  for (unsigned j = 0; j < A.columns(); ++j)
260  ret(i,j) = A(i,j) * d[i];
261  return ret;
262 }
263 
264 //: Add two vnl_diag_matrices. Just add the diag elements - n flops
265 // \relatesalso vnl_diag_matrix
266 template <class T>
268 {
269  assert(A.size() == B.size());
270  vnl_diag_matrix<T> ret = A;
271  for (unsigned i = 0; i < A.size(); ++i)
272  ret(i,i) += B(i,i);
273  return ret;
274 }
275 
276 //: Add a vnl_diag_matrix to a vnl_matrix. n adds, mn copies.
277 // \relatesalso vnl_diag_matrix
278 // \relatesalso vnl_matrix
279 template <class T>
281 {
282  const unsigned n = D.size();
283  assert(A.rows() == n); assert(A.columns() == n);
284  vnl_matrix<T> ret(A);
285  T const* d = D.data_block();
286  for (unsigned j = 0; j < n; ++j)
287  ret(j,j) += d[j];
288  return ret;
289 }
290 
291 //: Add a vnl_matrix to a vnl_diag_matrix. n adds, mn copies.
292 // \relatesalso vnl_diag_matrix
293 // \relatesalso vnl_matrix
294 template <class T>
296 {
297  return A + D;
298 }
299 
300 //: Subtract two vnl_diag_matrices. Just subtract the diag elements - n flops
301 // \relatesalso vnl_diag_matrix
302 template <class T>
304 {
305  assert(A.size() == B.size());
306  vnl_diag_matrix<T> ret = A;
307  for (unsigned i = 0; i < A.size(); ++i)
308  ret(i,i) -= B(i,i);
309  return ret;
310 }
311 
312 //: Subtract a vnl_diag_matrix from a vnl_matrix. n adds, mn copies.
313 // \relatesalso vnl_diag_matrix
314 // \relatesalso vnl_matrix
315 template <class T>
317 {
318  const unsigned n = D.size();
319  assert(A.rows() == n); assert(A.columns() == n);
320  vnl_matrix<T> ret(A);
321  T const* d = D.data_block();
322  for (unsigned j = 0; j < n; ++j)
323  ret(j,j) -= d[j];
324  return ret;
325 }
326 
327 //: Subtract a vnl_matrix from a vnl_diag_matrix. n adds, mn copies.
328 // \relatesalso vnl_diag_matrix
329 // \relatesalso vnl_matrix
330 template <class T>
332 {
333  const unsigned n = D.size();
334  assert(A.rows() == n); assert(A.columns() == n);
335  vnl_matrix<T> ret(n, n);
336  T const* d = D.data_block();
337  for (unsigned i = 0; i < n; ++i)
338  {
339  for (unsigned j = 0; j < i; ++j)
340  ret(i,j) = -A(i,j);
341  for (unsigned j = i+1; j < n; ++j)
342  ret(i,j) = -A(i,j);
343  ret(i,i) = d[i] - A(i,i);
344  }
345  return ret;
346 }
347 
348 //: Multiply a vnl_diag_matrix by a vnl_vector. n flops.
349 // \relatesalso vnl_diag_matrix
350 // \relatesalso vnl_vector
351 template <class T>
353 {
354  assert(A.size() == D.size());
355  return element_product(D.diagonal(), A);
356 }
357 
358 //: Multiply a vnl_vector by a vnl_diag_matrix. n flops.
359 // \relatesalso vnl_diag_matrix
360 // \relatesalso vnl_vector
361 template <class T>
363 {
364  assert(A.size() == D.size());
365  return element_product(D.diagonal(), A);
366 }
367 
368 #endif // vnl_diag_matrix_h_
vnl_diag_matrix & fill(T const &x)
unsigned int size() const
Return the total number of elements stored by the matrix.
vnl_bignum operator+(vnl_bignum const &r1, long r2)
Returns the sum of two bignum numbers.
Definition: vnl_bignum.h:279
void set_size(int n)
unsigned int rows() const
Return the number of rows.
An ordinary mathematical matrix.
bool set_size(size_t n)
Resize to n elements.
Definition: vnl_vector.hxx:250
const_iterator begin() const
unsigned int cols() const
Return the number of columns.
vnl_vector_fixed< T, n > element_product(const vnl_vector_fixed< T, n > &a, const vnl_vector_fixed< T, n > &b)
T get(unsigned r, unsigned c) const
get element with boundary checks.
size_t size() const
Return the length, number of elements, dimension of this vector.
Definition: vnl_vector.h:126
T const * data_block() const
Access the contiguous block storing the elements in the vector. O(1).
Definition: vnl_vector.h:230
void vnl_error_matrix_row_index(char const *fcn, int r)
Raise exception for invalid row index.
Definition: vnl_error.cxx:51
vnl_diag_matrix & set(vnl_vector< T > const &v)
Set diagonal elements using vector.
vnl_vector< T > const & diagonal() const
Return diagonal elements as a vector.
vnl_diag_matrix & set_diagonal(vnl_vector< T > const &v)
Sets the diagonal elements of this matrix to the specified list of values.
vnl_vector< T > diagonal_
vnl_diag_matrix & fill_diagonal(T const &v)
Set all diagonal elements of matrix to specified value.
iterator end()
Iterator pointing to element beyond end of data.
Definition: vnl_vector.h:246
vnl_diag_matrix(unsigned nn)
Construct an empty diagonal matrix.
std::ostream & operator<<(std::ostream &s, vnl_decnum const &r)
decimal output.
Definition: vnl_decnum.h:393
#define v
Definition: vnl_vector.h:42
vnl_vector< T >::const_iterator const_iterator
vnl_diag_matrix(unsigned nn, T const &value)
Construct a diagonal matrix with diagonal elements equal to value.
iterator begin()
Iterator pointing to start of data.
Definition: vnl_vector.h:243
An ordinary mathematical matrix.
Definition: vnl_adjugate.h:22
void put(unsigned r, unsigned c, T const &v)
set element with boundary checks.
T const * data_block() const
void clear()
Make the vector as if it had been default-constructed.
Definition: vnl_vector.hxx:240
unsigned int columns() const
Return the number of columns.
vnl_matrix< T > asMatrix() const
Convert a vnl_diag_matrix to a Matrix.
vnl_vector & fill(T const &v)
Set all values to v.
Definition: vnl_vector.hxx:314
vnl_diag_matrix(vnl_vector< T > const &that)
Construct a diagonal matrix from a vnl_vector.
Mathematical vector class, templated by type of element.
Definition: vnl_fwd.h:16
vnl_diag_matrix< T > & operator/=(T v)
In-place arithmetic operation.
T const * const_iterator
Const iterator type.
Definition: vnl_vector.h:249
const_iterator end() const
T determinant() const
Return determinant as product of diagonal values.
T * iterator
Type defs for iterators.
Definition: vnl_vector.h:241
stores a diagonal matrix as a single vector.
unsigned int rows() const
Return the number of rows.
Definition: vnl_matrix.h:179
vnl_bignum operator-(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the difference of two bignum numbers.
Definition: vnl_bignum.h:290
vnl_vector< T >::iterator iterator
vnl_matrix< T > as_ref() const
vnl_diag_matrix & invert_in_place()
Invert a vnl_diag_matrix in-situ.
vnl_bignum operator *(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the product of two bignum numbers.
Definition: vnl_bignum.h:302
unsigned int columns() const
Return the number of columns.
Definition: vnl_matrix.h:187
vnl_vector< T > get_diagonal() const
Return a vector (copy) with the content of the (main) diagonal.
vnl_diag_matrix & operator=(vnl_diag_matrix< T > const &that)
T * data_block()
Return pointer to the diagonal elements as a contiguous 1D C array;.