vnl_matrix_fixed_ref.h
Go to the documentation of this file.
1 // This is core/vnl/vnl_matrix_fixed_ref.h
2 #ifndef vnl_matrix_fixed_ref_h_
3 #define vnl_matrix_fixed_ref_h_
4 //:
5 // \file
6 // \brief Fixed size stack-stored vnl_matrix
7 //
8 // vnl_matrix_fixed_ref is a fixed-size vnl_matrix for which the data space
9 // has been supplied externally. This is useful for two main tasks:
10 //
11 // (a) Treating some row-based "C" matrix as a vnl_matrix in order to
12 // perform vnl_matrix operations on it.
13 //
14 // (b) Declaring a vnl_matrix that uses entirely stack-based storage for the
15 // matrix.
16 //
17 // The big warning is that returning a vnl_matrix_fixed_ref pointer will free
18 // non-heap memory if deleted through a vnl_matrix pointer. This should be
19 // very difficult though, as vnl_matrix_fixed_ref objects may not be constructed
20 // using operator new. This in turn is plausible as the point is to avoid
21 // such calls.
22 //
23 // \author Andrew W. Fitzgibbon, Oxford RRG
24 // \date 04 Aug 1996
25 //
26 // Additional comments on the vnl_matrix_fixed_ref and vnl_vector_fixed_ref
27 // classes, extracted from an email conversation between Paul P. Smyth,
28 // Vicon Motion Systems Ltd., from May 02, 2001, and Amitha Perera
29 // (who answers the following on Monday, October 07, 2002):
30 //
31 // I'm working on separating vnl_vector and vnl_vector_fixed in the VXL
32 // tree, as I mailed a while ago to the vxl-maintainers list. I noticed
33 // that you'd committed a vnl_vector_fixed_ref class which doesn't seem
34 // to provide any additional functionality over vnl_vector_ref. May I
35 // remove it, or is there some use for it?
36 //
37 // Paul Smyth writes:
38 // The rationale behind it was that I had some (fast) algorithms for
39 // matrix/vector operations that made use of compile-time knowledge of the
40 // vector and matrix sizes.
41 // This was typically appropriate when trying to interpret a fixed-size
42 // subvector within a large vector of parameters as e.g. a translation.
43 //
44 // As I saw it, the various types of vector possible were: (with their current
45 // names)
46 // - pointer to memory, plus compile-time knowledge of vector size ( T*, and enum{size}) = vnl_vector_fixed_ref
47 // - ownership of memory, plus compile-time size = vnl_vector_fixed
48 // - pointer to memory, plus run-time only knowledge of size (T* and size()) = vnl_vector_ref
49 // - ownership of memory, variably sized = vnl_vector
50 //
51 // I had a conversation with Andrew Fitzgibbon, where he reckoned that the best
52 // thing to do with vnl vectors etc. was to create entirely separate types, and
53 // routines for conversion between them (possibly implicitly), rather that
54 // trying to establish a class hierarchy, which may add too many burdens in
55 // terms of object size for small vectors/matrices.
56 //
57 // Sorry - I've now found the debate on the maintainers list!
58 //
59 // Anyway, I believe that vector_fixed_ref is very necessary, and that you
60 // should be able to convert from a vector_fixed to a vector_fixed_ref - say
61 // using an as_ref() member on vector_fixed or standalone function.
62 // And I believe that for the restructured classes, vector_fixed_ref and
63 // vector_fixed should not be related by inheritance, as that would place an
64 // excessive burden on the size of vector_fixed.
65 //
66 // ------
67 // Another issue - do you have a mechanism for dealing with const data safely?
68 // {
69 // template<typename T, int n>
70 // vnl_vector_fixed_ref(T* i_Data);
71 //
72 // void MyFunction(const vnl_vector<double> & Input)
73 // {
74 // // take a reference to the first 3 elements of Input
75 // vnl_vector_fixed_ref<double,3> ref(Input.begin());
76 // // compiler error - as making vector_fixed_ref from const
77 // double *
78 // }
79 // }
80 //
81 // The options appear to be
82 // 1) Make a separate class vnl_vector_fixed_ref_const
83 // 2) Make vnl_vector_fixed_ref so it can be instantiated with
84 // vnl_vector_fixed_ref<double,n> AND vnl_vector_fixed_ref<const double,n>, and
85 // gives appropriate behaviour - would probably require a to_const function
86 // which generates vnl_vector_fixed_ref<const T,n> from
87 // vnl_vector_fixed_ref<T,n>
88 //
89 // ------
90 // Another note is that a number of routines that use vector_fixed currently
91 // (e.g. cross_3d) should really use vector_fixed_ref as an input, because they
92 // should be able to operate on fixed vector references as well as fixed
93 // vectors.
94 //
95 // While I'm at it, has it been decided that the vnl_vector and vnl_vector_ref
96 // classes are to remain unchanged? Because having vnl_vector as the base, and
97 // vnl_vector_ref derived from it is a real pain in the backside. A vector
98 // which may or may not own its own memory is a more general type than one
99 // which does own its own memory, and having vnl_vector as the base means that
100 // all sorts of nastinesses can happen. Simply, a vector_ref Is-not a type of
101 // vector.
102 // If anything, it should be the other way round.
103 //
104 // void DoAssign(vnl_vector<double> & RefToMemoryIDontOwn, const vnl_vector<double> & NewContents)
105 // {
106 // RefToMemoryIDontOwn = NewContents;
107 // }
108 //
109 // void DeleteTwice()
110 // {
111 // vnl_vector<double> vec1(3, 0); // size 3 - news 3*double
112 // vnl_vector<double> vec2(4,1); // size 4 news 4 * double
113 // vnl_vector_ref<double> ref_to_1(3,vec1.begin()); // copies pointer
114 // DoAssign(ref_to_1, vec2); // deletes memory owned by 1, news 4 * double
115 // // vec1 now points to deleted memory, and will crash when goes out of scope
116 // }
117 //
118 // Maybe that issue isn't on your agenda - but it's a bit of a disaster. I know
119 // that fixing this might break some code.
120 //
121 // ---------
122 // Sorry for rolling all these things into one - I'd be interested to know what
123 // you think. But please don't kill my vnl_vector_ref!
124 //
125 // Paul.
126 //
127 // \verbatim
128 // Modifications:
129 // 27-Nov-1996 Peter Vanroose - added default constructor which allocates matrix storage
130 // 4-Jul-2003 Paul Smyth - general cleanup and rewrite; interface now as vnl_matrix_fixed
131 // 15-Aug-2003 Peter Vanroose - removed "duplicate" operator=(vnl_matrix_fixed<T,n> const&)
132 // 8-Dec-2006 Markus Moll - changed operator>> signature (to const& argument)
133 // 30-Mar-2009 Peter Vanroose - added arg_min() and arg_max()
134 // 24-Oct-2010 Peter Vanroose - mutators and filling methods now return *this
135 // 18-Jan-2011 Peter Vanroose - added methods set_diagonal() & get_diagonal()
136 // \endverbatim
137 //
138 //-----------------------------------------------------------------------------
139 
140 #include <iosfwd>
141 #include <cstring>
142 #include <cassert>
143 #ifdef _MSC_VER
144 # include <vcl_msvc_warnings.h>
145 #endif
146 #include <vnl/vnl_matrix_fixed.h>
147 #include <vnl/vnl_vector_fixed.h>
149 #include <vnl/vnl_c_vector.h>
150 #include "vnl/vnl_export.h"
151 
152 //: Fixed size stack-stored vnl_matrix
153 // vnl_matrix_fixed_ref is a fixed-size vnl_matrix for which the data space
154 // has been supplied externally. This is useful for two main tasks:
155 //
156 // (a) Treating some row-based "C" matrix as a vnl_matrix in order to
157 // perform vnl_matrix operations on it.
158 //
159 // (b) Declaring a vnl_matrix that uses entirely stack-based storage for the
160 // matrix.
161 //
162 // The big warning is that returning a vnl_matrix_fixed_ref pointer will free
163 // non-heap memory if deleted through a vnl_matrix pointer. This should be
164 // very difficult though, as vnl_matrix_fixed_ref objects may not be constructed
165 // using operator new. This in turn is plausible as the point is to avoid
166 // such calls.
167 //
168 
169 template <class T, unsigned num_rows, unsigned num_cols>
170 class VNL_EXPORT vnl_matrix_fixed_ref_const
171 {
172  protected:
173  const T* data_;
174  public:
176  : data_(rhs.data_block())
177  {
178  }
179  explicit vnl_matrix_fixed_ref_const(const T * dataptr)
180  : data_(dataptr)
181  {
182  }
184  : data_(rhs.data_)
185  {
186  }
187  //: Get j-th row
188  vnl_vector_fixed<T,num_rows> get_row(unsigned row_index) const
189  {
190  vnl_vector<T> v(num_cols);
191  for (unsigned int j = 0; j < num_cols; j++) // For each element in row
192  v[j] = (*this)(row_index,j);
193  return v;
194  }
195 
196  //: Get j-th column
197  vnl_vector_fixed<T,num_cols> get_column(unsigned column_index) const
198  {
199  vnl_vector<T> v(num_rows);
200  for (unsigned int j = 0; j < num_rows; j++)
201  v[j] = (*this)(j,column_index);
202  return v;
203  }
204 
205  //: Return a vector with the content of the (main) diagonal
206  vnl_vector<T> get_diagonal() const;
208  const T * data_block() const { return data_; }
209 
210  //: Const iterators
211  typedef T const *const_iterator;
212  //: Iterator pointing to start of data
213  const_iterator begin() const { return data_; }
214  //: Iterator pointing to element beyond end of data
215  const_iterator end() const { return begin() + this->size(); }
216 
217  //: Type defs for iterators
218  typedef const T element_type;
219  //: Type defs for iterators
220  typedef const T *iterator;
222  T const & operator() (unsigned r, unsigned c) const
223  {
224 #if VNL_CONFIG_CHECK_BOUNDS && (!defined NDEBUG)
225  assert(r<num_rows); // Check the row index is valid
226  assert(c<num_cols); // Check the column index is valid
227 #endif
228  return *(data_ + num_cols * r + c);
229  }
230 
231  //: return pointer to given row
232  // No boundary checking here.
233  T const * operator[] (unsigned r) const { return data_ + num_cols * r; }
234 
235  //: Return number of rows
236  unsigned rows() const { return num_rows; }
237 
238  //: Return number of columns
239  // A synonym for cols()
240  unsigned columns() const { return num_cols; }
241 
242  //: Return number of columns
243  // A synonym for columns()
244  unsigned cols() const { return num_cols; }
245 
246  //: Return number of elements
247  // This equals rows() * cols()
248  unsigned size() const { return num_rows*num_cols; }
249 
250  //: Print matrix to os in some hopefully sensible format
251  void print(std::ostream& os) const;
252 
253  void copy_out(T *) const;
254 
255  ////--------------------------- Additions ----------------------------
256 
257  //: Make a new matrix by applying function to each element.
258  vnl_matrix_fixed<T,num_rows,num_cols> apply(T (*f)(T)) const;
259 
260  //: Make a new matrix by applying function to each element.
261  vnl_matrix_fixed<T,num_rows,num_cols> apply(T (*f)(T const&)) const;
262 
263  //: Return transpose
264  vnl_matrix_fixed<T,num_cols,num_rows> transpose () const;
265 
266  //: Return conjugate transpose
267  vnl_matrix_fixed<T,num_cols,num_rows> conjugate_transpose () const;
268 
269  //: Extract a sub-matrix of size rows x cols, starting at (top,left)
270  // Thus it contains elements [top,top+rows-1][left,left+cols-1]
271  vnl_matrix<T> extract (unsigned rowz, unsigned colz,
272  unsigned top=0, unsigned left=0) const;
273 
274  //: Get n rows beginning at rowstart
275  vnl_matrix<T> get_n_rows (unsigned rowstart, unsigned n) const;
276 
277  //: Get n columns beginning at colstart
278  vnl_matrix<T> get_n_columns(unsigned colstart, unsigned n) const;
279 
280  //: Type def for norms.
281  typedef typename vnl_c_vector<T>::abs_t abs_t;
282 
283  //: Return sum of absolute values of elements
284  abs_t array_one_norm() const { return vnl_c_vector<T>::one_norm(begin(), size()); }
285 
286  //: Return square root of sum of squared absolute element values
287  abs_t array_two_norm() const { return vnl_c_vector<T>::two_norm(begin(), size()); }
288 
289  //: Return largest absolute element value
290  abs_t array_inf_norm() const { return vnl_c_vector<T>::inf_norm(begin(), size()); }
291 
292  //: Return sum of absolute values of elements
293  abs_t absolute_value_sum() const { return array_one_norm(); }
294 
295  //: Return largest absolute value
296  abs_t absolute_value_max() const { return array_inf_norm(); }
297 
298  // $ || M ||_1 := \max_j \sum_i | M_{ij} | $
299  abs_t operator_one_norm() const;
300 
301  // $ || M ||_\inf := \max_i \sum_j | M_{ij} | $
302  abs_t operator_inf_norm() const;
303 
304  //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements)
305  abs_t frobenius_norm() const { return vnl_c_vector<T>::two_norm(begin(), size()); }
306 
307  //: Return Frobenius norm of matrix (sqrt of sum of squares of its elements)
308  abs_t fro_norm() const { return frobenius_norm(); }
309 
310  //: Return RMS of all elements
311  abs_t rms() const { return vnl_c_vector<T>::rms_norm(begin(), size()); }
312 
313  //: Return minimum value of elements
314  T min_value() const { return vnl_c_vector<T>::min_value(begin(), size()); }
315 
316  //: Return maximum value of elements
317  T max_value() const { return vnl_c_vector<T>::max_value(begin(), size()); }
318 
319  //: Return location of minimum value of elements
320  unsigned arg_min() const { return vnl_c_vector<T>::arg_min(begin(), size()); }
321 
322  //: Return location of maximum value of elements
323  unsigned arg_max() const { return vnl_c_vector<T>::arg_max(begin(), size()); }
324 
325  //: Return mean of all matrix elements
326  T mean() const { return vnl_c_vector<T>::mean(begin(), size()); }
327 
328  // predicates
329 
330  //: Return true iff the size is zero.
331  bool empty() const { return num_rows==0 && num_cols==0; }
332 
333  //: Return true if all elements equal to identity.
334  bool is_identity() const;
335 
336  //: Return true if all elements equal to identity, within given tolerance
337  bool is_identity(double tol) const;
338 
339  //: Return true if all elements equal to zero.
340  bool is_zero() const;
341 
342  //: Return true if all elements equal to zero, within given tolerance
343  bool is_zero(double tol) const;
344 
345  //: Return true if finite
346  bool is_finite() const;
347 
348  //: Return true if matrix contains NaNs
349  bool has_nans() const;
350 
351  //: abort if size is not as expected
352  // This function does or tests nothing if NDEBUG is defined
353 #ifndef NDEBUG
354  void assert_size(unsigned rowz, unsigned colz) const
355 #else
356  void assert_size(unsigned , unsigned ) const
357 #endif
358  {
359 #ifndef NDEBUG
360  assert_size_internal(rowz, colz);
361 #endif
362  }
363  //: abort if matrix contains any INFs or NANs.
364  // This function does or tests nothing if NDEBUG is defined
365  void assert_finite() const
366  {
367 #ifndef NDEBUG
368  assert_finite_internal();
369 #endif
370  }
372  static void add( const T* a, const T* b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::add(a,b,r); }
373  static void add( const T* a, T b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::add(a,b,r); }
374  static void sub( const T* a, const T* b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::sub(a,b,r); }
375  static void sub( const T* a, T b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::sub(a,b,r); }
376  static void sub( T a, const T* b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::sub(a,b,r); }
377  static void mul( const T* a, const T* b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::mul(a,b,r); }
378  static void mul( const T* a, T b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::mul(a,b,r); }
379  static void div( const T* a, const T* b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::div(a,b,r); }
380  static void div( const T* a, T b, T* r ) { vnl_matrix_fixed<T,num_rows,num_cols>::div(a,b,r); }
382  static bool equal( const T* a, const T* b ) { return vnl_matrix_fixed<T,num_rows,num_cols>::equal(a,b); }
383 
384  private:
386  {
387  assert(!"Assignment is illegal for a vnl_matrix_fixed_ref_const");
388  return *this;
389  }
390 
391  void assert_finite_internal() const;
392 
393  void assert_size_internal(unsigned, unsigned) const;
394 };
395 
396 
397 template <class T, unsigned num_rows, unsigned num_cols>
398 class VNL_EXPORT vnl_matrix_fixed_ref : public vnl_matrix_fixed_ref_const<T,num_rows,num_cols>
399 {
401 
402  public:
403  // this is the only point where the const_cast happens
404  // the base class is used to store the pointer, so that conversion is not necessary
405  T * data_block() const {
406  return const_cast<T*>(this->data_);
407  }
409  : base(rhs.data_block())
410  {
411  }
412  explicit vnl_matrix_fixed_ref(T * dataptr)
413  : base(dataptr)
414  {
415  }
416 
417  //: Copy another vnl_matrix_fixed<T,m,n> into this.
419  {
420  std::memcpy(data_block(), rhs.data_block(), num_rows*num_cols*sizeof(T));
421  return *this;
422  }
423 
424  // Basic 2D-Array functionality-------------------------------------------
425 
426  //: set element
427  void put (unsigned r, unsigned c, T const& v) { (*this)(r,c) = v; }
428 
429  //: get element
430  T get (unsigned r, unsigned c) const { return (*this)(r,c); }
431 
432  //: return pointer to given row
433  // No boundary checking here.
434  T * operator[] (unsigned r) const { return data_block() + num_cols * r; }
435 
436  //: Access an element for reading or writing
437  // There are assert style boundary checks - #define NDEBUG to turn them off.
438  T & operator() (unsigned r, unsigned c) const
439  {
440 #if VNL_CONFIG_CHECK_BOUNDS && (!defined NDEBUG)
441  assert(r<num_rows); // Check the row index is valid
442  assert(c<num_cols); // Check the column index is valid
443 #endif
444  return *(this->data_block() + num_cols * r + c);
445  }
446 
447  // ----------------------- Filling and copying -----------------------
448 
449  //: Sets all elements of matrix to specified value, and returns "*this".
450  // Complexity $O(r.c)$
451  // Returning "*this" allows "chaining" two or more operations:
452  // e.g., to set a matrix to a column-normalized all-elements-equal matrix, say
453  // \code
454  // M.fill(1).normalize_columns();
455  // \endcode
456  // Returning "*this" also allows passing such a matrix as argument
457  // to a function f, without having to name the constructed matrix:
458  // \code
459  // f(vnl_matrix_fixed_ref_const<double,5,5>(1.0).normalize_columns());
460  // \endcode
461  vnl_matrix_fixed_ref const& fill (T) const;
462 
463  //: Sets all diagonal elements of matrix to specified value; returns "*this".
464  // Complexity $O(\min(r,c))$
465  // Returning "*this" allows "chaining" two or more operations:
466  // e.g., to set a 3x3 matrix to [5 0 0][0 10 0][0 0 15], just say
467  // \code
468  // M.fill_diagonal(5).scale_row(1,2).scale_column(2,3);
469  // \endcode
470  // Returning "*this" also allows passing a diagonal-filled matrix as argument
471  // to a function f, without having to name the constructed matrix:
472  // \code
473  // f(vnl_matrix_fixed_ref<double,3,3>().fill_diagonal(5));
474  // \endcode
475  vnl_matrix_fixed_ref const& fill_diagonal (T) const;
476 
477  //: Sets the diagonal elements of this matrix to the specified list of values.
478  // Returning "*this" allows "chaining" two or more operations: see the
479  // reasoning (and the examples) in the documentation for method
480  // fill_diagonal().
481  vnl_matrix_fixed_ref const& set_diagonal(vnl_vector<T> const&) const;
482 
483  //: Fills (laminates) this matrix with the given data, then returns it.
484  // We assume that the argument points to a contiguous rows*cols array, stored rowwise.
485  // No bounds checking on the array.
486  // Returning "*this" allows "chaining" two or more operations:
487  // e.g., to fill a square matrix column-wise, fill it rowwise then transpose:
488  // \code
489  // M.copy_in(array).inplace_transpose();
490  // \endcode
491  // Returning "*this" also allows passing a filled-in matrix as argument
492  // to a function f, without having to name the constructed matrix:
493  // \code
494  // f(vnl_matrix_fixed_ref<double,3,3>().copy_in(array));
495  // \endcode
496  vnl_matrix_fixed_ref const& copy_in(T const *) const;
497 
498  //: Fills (laminates) this matrix with the given data, then returns it.
499  // A synonym for copy_in()
500  vnl_matrix_fixed_ref const& set(T const *d) const { return copy_in(d); }
501 
502  //: Fills the given array with this matrix.
503  // We assume that the argument points to a contiguous rows*cols array, stored rowwise.
504  // No bounds checking on the array
505 
506  //: Transposes this matrix efficiently, if it is square, and returns it.
507  // Returning "*this" allows "chaining" two or more operations:
508  // e.g., to fill a square matrix column-wise, fill it rowwise then transpose:
509  // \code
510  // M.copy_in(array).inplace_transpose();
511  // \endcode
512  vnl_matrix_fixed_ref const& inplace_transpose() const;
513 
514  // ----------------------- Arithmetic --------------------------------
515  // note that these functions should not pass scalar as a const&.
516  // Look what would happen to A /= A(0,0).
517 
518  //: Add \a s to each element of lhs matrix in situ
519  vnl_matrix_fixed_ref const& operator+= (T s) const
520  {
521  base::add( data_block(), s, data_block() ); return *this;
522  }
523 
524  //: Subtract \a s from each element of lhs matrix in situ
525  vnl_matrix_fixed_ref const& operator-= (T s) const
526  {
527  base::sub( data_block(), s, data_block() ); return *this;
528  }
529 
530  //:
531  vnl_matrix_fixed_ref const& operator*= (T s) const
532  {
533  base::mul( data_block(), s, data_block() ); return *this;
534  }
535 
536  //:
537  vnl_matrix_fixed_ref const& operator/= (T s) const
538  {
539  base::div( data_block(), s, data_block() ); return *this;
540  }
541 
542  //:
544  {
545  base::add( data_block(), m.data_block(), data_block() ); return *this;
546  }
547 
548  //:
549  vnl_matrix_fixed_ref const& operator+= (vnl_matrix<T> const& m) const
550  {
551  assert( m.rows() == num_rows && m.cols() == num_cols );
552  base::add( data_block(), m.data_block(), data_block() ); return *this;
553  }
554 
555  //:
557  {
558  base::sub( data_block(), m.data_block(), data_block() ); return *this;
559  }
560 
561  //:
562  vnl_matrix_fixed_ref const& operator-= (vnl_matrix<T> const& m) const
563  {
564  assert( m.rows() == num_rows && m.cols() == num_cols );
565  base::sub( data_block(), m.data_block(), data_block() ); return *this;
566  }
567 
568  //: Negate all elements of matrix
570  {
572  base::sub( T(0), data_block(), r.data_block() );
573  return r;
574  }
575 
576  //:
578  {
580  for (unsigned i = 0; i < num_rows; ++i)
581  for (unsigned j = 0; j < num_cols; ++j)
582  {
583  T accum = this->operator()(i,0) * s(0,j);
584  for (unsigned k = 1; k < num_cols; ++k)
585  accum += this->operator()(i,k) * s(k,j);
586  out(i,j) = accum;
587  }
588  *this = out;
589  return *this;
590  }
591 
592  //: Set values of this matrix to those of M, starting at [top,left]
593  vnl_matrix_fixed_ref const & update (vnl_matrix<T> const&, unsigned top=0, unsigned left=0) const;
594 
595  //: Set the elements of the i'th column to v[i] (No bounds checking)
596  vnl_matrix_fixed_ref const& set_column(unsigned i, T const * v) const;
597 
598  //: Set the elements of the i'th column to value, then return *this.
599  vnl_matrix_fixed_ref const& set_column(unsigned i, T value ) const;
600 
601  //: Set j-th column to v, then return *this.
602  vnl_matrix_fixed_ref const& set_column(unsigned j, vnl_vector<T> const& v) const;
603 
604  //: Set j-th column to v, then return *this.
605  vnl_matrix_fixed_ref const& set_column(unsigned j, vnl_vector_fixed<T, num_rows> const& v) const;
606 
607  //: Set columns to those in M, starting at starting_column, then return *this.
608  vnl_matrix_fixed_ref const& set_columns(unsigned starting_column, vnl_matrix<T> const& M) const;
609 
610  //: Set the elements of the i'th row to v[i] (No bounds checking)
611  vnl_matrix_fixed_ref const& set_row (unsigned i, T const * v) const;
612 
613  //: Set the elements of the i'th row to value, then return *this.
614  vnl_matrix_fixed_ref const& set_row (unsigned i, T value ) const;
615 
616  //: Set the i-th row to v, then return *this.
617  vnl_matrix_fixed_ref const& set_row (unsigned i, vnl_vector<T> const& v) const;
618 
619  //: Set the i-th row to v, then return *this.
620  vnl_matrix_fixed_ref const& set_row (unsigned i, vnl_vector_fixed<T, num_cols> const& v) const;
621 
622  // ==== mutators ====
623 
624  //: Sets this matrix to an identity matrix, then returns "*this".
625  // Returning "*this" allows e.g. passing an identity matrix as argument to
626  // a function f, without having to name the constructed matrix:
627  // \code
628  // f(vnl_matrix_fixed_ref<double,5,5>().set_identity());
629  // \endcode
630  // Returning "*this" also allows "chaining" two or more operations:
631  // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say
632  // \code
633  // M.set_identity().scale_row(0,3).scale_column(1,2);
634  // \endcode
635  // If the matrix is not square, anyhow set main diagonal to 1, the rest to 0.
636  vnl_matrix_fixed_ref const& set_identity() const;
637 
638  //: Reverses the order of rows, and returns "*this".
639  // Returning "*this" allows "chaining" two or more operations:
640  // e.g., to flip both up-down and left-right, one could just say
641  // \code
642  // M.flipud().fliplr();
643  // \endcode
644  vnl_matrix_fixed_ref & flipud();
645 
646  //: Reverses the order of columns, and returns "*this".
647  // Returning "*this" allows "chaining" two or more operations:
648  // e.g., to flip both up-down and left-right, one could just say
649  // \code
650  // M.flipud().fliplr();
651  // \endcode
652  vnl_matrix_fixed_ref & fliplr();
653 
654  //: Normalizes each row so it is a unit vector, and returns "*this".
655  // Zero rows are not modified
656  // Returning "*this" allows "chaining" two or more operations:
657  // e.g., to set a matrix to a row-normalized all-elements-equal matrix, say
658  // \code
659  // M.fill(1).normalize_rows();
660  // \endcode
661  // Returning "*this" also allows passing such a matrix as argument
662  // to a function f, without having to name the constructed matrix:
663  // \code
664  // f(vnl_matrix_fixed_ref<double,5,5>(1.0).normalize_rows());
665  // \endcode
666  vnl_matrix_fixed_ref const& normalize_rows() const;
667 
668  //: Normalizes each column so it is a unit vector, and returns "*this".
669  // Zero columns are not modified
670  // Returning "*this" allows "chaining" two or more operations:
671  // e.g., to set a matrix to a column-normalized all-elements-equal matrix, say
672  // \code
673  // M.fill(1).normalize_columns();
674  // \endcode
675  // Returning "*this" also allows passing such a matrix as argument
676  // to a function f, without having to name the constructed matrix:
677  // \code
678  // f(vnl_matrix_fixed_ref<double,5,5>(1.0).normalize_columns());
679  // \endcode
680  vnl_matrix_fixed_ref const& normalize_columns() const;
681 
682  //: Scales elements in given row by a factor T, and returns "*this".
683  // Returning "*this" allows "chaining" two or more operations:
684  // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say
685  // \code
686  // M.set_identity().scale_row(0,3).scale_column(1,2);
687  // \endcode
688  vnl_matrix_fixed_ref const& scale_row (unsigned row, T value) const;
689 
690  //: Scales elements in given column by a factor T, and returns "*this".
691  // Returning "*this" allows "chaining" two or more operations:
692  // e.g., to set a 3x3 matrix to [3 0 0][0 2 0][0 0 1], one could say
693  // \code
694  // M.set_identity().scale_row(0,3).scale_column(1,2);
695  // \endcode
696  vnl_matrix_fixed_ref const& scale_column(unsigned col, T value) const;
697 
698  ////----------------------- Input/Output ----------------------------
699 
700  // : Read a vnl_matrix from an ascii std::istream, automatically determining file size if the input matrix has zero size.
701  bool read_ascii(std::istream& s) const;
702 
703  //----------------------------------------------------------------------
704  // Conversion to vnl_matrix_ref.
705 
706  // The const version of as_ref should return a const vnl_matrix_ref
707  // so that the vnl_matrix_ref::non_const() cannot be used on
708  // it. This prevents a const vnl_matrix_fixed from being cast into a
709  // non-const vnl_matrix reference, giving a slight increase in type safety.
710 
711  //: Explicit conversion to a vnl_matrix_ref.
712  // This is a cheap conversion for those functions that have an interface
713  // for vnl_matrix_ref but not for vnl_matrix_fixed_ref. There is also a
714  // conversion operator that should work most of the time.
715  // \sa vnl_matrix_ref::non_const
716  vnl_matrix_ref<T> as_ref() { return vnl_matrix_ref<T>( num_rows, num_cols, data_block() ); }
717 
718  //: Explicit conversion to a vnl_matrix_ref.
719  // This is a cheap conversion for those functions that have an interface
720  // for vnl_matrix_ref but not for vnl_matrix_fixed_ref. There is also a
721  // conversion operator that should work most of the time.
722  // \sa vnl_matrix_ref::non_const
723  const vnl_matrix_ref<T> as_ref() const { return vnl_matrix_ref<T>( num_rows, num_cols, const_cast<T*>(data_block()) ); }
724 
725  //: Cheap conversion to vnl_matrix_ref
726  // Sometimes, such as with templated functions, the compiler cannot
727  // use this user-defined conversion. For those cases, use the
728  // explicit as_ref() method instead.
729  operator const vnl_matrix_ref<T>() const { return vnl_matrix_ref<T>( num_rows, num_cols, const_cast<T*>(data_block()) ); }
730 
731  //: Convert to a vnl_matrix.
732  const vnl_matrix<T> as_matrix() const { return vnl_matrix<T>(const_cast<T*>(data_block()),num_rows,num_cols); }
733 
734  //----------------------------------------------------------------------
736  typedef T element_type;
737 
738  //: Iterators
739  typedef T *iterator;
740  //: Iterator pointing to start of data
741  iterator begin() const { return data_block(); }
742  //: Iterator pointing to element beyond end of data
743  iterator end() const { return begin() + this->size(); }
744  //--------------------------------------------------------------------------------
745 
746  //: Return true if *this == rhs
747  bool operator_eq (vnl_matrix_fixed_ref_const<T,num_rows,num_cols> const & rhs) const
748  {
750  }
751 
752  //: Equality operator
753  bool operator==(vnl_matrix_fixed_ref_const<T,num_rows,num_cols> const &that) const { return this->operator_eq(that); }
754 
755  //: Inequality operator
756  bool operator!=(vnl_matrix_fixed_ref_const<T,num_rows,num_cols> const &that) const { return !this->operator_eq(that); }
757 
758 //--------------------------------------------------------------------------------
759 };
760 
761  // Helper routines for arithmetic. These routines know the size from
762  // the template parameters. The vector-vector operations are
763  // element-wise.
764 
765 // Make the operators below inline because (1) they are small and
766 // (2) we then have less explicit instantiation trouble.
767 
768 // --- Matrix-scalar -------------------------------------------------------------
769 
770 template<class T, unsigned m, unsigned n>
771 inline
773 {
776  return r;
777 }
778 
779 template<class T, unsigned m, unsigned n>
780 inline
782 {
785  return r;
786 }
787 
788 template<class T, unsigned m, unsigned n>
789 inline
791 {
794  return r;
795 }
796 
797 template<class T, unsigned m, unsigned n>
798 inline
800 {
803  return r;
804 }
805 
806 template<class T, unsigned m, unsigned n>
807 inline
809 {
812  return r;
813 }
814 
815 template<class T, unsigned m, unsigned n>
816 inline
818 {
821  return r;
822 }
823 
824 template<class T, unsigned m, unsigned n>
825 inline
827 {
830  return r;
831 }
832 
833 template<class T, unsigned m, unsigned n>
834 inline
836 {
839  return r;
840 }
841 
842 template<class T, unsigned m, unsigned n>
843 inline
845 {
848  return r;
849 }
850 
851 
852 template<class T, unsigned m, unsigned n>
853 inline
856 {
859  return r;
860 }
861 
862 
863 template<class T, unsigned m, unsigned n>
864 inline
867 {
870  return r;
871 }
872 
873 
874 // The following two functions are helper functions that keep the
875 // matrix-matrix and matrix-vector multiplication code in one place,
876 // so that bug fixes, etc, can be localized.
877 template <class T, unsigned M, unsigned N>
878 inline
882 {
884  for (unsigned i = 0; i < M; ++i)
885  {
886  T accum = a(i,0) * b(0);
887  for (unsigned k = 1; k < N; ++k)
888  accum += a(i,k) * b(k);
889  out(i) = accum;
890  }
891  return out;
892 }
893 
894 // see comment above
895 template <class T, unsigned M, unsigned N, unsigned O>
896 inline
900 {
902  for (unsigned i = 0; i < M; ++i)
903  for (unsigned j = 0; j < O; ++j)
904  {
905  T accum = a(i,0) * b(0,j);
906  for (unsigned k = 1; k < N; ++k)
907  accum += a(i,k) * b(k,j);
908  out(i,j) = accum;
909  }
910  return out;
911 }
912 
913 // The version for correct compilers
914 
915 //: Multiply conformant vnl_matrix_fixed (M x N) and vector_fixed (N)
916 // \relatesalso vnl_vector_fixed
917 // \relatesalso vnl_matrix_fixed
918 template <class T, unsigned M, unsigned N>
919 inline
921 {
922  return vnl_matrix_fixed_mat_vec_mult(a,b);
923 }
924 
925 //: Multiply two conformant vnl_matrix_fixed (M x N) times (N x O)
926 // \relatesalso vnl_matrix_fixed
927 template <class T, unsigned M, unsigned N, unsigned O>
928 inline
930 {
931  return vnl_matrix_fixed_mat_mat_mult(a,b);
932 }
933 
934 // These overloads for the common case of mixing a fixed with a
935 // non-fixed. Because the operator* are templated, the fixed will not
936 // be automatically converted to a non-fixed-ref. These do it for you.
937 
938 template<class T, unsigned m, unsigned n>
940 {
941  return a.as_ref() + b;
942 }
943 
944 template<class T, unsigned m, unsigned n>
946 {
947  return a + b.as_ref();
948 }
949 
950 template<class T, unsigned m, unsigned n>
952 {
953  return a.as_ref() - b;
954 }
955 
956 template<class T, unsigned m, unsigned n>
958 {
959  return a - b.as_ref();
960 }
961 
962 template<class T, unsigned m, unsigned n>
964 {
965  return a.as_ref() * b;
966 }
967 
968 template<class T, unsigned m, unsigned n>
970 {
971  return a * b.as_ref();
972 }
973 
974 template<class T, unsigned m, unsigned n>
976 {
977  return a.as_ref() * b;
978 }
979 
980 template<class T, unsigned n>
982 {
983  return a * b.as_ref();
984 }
985 
986 
987 // --- I/O operations ------------------------------------------------------------
988 
989 template<class T, unsigned m, unsigned n>
990 inline
991 std::ostream& operator<< (std::ostream& os, vnl_matrix_fixed_ref_const<T,m,n> const& mat)
992 {
993  mat.print(os);
994  return os;
995 }
996 
997 template<class T, unsigned m, unsigned n>
998 inline
999 std::istream& operator>> (std::istream& is, vnl_matrix_fixed_ref<T,m,n> const& mat)
1000 {
1001  mat.read_ascii(is);
1002  return is;
1003 }
1004 
1005 #endif // vnl_matrix_fixed_ref_h_
vnl_vector_fixed< T, n > element_quotient(const vnl_vector_fixed< T, n > &a, const vnl_vector_fixed< T, n > &b)
vnl_bignum operator+(vnl_bignum const &r1, long r2)
Returns the sum of two bignum numbers.
Definition: vnl_bignum.h:279
vnl_matrix_fixed< T, M, O > vnl_matrix_fixed_mat_mat_mult(const vnl_matrix_fixed_ref_const< T, M, N > &a, const vnl_matrix_fixed_ref_const< T, N, O > &b)
vnl_vector_fixed< T, M > vnl_matrix_fixed_mat_vec_mult(const vnl_matrix_fixed_ref_const< T, M, N > &a, const vnl_vector_fixed_ref_const< T, N > &b)
Fixed size vnl_vector using user-supplied storage See vnl_matrix_fixed_ref for rationale.
const vnl_matrix_fixed_ref_const< T, num_rows, num_cols > & operator=(const vnl_matrix_fixed_ref_const< T, num_rows, num_cols > &) const
static unsigned arg_min(T const *, unsigned)
Returns location of min value of the vector.
T const * operator[](unsigned r) const
return pointer to given row.
T const * data_block() const
Access the contiguous block storing the elements in the matrix row-wise. O(1).
bool read_ascii(std::istream &s) const
const_iterator begin() const
Iterator pointing to start of data.
#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 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
Fixed size, stack-stored, space-efficient matrix.
Definition: vnl_fwd.h:23
const_iterator end() const
Iterator pointing to element beyond end of data.
static bool equal(const T *a, const T *b)
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
static void div(const T *a, T b, T *r)
T const * const_iterator
Const iterators.
vnl_c_vector< T >::abs_t abs_t
Type def for norms.
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_matrix_fixed< T, m, n > operator-(const vnl_matrix_fixed_ref_const< T, m, n > &mat1, const vnl_matrix_fixed_ref_const< T, m, n > &mat2)
static unsigned arg_max(T const *, unsigned)
Returns location of max value of the vector.
static T min_value(T const *, unsigned)
Returns min value of the vector.
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
unsigned size() const
Return number of elements.
static bool equal(const T *a, const T *b)
static void add(const T *a, T b, T *r)
vnl_numeric_traits< T >::abs_t abs_t
Definition: vnl_c_vector.h:42
T const & operator()(unsigned r, unsigned c) const
Mathematical vector class, templated by type of element.
Definition: vnl_fwd.h:16
Fixed length stack-stored, space-efficient vector.
Definition: vnl_fwd.h:22
fixed size matrix
Fixed length stack-stored vector.
void print(std::ostream &os) const
Print matrix to os in some hopefully sensible format.
const T element_type
Type defs for iterators.
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 void mul(const T *a, T b, T *r)
static T max_value(T const *, unsigned)
Returns max value of the vector.
static void sub(T a, const T *b, T *r)
static void sub(const T *a, T b, T *r)
const T * iterator
Type defs for iterators.
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
Fixed size stack-stored vnl_matrix.
Definition: vnl_fwd.h:27
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
static void add(const T *a, const T *b, T *r)
const vnl_vector_ref< T > as_ref() const
Explicit conversion to a vnl_vector_ref.