vnl_matrix_fixed.h
Go to the documentation of this file.
1 // This is core/vnl/vnl_matrix_fixed.h
2 #ifndef vnl_matrix_fixed_h_
3 #define vnl_matrix_fixed_h_
4 //:
5 // \file
6 // \brief fixed size matrix
7 //
8 // \author Andrew W. Fitzgibbon, Oxford RRG
9 // \date 04 Aug 96
10 //
11 // \verbatim
12 // Modifications
13 // Peter Vanroose, 23 Nov 1996: added explicit copy constructor
14 // LSB (Manchester) 15/03/2001: added Binary I/O and tidied up the documentation
15 // Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
16 // Oct.2002 - Amitha Perera - separated vnl_matrix and vnl_matrix_fixed,
17 // removed necessity for vnl_matrix_fixed_ref
18 // Oct.2002 - Peter Vanroose - added inplace_transpose() method
19 // Jul.2003 - Paul Smyth - fixed end() bug, made op*=() more general
20 // Mar.2009 - Peter Vanroose - added arg_min() and arg_max()
21 // Oct.2010 - Peter Vanroose - mutators and filling methods now return *this
22 // Jan.2011 - Peter Vanroose - added methods set_diagonal() & get_diagonal()
23 // \endverbatim
24 //-----------------------------------------------------------------------------
25 
26 #include <cstring>
27 #include <iosfwd>
28 #include <cassert>
29 #include <vcl_compiler.h>
30 #ifdef _MSC_VER
31 # include <vcl_msvc_warnings.h>
32 #endif
33 
34 #include "vnl_matrix.h"
35 #include "vnl_matrix_ref.h"
36 #include <vnl/vnl_vector.h>
37 #include <vnl/vnl_vector_fixed.h> // needed for e.g. vnl_matrix_fixed_mat_vec_mult()
38 #include <vnl/vnl_c_vector.h>
39 #include <vnl/vnl_config.h> // for VNL_CONFIG_CHECK_BOUNDS
40 #include "vnl/vnl_export.h"
41 
42 template <class T, unsigned int num_rows, unsigned int num_cols> class vnl_matrix_fixed;
43 
44 // This mess is for a MSVC6 workaround.
45 //
46 // The problem: the matrix-matrix operator* should be written as a
47 // non-member function since vxl (currently) forbids the use of member
48 // templates. However, when declared as
49 // \code
50 // template <class T, unsigned m, unsigned n, unsigned o>
51 // matrix<T,m,o> operator*( matrix<T,m,n>, matrix<T,n,o> );
52 // \endcode
53 // MSVC6 does not find it. A solution is to declare it as a member
54 // template. However, the obvious
55 // \code
56 // template <unsigned o>
57 // matrix<T,num_rows,o> operator*( matrix<T,num_cols,o> );
58 // \endcode
59 // causes an internal compiler error. It turns out that if the new
60 // template parameter "o" comes _first_, then all is okay. Now, we
61 // can't change the signature of vnl_matrix_fixed to <unsigned num_cols,
62 // unsigned num_rows, type>, so we use a "hidden" helper matrix. Except
63 // that user defined conversion operators and conversion constructors
64 // are not called for templated functions. So we have to use a helper
65 // base class. The base class is empty, which means that there is no
66 // loss in space or time efficiency. Finally, we have:
67 // \code
68 // template <unsigned num_cols, unsigned num_rows, class T>
69 // class fake_base { };
70 //
71 // template <class T, unsigned num_rows, unsigned num_cols>
72 // class matrix : public fake_base<num_cols,num_rows,T>
73 // {
74 // template <unsigned o>
75 // matrix<T,num_rows,o> operator*( fake_base<o,num_cols,T> );
76 // };
77 // \endcode
78 // Notice how "o" is first in the list of template parameters. Since
79 // base class conversions _are_ performed during template matching,
80 // matrix<T,m,n> is matched as fake_base<n,m,T>, and all is good. For
81 // some values of good.
82 //
83 // Of course, all this trickery is pre-processed away for conforming
84 // compilers.
85 //
86 template <class T, unsigned int num_rows, unsigned int num_cols>
87 class vnl_matrix_fixed;
88 template <class T, unsigned M, unsigned N>
89 inline
91 template <class T, unsigned M, unsigned N, unsigned O>
92 inline
94 
95 //: Fixed size, stack-stored, space-efficient matrix.
96 // vnl_matrix_fixed is a fixed-length, stack storage vector. It has
97 // the same storage size as a C-style array. It is not related via
98 // inheritance to vnl_matrix. However, it can be converted cheaply to
99 // a vnl_matrix_ref.
100 //
101 // Read the overview documentation of vnl_vector_fixed.
102 // The text there applies here.
103 template <class T, unsigned int num_rows, unsigned int num_cols>
104 class VNL_EXPORT vnl_matrix_fixed
105 {
106  T data_[num_rows][num_cols]; // Local storage
107 
108  public:
110  typedef size_t size_type;
111 
112  //: Construct an empty num_rows*num_cols matrix
113  vnl_matrix_fixed() = default;
114  //: Construct an m*n Matrix and copy rhs into it.
115  // Abort if rhs is not the same size.
116  vnl_matrix_fixed(const vnl_matrix_fixed& rhs) = default;
117  vnl_matrix_fixed(vnl_matrix_fixed&& other) = default;
118  //: Copy another vnl_matrix_fixed<T,m,n> into this.
119  vnl_matrix_fixed& operator=(const vnl_matrix_fixed& rhs) = default;
120  vnl_matrix_fixed& operator=(vnl_matrix_fixed&& rhs) = default;
121  ~vnl_matrix_fixed() = default;
122 
123 
124  //: Construct an empty num_rows*num_cols matrix
125  //
126  // The sole purpose of this constructor is to match the interface of
127  // vnl_matrix, so that algorithms can template over the matrix type
128  // itself. It is illegal to call this constructor without
129  // <tt>n==num_rows</tt> and <tt>m==num_cols</tt>.
130  vnl_matrix_fixed( unsigned VXL_USED_IN_DEBUG(n), unsigned VXL_USED_IN_DEBUG(m) )
131  {
132  assert( n == num_rows && m == num_cols );
133  }
134 
135  //: Construct an m*n matrix and fill with value
136  explicit vnl_matrix_fixed(T value)
137  {
138  T* p = data_[0];
139  unsigned int n = num_rows * num_cols;
140  while (n--)
141  *p++ = value;
142  }
143 
144  //: Construct an m*n Matrix and copy data into it row-wise.
145  explicit vnl_matrix_fixed(const T* datablck)
146  {
147  std::memcpy(data_[0], datablck, num_rows*num_cols*sizeof(T));
148  }
149 
150  //: Construct an m*n Matrix and copy rhs into it.
151  // Abort if rhs is not the same size.
152  vnl_matrix_fixed(const vnl_matrix<T>& rhs)
153  {
154  assert(rhs.rows() == num_rows && rhs.columns() == num_cols);
155  std::memcpy(data_[0], rhs.data_block(), num_rows*num_cols*sizeof(T));
156  }
157 
158 
159  //: Set all elements to value v
160  // Complexity $O(r.c)$
161  vnl_matrix_fixed& operator= (T const&v);
162 
163  //: Copy a vnl_matrix into this.
164  // Abort if rhs is not the same size.
165  vnl_matrix_fixed& operator=(const vnl_matrix<T>& rhs);
166 
167 // Basic 2D-Array functionality-------------------------------------------
168 
169  //: Return the total number of elements stored by the matrix.
170  // This equals rows() * cols()
171  inline unsigned int size() const { return num_rows*num_cols; }
172 
173  //: Return the number of rows.
174  inline unsigned int rows() const { return num_rows; }
175 
176  //: Return the number of columns.
177  // A synonym for columns().
178  inline unsigned int cols() const { return num_cols; }
179 
180  //: Return the number of columns.
181  // A synonym for cols().
182  inline unsigned int columns() const { return num_cols; }
183 
184  //: set element
185  inline void put (unsigned r, unsigned c, T const& v)
186  {
187 #if VNL_CONFIG_CHECK_BOUNDS
188  if (r >= num_rows) // If invalid size specified
189  vnl_error_matrix_row_index("put", r); // Raise exception
190  if (c >= num_cols) // If invalid size specified
191  vnl_error_matrix_col_index("put", c); // Raise exception
192 #endif
193  this->data_[r][c] = v;
194  }
195 
196  //: get element
197  inline T get (unsigned r, unsigned c) const
198  {
199 #if VNL_CONFIG_CHECK_BOUNDS
200  if (r >= num_rows) // If invalid size specified
201  vnl_error_matrix_row_index("get", r); // Raise exception
202  if (c >= num_cols) // If invalid size specified
203  vnl_error_matrix_col_index("get", c); // Raise exception
204 #endif
205  return this->data_[r][c];
206  }
207 
208  //: set element, and return *this
209  vnl_matrix_fixed& set (unsigned r, unsigned c, T const& v) { (*this)(r,c) = v; return *this; }
210 
211  //: return pointer to given row
212  // No boundary checking here.
213  T * operator[] (unsigned r) { return data_[r]; }
214 
215  //: return pointer to given row
216  // No boundary checking here.
217  T const * operator[] (unsigned r) const { return data_[r]; }
218 
219  //: Access an element for reading or writing
220  // There are assert style boundary checks - #define NDEBUG to turn them off.
221  T & operator() (unsigned r, unsigned c);
222 
223  //: Access an element for reading
224  // There are assert style boundary checks - #define NDEBUG to turn them off.
225  T const & operator() (unsigned r, unsigned c) const;
226 
227  // ----------------------- Filling and copying -----------------------
228 
229  //: Sets all elements of matrix to specified value, and returns "*this".
230  // Complexity $O(r.c)$
231  // Returning "*this" allows "chaining" two or more operations:
232  // e.g., to set a matrix to a column-normalized all-elements-equal matrix, say
233  // \code
234  // M.fill(1).normalize_columns();
235  // \endcode
236  // Returning "*this" also allows passing such a matrix as argument
237  // to a function f, without having to name the constructed matrix:
238  // \code
239  // f(vnl_matrix_fixed<double,5,5>(1.0).normalize_columns());
240  // \endcode
241  vnl_matrix_fixed& fill(T);
242 
243  //: Sets all diagonal elements of matrix to specified value; returns "*this".
244  // Complexity $O(\min(r,c))$
245  // Returning "*this" allows "chaining" two or more operations:
246  // e.g., to set a 3x3 matrix to [5 0 0][0 10 0][0 0 15], just say
247  // \code
248  // M.fill_diagonal(5).scale_row(1,2).scale_column(2,3);
249  // \endcode
250  // Returning "*this" also allows passing a diagonal-filled matrix as argument
251  // to a function f, without having to name the constructed matrix:
252  // \code
253  // f(vnl_matrix_fixed<double,3,3>().fill_diagonal(5));
254  // \endcode
255  vnl_matrix_fixed& fill_diagonal(T);
256 
257  //: Sets the diagonal elements of this matrix to the specified list of values.
258  // Returning "*this" allows "chaining" two or more operations: see the
259  // reasoning (and the examples) in the documentation for method
260  // fill_diagonal().
261  vnl_matrix_fixed& set_diagonal(vnl_vector<T> const&);
262 
263  //: Fills (laminates) this matrix with the given data, then returns it.
264  // We assume that the argument points to a contiguous rows*cols array, stored rowwise.
265  // No bounds checking on the array.
266  // Returning "*this" allows "chaining" two or more operations:
267  // e.g., to fill a square matrix column-wise, fill it rowwise then transpose:
268  // \code
269  // M.copy_in(array).inplace_transpose();
270  // \endcode
271  // Returning "*this" also allows passing a filled-in matrix as argument
272  // to a function f, without having to name the constructed matrix:
273  // \code
274  // f(vnl_matrix_fixed<double,3,3>().copy_in(array));
275  // \endcode
276  vnl_matrix_fixed& copy_in(T const *);
277 
278  //: Fills (laminates) this matrix with the given data, then returns it.
279  // A synonym for copy_in()
280  vnl_matrix_fixed& set(T const *d) { return copy_in(d); }
281 
282  //: Fills the given array with this matrix.
283  // We assume that the argument points to a contiguous rows*cols array, stored rowwise.
284  // No bounds checking on the array.
285  void copy_out(T *) const;
286 
287  //: Transposes this matrix efficiently, if it is square, and returns it.
288  // Returning "*this" allows "chaining" two or more operations:
289  // e.g., to fill a square matrix column-wise, fill it rowwise then transpose:
290  // \code
291  // M.copy_in(array).inplace_transpose();
292  // \endcode
293  vnl_matrix_fixed& inplace_transpose();
294 
295  // ----------------------- Arithmetic --------------------------------
296  // note that these functions should not pass scalar as a const&.
297  // Look what would happen to A /= A(0,0).
298 
299  //: Add \a s to each element of lhs matrix in situ
300  vnl_matrix_fixed& operator+= (T s)
301  {
302  self::add( data_block(), s, data_block() ); return *this;
303  }
304 
305  //: Subtract \a s from each element of lhs matrix in situ
306  vnl_matrix_fixed& operator-= (T s)
307  {
308  self::sub( data_block(), s, data_block() ); return *this;
309  }
310 
311  //:
312  vnl_matrix_fixed& operator*= (T s)
313  {
314  self::mul( data_block(), s, data_block() ); return *this;
315  }
316 
317  //:
318  vnl_matrix_fixed& operator/= (T s)
319  {
320  self::div( data_block(), s, data_block() ); return *this;
321  }
322 
323  //:
324  vnl_matrix_fixed& operator+= (vnl_matrix_fixed const& m)
325  {
326  self::add( data_block(), m.data_block(), data_block() ); return *this;
327  }
328 
329  //:
330  vnl_matrix_fixed& operator+= (vnl_matrix<T> const& m)
331  {
332  assert( m.rows() == rows() && m.cols() == cols() );
333  self::add( data_block(), m.data_block(), data_block() ); return *this;
334  }
335 
336  //:
337  vnl_matrix_fixed& operator-= (vnl_matrix_fixed const& m)
338  {
339  self::sub( data_block(), m.data_block(), data_block() ); return *this;
340  }
341 
342  //:
343  vnl_matrix_fixed& operator-= (vnl_matrix<T> const& m)
344  {
345  assert( m.rows() == rows() && m.cols() == cols() );
346  self::sub( data_block(), m.data_block(), data_block() );
347  return *this;
348  }
349 
350  //: Negate all elements of matrix
352  {
354  self::sub( T(0), data_block(), r.data_block() );
355  return r;
356  }
357 
358  //:
360  {
362  for (unsigned i = 0; i < num_rows; ++i)
363  for (unsigned j = 0; j < num_cols; ++j)
364  {
365  T accum = this->data_[i][0] * s(0,j);
366  for (unsigned k = 1; k < num_cols; ++k)
367  accum += this->data_[i][k] * s(k,j);
368  out(i,j) = accum;
369  }
370  return *this = out;
371  }
372 
373  ////--------------------------- Additions ----------------------------
374 
375  //: Make a new matrix by applying function to each element.
376  vnl_matrix_fixed apply(T (*f)(T)) const;
377 
378  //: Make a new matrix by applying function to each element.
379  vnl_matrix_fixed apply(T (*f)(T const&)) const;
380 
381  //: Make a vector by applying a function across rows.
382  vnl_vector_fixed<T,num_rows> apply_rowwise(T (*f)(vnl_vector_fixed<T,num_cols> const&)) const;
383 
384  //: Make a vector by applying a function across columns.
385  vnl_vector_fixed<T,num_cols> apply_columnwise(T (*f)(vnl_vector_fixed<T,num_rows> const&)) const;
386 
387  //: Return transpose
388  vnl_matrix_fixed<T,num_cols,num_rows> transpose() const;
389 
390  //: Return conjugate transpose
391  vnl_matrix_fixed<T,num_cols,num_rows> conjugate_transpose() const;
392 
393  //: Set values of this matrix to those of M, starting at [top,left]
394  vnl_matrix_fixed& update(vnl_matrix<T> const&, unsigned top=0, unsigned left=0);
395 
396  //: Set the elements of the i'th column to v[i] (No bounds checking)
397  vnl_matrix_fixed& set_column(unsigned i, T const * v);
398 
399  //: Set the elements of the i'th column to value, then return *this.
400  vnl_matrix_fixed& set_column(unsigned i, T value );
401 
402  //: Set j-th column to v, then return *this.
403  vnl_matrix_fixed& set_column(unsigned j, vnl_vector<T> const& v);
404 
405  //: Set j-th column to v, then return *this.
406  vnl_matrix_fixed& set_column(unsigned j, vnl_vector_fixed<T,num_rows> const& v);
407 
408  //: Set columns to those in M, starting at starting_column, then return *this.
409  vnl_matrix_fixed& set_columns(unsigned starting_column, vnl_matrix<T> const& M);
410 
411  //: Set the elements of the i'th row to v[i] (No bounds checking)
412  vnl_matrix_fixed& set_row (unsigned i, T const * v);
413 
414  //: Set the elements of the i'th row to value, then return *this.
415  vnl_matrix_fixed& set_row (unsigned i, T value );
416 
417  //: Set the i-th row, then return *this.
418  vnl_matrix_fixed& set_row (unsigned i, vnl_vector<T> const&);
419 
420  //: Set the i-th row, then return *this.
421  vnl_matrix_fixed& set_row (unsigned i, vnl_vector_fixed<T,num_cols> const&);
422 
423  //: Extract a sub-matrix of size r x c, starting at (top,left)
424  // Thus it contains elements [top,top+r-1][left,left+c-1]
425  vnl_matrix<T> extract (unsigned r, unsigned c,
426  unsigned top=0, unsigned left=0) const;
427 
428  //: Extract a sub-matrix starting at (top,left)
429  //
430  // The output is stored in \a sub_matrix, and it should have the
431  // required size on entry. Thus the result will contain elements
432  // [top,top+sub_matrix.rows()-1][left,left+sub_matrix.cols()-1]
433  void extract ( vnl_matrix<T>& sub_matrix,
434  unsigned top=0, unsigned left=0) const;
435 
436  //: Get a vector equal to the given row
437  vnl_vector_fixed<T,num_cols> get_row (unsigned row) const;
438 
439  //: Get a vector equal to the given column
440  vnl_vector_fixed<T,num_rows> get_column(unsigned col) const;
441 
442  //: Get a matrix composed of rows from the indices specified in the supplied vector.
443  vnl_matrix<T> get_rows(vnl_vector<unsigned int> i) const;
444 
445  //: Get a matrix composed of columns from the indices specified in the supplied vector.
446  vnl_matrix<T> get_columns(vnl_vector<unsigned int> i) const;
447 
448  //: Get n rows beginning at rowstart
449  vnl_matrix<T> get_n_rows (unsigned rowstart, unsigned n) const;
450 
451  //: Get n columns beginning at colstart
452  vnl_matrix<T> get_n_columns(unsigned colstart, unsigned n) const;
453 
454  //: Return a vector with the content of the (main) diagonal
455  vnl_vector<T> get_diagonal() const;
456 
457  //: Flatten row-major (C-style)
458  vnl_vector_fixed<T,num_rows*num_cols> flatten_row_major() const;
459 
460  //: Flatten column-major (Fortran-style)
461  vnl_vector_fixed<T,num_rows*num_cols> flatten_column_major() const;
462 
463  // ==== mutators ====
464 
465  //: Sets this matrix to an identity matrix, then returns "*this".
466  // Returning "*this" allows e.g. passing an identity matrix as argument to
467  // a function f, without having to name the constructed matrix:
468  // \code
469  // f(vnl_matrix_fixed<double,5,5>().set_identity());
470  // \endcode
471  // Returning "*this" also allows "chaining" two or more operations:
472  // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say
473  // \code
474  // M.set_identity().scale_row(0,3).scale_column(1,2);
475  // \endcode
476  // If the matrix is not square, anyhow set main diagonal to 1, the rest to 0.
477  vnl_matrix_fixed& set_identity();
478 
479  //: Reverses the order of rows, and returns "*this".
480  // Returning "*this" allows "chaining" two or more operations:
481  // e.g., to flip both up-down and left-right, one could just say
482  // \code
483  // M.flipud().fliplr();
484  // \endcode
485  vnl_matrix_fixed& flipud();
486 
487  //: Reverses the order of columns, and returns "*this".
488  // Returning "*this" allows "chaining" two or more operations:
489  // e.g., to flip both up-down and left-right, one could just say
490  // \code
491  // M.flipud().fliplr();
492  // \endcode
493  vnl_matrix_fixed& fliplr();
494 
495  //: Normalizes each row so it is a unit vector, and returns "*this".
496  // Zero rows are not modified
497  // Returning "*this" allows "chaining" two or more operations:
498  // e.g., to set a matrix to a row-normalized all-elements-equal matrix, say
499  // \code
500  // M.fill(1).normalize_rows();
501  // \endcode
502  // Returning "*this" also allows passing such a matrix as argument
503  // to a function f, without having to name the constructed matrix:
504  // \code
505  // f(vnl_matrix_fixed<double,5,5>(1.0).normalize_rows());
506  // \endcode
507  vnl_matrix_fixed& normalize_rows();
508 
509  //: Normalizes each column so it is a unit vector, and returns "*this".
510  // Zero columns are not modified
511  // Returning "*this" allows "chaining" two or more operations:
512  // e.g., to set a matrix to a column-normalized all-elements-equal matrix, say
513  // \code
514  // M.fill(1).normalize_columns();
515  // \endcode
516  // Returning "*this" also allows passing such a matrix as argument
517  // to a function f, without having to name the constructed matrix:
518  // \code
519  // f(vnl_matrix_fixed<double,5,5>(1.0).normalize_columns());
520  // \endcode
521  vnl_matrix_fixed& normalize_columns();
522 
523  //: Scales elements in given row by a factor T, and returns "*this".
524  // Returning "*this" allows "chaining" two or more operations:
525  // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say
526  // \code
527  // M.set_identity().scale_row(0,3).scale_column(1,2);
528  // \endcode
529  vnl_matrix_fixed& scale_row (unsigned row, T value);
530 
531  //: Scales elements in given column by a factor T, and returns "*this".
532  // Returning "*this" allows "chaining" two or more operations:
533  // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say
534  // \code
535  // M.set_identity().scale_row(0,3).scale_column(1,2);
536  // \endcode
537  vnl_matrix_fixed& scale_column(unsigned col, T value);
538 
539  //: Swap this matrix with that matrix
541 
542  //: Type def for norms.
543  typedef typename vnl_c_vector<T>::abs_t abs_t;
544 
545  //: Return sum of absolute values of elements
546  abs_t array_one_norm() const { return vnl_c_vector<T>::one_norm(begin(), size()); }
547 
548  //: Return square root of sum of squared absolute element values
549  abs_t array_two_norm() const { return vnl_c_vector<T>::two_norm(begin(), size()); }
550 
551  //: Return largest absolute element value
552  abs_t array_inf_norm() const { return vnl_c_vector<T>::inf_norm(begin(), size()); }
553 
554  //: Return sum of absolute values of elements
555  abs_t absolute_value_sum() const { return array_one_norm(); }
556 
557  //: Return largest absolute value
558  abs_t absolute_value_max() const { return array_inf_norm(); }
559 
560  // $ || M ||_1 := \max_j \sum_i | M_{ij} | $
561  abs_t operator_one_norm() const;
562 
563  // $ || M ||_\inf := \max_i \sum_j | M_{ij} | $
564  abs_t operator_inf_norm() const;
565 
566  //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements)
567  abs_t frobenius_norm() const { return vnl_c_vector<T>::two_norm(begin(), size()); }
568 
569  //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements)
570  abs_t fro_norm() const { return frobenius_norm(); }
571 
572  //: Return RMS of all elements
573  abs_t rms() const { return vnl_c_vector<T>::rms_norm(begin(), size()); }
574 
575  //: Return minimum value of elements
576  T min_value() const { return vnl_c_vector<T>::min_value(begin(), size()); }
577 
578  //: Return maximum value of elements
579  T max_value() const { return vnl_c_vector<T>::max_value(begin(), size()); }
580 
581  //: Return location of minimum value of elements
582  unsigned arg_min() const { return vnl_c_vector<T>::arg_min(begin(), size()); }
583 
584  //: Return location of maximum value of elements
585  unsigned arg_max() const { return vnl_c_vector<T>::arg_max(begin(), size()); }
586 
587  //: Return mean of all matrix elements
588  T mean() const { return vnl_c_vector<T>::mean(begin(), size()); }
589 
590  // predicates
591 
592  //: Return true iff the size is zero.
593  bool empty() const { return num_rows==0 && num_cols==0; }
594 
595  //: Return true if all elements equal to identity.
596  bool is_identity() const;
597 
598  //: Return true if all elements equal to identity, within given tolerance
599  bool is_identity(double tol) const;
600 
601  //: Return true if all elements equal to zero.
602  bool is_zero() const;
603 
604  //: Return true if all elements equal to zero, within given tolerance
605  bool is_zero(double tol) const;
606 
607  //: Return true if all elements of both matrices are equal, within given tolerance
608  bool is_equal(vnl_matrix_fixed<T,num_rows,num_cols> const& rhs, double tol) const;
609 
610  //: Return true if finite
611  bool is_finite() const;
612 
613  //: Return true if matrix contains NaNs
614  bool has_nans() const;
615 
616  //: abort if size is not as expected
617  // This function does or tests nothing if NDEBUG is defined
618  void assert_size(unsigned VXL_USED_IN_DEBUG(nr_rows), unsigned VXL_USED_IN_DEBUG(nr_cols) ) const
619  {
620 #ifndef NDEBUG
621  assert_size_internal(nr_rows, nr_cols);
622 #endif
623  }
624 
625  //: abort if matrix contains any INFs or NANs.
626  // This function does or tests nothing if NDEBUG is defined
627  void assert_finite() const
628  {
629 #ifndef NDEBUG
630  assert_finite_internal();
631 #endif
632  }
633 
634  ////----------------------- Input/Output ----------------------------
635 
636  // : Read a vnl_matrix from an ascii std::istream, automatically determining file size if the input matrix has zero size.
637  bool read_ascii(std::istream& s);
638 
639  //--------------------------------------------------------------------------------
640 
641  //: Access the contiguous block storing the elements in the matrix row-wise. O(1).
642  // 1d array, row-major order.
643  T const* data_block() const;
644 
645  //: Access the contiguous block storing the elements in the matrix row-wise. O(1).
646  // 1d array, row-major order.
647  T * data_block();
648 
649 
650  //----------------------------------------------------------------------
651  // Conversion to vnl_matrix_ref.
652 
653  // The const version of as_ref should return a const vnl_matrix_ref
654  // so that the vnl_matrix_ref::non_const() cannot be used on
655  // it. This prevents a const vnl_matrix_fixed from being cast into a
656  // non-const vnl_matrix reference, giving a slight increase in type safety.
657 
658  //: Explicit conversion to a vnl_matrix_ref.
659  // This is a cheap conversion for those functions that have an interface
660  // for vnl_matrix but not for vnl_matrix_fixed. There is also a
661  // conversion operator that should work most of the time.
662  // \sa vnl_matrix_ref::non_const
663  inline vnl_matrix_ref<T> as_ref() { return vnl_matrix_ref<T>( num_rows, num_cols, data_block() ); }
664 
665  //: Explicit conversion to a vnl_matrix_ref.
666  // This is a cheap conversion for those functions that have an interface
667  // for vnl_matrix but not for vnl_matrix_fixed. There is also a
668  // conversion operator that should work most of the time.
669  // \sa vnl_matrix_ref::non_const
670  inline const vnl_matrix_ref<T> as_ref() const { return vnl_matrix_ref<T>( num_rows, num_cols, const_cast<T*>(data_block()) ); }
671 
672  //: Cheap conversion to vnl_matrix_ref
673  // Sometimes, such as with templated functions, the compiler cannot
674  // use this user-defined conversion. For those cases, use the
675  // explicit as_ref() method instead.
676  inline operator const vnl_matrix_ref<T>() const { return vnl_matrix_ref<T>( num_rows, num_cols, const_cast<T*>(data_block()) ); }
677 
678  //: Convert to a vnl_matrix.
679  inline const vnl_matrix<T> as_matrix() const { return vnl_matrix<T>(const_cast<T*>(data_block()),num_rows,num_cols); }
680 
681  //----------------------------------------------------------------------
683  typedef T element_type;
684 
685  //: Iterators
686  typedef T *iterator;
687  //: Iterator pointing to start of data
688  inline iterator begin() { return data_[0]; }
689  //: Iterator pointing to element beyond end of data
690  inline iterator end() { return begin() + size(); }
691 
692  //: Const iterators
693  typedef T const *const_iterator;
694  //: Iterator pointing to start of data
695  inline const_iterator begin() const { return data_[0]; }
696  //: Iterator pointing to element beyond end of data
697  inline const_iterator end() const { return begin() + size(); }
698 
699  //--------------------------------------------------------------------------------
700 
701  //: Return true if *this == rhs
702  bool operator_eq (vnl_matrix_fixed const & rhs) const
703  {
704  return equal( this->data_block(), rhs.data_block() );
705  }
706 
707  //: Equality operator
708  bool operator==(vnl_matrix_fixed const &that) const { return this->operator_eq(that); }
709 
710  //: Inequality operator
711  bool operator!=(vnl_matrix_fixed const &that) const { return !this->operator_eq(that); }
712 
713  //: Equality operator
714  bool operator==(vnl_matrix<T> const &that) const { return this->operator_eq(that); }
715 
716  //: Inequality operator
717  bool operator!=(vnl_matrix<T> const &that) const { return !this->operator_eq(that); }
718 
719  //: Print matrix to os in some hopefully sensible format
720  void print(std::ostream& os) const;
721 
722 //--------------------------------------------------------------------------------
723 
724 
725  // Helper routines for arithmetic. These routines know the size from
726  // the template parameters. The vector-vector operations are
727  // element-wise.
728 
729  static void add( const T* a, const T* b, T* r );
730  static void add( const T* a, T b, T* r );
731  static void sub( const T* a, const T* b, T* r );
732  static void sub( const T* a, T b, T* r );
733  static void sub( T a, const T* b, T* r );
734  static void mul( const T* a, const T* b, T* r );
735  static void mul( const T* a, T b, T* r );
736  static void div( const T* a, const T* b, T* r );
737  static void div( const T* a, T b, T* r );
738 
739  static bool equal( const T* a, const T* b );
740 
741  private:
742  void assert_finite_internal() const;
743 
744  void assert_size_internal(unsigned, unsigned) const;
745 };
746 
747 // Make the operators below inline because (1) they are small and
748 // (2) we then have less explicit instantiation trouble.
749 
750 
751 // --- Matrix-scalar -------------------------------------------------------------
752 
753 template <class T, unsigned m, unsigned n>
754 inline
756 {
759  return r;
760 }
761 
762 template <class T, unsigned m, unsigned n>
763 inline
765 {
768  return r;
769 }
770 
771 template <class T, unsigned m, unsigned n>
772 inline
774  const vnl_matrix_fixed<T,m,n>& mat )
775 {
778  return r;
779 }
780 
781 template <class T, unsigned m, unsigned n>
782 inline
784 {
787  return r;
788 }
789 
790 template <class T, unsigned m, unsigned n>
791 inline
793 {
796  return r;
797 }
798 
799 template <class T, unsigned m, unsigned n>
800 inline
802  const vnl_matrix_fixed<T,m,n>& mat )
803 {
806  return r;
807 }
808 
809 template <class T, unsigned m, unsigned n>
810 inline
812 {
815  return r;
816 }
817 
818 template <class T, unsigned m, unsigned n>
819 inline
821  const vnl_matrix_fixed<T,m,n>& mat )
822 {
825  return r;
826 }
827 
828 template <class T, unsigned m, unsigned n>
829 inline
831 {
834  return r;
835 }
836 
837 
838 template <class T, unsigned m, unsigned n>
839 inline
841  const vnl_matrix_fixed<T,m,n>& mat2 )
842 {
845  return r;
846 }
847 
848 
849 template <class T, unsigned m, unsigned n>
850 inline
852  const vnl_matrix_fixed<T,m,n>& mat2)
853 {
856  return r;
857 }
858 
859 
860 // The following two functions are helper functions keep the
861 // matrix-matrix and matrix-vector multiplication code in one place,
862 // so that bug fixes, etc, can be localized.
863 template <class T, unsigned M, unsigned N>
864 inline
867  const vnl_vector_fixed<T, N>& b)
868 {
870  for (unsigned i = 0; i < M; ++i)
871  {
872  T accum = a(i,0) * b(0);
873  for (unsigned k = 1; k < N; ++k)
874  accum += a(i,k) * b(k);
875  out(i) = accum;
876  }
877  return out;
878 }
879 
880 template <class T, unsigned M, unsigned N>
881 inline
884  const vnl_matrix_fixed<T, M, N>& b)
885 {
887  for (unsigned i = 0; i < N; ++i)
888  {
889  T accum = a(0) * b(0,i);
890  for (unsigned k = 1; k < M; ++k)
891  accum += a(k) * b(k,i);
892  out(i) = accum;
893  }
894  return out;
895 }
896 
897 // see comment above
898 template <class T, unsigned M, unsigned N, unsigned O>
899 inline
902  const vnl_matrix_fixed<T, N, O>& b)
903 {
905  for (unsigned i = 0; i < M; ++i)
906  for (unsigned j = 0; j < O; ++j)
907  {
908  T accum = a(i,0) * b(0,j);
909  for (unsigned k = 1; k < N; ++k)
910  accum += a(i,k) * b(k,j);
911  out(i,j) = accum;
912  }
913  return out;
914 }
915 
916 // The version for correct compilers
917 
918 //: Multiply conformant vnl_matrix_fixed (M x N) and vector_fixed (N)
919 // \relatesalso vnl_vector_fixed
920 // \relatesalso vnl_matrix_fixed
921 template <class T, unsigned M, unsigned N>
922 inline
924 {
925  return vnl_matrix_fixed_mat_vec_mult(a, b);
926 }
927 
928 //: Multiply conformant vector_fixed (M) and vnl_matrix_fixed (M x N)
929 // \relatesalso vnl_vector_fixed
930 // \relatesalso vnl_matrix_fixed
931 template <class T, unsigned M, unsigned N>
932 inline
934 {
935  return vnl_matrix_fixed_vec_mat_mult(a, b);
936 }
937 
938 //: Multiply two conformant vnl_matrix_fixed (M x N) times (N x O)
939 // \relatesalso vnl_matrix_fixed
940 template <class T, unsigned M, unsigned N, unsigned O>
941 inline
943 {
944  return vnl_matrix_fixed_mat_mat_mult(a, b);
945 }
946 
947 
948 // These overloads for the common case of mixing a fixed with a
949 // non-fixed. Because the operator* are templated, the fixed will not
950 // be automatically converted to a non-fixed-ref. These do it for you.
951 
952 template <class T, unsigned m, unsigned n>
954 {
955  return a.as_ref() + b;
956 }
957 
958 template <class T, unsigned m, unsigned n>
960 {
961  return a + b.as_ref();
962 }
963 
964 template <class T, unsigned m, unsigned n>
966 {
967  return a.as_ref() - b;
968 }
969 
970 template <class T, unsigned m, unsigned n>
972 {
973  return a - b.as_ref();
974 }
975 
976 template <class T, unsigned m, unsigned n>
978 {
979  return a.as_ref() * b;
980 }
981 
982 template <class T, unsigned m, unsigned n>
984 {
985  return a * b.as_ref();
986 }
987 
988 template <class T, unsigned m, unsigned n>
990 {
991  return a.as_ref() * b;
992 }
993 
994 template <class T, unsigned n>
995 inline vnl_vector<T> operator*( const vnl_matrix<T>& a, const vnl_vector_fixed<T,n>& b )
996 {
997  return a * b.as_ref();
998 }
999 
1000 
1001 // --- I/O operations ------------------------------------------------------------
1002 
1003 template <class T, unsigned m, unsigned n>
1004 inline
1005 std::ostream& operator<< (std::ostream& os, vnl_matrix_fixed<T,m,n> const& mat)
1006 {
1007  mat.print(os);
1008  return os;
1009 }
1010 
1011 template <class T, unsigned m, unsigned n>
1012 inline
1013 std::istream& operator>> (std::istream& is, vnl_matrix_fixed<T,m,n>& mat)
1014 {
1015  mat.read_ascii(is);
1016  return is;
1017 }
1018 
1019 //:
1020 // \relatesalso vnl_vector_fixed
1021 template <class T, unsigned m, unsigned n> VNL_EXPORT
1024 #define VNL_MATRIX_FIXED_INSTANTIATE(T, M, N) \
1025 extern "please include vnl/vnl_matrix_fixed.hxx instead"
1026 
1027 #endif // vnl_matrix_fixed_h_
vnl_vector_fixed< T, n > element_quotient(const vnl_vector_fixed< T, n > &a, const vnl_vector_fixed< T, n > &b)
vnl_matrix_ref< T > as_ref()
Explicit conversion to a vnl_matrix_ref.
vnl_bignum operator+(vnl_bignum const &r1, long r2)
Returns the sum of two bignum numbers.
Definition: vnl_bignum.h:279
void swap(double &a, double &b)
An ordinary mathematical matrix.
static unsigned arg_min(T const *, unsigned)
Returns location of min value of the vector.
vnl_vector_fixed< T, M > vnl_matrix_fixed_mat_vec_mult(const vnl_matrix_fixed< T, M, N > &a, const vnl_vector_fixed< T, N > &b)
T const * data_block() const
Access the contiguous block storing the elements in the matrix row-wise. O(1).
#define m
Definition: vnl_vector.h:43
static void mul(const T *a, const T *b, T *r)
vnl_vector_fixed< T, n > element_product(const vnl_vector_fixed< T, n > &a, const vnl_vector_fixed< T, n > &b)
static abs_t rms_norm(T const *p, unsigned n)
rms_norm : sqrt of mean sum of squared abs values.
Definition: vnl_c_vector.h:136
static void sub(const T *a, const T *b, T *r)
void vnl_error_matrix_row_index(char const *fcn, int r)
Raise exception for invalid row index.
Definition: vnl_error.cxx:51
void add(const vnl_bignum &b1, const vnl_bignum &b2, vnl_bignum &sum)
add two non-infinite vnl_bignum values and save their sum.
Definition: vnl_bignum.cxx:887
vnl_vector_ref< T > as_ref()
Explicit conversion to a vnl_vector_ref.
Fixed size, stack-stored, space-efficient matrix.
Definition: vnl_fwd.h:23
void vnl_error_matrix_col_index(char const *fcn, int c)
Raise exception for invalid col index.
Definition: vnl_error.cxx:61
static abs_t one_norm(T const *p, unsigned n)
one_norm : sum of abs values.
Definition: vnl_c_vector.h:120
static abs_t two_norm(T const *p, unsigned n)
two_norm : sqrt of sum of squared abs values.
Definition: vnl_c_vector.h:124
std::ostream & operator<<(std::ostream &s, vnl_decnum const &r)
decimal output.
Definition: vnl_decnum.h:393
#define v
Definition: vnl_vector.h:42
static unsigned arg_max(T const *, unsigned)
Returns location of max value of the vector.
bool read_ascii(std::istream &s)
static T min_value(T const *, unsigned)
Returns min value of the vector.
T const * const_iterator
Const iterators.
vnl_vector_fixed< T, N > vnl_matrix_fixed_vec_mat_mult(const vnl_vector_fixed< T, M > &a, const vnl_matrix_fixed< T, M, N > &b)
An ordinary mathematical matrix.
Definition: vnl_adjugate.h:22
static T mean(T const *p, unsigned n)
Definition: vnl_c_vector.h:108
bool operator!=(long r1, vnl_bignum const &r2)
Definition: vnl_bignum.h:424
void print(std::ostream &os) const
Print matrix to os in some hopefully sensible format.
vnl_matrix_fixed< T, m, n > operator-(const vnl_matrix_fixed< T, m, n > &mat1, const vnl_matrix_fixed< T, m, n > &mat2)
vnl_numeric_traits< T >::abs_t abs_t
Definition: vnl_c_vector.h:42
Mathematical vector class, templated by type of element.
Definition: vnl_fwd.h:16
VNL_EXPORT vnl_matrix_fixed< T, m, n > outer_product(vnl_vector_fixed< T, m > const &a, vnl_vector_fixed< T, n > const &b)
T const * data_block() const
Access the contiguous block storing the elements in the matrix row-wise. O(1).
Definition: vnl_matrix.h:601
Fixed length stack-stored, space-efficient vector.
Definition: vnl_fwd.h:22
Fixed length stack-stored vector.
unsigned int rows() const
Return the number of rows.
Definition: vnl_matrix.h:179
VNL_EXPORT std::istream & operator>>(std::istream &s, vnl_decnum &r)
decimal input.
Definition: vnl_decnum.cxx:411
bool operator==(const vnl_amoeba_SimplexCorner &a, const vnl_amoeba_SimplexCorner &b)
Definition: vnl_amoeba.cxx:143
vnl_bignum operator-(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the difference of two bignum numbers.
Definition: vnl_bignum.h:290
static T max_value(T const *, unsigned)
Returns max value of the vector.
vnl_matrix_fixed< T, M, O > vnl_matrix_fixed_mat_mat_mult(const vnl_matrix_fixed< T, M, N > &a, const vnl_matrix_fixed< T, N, O > &b)
static void div(const T *a, const T *b, T *r)
vnl_bignum operator/(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the division of two bignum numbers.
Definition: vnl_bignum.h:349
vnl_matrix reference to user-supplied storage.
Definition: vnl_fwd.h:20
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
Math on blocks of memory.
static abs_t inf_norm(T const *p, unsigned n)
inf_norm : max of abs values.
Definition: vnl_c_vector.h:128
vnl_matrix reference to user-supplied storage.
static void add(const T *a, const T *b, T *r)
vnl_c_vector< T >::abs_t abs_t
Type def for norms.