vnl_matrix_fixed_ref.hxx
Go to the documentation of this file.
1 // This is core/vnl/vnl_matrix_fixed_ref.hxx
2 #ifndef vnl_matrix_fixed_ref_hxx_
3 #define vnl_matrix_fixed_ref_hxx_
4 
5 #include <cmath>
6 #include <iostream>
7 #include <cstdlib>
8 #include "vnl_matrix_fixed_ref.h"
9 //:
10 // \file
11 
12 #ifdef _MSC_VER
13 # include <vcl_msvc_warnings.h>
14 #endif
15 #include <cassert>
16 
17 #include <vnl/vnl_error.h>
18 #include <vnl/vnl_math.h>
19 
20 //------------------------------------------------------------
21 
22 template<class T, unsigned nrows, unsigned ncols>
25 {
26  for (unsigned int i = 0; i < nrows; i++)
27  for (unsigned int j = 0; j < ncols; j++)
28  (*this)(i,j) = value;
29  return *this;
30 }
31 
32 
33 template<class T, unsigned nrows, unsigned ncols>
36 {
37  for (unsigned int i = 0; i < nrows && i < ncols; i++)
38  (*this)(i,i) = value;
39  return *this;
40 }
41 
42 
43 template<class T, unsigned nrows, unsigned ncols>
46 {
47  assert(diag.size() >= nrows || diag.size() >= ncols);
48  // The length of the diagonal of a non-square matrix is the minimum of
49  // the matrix's width & height; that explains the "||" in the assert,
50  // and the "&&" in the upper bound for the "for".
51  for (unsigned int i = 0; i < nrows && i < ncols; ++i)
52  (*this)(i,i) = diag[i];
53  return *this;
54 }
55 
56 
57 template<class T, unsigned nrows, unsigned ncols>
58 void
60 {
61  for (unsigned int i = 0; i < nrows; i++)
62  {
63  os << (*this)(i,0);
64  for (unsigned int j = 1; j < ncols; j++)
65  os << ' ' << (*this)(i,j);
66  os << '\n';
67  }
68 }
69 
70 
71 template <class T, unsigned nrows, unsigned ncols>
74 {
76  vnl_c_vector<T>::apply(this->begin(), rows()*cols(), f, ret.data_block());
77  return ret;
78 }
79 
80 template <class T, unsigned nrows, unsigned ncols>
83 {
85  vnl_c_vector<T>::apply(this->begin(), rows()*cols(), f, ret.data_block());
86  return ret;
87 }
88 
89 ////--------------------------- Additions------------------------------------
90 
91 
92 template<class T, unsigned nrows, unsigned ncols>
95 {
97  for (unsigned int i = 0; i < cols(); i++)
98  for (unsigned int j = 0; j < rows(); j++)
99  result(i,j) = (*this)(j,i);
100  return result;
101 }
102 
103 template<class T, unsigned nrows, unsigned ncols>
106 {
107  vnl_matrix_fixed<T,ncols,nrows> result(transpose());
108  vnl_c_vector<T>::conjugate(result.begin(), // src
109  result.begin(), // dst
110  result.size()); // size of block
111  return result;
112 }
113 
114 template<class T, unsigned nrows, unsigned ncols>
117  unsigned top, unsigned left) const
118 {
119  const unsigned int bottom = top + m.rows();
120  const unsigned int right = left + m.cols();
121 #ifndef NDEBUG
122  if (nrows < bottom || ncols < right)
123  vnl_error_matrix_dimension ("update",
124  bottom, right, m.rows(), m.cols());
125 #endif
126  for (unsigned int i = top; i < bottom; i++)
127  for (unsigned int j = left; j < right; j++)
128  (*this)(i,j) = m(i-top,j-left);
129  return *this;
130 }
131 
132 
133 template<class T, unsigned nrows, unsigned ncols>
136  unsigned top, unsigned left) const
137 {
138 #ifndef NDEBUG
139  unsigned int bottom = top + rowz;
140  unsigned int right = left + colz;
141  if ((nrows < bottom) || (ncols < right))
142  vnl_error_matrix_dimension ("extract",
143  nrows, ncols, bottom, right);
144 #endif
145  vnl_matrix<T> result(rowz, colz);
146  for (unsigned int i = 0; i < rowz; i++) // actual copy of all elements
147  for (unsigned int j = 0; j < colz; j++) // in submatrix
148  result(i,j) = (*this)(top+i,left+j);
149  return result;
150 }
151 
152 
153 template<class T, unsigned nrows, unsigned ncols>
156 {
157  T* dp = this->data_block();
158  unsigned int i = nrows * ncols;
159  while (i--)
160  *dp++ = *p++;
161  return *this;
162 }
163 
164 template<class T, unsigned nrows, unsigned ncols>
166 {
167  T const* dp = this->data_block();
168  unsigned int i = nrows*ncols;
169  while (i--)
170  *p++ = *dp++;
171 }
172 
173 template<class T, unsigned nrows, unsigned ncols>
176 {
177  // Two simple loops are generally better than having a branch inside
178  // the loop. Probably worth the O(n) extra writes.
179  for (unsigned int i = 0; i < nrows; ++i)
180  for (unsigned int j = 0; j < ncols; ++j)
181  (*this)(i,j) = T(0);
182  for (unsigned int i = 0; i < nrows && i < ncols; ++i)
183  (*this)(i,i) = T(1);
184  return *this;
185 }
186 
187 //: Make each row of the matrix have unit norm.
188 // All-zero rows are ignored.
189 template<class T, unsigned nrows, unsigned ncols>
192 {
193  typedef typename vnl_numeric_traits<T>::abs_t Abs_t;
194  for (unsigned int i = 0; i < nrows; i++)
195  {
196  Abs_t norm(0); // double will not do for all types.
197  for (unsigned int j = 0; j < ncols; j++)
198  norm += vnl_math::squared_magnitude( (*this)(i,j) );
199 
200  if (norm != 0)
201  {
202  typedef typename vnl_numeric_traits<Abs_t>::real_t real_t;
203  real_t scale = real_t(1)/std::sqrt((real_t)norm);
204  for (unsigned int j = 0; j < ncols; j++)
205  {
206  // FIXME need correct rounding here
207  // There is e.g. no *standard* operator*=(complex<float>, double), hence the T() cast.
208  (*this)(i,j) *= (T)(scale);
209  }
210  }
211  }
212  return *this;
213 }
214 
215 template<class T, unsigned nrows, unsigned ncols>
218 {
219  typedef typename vnl_numeric_traits<T>::abs_t Abs_t;
220  for (unsigned int j = 0; j < ncols; j++) { // For each column in the Matrix
221  Abs_t norm(0); // double will not do for all types.
222  for (unsigned int i = 0; i < nrows; i++)
223  norm += vnl_math::squared_magnitude( (*this)(i,j) );
224 
225  if (norm != 0)
226  {
227  typedef typename vnl_numeric_traits<Abs_t>::real_t real_t;
228  real_t scale = real_t(1)/std::sqrt((real_t)norm);
229  for (unsigned int i = 0; i < nrows; i++)
230  {
231  // FIXME need correct rounding here
232  // There is e.g. no *standard* operator*=(complex<float>, double), hence the T() cast.
233  (*this)(i,j) *= (T)(scale);
234  }
235  }
236  }
237  return *this;
238 }
239 
240 template<class T, unsigned nrows, unsigned ncols>
242 vnl_matrix_fixed_ref<T,nrows,ncols>::scale_row(unsigned row_index, T value) const
243 {
244 #ifndef NDEBUG
245  if (row_index >= nrows)
246  vnl_error_matrix_row_index("scale_row", row_index);
247 #endif
248  for (unsigned int j = 0; j < ncols; j++)
249  (*this)(row_index,j) *= value;
250  return *this;
251 }
252 
253 template<class T, unsigned nrows, unsigned ncols>
255 vnl_matrix_fixed_ref<T,nrows,ncols>::scale_column(unsigned column_index, T value) const
256 {
257 #ifndef NDEBUG
258  if (column_index >= ncols)
259  vnl_error_matrix_col_index("scale_column", column_index);
260 #endif
261  for (unsigned int j = 0; j < nrows; j++)
262  (*this)(j,column_index) *= value;
263  return *this;
264 }
265 
266 //: Returns a copy of n rows, starting from "row"
267 template<class T, unsigned nrows, unsigned ncols>
270 {
271 #ifndef NDEBUG
272  if (row + n > nrows)
273  vnl_error_matrix_row_index ("get_n_rows", row);
274 #endif
275 
276  // Extract data rowwise.
277  return vnl_matrix<T>((*this)[row], n, ncols);
278 }
279 
280 template<class T, unsigned nrows, unsigned ncols>
283 {
284 #ifndef NDEBUG
285  if (column + n > ncols)
286  vnl_error_matrix_col_index ("get_n_columns", column);
287 #endif
288 
289  vnl_matrix<T> result(nrows, n);
290  for (unsigned int c = 0; c < n; ++c)
291  for (unsigned int r = 0; r < nrows; ++r)
292  result(r, c) = (*this)(r,column + c);
293  return result;
294 }
295 
296 //: Return a vector with the content of the (main) diagonal
297 template<class T, unsigned nrows, unsigned ncols>
299 {
300  vnl_vector<T> v(nrows < ncols ? nrows : ncols);
301  for (unsigned int j = 0; j < nrows && j < ncols; ++j)
302  v[j] = (*this)(j,j);
303  return v;
304 }
305 
306 //--------------------------------------------------------------------------------
307 
308 template<class T, unsigned nrows, unsigned ncols>
310 vnl_matrix_fixed_ref<T,nrows,ncols>::set_row(unsigned row_index, T const *v) const
311 {
312  for (unsigned int j = 0; j < ncols; j++)
313  (*this)(row_index,j) = v[j];
314  return *this;
315 }
316 
317 template<class T, unsigned nrows, unsigned ncols>
320 {
321  set_row(row_index,v.data_block());
322  return *this;
323 }
324 
325 template<class T, unsigned nrows, unsigned ncols>
328 {
329  set_row(row_index,v.data_block());
330  return *this;
331 }
332 
333 template<class T, unsigned nrows, unsigned ncols>
336 {
337  for (unsigned int j = 0; j < ncols; j++)
338  (*this)(row_index,j) = v;
339  return *this;
340 }
341 
342 //--------------------------------------------------------------------------------
343 
344 template<class T, unsigned nrows, unsigned ncols>
346 vnl_matrix_fixed_ref<T,nrows,ncols>::set_column(unsigned column_index, T const *v) const
347 {
348  for (unsigned int i = 0; i < nrows; i++)
349  (*this)(i,column_index) = v[i];
350  return *this;
351 }
352 
353 template<class T, unsigned nrows, unsigned ncols>
356 {
357  set_column(column_index,v.data_block());
358  return *this;
359 }
360 
361 template<class T, unsigned nrows, unsigned ncols>
364 {
365  set_column(column_index,v.data_block());
366  return *this;
367 }
368 
369 template<class T, unsigned nrows, unsigned ncols>
371 vnl_matrix_fixed_ref<T,nrows,ncols>::set_column(unsigned column_index, T v) const
372 {
373  for (unsigned int j = 0; j < nrows; j++)
374  (*this)(j,column_index) = v;
375  return *this;
376 }
377 
378 
379 template<class T, unsigned nrows, unsigned ncols>
381 vnl_matrix_fixed_ref<T,nrows,ncols>::set_columns(unsigned starting_column, vnl_matrix<T> const& m) const
382 {
383 #ifndef NDEBUG
384  if (nrows != m.rows() ||
385  ncols < m.cols() + starting_column) // Size match?
386  vnl_error_matrix_dimension ("set_columns",
387  nrows, ncols,
388  m.rows(), m.cols());
389 #endif
390 
391  for (unsigned int j = 0; j < m.cols(); ++j)
392  for (unsigned int i = 0; i < nrows; i++)
393  (*this)(i,starting_column + j) = m(i,j);
394  return *this;
395 }
396 
397 
398 template <class T, unsigned nrows, unsigned ncols>
399 bool
401 {
402  T const zero(0);
403  T const one(1);
404  for (unsigned int i = 0; i < nrows; ++i)
405  for (unsigned int j = 0; j < ncols; ++j)
406  {
407  T xm = (*this)(i,j);
408  if ( !((i == j) ? (xm == one) : (xm == zero)) )
409  return false;
410  }
411  return true;
412 }
413 
414 //: Return true if maximum absolute deviation of M from identity is <= tol.
415 template <class T, unsigned nrows, unsigned ncols>
416 bool
418 {
419  T one(1);
420  for (unsigned int i = 0; i < nrows; ++i)
421  for (unsigned int j = 0; j < ncols; ++j)
422  {
423  T xm = (*this)(i,j);
424  abs_t absdev = (i == j) ? vnl_math::abs(xm - one) : vnl_math::abs(xm);
425  if (absdev > tol)
426  return false;
427  }
428  return true;
429 }
430 
431 template <class T, unsigned nrows, unsigned ncols>
432 bool
434 {
435  T const zero(0);
436  for (unsigned int i = 0; i < nrows; ++i)
437  for (unsigned int j = 0; j < ncols; ++j)
438  if ( !( (*this)(i, j) == zero) )
439  return false;
440 
441  return true;
442 }
443 
444 template <class T, unsigned nrows, unsigned ncols>
445 bool
447 {
448  for (unsigned int i = 0; i < nrows; ++i)
449  for (unsigned int j = 0; j < ncols; ++j)
450  if (vnl_math::abs((*this)(i,j)) > tol)
451  return false;
452 
453  return true;
454 }
455 
456 template <class T, unsigned nrows, unsigned ncols>
457 bool
459 {
460  for (unsigned int i = 0; i < nrows; ++i)
461  for (unsigned int j = 0; j < ncols; ++j)
462  if (vnl_math::isnan((*this)(i,j)))
463  return true;
464 
465  return false;
466 }
467 
468 template <class T, unsigned nrows, unsigned ncols>
469 bool
471 {
472  for (unsigned int i = 0; i < nrows; ++i)
473  for (unsigned int j = 0; j < ncols; ++j)
474  if (!vnl_math::isfinite((*this)(i,j)))
475  return false;
476 
477  return true;
478 }
479 
480 //: Abort if any element of M is inf or nan
481 template <class T, unsigned nrows, unsigned ncols>
482 void
484 {
485  if (is_finite())
486  return;
487 
488  std::cerr << "\n\n" << __FILE__ " : " << __LINE__ << ": matrix has non-finite elements\n";
489 
490  if (rows() <= 20 && cols() <= 20)
491  std::cerr << __FILE__ ": here it is:\n" << *this << '\n';
492  else
493  {
494  std::cerr << __FILE__ ": it is quite big (" << rows() << 'x' << cols() << ")\n"
495  << __FILE__ ": in the following picture '-' means finite and '*' means non-finite:\n";
496 
497  for (unsigned int i=0; i<rows(); ++i)
498  {
499  for (unsigned int j=0; j<cols(); ++j)
500  std::cerr << char(vnl_math::isfinite((*this)(i, j)) ? '-' : '*');
501  std::cerr << '\n';
502  }
503  }
504  std::cerr << __FILE__ ": calling abort()\n";
505  std::abort();
506 }
507 
508 //: Abort unless M has the given size.
509 template <class T, unsigned nrows, unsigned ncols>
510 void
512 {
513  if (nrows!=rs || ncols!=cs)
514  {
515  std::cerr << __FILE__ ": size is " << nrows << 'x' << ncols
516  << ". should be " << rs << 'x' << cs << std::endl;
517  std::abort();
518  }
519 }
520 
521 template <class T, unsigned nrows, unsigned ncols>
522 bool
524 {
525  if (!s.good())
526  {
527  std::cerr << __FILE__ ": vnl_matrix_fixed_ref_const<T,nrows,ncols>::read_ascii: Called with bad stream\n";
528  return false;
529  }
530 
531  for (unsigned int i = 0; i < nrows; ++i)
532  for (unsigned int j = 0; j < ncols; ++j)
533  s >> (*this)(i,j);
534 
535  return s.good() || s.eof();
536 }
537 
538 
539 template <class T, unsigned nrows, unsigned ncols>
542 {
543  for (unsigned int r1 = 0; 2*r1+1 < nrows; ++r1)
544  {
545  const unsigned int r2 = nrows - 1 - r1;
546  for (unsigned int c = 0; c < ncols; ++c)
547  {
548  const T tmp = (*this)(r1, c);
549  (*this)(r1, c) = (*this)(r2, c);
550  (*this)(r2, c) = tmp;
551  }
552  }
553  return *this;
554 }
555 
556 
557 template <class T, unsigned nrows, unsigned ncols>
560 {
561  for (unsigned int c1 = 0; 2*c1+1 < ncols; ++c1)
562  {
563  const unsigned int c2 = ncols - 1 - c1;
564  for (unsigned int r = 0; r < nrows; ++r)
565  {
566  const T tmp = (*this)(r, c1);
567  (*this)(r, c1) = (*this)(r, c2);
568  (*this)(r, c2) = tmp;
569  }
570  }
571  return *this;
572 }
573 
574 template <class T, unsigned nrows, unsigned ncols>
577 {
578  abs_t m(0);
579  for (unsigned int j=0; j<ncols; ++j)
580  {
581  abs_t t(0);
582  for (unsigned int i=0; i<nrows; ++i)
583  t += vnl_math::abs( (*this)(i,j) );
584  if (t > m)
585  m = t;
586  }
587  return m;
588 }
589 
590 template <class T, unsigned nrows, unsigned ncols>
593 {
594  abs_t m(0);
595  for (unsigned int i=0; i<nrows; ++i)
596  {
597  abs_t t(0);
598  for (unsigned int j=0; j<ncols; ++j)
599  t += vnl_math::abs( (*this)(i,j) );
600  if (t > m)
601  m = t;
602  }
603  return m;
604 }
605 
606 //: Transpose square matrix M in place.
607 template <class T, unsigned nrows, unsigned ncols>
610 {
611  assert(nrows==ncols); // cannot inplace_transpose non-square fixed size matrix
612  for (unsigned i = 0; i < nrows; ++i)
613  for (unsigned j = i+1; j < ncols; ++j)
614  {
615  T t = (*this)(i,j);
616  (*this)(i,j) = (*this)(j,i);
617  (*this)(j,i) = t;
618  }
619  return *this;
620 }
621 
622 
623 #define VNL_MATRIX_FIXED_REF_INSTANTIATE(T,m,n) \
624 template class VNL_EXPORT vnl_matrix_fixed_ref_const<T, m, n >; \
625 template class VNL_EXPORT vnl_matrix_fixed_ref<T, m, n >
626 
627 #endif // vnl_matrix_fixed_ref_hxx_
vnl_matrix_fixed< T, num_cols, num_rows > conjugate_transpose() const
Return conjugate transpose.
static void conjugate(T const *, T *, unsigned)
vnl_matrix_fixed_ref const & set_identity() const
Sets this matrix to an identity matrix, then returns "*this".
vnl_matrix_fixed_ref const & set_columns(unsigned starting_column, vnl_matrix< T > const &M) const
Set columns to those in M, starting at starting_column, then return *this.
vnl_vector< T > get_diagonal() const
Return a vector with the content of the (main) diagonal.
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
vnl_matrix_fixed_ref const & scale_row(unsigned row, T value) const
Scales elements in given row by a factor T, and returns "*this".
#define m
Definition: vnl_vector.h:43
vnl_matrix_fixed< T, num_rows, num_cols > apply(T(*f)(T)) const
Make a new matrix by applying function to each element.
size_t size() const
Return the length, number of elements, dimension of this vector.
Definition: vnl_vector.h:126
vnl_matrix_fixed_ref & flipud()
Reverses the order of rows, and returns "*this".
vnl_matrix< T > get_n_columns(unsigned colstart, unsigned n) const
Get n columns beginning at colstart.
Namespace with standard math functions.
bool is_finite() const
Return true if finite.
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
void vnl_error_matrix_col_index(char const *fcn, int c)
Raise exception for invalid col index.
Definition: vnl_error.cxx:61
vnl_matrix_fixed_ref const & normalize_columns() const
Normalizes each column so it is a unit vector, and returns "*this".
vnl_c_vector< T >::abs_t abs_t
Type def for norms.
vnl_matrix_fixed_ref const & update(vnl_matrix< T > const &, unsigned top=0, unsigned left=0) const
Set values of this matrix to those of M, starting at [top,left].
vnl_bignum squared_magnitude(vnl_bignum const &x)
Definition: vnl_bignum.h:433
static void apply(T const *, unsigned, T(*f)(T), T *v_out)
vnl_matrix_fixed_ref const & normalize_rows() const
Normalizes each row so it is a unit vector, and returns "*this".
#define v
Definition: vnl_vector.h:42
bool isnan(vnl_bignum const &)
Definition: vnl_bignum.h:435
vnl_matrix_fixed_ref const & fill_diagonal(T) const
Sets all diagonal elements of matrix to specified value; returns "*this".
vnl_matrix_fixed_ref const & set_row(unsigned i, T const *v) const
Set the elements of the i'th row to v[i] (No bounds checking).
vnl_matrix< T > extract(unsigned rowz, unsigned colz, unsigned top=0, unsigned left=0) const
Extract a sub-matrix of size rows x cols, starting at (top,left).
bool is_zero() const
Return true if all elements equal to zero.
vnl_matrix_fixed_ref const & set_column(unsigned i, T const *v) const
Set the elements of the i'th column to v[i] (No bounds checking).
vnl_matrix_fixed_ref & fliplr()
Reverses the order of columns, and returns "*this".
vnl_matrix_fixed_ref const & copy_in(T const *) const
Fills (laminates) this matrix with the given data, then returns it.
An ordinary mathematical matrix.
Definition: vnl_adjugate.h:22
bool is_identity() const
Return true if all elements equal to identity.
vnl_matrix_fixed_ref const & set_diagonal(vnl_vector< T > const &) const
Sets the diagonal elements of this matrix to the specified list of values.
bool has_nans() const
Return true if matrix contains NaNs.
bool isfinite(vnl_bignum const &x)
Definition: vnl_bignum.h:436
void assert_size_internal(unsigned, unsigned) const
Abort unless M has the given size.
vnl_matrix_fixed_ref const & scale_column(unsigned col, T value) const
Scales elements in given column by a factor T, and returns "*this".
Mathematical vector class, templated by type of element.
Definition: vnl_fwd.h:16
vnl_matrix_fixed_ref const & fill(T) const
Sets all elements of matrix to specified value, and returns "*this".
vnl_matrix_fixed_ref const & inplace_transpose() const
Fills the given array with this matrix.
Fixed length stack-stored, space-efficient vector.
Definition: vnl_fwd.h:22
void print(std::ostream &os) const
Print matrix to os in some hopefully sensible format.
Fixed size stack-stored vnl_matrix.
vnl_bignum abs(vnl_bignum const &x)
Definition: vnl_bignum.h:432
void vnl_error_matrix_dimension(char const *fcn, int r1, int c1, int r2, int c2)
Raise exception for invalid dimensions.
Definition: vnl_error.cxx:70
vnl_matrix< T > get_n_rows(unsigned rowstart, unsigned n) const
Get n rows beginning at rowstart.
void assert_finite_internal() const
Abort if any element of M is inf or nan.
iterator begin()
Iterator pointing to start of data.
unsigned int size() const
Return the total number of elements stored by the matrix.
vnl_matrix_fixed< T, num_cols, num_rows > transpose() const
Return transpose.