MatrixCSR-Impl.h
Go to the documentation of this file.
1 /*************************************************************************
2 > File Name: MatrixCSR-Impl.h
3 > Project Name: CubbyFlow
4 > Author: Chan-Ho Chris Ohk
5 > Purpose: Vector expression for CSR matrix-vector multiplication.
6 > Created Time: 2017/09/27
7 > Copyright (c) 2018, Chan-Ho Chris Ohk
8 *************************************************************************/
9 #ifndef CUBBYFLOW_MATRIX_CSR_IMPL_H
10 #define CUBBYFLOW_MATRIX_CSR_IMPL_H
11 
12 #include <Core/Utils/CppUtils.h>
13 #include <Core/Utils/Parallel.h>
14 
15 #include <numeric>
16 
17 namespace CubbyFlow
18 {
19  template <typename T, typename VE>
20  MatrixCSRVectorMul<T, VE>::MatrixCSRVectorMul(const MatrixCSR<T>& m, const VE& v) : m_m(m), m_v(v)
21  {
22  assert(m_m.Cols() == m_v.size());
23  }
24 
25  template <typename T, typename VE>
26  MatrixCSRVectorMul<T, VE>::MatrixCSRVectorMul(const MatrixCSRVectorMul& other) : m_m(other.m_m), m_v(other.m_v)
27  {
28  // Do nothing
29  }
30 
31  template <typename T, typename VE>
33  {
34  return m_m.Rows();
35  }
36 
37  template <typename T, typename VE>
39  {
40  auto rp = m_m.RowPointersBegin();
41  auto ci = m_m.ColumnIndicesBegin();
42  auto nnz = m_m.NonZeroBegin();
43 
44  size_t colBegin = rp[i];
45  size_t colEnd = rp[i + 1];
46 
47  T sum = 0;
48  for (size_t jj = colBegin; jj < colEnd; ++jj)
49  {
50  size_t j = ci[jj];
51  sum += nnz[jj] * m_v[j];
52  }
53 
54  return sum;
55  }
56 
57  template <typename T, typename ME>
59  m_m1(m1), m_m2(m2), m_nnz(m1.NonZeroData()), m_rp(m1.RowPointersData()), m_ci(m1.ColumnIndicesData())
60  {
61  // Do nothing
62  }
63 
64  template <typename T, typename ME>
66  {
67  return { Rows(), Cols() };
68  }
69 
70  template <typename T, typename ME>
72  {
73  return m_m1.Rows();
74  }
75 
76  template <typename T, typename ME>
78  {
79  return m_m2.Cols();
80  }
81 
82  template <typename T, typename ME>
83  T MatrixCSRMatrixMul<T, ME>::operator()(size_t i, size_t j) const
84  {
85  size_t colBegin = m_rp[i];
86  size_t colEnd = m_rp[i + 1];
87 
88  T sum = 0;
89  for (size_t kk = colBegin; kk < colEnd; ++kk)
90  {
91  size_t k = m_ci[kk];
92  sum += m_nnz[kk] * m_m2(k, j);
93  }
94 
95  return sum;
96  }
97 
98  template <typename T>
99  MatrixCSR<T>::Element::Element() : i(0), j(0), value(0)
100  {
101  // Do nothing
102  }
103 
104  template <typename T>
105  MatrixCSR<T>::Element::Element(size_t _i, size_t _j, const T& _value) : i(_i), j(_j), value(_value)
106  {
107  // Do nothing
108  }
109 
110  template <typename T>
112  {
113  Clear();
114  }
115 
116  template <typename T>
117  MatrixCSR<T>::MatrixCSR(const std::initializer_list<std::initializer_list<T>>& list, T epsilon)
118  {
119  Compress(list, epsilon);
120  }
121 
122  template <typename T>
123  template <typename E>
125  {
126  Compress(other, epsilon);
127  }
128 
129  template <typename T>
131  {
132  Set(other);
133  }
134 
135  template <typename T>
137  {
138  (*this) = std::move(other);
139  }
140 
141  template <typename T>
143  {
144  m_size = { 0, 0 };
145  m_nonZeros.clear();
146  m_rowPointers.clear();
147  m_columnIndices.clear();
148  m_rowPointers.push_back(0);
149  }
150 
151  template <typename T>
152  void MatrixCSR<T>::Set(const T& s)
153  {
154  std::fill(m_nonZeros.begin(), m_nonZeros.end(), s);
155  }
156 
157  template <typename T>
158  void MatrixCSR<T>::Set(const MatrixCSR& other)
159  {
160  m_size = other.m_size;
161  m_nonZeros = other.m_nonZeros;
162  m_rowPointers = other.m_rowPointers;
163  m_columnIndices = other.m_columnIndices;
164  }
165 
166  template <typename T>
167  void MatrixCSR<T>::Reserve(size_t rows, size_t cols, size_t numNonZeros)
168  {
169  m_size = Size2(rows, cols);
170  m_rowPointers.resize(m_size.x + 1);
171  m_nonZeros.resize(numNonZeros);
172  m_columnIndices.resize(numNonZeros);
173  }
174 
175  template <typename T>
176  void MatrixCSR<T>::Compress(const std::initializer_list<std::initializer_list<T>>& list, T epsilon)
177  {
178  size_t numRows = list.size();
179  size_t numCols = (numRows > 0) ? list.begin()->size() : 0;
180 
181  m_size = { numRows, numCols };
182  m_nonZeros.clear();
183  m_rowPointers.clear();
184  m_columnIndices.clear();
185 
186  auto rowIter = list.begin();
187  for (size_t i = 0; i < numRows; ++i)
188  {
189  assert(numCols == rowIter->size());
190  m_rowPointers.push_back(m_nonZeros.size());
191 
192  auto colIter = rowIter->begin();
193  for (size_t j = 0; j < numCols; ++j)
194  {
195  if (std::fabs(*colIter) > epsilon)
196  {
197  m_nonZeros.push_back(*colIter);
198  m_columnIndices.push_back(j);
199  }
200 
201  ++colIter;
202  }
203 
204  ++rowIter;
205  }
206 
207  m_rowPointers.push_back(m_nonZeros.size());
208  }
209 
210  template <typename T>
211  template <typename E>
212  void MatrixCSR<T>::Compress(const MatrixExpression<T, E>& other, T epsilon)
213  {
214  size_t numRows = other.Rows();
215  size_t numCols = other.Cols();
216 
217  m_size = { numRows, numCols };
218  m_nonZeros.clear();
219  m_columnIndices.clear();
220 
221  const E& expression = other();
222 
223  for (size_t i = 0; i < numRows; ++i)
224  {
225  m_rowPointers.push_back(m_nonZeros.size());
226 
227  for (size_t j = 0; j < numCols; ++j)
228  {
229  T val = expression(i, j);
230 
231  if (std::fabs(val) > epsilon)
232  {
233  m_nonZeros.push_back(val);
234  m_columnIndices.push_back(j);
235  }
236  }
237  }
238 
239  m_rowPointers.push_back(m_nonZeros.size());
240  }
241 
242  template <typename T>
243  void MatrixCSR<T>::AddElement(size_t i, size_t j, const T& value)
244  {
245  AddElement({ i, j, value });
246  }
247 
248  template <typename T>
249  void MatrixCSR<T>::AddElement(const Element& element)
250  {
251  ssize_t numRowsToAdd = static_cast<ssize_t>(element.i) - static_cast<ssize_t>(m_size.x) + 1;
252  if (numRowsToAdd > 0)
253  {
254  for (ssize_t i = 0; i < numRowsToAdd; ++i)
255  {
256  AddRow({}, {});
257  }
258  }
259 
260  m_size.y = std::max(m_size.y, element.j + 1);
261 
262  size_t rowBegin = m_rowPointers[element.i];
263  size_t rowEnd = m_rowPointers[element.i + 1];
264 
265  auto colIdxIter = std::lower_bound(m_columnIndices.begin() + rowBegin, m_columnIndices.begin() + rowEnd, element.j);
266  auto offset = colIdxIter - m_columnIndices.begin();
267 
268  m_columnIndices.insert(colIdxIter, element.j);
269  m_nonZeros.insert(m_nonZeros.begin() + offset, element.value);
270 
271  for (size_t i = element.i + 1; i < m_rowPointers.size(); ++i)
272  {
273  ++m_rowPointers[i];
274  }
275  }
276 
277  template <typename T>
278  void MatrixCSR<T>::AddRow(const NonZeroContainerType& nonZeros, const IndexContainerType& columnIndices)
279  {
280  assert(nonZeros.size() == columnIndices.size());
281 
282  ++m_size.x;
283 
284  // TODO: Implement zip iterator
285  std::vector<std::pair<T, size_t>> zipped;
286  for (size_t i = 0; i < nonZeros.size(); ++i)
287  {
288  zipped.emplace_back(nonZeros[i], columnIndices[i]);
289  m_size.y = std::max(m_size.y, columnIndices[i] + 1);
290  }
291 
292  std::sort(zipped.begin(), zipped.end(), [](std::pair<T, size_t> a, std::pair<T, size_t> b)
293  {
294  return a.second < b.second;
295  });
296 
297  for (size_t i = 0; i < zipped.size(); ++i)
298  {
299  m_nonZeros.push_back(zipped[i].first);
300  m_columnIndices.push_back(zipped[i].second);
301  }
302 
303  m_rowPointers.push_back(m_nonZeros.size());
304  }
305 
306  template <typename T>
307  void MatrixCSR<T>::SetElement(size_t i, size_t j, const T& value)
308  {
309  SetElement({ i, j, value });
310  }
311 
312  template <typename T>
313  void MatrixCSR<T>::SetElement(const Element& element)
314  {
315  size_t nzIndex = HasElement(element.i, element.j);
316 
317  if (nzIndex == std::numeric_limits<size_t>::max())
318  {
319  AddElement(element);
320  }
321  else
322  {
323  m_nonZeros[nzIndex] = element.value;
324  }
325  }
326 
327  template <typename T>
328  bool MatrixCSR<T>::IsEqual(const MatrixCSR& other) const
329  {
330  if (m_size != other.m_size)
331  {
332  return false;
333  }
334 
335  if (m_nonZeros.size() != other.m_nonZeros.size())
336  {
337  return false;
338  }
339 
340  for (size_t i = 0; i < m_nonZeros.size(); ++i)
341  {
342  if (m_nonZeros[i] != other.m_nonZeros[i])
343  {
344  return false;
345  }
346 
347  if (m_columnIndices[i] != other.m_columnIndices[i])
348  {
349  return false;
350  }
351  }
352 
353  for (size_t i = 0; i < m_rowPointers.size(); ++i)
354  {
355  if (m_rowPointers[i] != other.m_rowPointers[i])
356  {
357  return false;
358  }
359  }
360 
361  return true;
362  }
363 
364  template <typename T>
365  bool MatrixCSR<T>::IsSimilar(const MatrixCSR& other, double tol) const
366  {
367  if (m_size != other.m_size)
368  {
369  return false;
370  }
371 
372  if (m_nonZeros.size() != other.m_nonZeros.size())
373  {
374  return false;
375  }
376 
377  for (size_t i = 0; i < m_nonZeros.size(); ++i)
378  {
379  if (std::fabs(m_nonZeros[i] - other.m_nonZeros[i]) > tol)
380  {
381  return false;
382  }
383 
384  if (m_columnIndices[i] != other.m_columnIndices[i])
385  {
386  return false;
387  }
388  }
389 
390  for (size_t i = 0; i < m_rowPointers.size(); ++i)
391  {
392  if (m_rowPointers[i] != other.m_rowPointers[i])
393  {
394  return false;
395  }
396  }
397 
398  return true;
399  }
400 
401  template <typename T>
403  {
404  return Rows() == Cols();
405  }
406 
407  template <typename T>
409  {
410  return m_size;
411  }
412 
413  template <typename T>
414  size_t MatrixCSR<T>::Rows() const
415  {
416  return m_size.x;
417  }
418 
419  template <typename T>
420  size_t MatrixCSR<T>::Cols() const
421  {
422  return m_size.y;
423  }
424 
425  template <typename T>
427  {
428  return m_nonZeros.size();
429  }
430 
431  template <typename T>
432  const T& MatrixCSR<T>::NonZero(size_t i) const
433  {
434  return m_nonZeros[i];
435  }
436 
437  template <typename T>
439  {
440  return m_nonZeros[i];
441  }
442 
443  template <typename T>
444  const size_t& MatrixCSR<T>::RowPointer(size_t i) const
445  {
446  return m_rowPointers[i];
447  }
448 
449  template <typename T>
450  const size_t& MatrixCSR<T>::ColumnIndex(size_t i) const
451  {
452  return m_columnIndices[i];
453  }
454 
455  template <typename T>
457  {
458  return m_nonZeros.data();
459  }
460 
461  template <typename T>
462  const T* MatrixCSR<T>::NonZeroData() const
463  {
464  return m_nonZeros.data();
465  }
466 
467  template <typename T>
468  const size_t* MatrixCSR<T>::RowPointersData() const
469  {
470  return m_rowPointers.data();
471  }
472 
473  template <typename T>
474  const size_t* MatrixCSR<T>::ColumnIndicesData() const
475  {
476  return m_columnIndices.data();
477  }
478 
479  template <typename T>
481  {
482  return m_nonZeros.begin();
483  }
484 
485  template <typename T>
487  {
488  return m_nonZeros.cbegin();
489  }
490 
491  template <typename T>
493  {
494  return m_nonZeros.end();
495  }
496 
497  template <typename T>
499  {
500  return m_nonZeros.cend();
501  }
502 
503  template <typename T>
505  {
506  return m_rowPointers.begin();
507  }
508 
509  template <typename T>
511  {
512  return m_rowPointers.cbegin();
513  }
514 
515  template <typename T>
517  {
518  return m_rowPointers.end();
519  }
520 
521  template <typename T>
523  {
524  return m_rowPointers.cend();
525  }
526 
527  template <typename T>
529  {
530  return m_columnIndices.begin();
531  }
532 
533  template <typename T>
535  {
536  return m_columnIndices.cbegin();
537  }
538 
539  template <typename T>
541  {
542  return m_columnIndices.end();
543  }
544 
545  template <typename T>
547  {
548  return m_columnIndices.cend();
549  }
550 
551  template <typename T>
552  MatrixCSR<T> MatrixCSR<T>::Add(const T& s) const
553  {
554  MatrixCSR ret(*this);
555  ParallelFor(ZERO_SIZE, ret.m_nonZeros.size(), [&](size_t i) { ret.m_nonZeros[i] += s; });
556  return ret;
557  }
558 
559  template <typename T>
561  {
562  return BinaryOp(m, std::plus<T>());
563  }
564 
565  template <typename T>
566  MatrixCSR<T> MatrixCSR<T>::Sub(const T& s) const
567  {
568  MatrixCSR ret(*this);
569  ParallelFor(ZERO_SIZE, ret.m_nonZeros.size(), [&](size_t i) { ret.m_nonZeros[i] -= s; });
570  return ret;
571  }
572 
573  template <typename T>
575  {
576  return BinaryOp(m, std::minus<T>());
577  }
578 
579  template <typename T>
580  MatrixCSR<T> MatrixCSR<T>::Mul(const T& s) const
581  {
582  MatrixCSR ret(*this);
583  ParallelFor(ZERO_SIZE, ret.m_nonZeros.size(), [&](size_t i) { ret.m_nonZeros[i] *= s; });
584  return ret;
585  }
586 
587  template <typename T>
588  template <typename VE>
590  {
591  return MatrixCSRVectorMul<T, VE>(*this, v());
592  };
593 
594  template <typename T>
595  template <typename ME>
597  {
598  return MatrixCSRMatrixMul<T, ME>(*this, m());
599  }
600 
601  template <typename T>
602  MatrixCSR<T> MatrixCSR<T>::Div(const T& s) const
603  {
604  MatrixCSR ret(*this);
605  ParallelFor(ZERO_SIZE, ret.m_nonZeros.size(), [&](size_t i) { ret.m_nonZeros[i] /= s; });
606  return ret;
607  }
608 
609  template <typename T>
611  {
612  return Add(s);
613  }
614 
615  template <typename T>
617  {
618  return Add(m);
619  }
620 
621  template <typename T>
623  {
624  MatrixCSR ret(*this);
625  ParallelFor(ZERO_SIZE, ret.m_nonZeros.size(), [&](size_t i) { ret.m_nonZeros[i] = s - ret.m_nonZeros[i]; });
626  return ret;
627  }
628 
629  template <typename T>
631  {
632  return m.Sub(*this);
633  }
634 
635  template <typename T>
637  {
638  return Mul(s);
639  }
640 
641  template <typename T>
643  {
644  MatrixCSR ret(*this);
645  ParallelFor(ZERO_SIZE, ret.m_nonZeros.size(), [&](size_t i) { ret.m_nonZeros[i] = s / ret.m_nonZeros[i]; });
646  return ret;
647  }
648 
649  template <typename T>
650  void MatrixCSR<T>::IAdd(const T& s)
651  {
652  ParallelFor(ZERO_SIZE, m_nonZeros.size(), [&](size_t i) { m_nonZeros[i] += s; });
653  }
654 
655  template <typename T>
657  {
658  Set(Add(m));
659  }
660 
661  template <typename T>
662  void MatrixCSR<T>::ISub(const T& s)
663  {
664  ParallelFor(ZERO_SIZE, m_nonZeros.size(), [&](size_t i) { m_nonZeros[i] -= s; });
665  }
666 
667  template <typename T>
669  {
670  Set(Sub(m));
671  }
672 
673  template <typename T>
674  void MatrixCSR<T>::IMul(const T& s)
675  {
676  ParallelFor(ZERO_SIZE, m_nonZeros.size(), [&](size_t i) { m_nonZeros[i] *= s; });
677  }
678 
679  template <typename T>
680  template <typename ME>
682  {
683  MatrixCSRD result = Mul(m);
684  *this = std::move(result);
685  }
686 
687  template <typename T>
688  void MatrixCSR<T>::IDiv(const T& s)
689  {
690  ParallelFor(ZERO_SIZE, m_nonZeros.size(), [&](size_t i) { m_nonZeros[i] /= s; });
691  }
692 
693  template <typename T>
695  {
696  return ParallelReduce(ZERO_SIZE, NumberOfNonZeros(), T(0),
697  [&](size_t start, size_t end, T init)
698  {
699  T result = init;
700 
701  for (size_t i = start; i < end; ++i)
702  {
703  result += m_nonZeros[i];
704  }
705 
706  return result;
707  }, std::plus<T>());
708  }
709 
710  template <typename T>
712  {
713  return Sum() / NumberOfNonZeros();
714  }
715 
716  template <typename T>
718  {
719  const T& (*m_min)(const T&, const T&) = std::min<T>;
720 
721  return ParallelReduce(ZERO_SIZE, NumberOfNonZeros(), std::numeric_limits<T>::max(),
722  [&](size_t start, size_t end, T init)
723  {
724  T result = init;
725 
726  for (size_t i = start; i < end; ++i)
727  {
728  result = std::min(result, m_nonZeros[i]);
729  }
730 
731  return result;
732  }, m_min);
733  }
734 
735  template <typename T>
737  {
738  const T& (*m_max)(const T&, const T&) = std::max<T>;
739 
740  return ParallelReduce(ZERO_SIZE, NumberOfNonZeros(), std::numeric_limits<T>::min(),
741  [&](size_t start, size_t end, T init)
742  {
743  T result = init;
744 
745  for (size_t i = start; i < end; ++i)
746  {
747  result = std::max(result, m_nonZeros[i]);
748  }
749 
750  return result;
751  }, m_max);
752  }
753 
754  template <typename T>
756  {
757  return ParallelReduce(ZERO_SIZE, NumberOfNonZeros(), std::numeric_limits<T>::max(),
758  [&](size_t start, size_t end, T init)
759  {
760  T result = init;
761 
762  for (size_t i = start; i < end; ++i)
763  {
764  result = CubbyFlow::AbsMin(result, m_nonZeros[i]);
765  }
766  return result;
767  }, CubbyFlow::AbsMin<T>);
768  }
769 
770  template <typename T>
772  {
773  return ParallelReduce(ZERO_SIZE, NumberOfNonZeros(), T(0),
774  [&](size_t start, size_t end, T init)
775  {
776  T result = init;
777 
778  for (size_t i = start; i < end; ++i)
779  {
780  result = CubbyFlow::AbsMax(result, m_nonZeros[i]);
781  }
782 
783  return result;
784  }, CubbyFlow::AbsMax<T>);
785  }
786 
787  template <typename T>
789  {
790  assert(IsSquare());
791 
792  return ParallelReduce(ZERO_SIZE, Rows(), T(0),
793  [&](size_t start, size_t end, T init)
794  {
795  T result = init;
796 
797  for (size_t i = start; i < end; ++i)
798  {
799  result += (*this)(i, i);
800  }
801 
802  return result;
803  }, std::plus<T>());
804  }
805 
806  template <typename T>
807  template <typename U>
809  {
810  MatrixCSR<U> ret;
811  ret.Reserve(Rows(), Cols(), NumberOfNonZeros());
812 
813  auto nnz = ret.NonZeroBegin();
814  auto ci = ret.ColumnIndicesBegin();
815  auto rp = ret.RowPointersBegin();
816 
817  ParallelFor(ZERO_SIZE, m_nonZeros.size(), [&](size_t i)
818  {
819  nnz[i] = static_cast<U>(m_nonZeros[i]);
820  ci[i] = m_columnIndices[i];
821  });
822 
823  ParallelFor(ZERO_SIZE, m_rowPointers.size(), [&](size_t i) { rp[i] = m_rowPointers[i]; });
824 
825  return ret;
826  }
827 
828  template <typename T>
829  template <typename E>
831  {
832  Set(m);
833  return *this;
834  }
835 
836  template <typename T>
838  {
839  Set(other);
840  return *this;
841  }
842 
843  template <typename T>
845  {
846  m_size = other.m_size;
847  other.m_size = Size2();
848  m_nonZeros = std::move(other.m_nonZeros);
849  m_rowPointers = std::move(other.m_rowPointers);
850  m_columnIndices = std::move(other.m_columnIndices);
851  return *this;
852  }
853 
854  template <typename T>
856  {
857  IAdd(s);
858  return *this;
859  }
860 
861  template <typename T>
863  {
864  IAdd(m);
865  return *this;
866  }
867 
868  template <typename T>
870  {
871  ISub(s);
872  return *this;
873  }
874 
875  template <typename T>
877  {
878  ISub(m);
879  return *this;
880  }
881 
882  template <typename T>
884  {
885  IMul(s);
886  return *this;
887  }
888 
889  template <typename T>
890  template <typename ME>
892  {
893  IMul(m);
894  return *this;
895  }
896 
897  template <typename T>
899  {
900  IDiv(s);
901  return *this;
902  }
903 
904  template <typename T>
905  T MatrixCSR<T>::operator()(size_t i, size_t j) const
906  {
907  size_t nzIndex = HasElement(i, j);
908 
909  if (nzIndex == std::numeric_limits<size_t>::max())
910  {
911  return 0.0;
912  }
913 
914  return m_nonZeros[nzIndex];
915  }
916 
917  template <typename T>
918  bool MatrixCSR<T>::operator==(const MatrixCSR& m) const
919  {
920  return IsEqual(m);
921  }
922 
923  template <typename T>
924  bool MatrixCSR<T>::operator!=(const MatrixCSR& m) const
925  {
926  return !IsEqual(m);
927  }
928 
929  template <typename T>
931  {
932  MatrixCSR ret;
933  ret.m_size = Size2(m, m);
934  ret.m_nonZeros.resize(m, 1.0);
935  ret.m_columnIndices.resize(m);
936  std::iota(ret.m_columnIndices.begin(), ret.m_columnIndices.end(), ZERO_SIZE);
937  ret.m_rowPointers.resize(m + 1);
938  std::iota(ret.m_rowPointers.begin(), ret.m_rowPointers.end(), ZERO_SIZE);
939  return ret;
940  }
941 
942  template <typename T>
943  size_t MatrixCSR<T>::HasElement(size_t i, size_t j) const
944  {
945  if (i >= m_size.x || j >= m_size.y)
946  {
947  return std::numeric_limits<size_t>::max();
948  }
949 
950  size_t rowBegin = m_rowPointers[i];
951  size_t rowEnd = m_rowPointers[i + 1];
952 
953  auto iter = BinaryFind(m_columnIndices.begin() + rowBegin, m_columnIndices.begin() + rowEnd, j);
954  if (iter != m_columnIndices.begin() + rowEnd)
955  {
956  return static_cast<size_t>(iter - m_columnIndices.begin());
957  }
958 
959  return std::numeric_limits<size_t>::max();
960  }
961 
962  template <typename T>
963  template <typename Op>
965  {
966  assert(m_size == m.m_size);
967 
968  MatrixCSR ret;
969 
970  for (size_t i = 0; i < m_size.x; ++i)
971  {
972  std::vector<size_t> col;
973  std::vector<double> nnz;
974 
975  auto colIterA = m_columnIndices.begin() + m_rowPointers[i];
976  auto colIterB = m.m_columnIndices.begin() + m.m_rowPointers[i];
977  auto colEndA = m_columnIndices.begin() + m_rowPointers[i + 1];
978  auto colEndB = m.m_columnIndices.begin() + m.m_rowPointers[i + 1];
979  auto nnzIterA = m_nonZeros.begin() + m_rowPointers[i];
980  auto nnzIterB = m.m_nonZeros.begin() + m.m_rowPointers[i];
981 
982  while (colIterA != colEndA || colIterB != colEndB)
983  {
984  if (colIterB == colEndB || *colIterA < *colIterB)
985  {
986  col.push_back(*colIterA);
987  nnz.push_back(op(*nnzIterA, 0));
988  ++colIterA;
989  ++nnzIterA;
990  }
991  else if (colIterA == colEndA || *colIterA > *colIterB)
992  {
993  col.push_back(*colIterB);
994  nnz.push_back(op(0, *nnzIterB));
995  ++colIterB;
996  ++nnzIterB;
997  }
998  else
999  {
1000  assert(*colIterA == *colIterB);
1001  col.push_back(*colIterB);
1002  nnz.push_back(op(*nnzIterA, *nnzIterB));
1003  ++colIterA;
1004  ++nnzIterA;
1005  ++colIterB;
1006  ++nnzIterB;
1007  }
1008  }
1009 
1010  ret.AddRow(nnz, col);
1011  }
1012 
1013  return ret;
1014  }
1015 
1016  // MARK: Operator overloadings
1017  template <typename T>
1019  {
1020  return a.Mul(-1);
1021  }
1022 
1023  template <typename T>
1025  {
1026  return a.Add(b);
1027  }
1028 
1029  template <typename T>
1031  {
1032  return a.Add(b);
1033  }
1034 
1035  template <typename T>
1037  {
1038  return b.Add(a);
1039  }
1040 
1041  template <typename T>
1043  {
1044  return a.Sub(b);
1045  }
1046 
1047  template <typename T>
1049  {
1050  return a.Sub(b);
1051  }
1052 
1053  template <typename T>
1055  {
1056  return b.RSub(a);
1057  }
1058 
1059  template <typename T>
1061  {
1062  return a.Mul(b);
1063  }
1064 
1065  template <typename T>
1067  {
1068  return b.RMul(a);
1069  }
1070 
1071  template <typename T, typename VE>
1073  {
1074  return a.Mul(b);
1075  }
1076 
1077  template <typename T, typename ME>
1079  {
1080  return a.Mul(b);
1081  }
1082 
1083  template <typename T>
1085  {
1086  return a.Div(b);
1087  }
1088 
1089  template <typename T>
1091  {
1092  return b.RDiv(a);
1093  }
1094 }
1095 
1096 #endif
Vector expression for CSR matrix-vector multiplication.
Definition: MatrixCSR.h:31
void ISub(const T &s)
Subtracts input scalar from this matrix.
Definition: MatrixCSR-Impl.h:662
bool operator!=(const MatrixCSR &m) const
Returns true if is not equal to m.
Definition: MatrixCSR-Impl.h:924
T Trace() const
Definition: MatrixCSR-Impl.h:788
MatrixCSR< U > CastTo() const
Type-casts to different value-typed matrix.
Definition: MatrixCSR-Impl.h:808
T AbsMin(T x, T y)
Returns the absolute minimum value among the two inputs.
Definition: MathUtils-Impl.h:39
void Clear()
Clears the matrix and make it zero-dimensional.
Definition: MatrixCSR-Impl.h:142
const T & NonZero(size_t i) const
Returns i-th non-zero element.
Definition: MatrixCSR-Impl.h:432
Matrix expression for CSR matrix-matrix multiplication.
Definition: MatrixCSR.h:60
const size_t * RowPointersData() const
Returns constant pointer of the row pointers data.
Definition: MatrixCSR-Impl.h:468
T AbsMax() const
Returns absolute maximum among all elements.
Definition: MatrixCSR-Impl.h:771
Matrix< T, 2, 2 > operator+(const Matrix< T, 2, 2 > &a, const Matrix< T, 2, 2 > &b)
Returns a + b (element-size).
Definition: Matrix2x2-Impl.h:660
T x
X (or the first) component of the point.
Definition: Point2.h:28
MatrixCSR & operator+=(const T &s)
Addition assignment with input scalar.
Definition: MatrixCSR-Impl.h:855
bool IsEqual(const MatrixCSR &other) const
Definition: MatrixCSR-Impl.h:328
MatrixCSRMatrixMul(const MatrixCSR< T > &m1, const ME &m2)
Definition: MatrixCSR-Impl.h:58
size_t Cols() const
Number of columns.
Definition: MatrixCSR-Impl.h:77
Base class for vector expression.
Definition: VectorExpression.h:28
std::vector< size_t > IndexContainerType
Definition: MatrixCSR.h:116
void IMul(const T &s)
Multiplies input scalar to this matrix.
Definition: MatrixCSR-Impl.h:674
T Sum() const
Returns sum of all elements.
Definition: MatrixCSR-Impl.h:694
2-D point class.
Definition: Point2.h:25
const size_t * ColumnIndicesData() const
Returns constant pointer of the column indices data.
Definition: MatrixCSR-Impl.h:474
IndexIterator ColumnIndicesEnd()
Returns the end iterator of the column indices.
Definition: MatrixCSR-Impl.h:540
IndexContainerType::const_iterator ConstIndexIterator
Definition: MatrixCSR.h:118
T Min() const
Returns minimum among all elements.
Definition: MatrixCSR-Impl.h:717
T * NonZeroData()
Returns pointer of the non-zero elements data.
Definition: MatrixCSR-Impl.h:456
void IDiv(const T &s)
Divides this matrix with input scalar.
Definition: MatrixCSR-Impl.h:688
const size_t & RowPointer(size_t i) const
Returns i-th row pointer.
Definition: MatrixCSR-Impl.h:444
MatrixCSR Div(const T &s) const
Returns this matrix / input scalar.
Definition: MatrixCSR-Impl.h:602
bool IsSimilar(const MatrixCSR &other, double tol=std::numeric_limits< double >::epsilon()) const
Returns true if this matrix is similar to the input matrix within the given tolerance.
Definition: MatrixCSR-Impl.h:365
ForwardIter BinaryFind(ForwardIter first, ForwardIter last, const T &value, Compare comp)
Definition: CppUtils-Impl.h:19
Point2< size_t > Size2
Definition: Size2.h:16
T operator[](size_t i) const
Returns vector element at i.
Definition: MatrixCSR-Impl.h:38
Size2 size() const
Returns the size of this matrix.
Definition: MatrixCSR-Impl.h:408
void Set(const T &s)
Sets whole matrix with input scalar.
Definition: MatrixCSR-Impl.h:152
MatrixCSR Add(const T &s) const
Returns this matrix + input scalar.
Definition: MatrixCSR-Impl.h:552
MatrixCSR Mul(const T &s) const
Returns this matrix * input scalar.
Definition: MatrixCSR-Impl.h:580
T y
Y (or the second) component of the point.
Definition: Point2.h:34
void AddElement(size_t i, size_t j, const T &value)
Adds non-zero element to (i, j).
Definition: MatrixCSR-Impl.h:243
void SetElement(size_t i, size_t j, const T &value)
Sets non-zero element to (i, j).
Definition: MatrixCSR-Impl.h:307
IndexContainerType::iterator IndexIterator
Definition: MatrixCSR.h:117
size_t Rows() const
Returns number of rows of this matrix.
Definition: MatrixCSR-Impl.h:414
Matrix< T, 2, 2 > operator/(const Matrix< T, 2, 2 > &a, T b)
Definition: Matrix2x2-Impl.h:720
Definition: pybind11Utils.h:24
void ParallelFor(IndexType beginIndex, IndexType endIndex, const Function &function, ExecutionPolicy policy)
Makes a for-loop from beginIndex to endIndex in parallel.
Definition: Parallel-Impl.h:201
bool IsSquare() const
Returns true if this matrix is a square matrix.
Definition: MatrixCSR-Impl.h:402
Size2 size() const
Size of the matrix.
Definition: MatrixCSR-Impl.h:65
IndexIterator ColumnIndicesBegin()
Returns the begin iterator of the column indices.
Definition: MatrixCSR-Impl.h:528
size_t NumberOfNonZeros() const
Returns the number of non-zero elements.
Definition: MatrixCSR-Impl.h:426
MatrixCSR Sub(const T &s) const
Returns this matrix - input scalar.
Definition: MatrixCSR-Impl.h:566
MatrixCSRVectorMul(const MatrixCSR< T > &m, const VE &v)
Definition: MatrixCSR-Impl.h:20
NonZeroIterator NonZeroEnd()
Returns the end iterator of the non-zero elements.
Definition: MatrixCSR-Impl.h:492
void Compress(const std::initializer_list< std::initializer_list< T >> &list, T epsilon=std::numeric_limits< T >::epsilon())
Compresses given initializer list list into a sparse matrix.
Definition: MatrixCSR-Impl.h:176
IndexIterator RowPointersEnd()
Returns the end iterator of the row pointers.
Definition: MatrixCSR-Impl.h:516
MatrixCSR RMul(const T &s) const
Returns input scalar * this matrix.
Definition: MatrixCSR-Impl.h:636
typename NonZeroContainerType::iterator NonZeroIterator
Definition: MatrixCSR.h:113
size_t Rows() const
Number of rows.
Definition: MatrixExpression-Impl.h:22
MatrixCSR & operator*=(const T &s)
Multiplication assignment with input scalar.
Definition: MatrixCSR-Impl.h:883
static MatrixCSR< T > MakeIdentity(size_t m)
Makes a m x m matrix with all diagonal elements to 1, and other elements to 0.
Definition: MatrixCSR-Impl.h:930
Element()
Definition: MatrixCSR-Impl.h:99
Compressed Sparse Row (CSR) matrix class.
Definition: MatrixCSR.h:19
Matrix< T, 2, 2 > operator-(const Matrix< T, 2, 2 > &a)
Returns a matrix with opposite sign.
Definition: Matrix2x2-Impl.h:654
typename NonZeroContainerType::const_iterator ConstNonZeroIterator
Definition: MatrixCSR.h:114
MatrixCSR RAdd(const T &s) const
Returns input scalar + this matrix.
Definition: MatrixCSR-Impl.h:610
const MatrixCSRMatrixMul< T, ME > & operator()() const
Returns actual implementation (the subclass).
Definition: MatrixExpression-Impl.h:34
constexpr size_t ZERO_SIZE
Zero size_t.
Definition: Constants.h:18
void Reserve(size_t rows, size_t cols, size_t numNonZeros)
Reserves memory space of this matrix.
Definition: MatrixCSR-Impl.h:167
void IAdd(const T &s)
Adds input scalar to this matrix.
Definition: MatrixCSR-Impl.h:650
T Max() const
Returns maximum among all elements.
Definition: MatrixCSR-Impl.h:736
Base class for matrix expression.
Definition: MatrixExpression.h:27
size_t Rows() const
Number of rows.
Definition: MatrixCSR-Impl.h:71
size_t Cols() const
Returns number of columns of this matrix.
Definition: MatrixCSR-Impl.h:420
MatrixCSR & operator=(const E &m)
Compresses input (dense) matrix expression into a sparse matrix.
MatrixCSR & operator/=(const T &s)
Division assignment with input scalar.
Definition: MatrixCSR-Impl.h:898
MatrixCSR RDiv(const T &s) const
Returns input matrix / this scalar.
Definition: MatrixCSR-Impl.h:642
Vector< T, 3 > operator*(const Quaternion< T > &q, const Vector< T, 3 > &v)
Returns quaternion q * vector v.
Definition: Quaternion-Impl.h:481
const size_t & ColumnIndex(size_t i) const
Returns i-th column index.
Definition: MatrixCSR-Impl.h:450
MatrixCSR & operator-=(const T &s)
Subtraction assignment with input scalar.
Definition: MatrixCSR-Impl.h:869
T AbsMax(T x, T y)
Returns the absolute maximum value among the two inputs.
Definition: MathUtils-Impl.h:45
size_t size() const
Size of the vector.
Definition: MatrixCSR-Impl.h:32
MatrixCSR()
Constructs an empty matrix.
Definition: MatrixCSR-Impl.h:111
MatrixCSR RSub(const T &s) const
Returns input scalar - this matrix.
Definition: MatrixCSR-Impl.h:622
size_t Cols() const
Number of columns.
Definition: MatrixExpression-Impl.h:28
T Avg() const
Returns average of all elements.
Definition: MatrixCSR-Impl.h:711
bool operator==(const MatrixCSR &m) const
Returns true if is equal to m.
Definition: MatrixCSR-Impl.h:918
Value ParallelReduce(IndexType beginIndex, IndexType endIndex, const Value &identity, const Function &function, const Reduce &reduce, ExecutionPolicy policy)
Performs reduce operation in parallel.
Definition: Parallel-Impl.h:407
NonZeroIterator NonZeroBegin()
Returns the begin iterator of the non-zero elements.
Definition: MatrixCSR-Impl.h:480
T AbsMin() const
Returns absolute minimum among all elements.
Definition: MatrixCSR-Impl.h:755
void AddRow(const NonZeroContainerType &nonZeros, const IndexContainerType &columnIndices)
Definition: MatrixCSR-Impl.h:278
IndexIterator RowPointersBegin()
Returns the begin iterator of the row pointers.
Definition: MatrixCSR-Impl.h:504
std::vector< double > NonZeroContainerType
Definition: MatrixCSR.h:112