vnl_sparse_matrix.hxx
Go to the documentation of this file.
1 // This is core/vnl/vnl_sparse_matrix.hxx
2 #ifndef vnl_sparse_matrix_hxx_
3 #define vnl_sparse_matrix_hxx_
4 //:
5 // \file
6 
7 #include <algorithm>
8 #include <iostream>
9 #include "vnl_sparse_matrix.h"
10 
11 #include <cassert>
12 #ifdef _MSC_VER
13 # include <vcl_msvc_warnings.h>
14 #endif
15 
16 #include <vnl/vnl_math.h>
17 #include <vnl/vnl_complex_traits.h>
18 
19 #ifdef DEBUG_SPARSE
20 # include <vnl/vnl_matrix.h>
21 #endif
22 
23 // Implementation of vnl_sparse_matrix
24 //------------------------------------------------------------
25 
26 //: Construct an empty matrix
27 template <class T>
29  : rs_(0), cs_(0)
30 {
31 }
32 
33 //------------------------------------------------------------
34 //: Construct an empty m*n matrix. There are m rows and n columns.
35 template <class T>
36 vnl_sparse_matrix<T>::vnl_sparse_matrix(unsigned int m, unsigned int n)
37  : elements(m), rs_(m), cs_(n)
38 {
39 }
40 
41 //------------------------------------------------------------
42 //: Construct an m*n Matrix and copy rhs into it.
43 template <class T>
45  : elements(rhs.elements), rs_(rhs.rs_), cs_(rhs.cs_)
46 {
47 }
48 
49 //------------------------------------------------------------
50 //: Copy another vnl_sparse_matrix<T> into this.
51 template <class T>
53 {
54  if (this == &rhs)
55  return *this;
56 
57  elements = rhs.elements;
58  rs_ = rhs.rs_;
59  cs_ = rhs.cs_;
60 
61  return *this;
62 }
63 
64 //------------------------------------------------------------
65 //: Multiply this*rhs, another sparse matrix.
66 template <class T>
68 {
69  assert(rhs.rows() == columns());
70  assert(this != &result); // make sure not to overwrite *this
71  assert(&rhs != &result); // make sure not to overwrite rhs
72  unsigned int result_rows = rows();
73  unsigned int result_cols = rhs.columns();
74 
75  // Early return: empty result matrix
76  if (result_rows <= 0 || result_cols <= 0) return;
77 
78  result.cs_ = result_cols;
79  if (result.rows() != result_rows)
80  {
81  // Clear result matrix.
82  result.elements.clear();
83  // give the result matrix enough rows (but only if not yet correct).
84  result.elements.resize(result_rows);
85  result.rs_ = result_rows;
86  for (unsigned row_id=0; row_id<result_rows; ++row_id)
87  result.elements[row_id] = row();
88  }
89 
90  // Now, iterate over non-zero rows of this.
91  for (unsigned row_id=0; row_id<elements.size(); ++row_id) {
92  // Get the row from this matrix (lhs).
93  row const& this_row = elements[row_id];
94 
95  // Skip to next row if empty.
96  if (this_row.empty())
97  continue;
98 
99  // Get the new row in the result matrix.
100  row& result_row = result.elements[row_id];
101 
102  // Iterate over the row.
103  for (typename row::const_iterator col_iter = this_row.begin();
104  col_iter != this_row.end();
105  ++col_iter)
106  {
107  // Get the element from the row.
108  vnl_sparse_matrix_pair<T> const & entry = *col_iter;
109  unsigned const col_id = entry.first;
110 
111  // So we are at (row_id,col_id) = this_val in lhs matrix (this).
112  // This must be multiplied by each entry in row col_id in
113  // the rhs matrix, and the result added to result_row[col_id].
114 
115  // If that row in rhs is empty, there is nothing to do.
116  row const & rhs_row = rhs.elements[col_id];
117  if (rhs_row.empty())
118  continue;
119 
120  // Else iterate over rhs's row.
121  typename row::iterator result_col_iter = result_row.begin();
122  for (typename row::const_iterator rhs_col_iter = rhs_row.begin();
123  rhs_col_iter != rhs_row.end();
124  ++rhs_col_iter)
125  {
126  const vnl_sparse_matrix_pair<T>& rhs_entry = *rhs_col_iter;
127  unsigned int const dest_col = rhs_entry.first;
128 
129  // Calculate the product.
130  T prod = entry.second * rhs_entry.second;
131 
132  // This must be added into result_row, at column dest_col.
133  while ((result_col_iter != result_row.end()) &&
134  ((*result_col_iter).first < dest_col))
135  ++result_col_iter;
136 
137  if ((result_col_iter == result_row.end()) ||
138  ((*result_col_iter).first != dest_col))
139  {
140  // Add new column to the row.
141  result_col_iter = result_row.insert(result_col_iter, vnl_sparse_matrix_pair<T>(dest_col,prod));
142  }
143  else
144  {
145  // Else add product to existing contents.
146  (*result_col_iter).second += prod;
147  }
148  }
149  }
150  }
151 }
152 
153 //------------------------------------------------------------
154 //: Multiply this*p, a fortran order matrix.
155 // The matrix p has n rows and m columns, and is in fortran order, ie. columns first.
156 template <class T>
157 void vnl_sparse_matrix<T>::mult(unsigned int prows, unsigned int pcols,
158  T const* p, T* q) const
159 {
160  assert(prows == columns());
161 
162  // Clear q matrix.
163  int size = rows()*pcols;
164  for (int temp=0; temp<size; temp++)
165  q[temp] = T(0);
166 
167 #ifdef DEBUG_SPARSE
168  vnl_matrix<double> md(rows(),columns());
169  for (int rr = 0; rr<rows(); rr++)
170  for (int cc = 0; cc<columns(); cc++)
171  md(rr,cc) = (*this)(rr,cc);
172 
173  vnl_matrix<double> pd(prows,pcols);
174  for (int rr = 0; rr<prows; rr++)
175  for (int cc = 0; cc<pcols; cc++)
176  pd(rr,cc) = p[rr + cc*prows];
177 
178  std::cout << "Initial p:\n";
179  for (int rr = 0; rr<prows; rr++) {
180  for (int cc = 0; cc<pcols; cc++) {
181  T pval = p[rr + cc*prows];
182  std::cout << pval << ' ';
183  }
184  std::cout << '\n';
185  }
186 #endif
187 
188  // Now, iterate over non-zero rows of this.
189  for (unsigned row_id=0; row_id<elements.size(); ++row_id) {
190  // Get the row from this matrix (lhs).
191  row const & this_row = elements[row_id];
192 
193  // Skip to next row if empty.
194  if (this_row.empty())
195  continue;
196 
197  // Iterate over the row.
198  for (typename row::const_iterator col_iter = this_row.begin();
199  col_iter != this_row.end();
200  ++col_iter)
201  {
202  // Get the element from the row.
203  vnl_sparse_matrix_pair<T> const & entry = *col_iter;
204  unsigned const col_id = entry.first;
205 
206  // So we are at (row_id,col_id) = this_val in lhs matrix
207  // (this). This must be multiplied by each entry in row
208  // col_id in the p matrix, and the result added to
209  // (row_id,p_col_id) in the q matrix.
210  //
211 
212  // Iterate over p's row.
213  for (unsigned int p_col_id = 0; p_col_id < pcols; p_col_id++) {
214  // Get the correct position from p.
215  T pval = p[col_id + p_col_id*prows];
216 
217  // Calculate the product.
218  T prod = entry.second * pval;
219 
220  // Add the product into the correct position in q (fortran order)
221  q[row_id + p_col_id*rows()] += prod;
222  }
223  }
224  }
225 
226 #ifdef DEBUG_SPARSE
227  std::cout << "Final q:\n";
228  for (int rr = 0; rr<prows; rr++) {
229  for (int cc = 0; cc<pcols; cc++) {
230  T pval = q[rr + cc*prows];
231  std::cout << pval << ' ';
232  }
233  std::cout << '\n';
234  }
235  std::cout << "nonsparse: " << md*pd << '\n';
236 #endif
237 }
238 
239 
240 //------------------------------------------------------------
241 //: Multiply this*rhs, a vector.
242 template <class T>
244 {
245  assert(rhs.size() == columns());
246 
247  result.set_size( rows() );
248  result.fill(T(0));
249 
250  int rhs_row_id =0;
251  typename std::vector<row>::const_iterator lhs_row_iter = elements.begin();
252  for ( ; lhs_row_iter != elements.end(); ++lhs_row_iter, rhs_row_id++ ) {
253  row const & lhs_row = *lhs_row_iter;
254  if (lhs_row.empty()) continue;
255 
256  typename row::const_iterator lhs_col_iter = lhs_row.begin();
257  for ( ; lhs_col_iter != lhs_row.end(); ++lhs_col_iter) {
258  vnl_sparse_matrix_pair<T> const & entry = *lhs_col_iter;
259  unsigned const lhs_col_id = entry.first;
260 
261  result[ rhs_row_id ] += rhs[ lhs_col_id ] * entry.second;
262  }
263  }
264 }
265 
266 //------------------------------------------------------------
267 //: Multiply lhs*this, where lhs is a vector
268 template <class T>
270 {
271  assert(lhs.size() == rows());
272 
273  // Resize and clear result vector
274  result.set_size( columns() );
275  result.fill(T(0));
276 
277  // Now, iterate over lhs values and rows of rhs
278  unsigned lhs_col_id = 0;
279  for (typename std::vector<row>::const_iterator rhs_row_iter = elements.begin();
280  rhs_row_iter != elements.end();
281  ++rhs_row_iter, lhs_col_id++ )
282  {
283  // Get the row from rhs matrix.
284  row const & rhs_row = *rhs_row_iter;
285 
286  // Skip to next row if empty.
287  if (rhs_row.empty()) continue;
288 
289  // Iterate over values in rhs row
290  for (typename row::const_iterator rhs_col_iter = rhs_row.begin();
291  rhs_col_iter != rhs_row.end();
292  ++rhs_col_iter)
293  {
294  // Get the element from the row.
295  vnl_sparse_matrix_pair<T> const& entry = *rhs_col_iter;
296  unsigned const rhs_col_id = entry.first;
297 
298  result[ rhs_col_id ] += lhs[ lhs_col_id ] * entry.second;
299  }
300  }
301 }
302 
303 //------------------------------------------------------------
304 //: Add rhs to this.
305 template <class T>
307  vnl_sparse_matrix<T>& result) const
308 {
309  assert((rhs.rows() == rows()) && (rhs.columns() == columns()));
310 
311  // Clear result matrix.
312  result.elements.clear();
313 
314  // Now give the result matrix enough rows.
315  result.elements.resize(rows());
316  result.rs_ = rows();
317  result.cs_ = columns();
318 
319  // Now, iterate over non-zero rows of this.
320  unsigned int row_id = 0;
321  for (typename std::vector<row>::const_iterator row_iter = elements.begin();
322  row_iter != elements.end();
323  ++row_iter, ++row_id)
324  {
325  // Get the row from this matrix (lhs).
326  row const & this_row = *row_iter;
327 
328  // Get the new row in the result matrix.
329  row& result_row = result.elements[row_id];
330 
331  // Store this into result row.
332  result_row = this_row;
333 
334  // If rhs row is empty, we are done.
335  if (rhs.empty_row(row_id))
336  continue;
337 
338  // Get the rhs row.
339  row const& rhs_row = rhs.elements[row_id];
340 
341  // Iterate over the rhs row.
342  for (typename row::const_iterator col_iter = rhs_row.begin();
343  col_iter != rhs_row.end();
344  ++col_iter)
345  {
346  // Get the element from the row.
347  vnl_sparse_matrix_pair<T> const& entry = *col_iter;
348  unsigned const col_id = entry.first;
349 
350  // So we are at (row_id,col_id) in rhs matrix.
351  result(row_id,col_id) += entry.second;
352  }
353  }
354 }
355 
356 //------------------------------------------------------------
357 //: Subtract rhs from this.
358 template <class T>
360  vnl_sparse_matrix<T>& result) const
361 {
362  assert((rhs.rows() == rows()) && (rhs.columns() == columns()));
363 
364  // Clear result matrix.
365  result.elements.clear();
366 
367  // Now give the result matrix enough rows.
368  result.elements.resize(rows());
369  result.rs_ = rows();
370  result.cs_ = columns();
371 
372  // Now, iterate over non-zero rows of this.
373  unsigned int row_id = 0;
374  for (typename std::vector<row>::const_iterator row_iter = elements.begin();
375  row_iter != elements.end();
376  ++row_iter, ++row_id)
377  {
378  // Get the row from this matrix (lhs).
379  row const& this_row = *row_iter;
380 
381  // Get the new row in the result matrix.
382  row& result_row = result.elements[row_id];
383 
384  // Store this into result row.
385  result_row = this_row;
386 
387  // If rhs row is empty, we are done.
388  if (rhs.empty_row(row_id))
389  continue;
390 
391  // Get the rhs row.
392  row const& rhs_row = rhs.elements[row_id];
393 
394  // Iterate over the rhs row.
395  for (typename row::const_iterator col_iter = rhs_row.begin();
396  col_iter != rhs_row.end();
397  ++col_iter)
398  {
399  // Get the element from the row.
400  vnl_sparse_matrix_pair<T> const& entry = *col_iter;
401  unsigned const col_id = entry.first;
402 
403  // So we are at (row_id,col_id) in rhs matrix.
404  result(row_id,col_id) -= entry.second;
405  }
406  }
407 }
408 
409 //------------------------------------------------------------
410 //: Get a reference to an entry in the matrix.
411 template <class T>
412 T& vnl_sparse_matrix<T>::operator()(unsigned int r, unsigned int c)
413 {
414  assert((r < rows()) && (c < columns()));
415  row& rw = elements[r];
416  typename row::iterator ri;
417  for (ri = rw.begin(); (ri != rw.end()) && ((*ri).first < c); ++ri)
418  /*nothing*/;
419 
420  if ((ri == rw.end()) || ((*ri).first != c)) {
421  // Add new column to the row.
422  ri = rw.insert(ri, vnl_sparse_matrix_pair<T>(c,T()));
423  }
424 
425  return (*ri).second;
426 }
427 
428 //------------------------------------------------------------
429 //: Get the value of an entry in the matrix.
430 template <class T>
431 T vnl_sparse_matrix<T>::operator()(unsigned int r, unsigned int c) const
432 {
433  assert((r < rows()) && (c < columns()));
434  row const& rw = elements[r];
435  typename row::const_iterator ri = rw.begin();
436  while (ri != rw.end() && (*ri).first < c)
437  ++ri;
438  if (ri == rw.end() || (*ri).first != c)
439  return T(); // uninitialised value (default constructor) is returned
440  else
441  return (*ri).second;
442 }
443 
444 //------------------------------------------------------------
445 //: Get an entry in the matrix.
446 // This is the "const" version of operator().
447 template <class T>
448 T vnl_sparse_matrix<T>::get(unsigned int r, unsigned int c) const
449 {
450  assert((r < rows()) && (c < columns()));
451  row const& rw = elements[r];
452  typename row::const_iterator ri = rw.begin();
453  while (ri != rw.end() && (*ri).first < c)
454  ++ri;
455  if (ri == rw.end() || (*ri).first != c)
456  return T(); // uninitialised value (default constructor) is returned
457  else
458  return (*ri).second;
459 }
460 
461 //------------------------------------------------------------
462 //: Put (i.e., add or overwrite) an entry into the matrix.
463 template <class T>
464 void vnl_sparse_matrix<T>::put(unsigned int r, unsigned int c, T v)
465 {
466  assert((r < rows()) && (c < columns()));
467  row& rw = elements[r];
468  typename row::iterator ri = rw.begin();
469  while (ri != rw.end() && (*ri).first < c)
470  ++ri;
471 
472  if (ri == rw.end() || (*ri).first != c) {
473  // Add new column to the row.
474  rw.insert(ri, vnl_sparse_matrix_pair<T>(c,v));
475  }
476  else
477  (*ri).second = v;
478 }
479 
480 template <class T>
482 {
483  result.set_size( columns() );
484  result.fill(T(0));
485 
486  typename std::vector<row>::const_iterator row_iter = elements.begin();
487  for ( ; row_iter != elements.end(); ++row_iter) {
488  row const& this_row = *row_iter;
489  typename row::const_iterator col_iter = this_row.begin();
490  for ( ; col_iter != this_row.end(); ++col_iter) {
491  vnl_sparse_matrix_pair<T> const& entry = *col_iter;
492  unsigned const col_id = entry.first;
493  result[col_id] += entry.second * entry.second;
494  }
495  }
496 }
497 
498 //------------------------------------------------------------
499 //: Set row in the matrix.
500 
501 template <class T>
504  std::vector<int> const& colz,
505  std::vector<T> const& vals)
506 {
507  assert (r < rows());
508  assert (colz.size() == vals.size());
509 
510  row& rw = elements[r];
511  if (rw.size() != colz.size()) rw = row(colz.size());
512  for (unsigned int i=0; i < colz.size(); ++i)
513  rw[i] = vnl_sparse_matrix_pair<T>(colz[i], vals[i]);
514  typedef typename vnl_sparse_matrix_pair<T>::less less;
515  std::sort(rw.begin(), rw.end(), less());
516  return *this;
517 }
518 
519 template <class T>
522 {
523  if (rs_ == 0) {
524  rs_ = A.rs_;
525  cs_ = A.cs_;
526  elements = A.elements;
527  }
528  else {
529  assert(cs_ == A.cs_);
530  rs_ += A.rs_;
531  elements.insert(elements.end(), A.elements.begin(), A.elements.end());
532  }
533  return *this;
534 }
535 
536 
537 //------------------------------------------------------------
538 //: This is occasionally useful. Sums a row of the matrix efficiently.
539 template <class T>
541 {
542  assert(r < rows());
543  row & rw = elements[r];
544  T sum = T(0);
545  for (typename row::iterator ri = rw.begin(); ri != rw.end(); ++ri)
546  sum += (*ri).second;
547 
548  return sum;
549 }
550 
551 template <class T>
553 vnl_sparse_matrix<T>::scale_row(unsigned int r, T scale)
554 {
555  assert(r < rows());
556  row& rw = elements[r];
557  for (typename row::iterator ri = rw.begin(); ri != rw.end(); ++ri)
558  (*ri).second *= scale;
559  return *this;
560 }
561 
562 //------------------------------------------------------------
563 //: Resizes the matrix so that it has r rows and c columns, clearing the current contents.
564 //
565 template <class T>
567 {
568  rs_ = r;
569  cs_ = c;
570  elements.resize(r);
571  typename vnl_sparse_matrix_elements::iterator ie;
572  for (ie = elements.begin(); ie != elements.end(); ++ie)
573  {
574  // just set matrix to 0
575  ie->clear();
576  }
577  reset(); // reset iterator
578 }
579 
580 //------------------------------------------------------------
581 //: Resizes the matrix so that it has r rows and c columns, leaving the current contents.
582 // This is more wasteful of resources than set_size, but it preserves the contents.
583 //
584 template <class T>
585 void vnl_sparse_matrix<T>::resize( int r, int c)
586 {
587  unsigned int oldCs = cs_;
588 
589  rs_ = r;
590  cs_ = c;
591  elements.resize(r);
592 
593  // If the array has fewer columns now, we also need to cut them out
594  if (oldCs > cs_) {
595  for (unsigned int i = 0; i < elements.size(); ++i) {
596  row& rw = elements[i];
597  typename row::iterator iter;
598  for (iter = rw.begin(); iter != rw.end() && (*iter).first<cs_ ; ++iter)
599  /*nothing*/;
600  if (iter != rw.end()) rw.erase(iter,rw.end());
601  }
602  }
603 
604  reset(); // reset iterator
605 }
606 
607 //------------------------------------------------------------
608 //: Resets the internal iterator
609 template <class T>
611 {
612  itr_isreset = true;
613  itr_row = 0;
614 }
615 
616 //------------------------------------------------------------
617 //: Moves the internal iterator to next non-zero entry in matrix.
618 // Returns true if there is another value, false otherwise. Use
619 // in combination with methods reset, getrow, getcolumn, and value.
620 //
621 template <class T>
623 {
624  if ( itr_row >= rows() )
625  return false;
626 
627  if ( itr_isreset ) {
628  // itr_cur is not pointing to an entry
629  itr_row = 0;
630  itr_isreset = false;
631  }
632  else {
633  // itr_cur is pointing to an entry.
634  // Try to move to next entry in current row.
635  itr_cur++;
636  if ( itr_cur != elements[itr_row].end() )
637  return true; // found next entry in current row
638  else
639  itr_row++;
640  }
641 
642  // search for next entry starting at row itr_row
643  while ( itr_row < rows() ) {
644  itr_cur = elements[itr_row].begin();
645  if ( itr_cur != elements[itr_row].end() )
646  return true;
647  else
648  itr_row++;
649  }
650 
651  return itr_row < rows();
652 }
653 
654 //------------------------------------------------------------
655 //: Returns the row of the entry pointed to by internal iterator.
656 //
657 template <class T>
659 {
660  return itr_row;
661 }
662 
663 //------------------------------------------------------------
664 //: Returns the column of the entry pointed to by internal iterator.
665 //
666 template <class T>
668 {
669  return (*itr_cur).first;
670 }
671 
672 //------------------------------------------------------------
673 //: Returns the value pointed to by the internal iterator.
674 //
675 template <class T>
677 {
678  return (*itr_cur).second;
679 }
680 
681 //------------------------------------------------------------
682 //: Comparison
683 //
684 template <class T>
686 {
687  // first of all, sizes must match:
688  if (rhs.rows() != rows() || rhs.columns() != columns()) {
689 #ifdef DEBUG_SPARSE
690  std::cerr << "Sizes are different: " << rows() << 'x' << columns() << ' ' << rhs.rows() << 'x' << rhs.columns() << '\n';
691 #endif
692  return false;
693  }
694 
695  // Now, iterate over non-zero rows of this and of rhs.
696  unsigned int row_id = 0;
697  for (typename std::vector<row>::const_iterator row_iter = elements.begin();
698  row_iter != elements.end();
699  ++row_iter, ++row_id)
700  {
701  // Get the row from this matrix (lhs).
702  row const& this_row = *row_iter;
703 
704  // Get the rhs row.
705  row const& rhs_row = rhs.elements[row_id];
706 
707  // first of all, row sizes must match:
708  if (rhs_row.size() != this_row.size())
709  return false;
710 
711  // Iterate over the rhs row.
712  for (typename row::const_iterator col_iter = rhs_row.begin();
713  col_iter != rhs_row.end();
714  ++col_iter)
715  {
716  // Get the element from the row.
717  vnl_sparse_matrix_pair<T> const& entry = *col_iter;
718  unsigned const col_id = entry.first;
719 
720  // So we are at (row_id,col_id) in rhs matrix.
721  if (get(row_id,col_id) != entry.second)
722  return false;
723  }
724  }
725  // if we reach this point, all comparisons succeeded:
726  return true;
727 }
728 
729 //: Unary minus
730 template <class T>
732 {
733  // The matrix to be returned:
734  vnl_sparse_matrix<T> result(rows(), columns());
735 
736  // Iterate over non-zero rows of this matrix.
737  unsigned int row_id = 0;
738  for (typename std::vector<row>::const_iterator row_iter = elements.begin();
739  row_iter != elements.end();
740  ++row_iter, ++row_id)
741  {
742  // Get the row.
743  row const& this_row = *row_iter;
744 
745  // Iterate over the row.
746  for (typename row::const_iterator col_iter = this_row.begin();
747  col_iter != this_row.end();
748  ++col_iter)
749  {
750  // Assign the corresponding result element.
751  vnl_sparse_matrix_pair<T> const& entry = *col_iter;
752  result(row_id, entry.first) = - entry.second;
753  }
754  }
755  return result;
756 }
757 
758 //: addition
759 template <class T>
761 {
762  vnl_sparse_matrix<T> result(rows(), columns());
763  add(rhs, result);
764  return result;
765 }
766 
767 //: subtraction
768 template <class T>
770 {
771  vnl_sparse_matrix<T> result(rows(), columns());
772  subtract(rhs, result);
773  return result;
774 }
775 
776 //: multiplication
777 template <class T>
779 {
780  vnl_sparse_matrix<T> result(rows(), rhs.columns());
781  mult(rhs, result);
782  return result;
783 }
784 
785 //: in-place scalar multiplication
786 template <class T>
788 {
789  // Iterate over non-zero rows of this matrix.
790  for (typename std::vector<row>::iterator row_iter = elements.begin();
791  row_iter != elements.end();
792  ++row_iter)
793  {
794  // Get the row.
795  row& this_row = *row_iter;
796 
797  // Iterate over the row.
798  for (typename row::iterator col_iter = this_row.begin();
799  col_iter != this_row.end();
800  ++col_iter)
801  {
802  // Change the corresponding element.
803  col_iter->second *= rhs;
804  }
805  }
806  return *this;
807 }
808 
809 //: in-place scalar division
810 template <class T>
812 {
813  // Iterate over non-zero rows of this matrix.
814  for (typename std::vector<row>::iterator row_iter = elements.begin();
815  row_iter != elements.end();
816  ++row_iter)
817  {
818  // Get the row.
819  row& this_row = *row_iter;
820 
821  // Iterate over the row.
822  for (typename row::iterator col_iter = this_row.begin();
823  col_iter != this_row.end();
824  ++col_iter)
825  {
826  // Change the corresponding element.
827  col_iter->second /= rhs;
828  }
829  }
830  return *this;
831 }
832 
833 //: scalar multiplication
834 template <class T>
836 {
837  vnl_sparse_matrix<T> result = *this;
838  return result *= rhs;
839 }
840 
841 //: scalar division
842 template <class T>
844 {
845  vnl_sparse_matrix<T> result = *this;
846  return result /= rhs;
847 }
848 
849 //: in-place addition
850 template <class T>
852 {
853  return *this = operator+(rhs);
854 }
855 
856 //: in-place subtraction
857 template <class T>
859 {
860  return *this = operator-(rhs);
861 }
862 
863 //: in-place multiplication
864 template <class T>
866 {
867  return *this = operator*(rhs);
868 }
869 
870 //: Make each row of the matrix have unit norm.
871 // All-zero rows are ignored.
872 template<class T>
874 {
875  typedef typename vnl_numeric_traits<T>::abs_t Abs_t;
876  typedef typename vnl_numeric_traits<T>::real_t Real_t;
877  typedef typename vnl_numeric_traits<Real_t>::abs_t abs_real_t;
878 
879  // Iterate through the matrix rows, and normalize one at a time:
880  for (typename std::vector<row>::iterator row_iter = elements.begin();
881  row_iter != elements.end();
882  ++row_iter)
883  {
884  // Get the row.
885  row& this_row = *row_iter;
886 
887  Abs_t norm(0); // double will not do for all types.
888 
889  // Iterate over the row
890  for (typename row::iterator col_iter = this_row.begin();
891  col_iter != this_row.end();
892  ++col_iter)
893  {
894  vnl_sparse_matrix_pair<T>& entry = *col_iter;
895  norm += vnl_math::squared_magnitude(entry.second);
896  }
897  if (norm != 0) {
898  abs_real_t scale = abs_real_t(1)/(std::sqrt((abs_real_t)norm));
899  // Iterate again over the row
900  for (typename row::iterator col_iter = this_row.begin();
901  col_iter != this_row.end();
902  ++col_iter)
903  {
904  vnl_sparse_matrix_pair<T>& entry = *col_iter;
905  entry.second = T(Real_t(entry.second) * scale);
906  }
907  }
908  }
909  return *this;
910 }
911 
912 //: Fill this matrix with 1s on the main diagonal and 0s elsewhere.
913 template<class T>
915 {
916  // Iterate through the matrix rows, and set one at a time:
917  unsigned int rownum = 0;
918  for (typename std::vector<row>::iterator row_iter = elements.begin();
919  row_iter != elements.end() && rownum < cols();
920  ++row_iter, ++rownum)
921  {
922  row& rw = *row_iter;
923  rw.clear();
924  rw[0] = vnl_sparse_matrix_pair<T>(rownum,T(1));
925  }
926  return *this;
927 }
928 
929 //: returns a new sparse matrix, viz. the transpose of this
930 template<class T>
932 {
933  vnl_sparse_matrix<T> result(cols(), rows());
934  unsigned int rownum = 0; // row number in this matrix
935  // iterate through the rows of this matrix,
936  // and add every element thus found to the new result matrix
937  for (typename std::vector<row>::const_iterator row_iter = elements.begin();
938  row_iter != elements.end();
939  ++row_iter, ++rownum)
940  {
941  row const& this_row = *row_iter;
942  for (typename row::const_iterator col_iter = this_row.begin();
943  col_iter != this_row.end();
944  ++col_iter)
945  {
946  vnl_sparse_matrix_pair<T> entry = *col_iter; // new copy of element
947  row& rw = result.elements[entry.first];
948  entry.first = rownum; // modify element: its column number is now rownum
949  rw.insert(rw.end(), entry); // insert at the end of the row
950  }
951  }
952  return result;
953 }
954 
955 //: returns a new sparse matrix, viz. the conjugate (or Hermitian) transpose of this
956 template<class T>
958 {
959  vnl_sparse_matrix<T> result(transpose());
960  for (typename std::vector<row>::iterator row_iter = result.elements.begin();
961  row_iter != result.elements.end();
962  ++row_iter)
963  {
964  row& this_row = *row_iter;
965  for (typename row::iterator col_iter = this_row.begin();
966  col_iter != this_row.end();
967  ++col_iter)
968  {
969  vnl_sparse_matrix_pair<T>& entry = *col_iter;
971  }
972  }
973  return result;
974 }
975 
976 #define VNL_SPARSE_MATRIX_INSTANTIATE(T) \
977 template class VNL_EXPORT vnl_sparse_matrix<T >
978 
979 #endif // vnl_sparse_matrix_hxx_
vnl_sparse_matrix< T > operator+(vnl_sparse_matrix< T > const &rhs) const
addition.
vnl_sparse_matrix & scale_row(unsigned int r, T scale)
Useful for normalizing row sums in convolution operators.
vnl_bignum operator+(vnl_bignum const &r1, long r2)
Returns the sum of two bignum numbers.
Definition: vnl_bignum.h:279
std::vector< pair_t > row
unsigned int columns() const
Get the number of columns in the matrix.
vnl_sparse_matrix< T > operator-() const
Unary minus.
vnl_sparse_matrix< T > transpose() const
returns a new sparse matrix, viz. the transpose of this.
An ordinary mathematical matrix.
void mult(vnl_vector< T > const &rhs, vnl_vector< T > &result) const
Multiply this*rhs, where rhs is a vector.
bool set_size(size_t n)
Resize to n elements.
Definition: vnl_vector.hxx:250
vnl_sparse_matrix< T > & operator-=(vnl_sparse_matrix< T > const &rhs)
in-place subtraction.
Simple sparse matrix.
To allow templated algorithms to determine appropriate actions of conjugation, complexification etc.
T value() const
Returns the value pointed to by the internal iterator.
T sum_row(unsigned int r)
This is occasionally useful.
void resize(int r, int c)
Resizes the array to have r rows and c cols.
#define m
Definition: vnl_vector.h:43
size_t size() const
Return the length, number of elements, dimension of this vector.
Definition: vnl_vector.h:126
vnl_sparse_matrix & set_row(unsigned int r, std::vector< int > const &cols, std::vector< T > const &vals)
Set a whole row at once. Much faster. Returns *this.
void set_size(int r, int c)
Resizes the array to have r rows and c cols – sets elements to null.
Namespace with standard math functions.
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_sparse_matrix< T > & operator+=(vnl_sparse_matrix< T > const &rhs)
in-place addition.
void reset() const
Resets the internal iterator.
bool operator==(vnl_sparse_matrix< T > const &rhs) const
Comparison.
void subtract(const vnl_sparse_matrix< T > &rhs, vnl_sparse_matrix< T > &result) const
Subtract rhs from this.
void put(unsigned int row, unsigned int column, T value)
Put (i.e., add or overwrite) an entry into the matrix.
vnl_bignum squared_magnitude(vnl_bignum const &x)
Definition: vnl_bignum.h:433
void clear()
Set all elements to null.
vnl_sparse_matrix_elements elements
bool empty_row(unsigned int r) const
Return whether a given row is empty.
#define v
Definition: vnl_vector.h:42
void diag_AtA(vnl_vector< T > &result) const
Get diag(A_transpose * A).
void subtract(const vnl_bignum &bmax, const vnl_bignum &bmin, vnl_bignum &diff)
subtract bmin from bmax (unsigned, non-infinite), result in diff.
Definition: vnl_bignum.cxx:947
void pre_mult(const vnl_vector< T > &lhs, vnl_vector< T > &result) const
Multiplies lhs*this, where lhs is a vector.
iterator begin()
Iterator pointing to start of data.
Definition: vnl_vector.h:243
vnl_sparse_matrix< T > operator/(T const &rhs) const
scalar division.
vnl_sparse_matrix< T > & operator/=(T const &rhs)
in-place scalar division.
unsigned int rows() const
Get the number of rows in the matrix.
vnl_sparse_matrix< T > operator *(vnl_sparse_matrix< T > const &rhs) const
multiplication.
vnl_vector & fill(T const &v)
Set all values to v.
Definition: vnl_vector.hxx:314
Mathematical vector class, templated by type of element.
Definition: vnl_fwd.h:16
vnl_sparse_matrix< T > conjugate_transpose() const
returns a new sparse matrix, viz. the conjugate (or Hermitian) transpose of this.
vnl_sparse_matrix< T > & operator=(vnl_sparse_matrix< T > const &rhs)
Copy another vnl_sparse_matrix<T> into this.
Simple sparse matrix.
vnl_sparse_matrix & set_identity()
Sets this matrix to an identity matrix, then returns "*this".
int getrow() const
Returns the row of the entry pointed to by internal iterator.
vnl_sparse_matrix()
Construct an empty matrix.
Stores elements of sparse matrix.
vnl_bignum operator-(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the difference of two bignum numbers.
Definition: vnl_bignum.h:290
vnl_sparse_matrix< T > & vcat(vnl_sparse_matrix< T > const &A)
Laminate matrix A onto the bottom of this one.
vnl_sparse_matrix< T > & operator *=(vnl_sparse_matrix< T > const &rhs)
in-place multiplication.
T get(unsigned int row, unsigned int column) const
Get an entry in the matrix.
vnl_bignum operator *(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the product of two bignum numbers.
Definition: vnl_bignum.h:302
bool next() const
Moves the internal iterator to next non-zero entry in matrix.
int getcolumn() const
Returns the column of the entry pointed to by internal iterator.
T & operator()(unsigned int row, unsigned int column)
Get a reference to an entry in the matrix.
vnl_sparse_matrix & normalize_rows()
Normalizes each row so it is a unit vector, and returns "*this".
void add(const vnl_sparse_matrix< T > &rhs, vnl_sparse_matrix< T > &result) const
Add rhs to this.