Matrix-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_IMPL_HPP
12 #define CUBBYFLOW_MATRIX_IMPL_HPP
13 
14 #include <Core/Utils/Functors.hpp>
15 
16 #include <numeric>
17 
18 namespace CubbyFlow
19 {
20 namespace Internal
21 {
22 // TODO: With C++17, fold expression could be used instead.
23 template <typename M1, typename M2, size_t J>
24 struct DotProduct
25 {
26  constexpr static auto call(const M1& a, const M2& b, size_t i, size_t j)
27  {
28  return DotProduct<M1, M2, J - 1>::call(a, b, i, j) + a(i, J) * b(J, j);
29  }
30 };
31 
32 template <typename M1, typename M2>
33 struct DotProduct<M1, M2, 0>
34 {
35  constexpr static auto call(const M1& a, const M2& b, size_t i, size_t j)
36  {
37  return a(i, 0) * b(0, j);
38  }
39 };
40 
41 // TODO: With C++17, fold expression could be used instead.
42 template <typename T, size_t Rows, size_t Cols, typename ReduceOperation,
43  typename UnaryOperation, size_t I>
44 struct Reduce
45 {
46  // For vector-like Matrix
47  template <typename U = T>
48  constexpr static std::enable_if_t<(Cols == 1), U> Call(
49  const Matrix<T, Rows, 1>& a, const T& init, ReduceOperation op,
50  UnaryOperation uop)
51  {
52  return op(
54  a, init, op, uop),
55  uop(a(I, 0)));
56  }
57 
58  // For vector-like Matrix with zero init
59  template <typename U = T>
60  constexpr static std::enable_if_t<(Cols == 1), U> Call(
61  const Matrix<T, Rows, 1>& a, ReduceOperation op, UnaryOperation uop)
62  {
63  return op(
65  a, op, uop),
66  uop(a(I, 0)));
67  }
68 
69  // For Matrix
70  constexpr static T Call(const Matrix<T, Rows, Cols>& a, const T& init,
71  ReduceOperation op, UnaryOperation uop)
72  {
73  return op(
75  a, init, op, uop),
76  uop(a[I]));
77  }
78 
79  // For Matrix with zero init
80  constexpr static T Call(const Matrix<T, Rows, Cols>& a, ReduceOperation op,
81  UnaryOperation uop)
82  {
83  return op(
85  a, op, uop),
86  uop(a[I]));
87  }
88 
89  // For diagonal elements on Matrix
90  constexpr static T CallDiag(const Matrix<T, Rows, Cols>& a, const T& init,
91  ReduceOperation op, UnaryOperation uop)
92  {
93  return op(Reduce<T, Rows, Cols, ReduceOperation, UnaryOperation,
94  I - 1>::CallDiag(a, init, op, uop),
95  uop(a(I, I)));
96  }
97 };
98 
99 template <typename T, size_t Rows, size_t Cols, typename ReduceOperation,
100  typename UnaryOperation>
101 struct Reduce<T, Rows, Cols, ReduceOperation, UnaryOperation, 0>
102 {
103  // For vector-like Matrix
104  template <typename U = T>
105  constexpr static std::enable_if_t<(Cols > 1), U> Call(
106  const Matrix<T, Rows, 1>& a, const T& init, ReduceOperation op,
107  UnaryOperation uop)
108  {
109  return op(uop(a(0, 0)), init);
110  }
111 
112  // For vector-like Matrix with zero init
113  template <typename U = T>
114  constexpr static std::enable_if_t<(Cols == 1), U> Call(
115  const Matrix<T, Rows, 1>& a, ReduceOperation op, UnaryOperation uop)
116  {
117  return uop(a(0, 0));
118  }
119 
120  // For Matrix
121  constexpr static T Call(const Matrix<T, Rows, Cols>& a, const T& init,
122  ReduceOperation op, UnaryOperation uop)
123  {
124  return op(uop(a[0]), init);
125  }
126 
127  // For MatrixBase with zero init
128  constexpr static T Call(const Matrix<T, Rows, Cols>& a, ReduceOperation op,
129  UnaryOperation uop)
130  {
131  return uop(a[0]);
132  }
133 
134  // For diagonal elements on MatrixBase
135  constexpr static T CallDiag(const Matrix<T, Rows, Cols>& a, const T& init,
136  ReduceOperation op, UnaryOperation uop)
137  {
138  return op(uop(a(0, 0)), init);
139  }
140 };
141 
142 // We can use std::logical_and<>, but explicitly putting && helps compiler
143 // to early terminate the loop (at least for gcc 8.1 as I checked the
144 // assembly).
145 // TODO: With C++17, fold expression could be used instead.
146 template <typename T, size_t Rows, size_t Cols, typename BinaryOperation,
147  size_t I>
149 {
150  constexpr static bool Call(const Matrix<T, Rows, Cols>& a,
151  const Matrix<T, Rows, Cols>& b,
152  BinaryOperation op)
153  {
155  op) &&
156  op(a[I], b[I]);
157  }
158 };
159 
160 template <typename T, size_t Rows, size_t Cols, typename BinaryOperation>
161 struct FoldWithAnd<T, Rows, Cols, BinaryOperation, 0>
162 {
163  constexpr static bool Call(const Matrix<T, Rows, Cols>& a,
164  const Matrix<T, Rows, Cols>& b,
165  BinaryOperation op)
166  {
167  return op(a[0], b[0]);
168  }
169 };
170 
171 } // namespace Internal
172 
173 template <typename T, size_t Rows, size_t Cols>
175 {
176  Fill(value);
177 }
178 
179 template <typename T, size_t Rows, size_t Cols>
180 template <size_t R, size_t C, typename E>
182 {
183  assert(expression.GetRows() == Rows && expression.GetCols() == Cols);
184 
185  CopyFrom(expression);
186 }
187 
188 template <typename T, size_t Rows, size_t Cols>
190 {
191  size_t i = 0;
192 
193  for (auto rows : lst)
194  {
195  assert(i < Rows);
196 
197  size_t j = 0;
198 
199  for (auto col : rows)
200  {
201  assert(j < Cols);
202 
203  (*this)(i, j) = col;
204  ++j;
205  }
206 
207  ++i;
208  }
209 }
210 
211 template <typename T, size_t Rows, size_t Cols>
213 {
214  size_t cnt = 0;
215 
216  for (size_t i = 0; i < Rows; ++i)
217  {
218  for (size_t j = 0; j < Cols; ++j)
219  {
220  (*this)(i, j) = ptr[cnt++];
221  }
222  }
223 }
224 
225 template <typename T, size_t Rows, size_t Cols>
226 void Matrix<T, Rows, Cols>::Fill(const T& val)
227 {
228  m_elements.fill(val);
229 }
230 
231 template <typename T, size_t Rows, size_t Cols>
232 void Matrix<T, Rows, Cols>::Fill(const std::function<T(size_t i)>& func)
233 {
234  for (size_t i = 0; i < Rows * Cols; ++i)
235  {
236  m_elements[i] = func(i);
237  }
238 }
239 
240 template <typename T, size_t Rows, size_t Cols>
242  const std::function<T(size_t i, size_t j)>& func)
243 {
244  for (size_t i = 0; i < Rows; ++i)
245  {
246  for (size_t j = 0; j < Cols; ++j)
247  {
248  (*this)(i, j) = func(i, j);
249  }
250  }
251 }
252 
253 template <typename T, size_t Rows, size_t Cols>
255 {
256  m_elements.swap(other.m_elements);
257 }
258 
259 template <typename T, size_t Rows, size_t Cols>
260 constexpr size_t Matrix<T, Rows, Cols>::GetRows() const
261 {
262  return Rows;
263 }
264 
265 template <typename T, size_t Rows, size_t Cols>
266 constexpr size_t Matrix<T, Rows, Cols>::GetCols() const
267 {
268  return Cols;
269 }
270 
271 template <typename T, size_t Rows, size_t Cols>
273 {
274  return &m_elements[0];
275 }
276 
277 template <typename T, size_t Rows, size_t Cols>
278 constexpr typename Matrix<T, Rows, Cols>::ConstIterator
280 {
281  return &m_elements[0];
282 }
283 
284 template <typename T, size_t Rows, size_t Cols>
286 {
287  return begin() + Rows * Cols;
288 }
289 
290 template <typename T, size_t Rows, size_t Cols>
291 constexpr typename Matrix<T, Rows, Cols>::ConstIterator
293 {
294  return begin() + Rows * Cols;
295 }
296 
297 template <typename T, size_t Rows, size_t Cols>
299 {
300  return &m_elements[0];
301 }
302 
303 template <typename T, size_t Rows, size_t Cols>
304 constexpr typename Matrix<T, Rows, Cols>::ConstPointer
306 {
307  return &m_elements[0];
308 }
309 
310 template <typename T, size_t Rows, size_t Cols>
312  size_t i)
313 {
314  assert(i < Rows * Cols);
315 
316  return m_elements[i];
317 }
318 
319 template <typename T, size_t Rows, size_t Cols>
322 {
323  assert(i < Rows * Cols);
324 
325  return m_elements[i];
326 }
327 
328 template <typename T>
329 template <size_t R, size_t C, typename E>
331 {
332  assert(expression.GetRows() == 1 && expression.GetCols() == 1);
333 
334  x = expression.Eval(0, 0);
335 }
336 
337 template <typename T>
338 Matrix<T, 1, 1>::Matrix(const std::initializer_list<T>& lst)
339 {
340  assert(lst.size() > 0);
341 
342  x = *lst.begin();
343 }
344 
345 template <typename T>
346 void Matrix<T, 1, 1>::Fill(const T& val)
347 {
348  x = val;
349 }
350 
351 template <typename T>
352 void Matrix<T, 1, 1>::Fill(const std::function<T(size_t i)>& func)
353 {
354  x = func(0);
355 }
356 
357 template <typename T>
358 void Matrix<T, 1, 1>::Fill(const std::function<T(size_t i, size_t j)>& func)
359 {
360  x = func(0, 0);
361 }
362 
363 template <typename T>
365 {
366  std::swap(x, other.x);
367 }
368 
369 template <typename T>
370 constexpr size_t Matrix<T, 1, 1>::GetRows() const
371 {
372  return 1;
373 }
374 
375 template <typename T>
376 constexpr size_t Matrix<T, 1, 1>::GetCols() const
377 {
378  return 1;
379 }
380 
381 template <typename T>
383 {
384  return &x;
385 }
386 
387 template <typename T>
389 {
390  return &x;
391 }
392 
393 template <typename T>
395 {
396  return begin() + 1;
397 }
398 
399 template <typename T>
401 {
402  return begin() + 1;
403 }
404 
405 template <typename T>
407 {
408  return &x;
409 }
410 
411 template <typename T>
413 {
414  return &x;
415 }
416 
417 template <typename T>
419 {
420  assert(i < 1);
421 
422  return (&x)[i];
423 }
424 
425 template <typename T>
427  size_t i) const
428 {
429  assert(i < 1);
430 
431  return (&x)[i];
432 }
433 
434 template <typename T>
436 {
437  return Matrix<T, 1, 1>{ 1 };
438 }
439 
440 template <typename T>
442 {
443  return MakeUnitX();
444 }
445 
446 template <typename T>
447 template <size_t R, size_t C, typename E>
449 {
450  assert(expression.GetRows() == 2 && expression.GetCols() == 1);
451 
452  x = expression.Eval(0, 0);
453  y = expression.Eval(1, 0);
454 }
455 
456 template <typename T>
457 Matrix<T, 2, 1>::Matrix(const std::initializer_list<T>& lst)
458 {
459  assert(lst.size() > 1);
460 
461  auto iter = lst.begin();
462  x = *(iter++);
463  y = *(iter);
464 }
465 
466 template <typename T>
467 void Matrix<T, 2, 1>::Fill(const T& val)
468 {
469  x = y = val;
470 }
471 
472 template <typename T>
473 void Matrix<T, 2, 1>::Fill(const std::function<T(size_t i)>& func)
474 {
475  x = func(0);
476  y = func(1);
477 }
478 
479 template <typename T>
480 void Matrix<T, 2, 1>::Fill(const std::function<T(size_t i, size_t j)>& func)
481 {
482  x = func(0, 0);
483  y = func(1, 0);
484 }
485 
486 template <typename T>
488 {
489  std::swap(x, other.x);
490  std::swap(y, other.y);
491 }
492 
493 template <typename T>
494 constexpr size_t Matrix<T, 2, 1>::GetRows() const
495 {
496  return 2;
497 }
498 
499 template <typename T>
500 constexpr size_t Matrix<T, 2, 1>::GetCols() const
501 {
502  return 1;
503 }
504 
505 template <typename T>
507 {
508  return &x;
509 }
510 
511 template <typename T>
513 {
514  return &x;
515 }
516 
517 template <typename T>
519 {
520  return begin() + 2;
521 }
522 
523 template <typename T>
525 {
526  return begin() + 2;
527 }
528 
529 template <typename T>
531 {
532  return &x;
533 }
534 
535 template <typename T>
537 {
538  return &x;
539 }
540 
541 template <typename T>
543 {
544  assert(i < 2);
545 
546  return (&x)[i];
547 }
548 
549 template <typename T>
551  size_t i) const
552 {
553  assert(i < 2);
554 
555  return (&x)[i];
556 }
557 
558 template <typename T>
560 {
561  return Matrix<T, 2, 1>{ 1, 0 };
562 }
563 
564 template <typename T>
566 {
567  return Matrix<T, 2, 1>{ 0, 1 };
568 }
569 
570 template <typename T>
572 {
573  return Matrix<T, 2, 1>(i == 0, i == 1);
574 }
575 
576 template <typename T>
577 template <size_t R, size_t C, typename E>
579 {
580  assert(expression.GetRows() == 3 && expression.GetCols() == 1);
581 
582  x = expression.Eval(0, 0);
583  y = expression.Eval(1, 0);
584  z = expression.Eval(2, 0);
585 }
586 
587 template <typename T>
588 Matrix<T, 3, 1>::Matrix(const std::initializer_list<T>& lst)
589 {
590  assert(lst.size() > 2);
591 
592  auto iter = lst.begin();
593  x = *(iter++);
594  y = *(iter++);
595  z = *(iter);
596 }
597 
598 template <typename T>
599 void Matrix<T, 3, 1>::Fill(const T& val)
600 {
601  x = y = z = val;
602 }
603 
604 template <typename T>
605 void Matrix<T, 3, 1>::Fill(const std::function<T(size_t i)>& func)
606 {
607  x = func(0);
608  y = func(1);
609  z = func(2);
610 }
611 
612 template <typename T>
613 void Matrix<T, 3, 1>::Fill(const std::function<T(size_t i, size_t j)>& func)
614 {
615  x = func(0, 0);
616  y = func(1, 0);
617  z = func(2, 0);
618 }
619 
620 template <typename T>
622 {
623  std::swap(x, other.x);
624  std::swap(y, other.y);
625  std::swap(z, other.z);
626 }
627 
628 template <typename T>
629 constexpr size_t Matrix<T, 3, 1>::GetRows() const
630 {
631  return 3;
632 }
633 
634 template <typename T>
635 constexpr size_t Matrix<T, 3, 1>::GetCols() const
636 {
637  return 1;
638 }
639 
640 template <typename T>
642 {
643  return &x;
644 }
645 
646 template <typename T>
648 {
649  return &x;
650 }
651 
652 template <typename T>
654 {
655  return begin() + 3;
656 }
657 
658 template <typename T>
660 {
661  return begin() + 3;
662 }
663 
664 template <typename T>
666 {
667  return &x;
668 }
669 
670 template <typename T>
672 {
673  return &x;
674 }
675 
676 template <typename T>
678 {
679  assert(i < 3);
680 
681  return (&x)[i];
682 }
683 
684 template <typename T>
686  size_t i) const
687 {
688  assert(i < 3);
689 
690  return (&x)[i];
691 }
692 
693 template <typename T>
695 {
696  return Matrix<T, 3, 1>{ 1, 0, 0 };
697 }
698 
699 template <typename T>
701 {
702  return Matrix<T, 3, 1>{ 0, 1, 0 };
703 }
704 
705 template <typename T>
707 {
708  return Matrix<T, 3, 1>{ 0, 0, 1 };
709 }
710 
711 template <typename T>
713 {
714  return Matrix<T, 3, 1>(i == 0, i == 1, i == 2);
715 }
716 
717 template <typename T>
718 template <size_t R, size_t C, typename E>
720 {
721  assert(expression.GetRows() == 4 && expression.GetCols() == 1);
722 
723  x = expression.Eval(0, 0);
724  y = expression.Eval(1, 0);
725  z = expression.Eval(2, 0);
726  w = expression.Eval(3, 0);
727 }
728 
729 template <typename T>
730 Matrix<T, 4, 1>::Matrix(const std::initializer_list<T>& lst)
731 {
732  assert(lst.size() > 3);
733 
734  auto iter = lst.begin();
735  x = *(iter++);
736  y = *(iter++);
737  z = *(iter++);
738  w = *(iter);
739 }
740 
741 template <typename T>
742 void Matrix<T, 4, 1>::Fill(const T& val)
743 {
744  x = y = z = w = val;
745 }
746 
747 template <typename T>
748 void Matrix<T, 4, 1>::Fill(const std::function<T(size_t i)>& func)
749 {
750  x = func(0);
751  y = func(1);
752  z = func(2);
753  w = func(3);
754 }
755 
756 template <typename T>
757 void Matrix<T, 4, 1>::Fill(const std::function<T(size_t i, size_t j)>& func)
758 {
759  x = func(0, 0);
760  y = func(1, 0);
761  z = func(2, 0);
762  w = func(3, 0);
763 }
764 
765 template <typename T>
767 {
768  std::swap(x, other.x);
769  std::swap(y, other.y);
770  std::swap(z, other.z);
771  std::swap(w, other.w);
772 }
773 
774 template <typename T>
775 constexpr size_t Matrix<T, 4, 1>::GetRows() const
776 {
777  return 4;
778 }
779 
780 template <typename T>
781 constexpr size_t Matrix<T, 4, 1>::GetCols() const
782 {
783  return 1;
784 }
785 
786 template <typename T>
788 {
789  return &x;
790 }
791 
792 template <typename T>
794 {
795  return &x;
796 }
797 
798 template <typename T>
800 {
801  return begin() + 4;
802 }
803 
804 template <typename T>
806 {
807  return begin() + 4;
808 }
809 
810 template <typename T>
812 {
813  return &x;
814 }
815 
816 template <typename T>
818 {
819  return &x;
820 }
821 
822 template <typename T>
824 {
825  assert(i < 4);
826 
827  return (&x)[i];
828 }
829 
830 template <typename T>
832  size_t i) const
833 {
834  assert(i < 4);
835 
836  return (&x)[i];
837 }
838 
839 template <typename T>
841 {
842  return Matrix<T, 4, 1>{ 1, 0, 0, 0 };
843 }
844 
845 template <typename T>
847 {
848  return Matrix<T, 4, 1>{ 0, 1, 0, 0 };
849 }
850 
851 template <typename T>
853 {
854  return Matrix<T, 4, 1>{ 0, 0, 1, 0 };
855 }
856 
857 template <typename T>
859 {
860  return Matrix<T, 4, 1>{ 0, 0, 0, 1 };
861 }
862 
863 template <typename T>
865 {
866  return Matrix<T, 4, 1>(i == 0, i == 1, i == 2, i == 3);
867 }
868 
869 template <typename T>
871 {
872  // Do nothing
873 }
874 
875 template <typename T>
877  size_t rows, size_t cols, ConstReference value)
878 {
879  m_elements.resize(rows * cols);
880  m_rows = rows;
881  m_cols = cols;
882 
883  Fill(value);
884 }
885 
886 template <typename T>
887 template <size_t R, size_t C, typename E>
889  const MatrixExpression<T, R, C, E>& expression)
890  : Matrix(expression.GetRows(), expression.GetCols())
891 {
892  CopyFrom(expression);
893 }
894 
895 template <typename T>
898 {
899  size_t i = 0;
900 
901  for (auto rows : lst)
902  {
903  size_t j = 0;
904 
905  for (auto col : rows)
906  {
907  (void)col;
908  ++j;
909  }
910 
911  m_cols = j;
912  ++i;
913  }
914 
915  m_rows = i;
916  m_elements.resize(m_rows * m_cols);
917 
918  i = 0;
919 
920  for (auto rows : lst)
921  {
922  assert(i < m_rows);
923 
924  size_t j = 0;
925 
926  for (auto col : rows)
927  {
928  assert(j < m_cols);
929 
930  (*this)(i, j) = col;
931  ++j;
932  }
933 
934  ++i;
935  }
936 }
937 
938 template <typename T>
940  size_t cols,
941  ConstPointer ptr)
942  : Matrix(rows, cols)
943 {
944  size_t cnt = 0;
945 
946  for (size_t i = 0; i < rows; ++i)
947  {
948  for (size_t j = 0; j < cols; ++j)
949  {
950  (*this)(i, j) = ptr[cnt++];
951  }
952  }
953 }
954 
955 template <typename T>
957  : m_elements(other.m_elements), m_rows(other.m_rows), m_cols(other.m_cols)
958 {
959  // Do nothing
960 }
961 
962 template <typename T>
964  Matrix&& other) noexcept
965  : m_elements(std::move(other.m_elements)),
966  m_rows(other.m_rows),
967  m_cols(other.m_cols)
968 {
969  // Do nothing
970 }
971 
972 template <typename T>
975  const Matrix& other)
976 {
977  m_elements = other.m_elements;
978  m_rows = other.m_rows;
979  m_cols = other.m_cols;
980  return *this;
981 }
982 
983 template <typename T>
986  Matrix&& other) noexcept
987 {
988  m_elements = std::move(other.m_elements);
989  m_rows = other.m_rows;
990  m_cols = other.m_cols;
991  other.m_rows = 0;
992  other.m_cols = 0;
993  return *this;
994 }
995 
996 template <typename T>
998 {
999  std::fill(m_elements.begin(), m_elements.end(), val);
1000 }
1001 
1002 template <typename T>
1004  const std::function<T(size_t i)>& func)
1005 {
1006  for (size_t i = 0; i < m_elements.size(); ++i)
1007  {
1008  m_elements[i] = func(i);
1009  }
1010 }
1011 
1012 template <typename T>
1014  const std::function<T(size_t i, size_t j)>& func)
1015 {
1016  for (size_t i = 0; i < GetRows(); ++i)
1017  {
1018  for (size_t j = 0; j < GetCols(); ++j)
1019  {
1020  (*this)(i, j) = func(i, j);
1021  }
1022  }
1023 }
1024 
1025 template <typename T>
1027 {
1028  m_elements.swap(other.m_elements);
1029 
1030  std::swap(m_rows, other.m_rows);
1031  std::swap(m_cols, other.m_cols);
1032 }
1033 
1034 template <typename T>
1036  size_t rows, size_t cols, ConstReference val)
1037 {
1038  Matrix newMatrix{ rows, cols, val };
1039  const size_t minRows = std::min(rows, m_rows);
1040  const size_t minCols = std::min(cols, m_cols);
1041 
1042  for (size_t i = 0; i < minRows; ++i)
1043  {
1044  for (size_t j = 0; j < minCols; ++j)
1045  {
1046  newMatrix(i, j) = (*this)(i, j);
1047  }
1048  }
1049 
1050  *this = std::move(newMatrix);
1051 }
1052 
1053 template <typename T>
1055 {
1056  m_elements.clear();
1057 
1058  m_rows = 0;
1059  m_cols = 0;
1060 }
1061 
1062 template <typename T>
1064 {
1065  return m_rows;
1066 }
1067 
1068 template <typename T>
1070 {
1071  return m_cols;
1072 }
1073 
1074 template <typename T>
1077 {
1078  return &m_elements[0];
1079 }
1080 
1081 template <typename T>
1084 {
1085  return &m_elements[0];
1086 }
1087 
1088 template <typename T>
1091 {
1092  return begin() + m_rows * m_cols;
1093 }
1094 
1095 template <typename T>
1098 {
1099  return begin() + m_rows * m_cols;
1100 }
1101 
1102 template <typename T>
1105 {
1106  return &m_elements[0];
1107 }
1108 
1109 template <typename T>
1112 {
1113  return &m_elements[0];
1114 }
1115 
1116 template <typename T>
1119 {
1120  assert(i < m_rows * m_cols);
1121 
1122  return m_elements[i];
1123 }
1124 
1125 template <typename T>
1128 {
1129  assert(i < m_rows * m_cols);
1130 
1131  return m_elements[i];
1132 }
1133 
1134 template <typename T>
1136 {
1137  // Do nothing
1138 }
1139 
1140 template <typename T>
1142 {
1143  m_elements.resize(rows, value);
1144 }
1145 
1146 template <typename T>
1147 template <size_t R, size_t C, typename E>
1149  const MatrixExpression<T, R, C, E>& expression)
1150  : Matrix(expression.GetRows(), 1)
1151 {
1152  CopyFrom(expression);
1153 }
1154 
1155 template <typename T>
1156 Matrix<T, MATRIX_SIZE_DYNAMIC, 1>::Matrix(const std::initializer_list<T>& lst)
1157 {
1158  size_t sz = lst.size();
1159  m_elements.resize(sz);
1160 
1161  size_t i = 0;
1162 
1163  for (auto row : lst)
1164  {
1165  m_elements[i] = static_cast<T>(row);
1166  ++i;
1167  }
1168 }
1169 
1170 template <typename T>
1172  : Matrix(rows)
1173 {
1174  size_t cnt = 0;
1175 
1176  for (size_t i = 0; i < rows; ++i)
1177  {
1178  (*this)[i] = ptr[cnt++];
1179  }
1180 }
1181 
1182 template <typename T>
1184  : m_elements(other.m_elements)
1185 {
1186  // Do nothing
1187 }
1188 
1189 template <typename T>
1191  : m_elements(std::move(other.m_elements))
1192 {
1193  // Do nothing
1194 }
1195 
1196 template <typename T>
1198  const Matrix& other)
1199 {
1200  m_elements = other.m_elements;
1201  return *this;
1202 }
1203 
1204 template <typename T>
1206  Matrix&& other) noexcept
1207 {
1208  m_elements = std::move(other.m_elements);
1209  return *this;
1210 }
1211 
1212 template <typename T>
1214 {
1215  std::fill(m_elements.begin(), m_elements.end(), val);
1216 }
1217 
1218 template <typename T>
1220  const std::function<T(size_t i)>& func)
1221 {
1222  for (size_t i = 0; i < m_elements.size(); ++i)
1223  {
1224  m_elements[i] = func(i);
1225  }
1226 }
1227 
1228 template <typename T>
1230  const std::function<T(size_t i, size_t j)>& func)
1231 {
1232  for (size_t i = 0; i < GetRows(); ++i)
1233  {
1234  m_elements[i] = func(i, 0);
1235  }
1236 }
1237 
1238 template <typename T>
1240 {
1241  m_elements.swap(other.m_elements);
1242 }
1243 
1244 template <typename T>
1246 {
1247  m_elements.resize(rows, val);
1248 }
1249 
1250 template <typename T>
1252 {
1253  m_elements.push_back(newElem);
1254 }
1255 
1256 template <typename T>
1258 {
1259  m_elements.insert(m_elements.end(), newElems.m_elements.begin(),
1260  newElems.m_elements.end());
1261 }
1262 
1263 template <typename T>
1265 {
1266  m_elements.clear();
1267 }
1268 
1269 template <typename T>
1271 {
1272  return m_elements.size();
1273 }
1274 
1275 template <typename T>
1277 {
1278  return 1;
1279 }
1280 
1281 template <typename T>
1284 {
1285  return &m_elements[0];
1286 }
1287 
1288 template <typename T>
1291 {
1292  return &m_elements[0];
1293 }
1294 
1295 template <typename T>
1298 {
1299  return begin() + m_elements.size();
1300 }
1301 
1302 template <typename T>
1305 {
1306  return begin() + m_elements.size();
1307 }
1308 
1309 template <typename T>
1312 {
1313  return &m_elements[0];
1314 }
1315 
1316 template <typename T>
1319 {
1320  return &m_elements[0];
1321 }
1322 
1323 template <typename T>
1326 {
1327  assert(i < m_elements.size());
1328 
1329  return m_elements[i];
1330 }
1331 
1332 template <typename T>
1335 {
1336  assert(i < m_elements.size());
1337 
1338  return m_elements[i];
1339 }
1340 
1341 template <typename T, size_t R1, size_t C1, size_t R2, size_t C2, typename M2>
1343 {
1344  a = a + b;
1345 }
1346 
1347 template <typename T, size_t Rows, size_t Cols>
1348 void operator+=(Matrix<T, Rows, Cols>& a, const T& b)
1349 {
1350  a = a + b;
1351 }
1352 
1353 template <typename T, size_t R1, size_t C1, size_t R2, size_t C2, typename M2>
1355 {
1356  a = a - b;
1357 }
1358 
1359 template <typename T, size_t Rows, size_t Cols>
1360 void operator-=(Matrix<T, Rows, Cols>& a, const T& b)
1361 {
1362  a = a - b;
1363 }
1364 
1365 template <typename T, size_t R1, size_t C1, size_t R2, size_t C2, typename M2>
1367 {
1368  assert(a.GetCols() == b.GetRows());
1369 
1370  Matrix<T, R1, C2> c = a * b;
1371  a = c;
1372 }
1373 
1374 template <typename T, size_t R1, size_t C1, size_t R2, size_t C2, typename M2>
1376 {
1377  assert(a.GetRows() == b.GetRows() && a.GetCols() == b.GetCols());
1378 
1380  a, b.GetDerived()
1381  };
1382 }
1383 
1384 template <typename T, size_t Rows, size_t Cols>
1385 void operator*=(Matrix<T, Rows, Cols>& a, const T& b)
1386 {
1388  a, b
1389  };
1390 }
1391 
1392 template <typename T, size_t R1, size_t C1, size_t R2, size_t C2, typename M2>
1394 {
1396  a, b.GetDerived());
1397 }
1398 
1399 template <typename T, size_t Rows, size_t Cols>
1400 void operator/=(Matrix<T, Rows, Cols>& a, const T& b)
1401 {
1403  a, b
1404  };
1405 }
1406 
1407 template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1408 constexpr std::enable_if_t<IsMatrixSizeStatic<Rows, Cols>(), bool> operator==(
1411 {
1413  Rows * Cols - 1>::Call(a, b,
1414  std::equal_to<T>());
1415 }
1416 
1417 template <typename T, size_t R1, size_t C1, size_t R2, size_t C2, typename M1,
1418  typename M2>
1421 {
1422  if (a.GetRows() != b.GetRows() || a.GetCols() != b.GetCols())
1423  {
1424  return false;
1425  }
1426 
1427  for (size_t i = 0; i < a.GetRows(); ++i)
1428  {
1429  for (size_t j = 0; j < a.GetCols(); ++j)
1430  {
1431  if (a.Eval(i, j) != b.Eval(i, j))
1432  {
1433  return false;
1434  }
1435  }
1436  }
1437 
1438  return true;
1439 }
1440 
1441 template <typename T, size_t R1, size_t C1, size_t R2, size_t C2, typename M1,
1442  typename M2>
1445 {
1446  return !(a == b);
1447 }
1448 
1449 template <typename T, size_t Rows, size_t Cols, typename M1,
1450  typename BinaryOperation>
1451 constexpr std::enable_if_t<TraitIsMatrixSizeStatic<Rows, Cols>::value, T>
1453  BinaryOperation op)
1454 {
1456  Rows * Cols - 1>::Call(a, init, op, NoOp<T>());
1457 }
1458 
1459 template <typename T, size_t Rows, size_t Cols, typename M1>
1460 constexpr std::enable_if_t<TraitIsMatrixSizeStatic<Rows, Cols>::value, T>
1462 {
1464  Rows * Cols - 1>::Call(a, init, std::plus<T>(),
1465  NoOp<T>());
1466 }
1467 
1468 template <typename T, size_t Rows, size_t Cols, typename M1>
1469 constexpr std::enable_if_t<TraitIsMatrixSizeStatic<Rows, Cols>::value, T>
1471 {
1473  Rows * Cols - 1>::Call(a, std::plus<T>(),
1474  NoOp<T>());
1475 }
1476 
1477 template <typename T, size_t Rows, size_t Cols, typename M1,
1478  typename BinaryOperation>
1479 constexpr std::enable_if_t<TraitIsMatrixSizeDynamic<Rows, Cols>::value, T>
1481  BinaryOperation op)
1482 {
1483  return std::accumulate(a.begin(), a.end(), init, op);
1484 }
1485 
1486 template <typename T, size_t Rows, size_t Cols, typename M1>
1487 constexpr std::enable_if_t<TraitIsMatrixSizeDynamic<Rows, Cols>::value, T>
1489 {
1490  return std::accumulate(a.begin(), a.end(), init, std::plus<T>());
1491 }
1492 
1493 template <typename T, size_t Rows, size_t Cols, typename M1>
1494 constexpr std::enable_if_t<TraitIsMatrixSizeDynamic<Rows, Cols>::value, T>
1496 {
1497  return std::accumulate(a.begin(), a.end(), T{}, std::plus<T>());
1498 }
1499 
1500 // Product
1501 
1502 template <typename T, size_t Rows, size_t Cols, typename M1>
1503 constexpr T Product(const MatrixExpression<T, Rows, Cols, M1>& a, const T& init)
1504 {
1505  return Accumulate(a, init, std::multiplies<T>());
1506 }
1507 
1508 // Interpolation
1509 template <typename T, size_t Rows, size_t Cols, typename M1, typename M2,
1510  typename M3, typename M4>
1511 std::enable_if_t<IsMatrixSizeStatic<Rows, Cols>(), Matrix<T, Rows, Cols>>
1515  const MatrixExpression<T, Rows, Cols, M4>& f3, T f)
1516 {
1517  Matrix<T, Rows, Cols> result;
1518 
1519  for (size_t i = 0; i < f0.GetRows(); ++i)
1520  {
1521  for (size_t j = 0; j < f0.GetCols(); ++j)
1522  {
1523  result(i, j) = MonotonicCatmullRom(f0.Eval(i, j), f1.Eval(i, j),
1524  f2.Eval(i, j), f3.Eval(i, j), f);
1525  }
1526  }
1527 
1528  return result;
1529 }
1530 } // namespace CubbyFlow
1531 
1532 #endif
constexpr Matrix()
Definition: Matrix.hpp:47
Matrix expression for element-wise binary operation.
Definition: MatrixExpression.hpp:452
constexpr size_t GetCols() const
Returns the number of columns.
Definition: MatrixExpression-Impl.hpp:27
const T * ConstPointer
Definition: Matrix.hpp:622
static constexpr std::enable_if_t<(Cols==1), U > Call(const Matrix< T, Rows, 1 > &a, ReduceOperation op, UnaryOperation uop)
Definition: Matrix-Impl.hpp:114
static constexpr bool Call(const Matrix< T, Rows, Cols > &a, const Matrix< T, Rows, Cols > &b, BinaryOperation op)
Definition: Matrix-Impl.hpp:163
const double & ConstReference
Definition: Matrix.hpp:41
Definition: Matrix-Impl.hpp:148
constexpr size_t GetRows() const
Returns the number of rows.
Definition: MatrixExpression-Impl.hpp:21
static constexpr T Call(const Matrix< T, Rows, Cols > &a, const T &init, ReduceOperation op, UnaryOperation uop)
Definition: Matrix-Impl.hpp:121
T * Pointer
Definition: Matrix.hpp:42
constexpr std::enable_if_t< IsMatrixSizeStatic< Rows, Cols >), bool > operator==(const MatrixExpression< T, Rows, Cols, M1 > &a, const MatrixExpression< T, Rows, Cols, M2 > &b)
Definition: Matrix-Impl.hpp:1408
static constexpr T CallDiag(const Matrix< T, Rows, Cols > &a, const T &init, ReduceOperation op, UnaryOperation uop)
Definition: Matrix-Impl.hpp:90
void CopyFrom(const MatrixExpression< T, R, C, E > &expression)
Copies from generic expression.
Definition: MatrixDenseBase-Impl.hpp:21
static constexpr std::enable_if_t<(Cols > 1), U > Call(const Matrix< T, Rows, 1 > &a, const T &init, ReduceOperation op, UnaryOperation uop)
Definition: Matrix-Impl.hpp:105
T Eval(size_t i, size_t j) const
Returns the evaluated value for (i, j).
Definition: MatrixExpression-Impl.hpp:33
const double * ConstPointer
Definition: Matrix.hpp:43
static constexpr std::enable_if_t<(Cols==1), U > Call(const Matrix< T, Rows, 1 > &a, const T &init, ReduceOperation op, UnaryOperation uop)
Definition: Matrix-Impl.hpp:48
Definition: Matrix-Impl.hpp:24
void ElemIDiv(Matrix< T, R1, C1 > &a, const MatrixExpression< T, R2, C2, M2 > &b)
Definition: Matrix-Impl.hpp:1393
Pointer data()
Definition: Matrix-Impl.hpp:298
void Fill(const T &val)
Definition: Matrix-Impl.hpp:226
Iterator end()
Definition: Matrix-Impl.hpp:285
Definition: Matrix.hpp:420
static constexpr bool Call(const Matrix< T, Rows, Cols > &a, const Matrix< T, Rows, Cols > &b, BinaryOperation op)
Definition: Matrix-Impl.hpp:150
Definition: Matrix.hpp:27
constexpr T Product(const MatrixExpression< T, Rows, Cols, M1 > &a, const T &init)
Definition: Matrix-Impl.hpp:1503
T & Reference
Definition: Matrix.hpp:40
Matrix & operator=(const Matrix &other)
Definition: Matrix.hpp:81
const T & ConstReference
Definition: Matrix.hpp:620
void operator+=(Matrix< T, R1, C1 > &a, const MatrixExpression< T, R2, C2, M2 > &b)
Definition: Matrix-Impl.hpp:1342
Definition: pybind11Utils.hpp:20
static constexpr std::enable_if_t<(Cols==1), U > Call(const Matrix< T, Rows, 1 > &a, ReduceOperation op, UnaryOperation uop)
Definition: Matrix-Impl.hpp:60
void Fill(ArrayView< T, N > a, const Vector< size_t, N > &begin, const Vector< size_t, N > &end, const T &val)
Definition: ArrayUtils-Impl.hpp:19
No-op operator.
Definition: Functors.hpp:20
static constexpr T Call(const Matrix< T, Rows, Cols > &a, ReduceOperation op, UnaryOperation uop)
Definition: Matrix-Impl.hpp:128
Pointer Iterator
Definition: Matrix.hpp:44
Definition: Matrix.hpp:216
void operator/=(Matrix< T, Rows, Cols > &a, const T &b)
Definition: Matrix-Impl.hpp:1400
ConstPointer ConstIterator
Definition: Matrix.hpp:45
Definition: Matrix-Impl.hpp:44
Definition: Matrix.hpp:312
static constexpr auto call(const M1 &a, const M2 &b, size_t i, size_t j)
Definition: Matrix-Impl.hpp:26
constexpr size_t GetCols() const
Definition: Matrix-Impl.hpp:266
static constexpr T Call(const Matrix< T, Rows, Cols > &a, ReduceOperation op, UnaryOperation uop)
Definition: Matrix-Impl.hpp:80
Derived & GetDerived()
Returns actual implementation (the subclass).
Definition: MatrixExpression-Impl.hpp:509
void operator*=(Matrix< T, R1, C1 > &a, const MatrixExpression< T, R2, C2, M2 > &b)
Definition: Matrix-Impl.hpp:1366
Definition: Matrix.hpp:126
Base class for matrix expression.
Definition: MatrixExpression.hpp:93
static constexpr T Call(const Matrix< T, Rows, Cols > &a, const T &init, ReduceOperation op, UnaryOperation uop)
Definition: Matrix-Impl.hpp:70
static constexpr T CallDiag(const Matrix< T, Rows, Cols > &a, const T &init, ReduceOperation op, UnaryOperation uop)
Definition: Matrix-Impl.hpp:135
constexpr std::enable_if_t< TraitIsMatrixSizeStatic< Rows, Cols >::value, T > Accumulate(const MatrixExpression< T, Rows, Cols, M1 > &a, const T &init, BinaryOperation op)
Definition: Matrix-Impl.hpp:1452
bool operator!=(const MatrixExpression< T, R1, C1, M1 > &a, const MatrixExpression< T, R2, C2, M2 > &b)
Definition: Matrix-Impl.hpp:1443
void operator-=(Matrix< T, R1, C1 > &a, const MatrixExpression< T, R2, C2, M2 > &b)
Definition: Matrix-Impl.hpp:1354
Reference operator[](size_t i)
Definition: Matrix-Impl.hpp:311
typename NestedInitializerLists< T, N >::Type NestedInitializerListsT
Definition: NestedInitializerList.hpp:57
Iterator begin()
Definition: Matrix-Impl.hpp:272
std::enable_if_t< std::is_arithmetic< T >::value, T > MonotonicCatmullRom(const T &f0, const T &f1, const T &f2, const T &f3, T t)
Computes monotonic Catmull-Rom interpolation.
Definition: MathUtils-Impl.hpp:336
constexpr size_t GetRows() const
Definition: Matrix-Impl.hpp:260
void Swap(Matrix &other)
Definition: Matrix-Impl.hpp:254
void ElemIMul(Matrix< T, R1, C1 > &a, const MatrixExpression< T, R2, C2, M2 > &b)
Definition: Matrix-Impl.hpp:1375
static constexpr auto call(const M1 &a, const M2 &b, size_t i, size_t j)
Definition: Matrix-Impl.hpp:35
Definition: MatrixExpression.hpp:79