vnl_diag_matrix_fixed.h
Go to the documentation of this file.
1 // This is core/vnl/vnl_diag_matrix_fixed.h
2 #ifndef vnl_diag_matrix_fixed_h_
3 #define vnl_diag_matrix_fixed_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_fixed.h>
26 #include <vnl/vnl_matrix_fixed.h>
27 #include "vnl/vnl_export.h"
28 
29 // forward declarations
30 template <class T, unsigned int N> class vnl_diag_matrix_fixed;
31 template <class T, unsigned int N> VNL_EXPORT vnl_vector_fixed<T,N> operator*(vnl_diag_matrix_fixed<T,N> const&, vnl_vector_fixed<T,N> const&);
32 
33 //: stores a diagonal matrix as a single vector.
34 // vnl_diag_matrix_fixed 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, unsigned int N>
40 class VNL_EXPORT vnl_diag_matrix_fixed
41 {
43 
44  public:
45  vnl_diag_matrix_fixed() : diagonal_() {}
46 
47 
48  //: Construct a diagonal matrix with diagonal elements equal to value.
49  vnl_diag_matrix_fixed(T const& value) : diagonal_(value) {}
50 
51  //: Construct a diagonal matrix from a vnl_vector_fixed.
52  // The vector elements become the diagonal elements.
53  explicit vnl_diag_matrix_fixed(vnl_vector_fixed<T,N> const& that): diagonal_(that) {}
54  ~vnl_diag_matrix_fixed() = default;
55 
57  this->diagonal_ = that.diagonal_;
58  return *this;
59  }
60 
61  // Operations----------------------------------------------------------------
62 
63  //: In-place arithmetic operation
64  inline vnl_diag_matrix_fixed<T,N>& operator*=(T v) { diagonal_ *= v; return *this; }
65  //: In-place arithmetic operation
66  inline vnl_diag_matrix_fixed<T,N>& operator/=(T v) { diagonal_ /= v; return *this; }
67 
68  // Computations--------------------------------------------------------------
69 
70  inline vnl_diag_matrix_fixed& invert_in_place();
71  T determinant() const;
72  vnl_vector_fixed<T,N> solve(vnl_vector_fixed<T,N> const& b) const;
73  void solve(vnl_vector_fixed<T,N> const& b, vnl_vector_fixed<T,N>* out) const;
74 
75  // Data Access---------------------------------------------------------------
76 
77  inline T operator () (unsigned i, unsigned j) const {
78  return (i != j) ? T(0) : diagonal_[i];
79  }
80 
81  inline T& operator () (unsigned i, unsigned j) {
82  assert(i == j);
83  // Avoid unused parameter warning
84  (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_fixed<T,N> get_diagonal() const { return diagonal_; }
95 
96  //: Return diagonal elements as a vector
97  inline vnl_vector_fixed<T,N> const& diagonal() const { return diagonal_; }
98 
99  //: Set all diagonal elements of matrix to specified value.
100  inline vnl_diag_matrix_fixed& 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_fixed& set_diagonal(vnl_vector_fixed<T,N> const& v) { diagonal_ = v; return *this; }
104 
105  // iterators
106 
108  iterator begin();
109  iterator end();
111  const_iterator begin() const;
112  const_iterator end() const;
113 
114  //: Return the total number of elements stored by the matrix.
115  // Since vnl_diag_matrix_fixed 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  {
133  assert(r == c);
134  (void)c;
135 #if VNL_CONFIG_CHECK_BOUNDS
136  if (r >= this->size()) // If invalid size specified
137  vnl_error_matrix_row_index("put", r); // Raise exception
138 #endif
139  diagonal_[r] = v;
140  }
141 
142  //: get element with boundary checks.
143  inline T get (unsigned r, unsigned c) const
144  {
145  assert(r == c);
146  (void)c;
147 #if VNL_CONFIG_CHECK_BOUNDS
148  if (r >= this->size()) // If invalid size specified
149  vnl_error_matrix_row_index("get", r); // Raise exception
150 #endif
151  return diagonal_[r];
152  }
153 
154  // Need this until we add a vnl_diag_matrix_fixed ctor to vnl_matrix;
155  inline vnl_matrix_fixed<T,N,N> as_matrix_fixed() const;
156 
157  inline vnl_matrix_fixed<T,N,N> as_ref() const { return as_matrix_fixed(); }
158 
159  // This is as good as a vnl_diag_matrix_fixed ctor for vnl_matrix_fixed:
160  inline operator vnl_matrix_fixed<T,N,N> () const { return as_matrix_fixed(); }
161 
162  inline vnl_diag_matrix_fixed& fill(T const &x) { diagonal_.fill(x); return *this; }
163 
164  //: Return pointer to the diagonal elements as a contiguous 1D C array;
165  inline T* data_block() { return diagonal_.data_block(); }
166  inline T const* data_block() const { return diagonal_.data_block(); }
167 
168  //: Set diagonal elements using vector, then return *this
169  inline vnl_diag_matrix_fixed& set(vnl_vector_fixed<T,N> const& v) { diagonal_=v; return *this; }
170 
171  private:
172 };
173 
174 //:
175 // \relatesalso vnl_diag_matrix_fixed
176 template <class T, unsigned int N> VNL_EXPORT
177 std::ostream& operator<< (std::ostream&, vnl_diag_matrix_fixed<T,N> const&);
178 
179 //: Convert a vnl_diag_matrix_fixed to a Matrix.
180 template <class T, unsigned int N>
182 {
184  for (unsigned i = 0; i < N; ++i)
185  {
186  unsigned j;
187  for (j = 0; j < i; ++j)
188  ret(i,j) = T(0);
189  for (j = i+1; j < N; ++j)
190  ret(i,j) = T(0);
191  ret(i,i) = diagonal_[i];
192  }
193  return ret;
194 }
195 
196 //: Invert a vnl_diag_matrix_fixed in-situ, then returns *this.
197 // Just replaces each element with its reciprocal.
198 template <class T, unsigned int N>
200 {
201  T* d = data_block();
202  T one = T(1);
203  for (unsigned i = 0; i < N; ++i)
204  d[i] = one / d[i];
205  return *this;
206 }
207 
208 //: Return determinant as product of diagonal values.
209 template <class T, unsigned int N>
211 {
212  T det = T(1);
213  T const* d = data_block();
214  for (unsigned i = 0; i < N; ++i)
215  det *= d[i];
216  return det;
217 }
218 
219 //: Multiply two vnl_diag_matrices. Just multiply the diag elements - n flops
220 // \relatesalso vnl_diag_matrix_fixed
221 template <class T, unsigned int N>
223 {
225  for (unsigned i = 0; i < N; ++i)
226  ret(i,i) *= B(i,i);
227  return ret;
228 }
229 
230 //: Multiply a vnl_matrix by a vnl_diag_matrix_fixed. Just scales the columns - mn flops
231 // \relatesalso vnl_diag_matrix_fixed
232 // \relatesalso vnl_matrix
233 template <class T, unsigned int R, unsigned int C>
235 {
237  for (unsigned i = 0; i < R; ++i)
238  for (unsigned j = 0; j < C; ++j)
239  ret(i,j) = A(i,j) * D(j,j);
240  return ret;
241 }
242 
243 //: Multiply a vnl_diag_matrix_fixed by a vnl_matrix. Just scales the rows - mn flops
244 // \relatesalso vnl_diag_matrix_fixed
245 // \relatesalso vnl_matrix
246 template <class T, unsigned int R, unsigned int C>
248 {
250  T const* d = D.data_block();
251  for (unsigned i = 0; i < R; ++i)
252  for (unsigned j = 0; j < C; ++j)
253  ret(i,j) = A(i,j) * d[i];
254  return ret;
255 }
256 
257 //: Add two vnl_diag_matrices. Just add the diag elements - n flops
258 // \relatesalso vnl_diag_matrix_fixed
259 template <class T, unsigned int N>
261 {
263  for (unsigned i = 0; i < N; ++i)
264  ret(i,i) += B(i,i);
265  return ret;
266 }
267 
268 //: Add a vnl_diag_matrix_fixed to a vnl_matrix. n adds, mn copies.
269 // \relatesalso vnl_diag_matrix_fixed
270 // \relatesalso vnl_matrix
271 template <class T, unsigned int N>
273 {
275  T const* d = D.data_block();
276  for (unsigned j = 0; j < N; ++j)
277  ret(j,j) += d[j];
278  return ret;
279 }
280 
281 //: Add a vnl_matrix to a vnl_diag_matrix_fixed. n adds, mn copies.
282 // \relatesalso vnl_diag_matrix_fixed
283 // \relatesalso vnl_matrix
284 template <class T, unsigned int N>
286 {
287  return A + D;
288 }
289 
290 //: Subtract two vnl_diag_matrices. Just subtract the diag elements - n flops
291 // \relatesalso vnl_diag_matrix_fixed
292 template <class T, unsigned int N>
294 {
296  for (unsigned i = 0; i < N; ++i)
297  ret(i,i) -= B(i,i);
298  return ret;
299 }
300 
301 //: Subtract a vnl_diag_matrix_fixed from a vnl_matrix. n adds, mn copies.
302 // \relatesalso vnl_diag_matrix_fixed
303 // \relatesalso vnl_matrix
304 template <class T, unsigned int N>
306 {
308  T const* d = D.data_block();
309  for (unsigned j = 0; j < N; ++j)
310  ret(j,j) -= d[j];
311  return ret;
312 }
313 
314 //: Subtract a vnl_matrix from a vnl_diag_matrix_fixed. n adds, mn copies.
315 // \relatesalso vnl_diag_matrix_fixed
316 // \relatesalso vnl_matrix
317 template <class T, unsigned int N>
319 {
321  T const* d = D.data_block();
322  for (unsigned i = 0; i < N; ++i)
323  {
324  for (unsigned j = 0; j < i; ++j)
325  ret(i,j) = -A(i,j);
326  for (unsigned j = i+1; j < N; ++j)
327  ret(i,j) = -A(i,j);
328  ret(i,i) = d[i] - A(i,i);
329  }
330  return ret;
331 }
332 
333 //: Multiply a vnl_diag_matrix_fixed by a vnl_vector_fixed. n flops.
334 // \relatesalso vnl_diag_matrix_fixed
335 // \relatesalso vnl_vector_fixed
336 template <class T, unsigned int N>
338 {
339  return element_product(D.diagonal(), A);
340 }
341 
342 //: Multiply a vnl_vector_fixed by a vnl_diag_matrix_fixed. n flops.
343 // \relatesalso vnl_diag_matrix_fixed
344 // \relatesalso vnl_vector_fixed
345 template <class T, unsigned int N>
347 {
348  return element_product(D.diagonal(), A);
349 }
350 
351 #endif // vnl_diag_matrix_fixed_h_
T determinant() const
Return determinant as product of diagonal values.
vnl_bignum operator+(vnl_bignum const &r1, long r2)
Returns the sum of two bignum numbers.
Definition: vnl_bignum.h:279
vnl_vector_fixed< T, N > get_diagonal() const
Return a vector (copy) with the content of the (main) diagonal.
vnl_vector_fixed< T, N >::const_iterator const_iterator
vnl_diag_matrix_fixed & operator=(vnl_diag_matrix_fixed< T, N > const &that)
unsigned int cols() const
Return the number of columns.
vnl_diag_matrix_fixed & fill_diagonal(T const &v)
Set all diagonal elements of matrix to specified value.
vnl_vector_fixed< T, n > element_product(const vnl_vector_fixed< T, n > &a, const vnl_vector_fixed< T, n > &b)
unsigned int size() const
Length of the vector.
vnl_diag_matrix_fixed & invert_in_place()
Invert a vnl_diag_matrix_fixed in-situ, then returns *this.
vnl_diag_matrix_fixed(T const &value)
Construct a diagonal matrix with diagonal elements equal to value.
void vnl_error_matrix_row_index(char const *fcn, int r)
Raise exception for invalid row index.
Definition: vnl_error.cxx:51
Fixed size, stack-stored, space-efficient matrix.
Definition: vnl_fwd.h:23
vnl_vector_fixed & fill(T const &v)
Set all values to v.
vnl_matrix_fixed< T, N, N > as_matrix_fixed() const
Convert a vnl_diag_matrix_fixed to a Matrix.
vnl_diag_matrix_fixed< T, N > & operator/=(T v)
In-place arithmetic operation.
unsigned int size() const
Return the total number of elements stored by the matrix.
vnl_vector_fixed< T, N > const & diagonal() const
Return diagonal elements as a vector.
std::ostream & operator<<(std::ostream &s, vnl_decnum const &r)
decimal output.
Definition: vnl_decnum.h:393
void put(unsigned r, unsigned c, T const &v)
set element with boundary checks.
#define v
Definition: vnl_vector.h:42
vnl_diag_matrix_fixed & fill(T const &x)
unsigned int rows() const
Return the number of rows.
T const * data_block() const
vnl_vector_fixed< T, N > diagonal_
T get(unsigned r, unsigned c) const
get element with boundary checks.
T const * data_block() const
Access the contiguous block storing the elements in the vector.
vnl_diag_matrix_fixed & set(vnl_vector_fixed< T, N > const &v)
Set diagonal elements using vector, then return *this.
unsigned int columns() const
Return the number of columns.
fixed size matrix
Fixed length stack-stored vector.
stores a diagonal matrix as a single vector.
vnl_matrix_fixed< T, N, N > as_ref() const
vnl_bignum operator-(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the difference of two bignum numbers.
Definition: vnl_bignum.h:290
vnl_diag_matrix_fixed(vnl_vector_fixed< T, N > const &that)
Construct a diagonal matrix from a vnl_vector_fixed.
T * data_block()
Return pointer to the diagonal elements as a contiguous 1D C array;.
vnl_vector_fixed< T, N >::iterator iterator
vnl_bignum operator *(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the product of two bignum numbers.
Definition: vnl_bignum.h:302
vnl_diag_matrix_fixed & set_diagonal(vnl_vector_fixed< T, N > const &v)
Sets the diagonal elements of this matrix to the specified list of values.