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