Loading...
Searching...
No Matches
MatrixExpression-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_EXPRESSION_IMPL_HPP
12#define CUBBYFLOW_MATRIX_EXPRESSION_IMPL_HPP
13
15
16#include <cassert>
17
18namespace CubbyFlow
19{
20template <typename T, size_t Rows, size_t Cols, typename D>
22{
23 return static_cast<const D&>(*this).GetRows();
24}
25
26template <typename T, size_t Rows, size_t Cols, typename D>
28{
29 return static_cast<const D&>(*this).GetCols();
30}
31
32template <typename T, size_t Rows, size_t Cols, typename D>
34{
35 return GetDerived()(i, j);
36}
37
38template <typename T, size_t Rows, size_t Cols, typename D>
43
44template <typename T, size_t Rows, size_t Cols, typename D>
45template <size_t R, size_t C, typename E>
47 const MatrixExpression<T, R, C, E>& expression, double tol) const
48{
50 {
51 return false;
52 }
53
55
56 for (size_t i = 0; i < GetRows(); ++i)
57 {
58 for (size_t j = 0; j < GetCols(); ++j)
59 {
60 if (!op(Eval(i, j), expression.Eval(i, j)))
61 {
62 return false;
63 }
64 }
65 }
66
67 return true;
68}
69
70template <typename T, size_t Rows, size_t Cols, typename D>
72{
73 return GetRows() == GetCols();
74}
75
76template <typename T, size_t Rows, size_t Cols, typename D>
78{
79 T s = 0;
80
81 for (size_t i = 0; i < GetRows(); ++i)
82 {
83 for (size_t j = 0; j < GetCols(); ++j)
84 {
85 s += Eval(i, j);
86 }
87 }
88
89 return s;
90}
91
92template <typename T, size_t Rows, size_t Cols, typename D>
94{
95 return Sum() / (GetRows() * GetCols());
96}
97
98template <typename T, size_t Rows, size_t Cols, typename D>
100{
101 T s = Eval(0, 0);
103 for (size_t j = 1; j < GetCols(); ++j)
104 {
105 s = std::min(s, Eval(0, j));
106 }
108 for (size_t i = 1; i < GetRows(); ++i)
109 {
110 for (size_t j = 0; j < GetCols(); ++j)
111 {
112 s = std::min(s, Eval(i, j));
113 }
114 }
115
116 return s;
118
119template <typename T, size_t Rows, size_t Cols, typename D>
122 T s = Eval(0, 0);
124 for (size_t j = 1; j < GetCols(); ++j)
126 s = std::max(s, Eval(0, j));
128
129 for (size_t i = 1; i < GetRows(); ++i)
130 {
131 for (size_t j = 0; j < GetCols(); ++j)
132 {
133 s = std::max(s, Eval(i, j));
134 }
136
137 return s;
138}
140template <typename T, size_t Rows, size_t Cols, typename D>
142{
143 T s = Eval(0, 0);
144
145 for (size_t j = 1; j < GetCols(); ++j)
146 {
148 }
149
150 for (size_t i = 1; i < GetRows(); ++i)
151 {
152 for (size_t j = 0; j < GetCols(); ++j)
153 {
154 s = CubbyFlow::AbsMin(s, Eval(i, j));
155 }
156 }
157
158 return s;
159}
160
161template <typename T, size_t Rows, size_t Cols, typename D>
163{
164 T s = Eval(0, 0);
165
166 for (size_t j = 1; j < GetCols(); ++j)
167 {
169 }
170
171 for (size_t i = 1; i < GetRows(); ++i)
173 for (size_t j = 0; j < GetCols(); ++j)
174 {
175 s = CubbyFlow::AbsMax(s, Eval(i, j));
177 }
178
179 return s;
181
182template <typename T, size_t Rows, size_t Cols, typename D>
184{
186
187 T result = Eval(0, 0);
188
189 for (size_t i = 1; i < GetRows(); ++i)
190 {
191 result += Eval(i, i);
192 }
193
194 return result;
195}
196
197template <typename T, size_t Rows, size_t Cols, typename D>
199{
200 assert(GetRows() == GetCols());
201
202 return Determinant(*this);
203}
204
205template <typename T, size_t Rows, size_t Cols, typename D>
207{
208 assert(GetCols() == 1);
209
210 size_t ret = 0;
211 T best = Eval(0, 0);
212
213 for (size_t i = 1; i < GetRows(); ++i)
214 {
215 T curr = Eval(i, 0);
216
217 if (std::fabs(curr) > std::fabs(best))
218 {
219 best = curr;
220 ret = i;
221 }
222 }
223
224 return ret;
225}
226
227template <typename T, size_t Rows, size_t Cols, typename D>
229{
230 assert(GetCols() == 1);
231
232 size_t ret = 0;
233 T best = Eval(0, 0);
234
235 for (size_t i = 1; i < GetRows(); ++i)
236 {
237 T curr = Eval(i, 0);
238
239 if (std::fabs(curr) < std::fabs(best))
240 {
241 best = curr;
242 ret = i;
243 }
244 }
245
246 return ret;
248
249template <typename T, size_t Rows, size_t Cols, typename D>
251{
252 return std::sqrt(NormSquared());
253}
254
255template <typename T, size_t Rows, size_t Cols, typename D>
257{
258 T result = 0;
259
260 for (size_t i = 0; i < GetRows(); ++i)
261 {
262 for (size_t j = 0; j < GetCols(); ++j)
263 {
264 result += Eval(i, j) * Eval(i, j);
265 }
266 }
268 return result;
269}
270
271template <typename T, size_t Rows, size_t Cols, typename D>
276
277template <typename T, size_t Rows, size_t Cols, typename D>
279{
280 assert(GetCols() == 1);
281
282 return Norm();
283}
284
285template <typename T, size_t Rows, size_t Cols, typename D>
287{
288 assert(GetCols() == 1);
289
290 return NormSquared();
291}
292
293template <typename T, size_t Rows, size_t Cols, typename D>
294template <size_t R, size_t C, typename E>
302
303template <typename T, size_t Rows, size_t Cols, typename D>
304template <size_t R, size_t C, typename E>
307{
308 assert(GetCols() == 1);
309
310 return D(GetDerived() - other.GetDerived()).NormSquared();
311}
312
313template <typename T, size_t Rows, size_t Cols, typename D>
320
321template <typename T, size_t Rows, size_t Cols, typename D>
327
328template <typename T, size_t Rows, size_t Cols, typename D>
334
335template <typename T, size_t Rows, size_t Cols, typename D>
338{
339 return MatrixTri<T, Rows, Cols, const D&>{ GetDerived(), false, true };
340}
341
342template <typename T, size_t Rows, size_t Cols, typename D>
345{
346 return MatrixTri<T, Rows, Cols, const D&>{ GetDerived(), true, true };
347}
348
349template <typename T, size_t Rows, size_t Cols, typename D>
352{
353 return MatrixTri<T, Rows, Cols, const D&>{ GetDerived(), false, false };
354}
355
356template <typename T, size_t Rows, size_t Cols, typename D>
359{
360 return MatrixTri<T, Rows, Cols, const D&>{ GetDerived(), true, false };
361}
362
363template <typename T, size_t Rows, size_t Cols, typename D>
369
370template <typename T, size_t Rows, size_t Cols, typename D>
377
378template <typename T, size_t Rows, size_t Cols, typename D>
379template <typename U>
385
386template <typename T, size_t Rows, size_t Cols, typename D>
387template <size_t R, size_t C, typename E, typename U>
388std::enable_if_t<(IsMatrixSizeDynamic<Rows, Cols>() || Cols == 1) &&
389 (IsMatrixSizeDynamic<R, C>() || C == 1),
390 U>
393{
394 assert(expression.GetRows() == GetRows() && expression.GetCols() == 1);
395
396 T sum = Eval(0, 0) * expression.Eval(0, 0);
397
398 for (size_t i = 1; i < GetRows(); ++i)
399 {
400 sum += Eval(i, 0) * expression.Eval(i, 0);
401 }
402
403 return sum;
404}
405
406template <typename T, size_t Rows, size_t Cols, typename D>
407template <size_t R, size_t C, typename E, typename U>
408std::enable_if_t<(IsMatrixSizeDynamic<Rows, Cols>() ||
409 (Rows == 2 && Cols == 1)) &&
410 (IsMatrixSizeDynamic<R, C>() || (R == 2 && C == 1)),
411 U>
414{
415 assert(GetRows() == 2 && GetCols() == 1 && expression.GetRows() == 2 &&
416 expression.GetCols() == 1);
417
418 return Eval(0, 0) * expression.Eval(1, 0) -
419 expression.Eval(0, 0) * Eval(1, 0);
420}
421
422template <typename T, size_t Rows, size_t Cols, typename D>
423template <size_t R, size_t C, typename E, typename U>
424std::enable_if_t<(IsMatrixSizeDynamic<Rows, Cols>() ||
425 (Rows == 3 && Cols == 1)) &&
426 (IsMatrixSizeDynamic<R, C>() || (R == 3 && C == 1)),
430{
431 assert(GetRows() == 3 && GetCols() == 1 && exp.GetRows() == 3 &&
432 exp.GetCols() == 1);
433
434 return Matrix<U, 3, 1>{
435 Eval(1, 0) * exp.Eval(2, 0) - exp.Eval(1, 0) * Eval(2, 0),
436 Eval(2, 0) * exp.Eval(0, 0) - exp.Eval(2, 0) * Eval(0, 0),
437 Eval(0, 0) * exp.Eval(1, 0) - exp.Eval(0, 0) * Eval(1, 0)
438 };
439}
440
441template <typename T, size_t Rows, size_t Cols, typename D>
442template <size_t R, size_t C, typename E, typename U>
443std::enable_if_t<(IsMatrixSizeDynamic<Rows, Cols>() ||
444 ((Rows == 2 || Rows == 3) && Cols == 1)) &&
446 ((R == 2 || R == 3) && C == 1)),
449 const MatrixExpression<T, R, C, E>& normal) const
450{
451 assert((GetRows() == 2 || GetRows() == 3) && GetCols() == 1 &&
452 normal.GetRows() == GetRows() && normal.GetCols() == 1);
453
454 // this - 2(this.n)n
455 return (*this) - 2 * Dot(normal) * normal;
456}
457
458template <typename T, size_t Rows, size_t Cols, typename D>
459template <size_t R, size_t C, typename E, typename U>
460std::enable_if_t<(IsMatrixSizeDynamic<Rows, Cols>() ||
461 ((Rows == 2 || Rows == 3) && Cols == 1)) &&
463 ((R == 2 || R == 3) && C == 1)),
466 const MatrixExpression<T, R, C, E>& normal) const
467{
468 assert((GetRows() == 2 || GetRows() == 3) && GetCols() == 1 &&
469 normal.GetRows() == GetRows() && normal.GetCols() == 1);
470
471 // this - this.n n
472 return (*this) - this->Dot(normal) * normal;
473}
474
475template <typename T, size_t Rows, size_t Cols, typename D>
476template <typename U>
477std::enable_if_t<(IsMatrixSizeDynamic<Rows, Cols>() ||
478 (Rows == 2 && Cols == 1)),
481{
482 assert(GetRows() == 2 && GetCols() == 1);
483
484 return Matrix<U, 2, 1>{ -Eval(1, 0), Eval(0, 0) };
485}
486
487template <typename T, size_t Rows, size_t Cols, typename D>
488template <typename U>
489std::enable_if_t<(IsMatrixSizeDynamic<Rows, Cols>() ||
490 (Rows == 3 && Cols == 1)),
491 std::tuple<Matrix<U, 3, 1>, Matrix<U, 3, 1>>>
493{
494 assert(GetRows() == 3 && GetCols() == 1);
495
496 using V = Matrix<T, 3, 1>;
497
498 V a =
499 ((std::fabs(Eval(1, 0)) > 0 || std::fabs(Eval(2, 0)) > 0) ? V(1, 0, 0)
500 : V(0, 1, 0))
501 .Cross(*this)
502 .Normalized();
503 V b = this->Cross(a);
504
505 return std::make_tuple(a, b);
506}
507
508template <typename T, size_t Rows, size_t Cols, typename D>
510{
511 return static_cast<D&>(*this);
512}
513
514template <typename T, size_t Rows, size_t Cols, typename D>
516{
517 return static_cast<const D&>(*this);
518}
519
520template <typename T, size_t Rows, size_t Cols, typename D>
523{
524 return m.Eval(0, 0);
525}
526
527template <typename T, size_t Rows, size_t Cols, typename D>
530{
531 return m.Eval(0, 0) * m.Eval(1, 1) - m.Eval(1, 0) * m.Eval(0, 1);
532}
533
534template <typename T, size_t Rows, size_t Cols, typename D>
537{
538 return m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(2, 2) -
539 m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(2, 1) +
540 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(2, 0) -
541 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(2, 2) +
542 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(2, 1) -
543 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(2, 0);
544}
545
546template <typename T, size_t Rows, size_t Cols, typename D>
549{
550 return m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(2, 2) * m.Eval(3, 3) +
551 m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(2, 3) * m.Eval(3, 1) +
552 m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(2, 1) * m.Eval(3, 2) +
553 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(2, 3) * m.Eval(3, 2) +
554 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(2, 0) * m.Eval(3, 3) +
555 m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(2, 2) * m.Eval(3, 0) +
556 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(2, 1) * m.Eval(3, 3) +
557 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(2, 3) * m.Eval(3, 0) +
558 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(2, 0) * m.Eval(3, 1) +
559 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(2, 2) * m.Eval(3, 1) +
560 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(2, 0) * m.Eval(3, 2) +
561 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(2, 1) * m.Eval(3, 0) -
562 m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(2, 3) * m.Eval(3, 2) -
563 m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(2, 1) * m.Eval(3, 3) -
564 m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(2, 2) * m.Eval(3, 1) -
565 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(2, 2) * m.Eval(3, 3) -
566 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(2, 3) * m.Eval(3, 0) -
567 m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(2, 0) * m.Eval(3, 2) -
568 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(2, 3) * m.Eval(3, 1) -
569 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(2, 0) * m.Eval(3, 3) -
570 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(2, 1) * m.Eval(3, 0) -
571 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(2, 1) * m.Eval(3, 2) -
572 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(2, 2) * m.Eval(3, 0) -
573 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(2, 0) * m.Eval(3, 1);
574}
575
576template <typename T, size_t Rows, size_t Cols, typename D>
577template <typename U>
578std::enable_if_t<(Rows > 4 && Cols > 4) || IsMatrixSizeDynamic<Rows, Cols>(), U>
580{
581 // Computes inverse matrix using Gaussian elimination method.
582 // https://martin-thoma.com/solving-linear-equations-with-gaussian-elimination/
584
585 T result = 1;
586
587 for (size_t i = 0; i < m.GetRows(); ++i)
588 {
589 // Search for maximum in this column
590 T maxEl = std::fabs(a(i, i));
591 size_t maxRow = i;
592
593 for (size_t k = i + 1; k < m.GetRows(); ++k)
594 {
595 if (std::fabs(a(k, i)) > maxEl)
596 {
597 maxEl = std::fabs(a(k, i));
598 maxRow = k;
599 }
600 }
601
602 // Swap maximum row with current row (column by column)
603 if (maxRow != i)
604 {
605 for (size_t k = i; k < m.GetRows(); ++k)
606 {
607 std::swap(a(maxRow, k), a(i, k));
608 }
609 result *= -1;
610 }
611
612 // Make all rows below this one 0 in current column
613 for (size_t k = i + 1; k < m.GetRows(); ++k)
614 {
615 T c = -a(k, i) / a(i, i);
616
617 for (size_t j = i; j < m.GetRows(); ++j)
618 {
619 if (i == j)
620 {
621 a(k, j) = 0;
622 }
623 else
624 {
625 a(k, j) += c * a(i, j);
626 }
627 }
628 }
629 }
630
631 for (size_t i = 0; i < m.GetRows(); ++i)
632 {
633 result *= a(i, i);
634 }
635
636 return result;
637}
638
639template <typename T, size_t Rows, size_t Cols, typename D>
642{
643 result(0, 0) = 1 / m(0, 0);
644}
645
646template <typename T, size_t Rows, size_t Cols, typename D>
649{
650 T d = Determinant(m);
651
652 result(0, 0) = m.Eval(1, 1) / d;
653 result(0, 1) = -m.Eval(0, 1) / d;
654 result(1, 0) = -m.Eval(1, 0) / d;
655 result(1, 1) = m.Eval(0, 0) / d;
656}
657
658template <typename T, size_t Rows, size_t Cols, typename D>
661{
662 T d = Determinant(m);
663
664 result(0, 0) =
665 (m.Eval(1, 1) * m.Eval(2, 2) - m.Eval(1, 2) * m.Eval(2, 1)) / d;
666 result(0, 1) =
667 (m.Eval(0, 2) * m.Eval(2, 1) - m.Eval(0, 1) * m.Eval(2, 2)) / d;
668 result(0, 2) =
669 (m.Eval(0, 1) * m.Eval(1, 2) - m.Eval(0, 2) * m.Eval(1, 1)) / d;
670 result(1, 0) =
671 (m.Eval(1, 2) * m.Eval(2, 0) - m.Eval(1, 0) * m.Eval(2, 2)) / d;
672 result(1, 1) =
673 (m.Eval(0, 0) * m.Eval(2, 2) - m.Eval(0, 2) * m.Eval(2, 0)) / d;
674 result(1, 2) =
675 (m.Eval(0, 2) * m.Eval(1, 0) - m.Eval(0, 0) * m.Eval(1, 2)) / d;
676 result(2, 0) =
677 (m.Eval(1, 0) * m.Eval(2, 1) - m.Eval(1, 1) * m.Eval(2, 0)) / d;
678 result(2, 1) =
679 (m.Eval(0, 1) * m.Eval(2, 0) - m.Eval(0, 0) * m.Eval(2, 1)) / d;
680 result(2, 2) =
681 (m.Eval(0, 0) * m.Eval(1, 1) - m.Eval(0, 1) * m.Eval(1, 0)) / d;
682}
683
684template <typename T, size_t Rows, size_t Cols, typename D>
687{
688 T d = Determinant(m);
689
690 result(0, 0) = (m.Eval(1, 1) * m.Eval(2, 2) * m.Eval(3, 3) +
691 m.Eval(1, 2) * m.Eval(2, 3) * m.Eval(3, 1) +
692 m.Eval(1, 3) * m.Eval(2, 1) * m.Eval(3, 2) -
693 m.Eval(1, 1) * m.Eval(2, 3) * m.Eval(3, 2) -
694 m.Eval(1, 2) * m.Eval(2, 1) * m.Eval(3, 3) -
695 m.Eval(1, 3) * m.Eval(2, 2) * m.Eval(3, 1)) /
696 d;
697 result(0, 1) = (m.Eval(0, 1) * m.Eval(2, 3) * m.Eval(3, 2) +
698 m.Eval(0, 2) * m.Eval(2, 1) * m.Eval(3, 3) +
699 m.Eval(0, 3) * m.Eval(2, 2) * m.Eval(3, 1) -
700 m.Eval(0, 1) * m.Eval(2, 2) * m.Eval(3, 3) -
701 m.Eval(0, 2) * m.Eval(2, 3) * m.Eval(3, 1) -
702 m.Eval(0, 3) * m.Eval(2, 1) * m.Eval(3, 2)) /
703 d;
704 result(0, 2) = (m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(3, 3) +
705 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(3, 1) +
706 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(3, 2) -
707 m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(3, 2) -
708 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(3, 3) -
709 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(3, 1)) /
710 d;
711 result(0, 3) = (m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(2, 2) +
712 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(2, 3) +
713 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(2, 1) -
714 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(2, 3) -
715 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(2, 1) -
716 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(2, 2)) /
717 d;
718 result(1, 0) = (m.Eval(1, 0) * m.Eval(2, 3) * m.Eval(3, 2) +
719 m.Eval(1, 2) * m.Eval(2, 0) * m.Eval(3, 3) +
720 m.Eval(1, 3) * m.Eval(2, 2) * m.Eval(3, 0) -
721 m.Eval(1, 0) * m.Eval(2, 2) * m.Eval(3, 3) -
722 m.Eval(1, 2) * m.Eval(2, 3) * m.Eval(3, 0) -
723 m.Eval(1, 3) * m.Eval(2, 0) * m.Eval(3, 2)) /
724 d;
725 result(1, 1) = (m.Eval(0, 0) * m.Eval(2, 2) * m.Eval(3, 3) +
726 m.Eval(0, 2) * m.Eval(2, 3) * m.Eval(3, 0) +
727 m.Eval(0, 3) * m.Eval(2, 0) * m.Eval(3, 2) -
728 m.Eval(0, 0) * m.Eval(2, 3) * m.Eval(3, 2) -
729 m.Eval(0, 2) * m.Eval(2, 0) * m.Eval(3, 3) -
730 m.Eval(0, 3) * m.Eval(2, 2) * m.Eval(3, 0)) /
731 d;
732 result(1, 2) = (m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(3, 2) +
733 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(3, 3) +
734 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(3, 0) -
735 m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(3, 3) -
736 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(3, 0) -
737 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(3, 2)) /
738 d;
739 result(1, 3) = (m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(2, 3) +
740 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(2, 0) +
741 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(2, 2) -
742 m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(2, 2) -
743 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(2, 3) -
744 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(2, 0)) /
745 d;
746 result(2, 0) = (m.Eval(1, 0) * m.Eval(2, 1) * m.Eval(3, 3) +
747 m.Eval(1, 1) * m.Eval(2, 3) * m.Eval(3, 0) +
748 m.Eval(1, 3) * m.Eval(2, 0) * m.Eval(3, 1) -
749 m.Eval(1, 0) * m.Eval(2, 3) * m.Eval(3, 1) -
750 m.Eval(1, 1) * m.Eval(2, 0) * m.Eval(3, 3) -
751 m.Eval(1, 3) * m.Eval(2, 1) * m.Eval(3, 0)) /
752 d;
753 result(2, 1) = (m.Eval(0, 0) * m.Eval(2, 3) * m.Eval(3, 1) +
754 m.Eval(0, 1) * m.Eval(2, 0) * m.Eval(3, 3) +
755 m.Eval(0, 3) * m.Eval(2, 1) * m.Eval(3, 0) -
756 m.Eval(0, 0) * m.Eval(2, 1) * m.Eval(3, 3) -
757 m.Eval(0, 1) * m.Eval(2, 3) * m.Eval(3, 0) -
758 m.Eval(0, 3) * m.Eval(2, 0) * m.Eval(3, 1)) /
759 d;
760 result(2, 2) = (m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(3, 3) +
761 m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(3, 0) +
762 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(3, 1) -
763 m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(3, 1) -
764 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(3, 3) -
765 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(3, 0)) /
766 d;
767 result(2, 3) = (m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(2, 1) +
768 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(2, 3) +
769 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(2, 0) -
770 m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(2, 3) -
771 m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(2, 0) -
772 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(2, 1)) /
773 d;
774 result(3, 0) = (m.Eval(1, 0) * m.Eval(2, 2) * m.Eval(3, 1) +
775 m.Eval(1, 1) * m.Eval(2, 0) * m.Eval(3, 2) +
776 m.Eval(1, 2) * m.Eval(2, 1) * m.Eval(3, 0) -
777 m.Eval(1, 0) * m.Eval(2, 1) * m.Eval(3, 2) -
778 m.Eval(1, 1) * m.Eval(2, 2) * m.Eval(3, 0) -
779 m.Eval(1, 2) * m.Eval(2, 0) * m.Eval(3, 1)) /
780 d;
781 result(3, 1) = (m.Eval(0, 0) * m.Eval(2, 1) * m.Eval(3, 2) +
782 m.Eval(0, 1) * m.Eval(2, 2) * m.Eval(3, 0) +
783 m.Eval(0, 2) * m.Eval(2, 0) * m.Eval(3, 1) -
784 m.Eval(0, 0) * m.Eval(2, 2) * m.Eval(3, 1) -
785 m.Eval(0, 1) * m.Eval(2, 0) * m.Eval(3, 2) -
786 m.Eval(0, 2) * m.Eval(2, 1) * m.Eval(3, 0)) /
787 d;
788 result(3, 2) = (m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(3, 1) +
789 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(3, 2) +
790 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(3, 0) -
791 m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(3, 2) -
792 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(3, 0) -
793 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(3, 1)) /
794 d;
795 result(3, 3) = (m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(2, 2) +
796 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(2, 0) +
797 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(2, 1) -
798 m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(2, 1) -
799 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(2, 2) -
800 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(2, 0)) /
801 d;
802}
803
804template <typename T, size_t Rows, size_t Cols, typename Derived>
805template <typename M>
808 std::enable_if_t<
809 (Rows > 4 && Cols > 4) || IsMatrixSizeDynamic<Rows, Cols>(), M>& result)
810{
811 // Computes inverse matrix using Gaussian elimination method.
812 // https://martin-thoma.com/solving-linear-equations-with-gaussian-elimination/
814
816
818 a.GetRows(), a.GetCols(), 1 } };
819 const size_t n = m.GetRows();
820
821 for (size_t i = 0; i < n; ++i)
822 {
823 // Search for maximum in this column
824 T maxEl = std::fabs(a(i, i));
825 size_t maxRow = i;
826
827 for (size_t k = i + 1; k < n; ++k)
828 {
829 if (std::fabs(a(k, i)) > maxEl)
830 {
831 maxEl = std::fabs(a(k, i));
832 maxRow = k;
833 }
834 }
835
836 // Swap maximum row with current row (column by column)
837 if (maxRow != i)
838 {
839 for (size_t k = i; k < n; ++k)
840 {
841 std::swap(a(maxRow, k), a(i, k));
842 }
843
844 for (size_t k = 0; k < n; ++k)
845 {
846 std::swap(result(maxRow, k), result(i, k));
847 }
848 }
849
850 // Make all rows except this one 0 in current column
851 for (size_t k = 0; k < n; ++k)
852 {
853 if (k == i)
854 {
855 continue;
856 }
857
858 T c = -a(k, i) / a(i, i);
859
860 for (size_t j = 0; j < n; ++j)
861 {
862 result(k, j) += c * result(i, j);
863
864 if (i == j)
865 {
866 a(k, j) = 0;
867 }
868 else if (i < j)
869 {
870 a(k, j) += c * a(i, j);
871 }
872 }
873 }
874
875 // Scale
876 for (size_t k = 0; k < n; ++k)
877 {
878 T c = 1 / a(k, k);
879
880 for (size_t j = 0; j < n; ++j)
881 {
882 a(k, j) *= c;
883 result(k, j) *= c;
884 }
885 }
886 }
887}
888
889template <typename T, size_t Rows, size_t Cols>
891{
892 return m_rows;
893}
894
895template <typename T, size_t Rows, size_t Cols>
897{
898 return m_cols;
899}
900
901template <typename T, size_t Rows, size_t Cols>
902constexpr T MatrixConstant<T, Rows, Cols>::operator()(size_t, size_t) const
903{
904 return m_val;
905}
906
907template <typename T, size_t Rows, size_t Cols, typename M1>
909{
910 return m_mat1.GetRows();
911}
912
913template <typename T, size_t Rows, size_t Cols, typename M1>
915{
916 return m_mat1.GetCols();
917}
918
919template <typename T, size_t Rows, size_t Cols, typename M1>
921{
922 if (i == j)
923 {
924 return m_mat1(i, j);
925 }
926
927 return T{};
928}
929
930template <typename T, size_t Rows, size_t Cols, typename M1>
932{
933 return m_mat1.GetRows();
934}
935
936template <typename T, size_t Rows, size_t Cols, typename M1>
938{
939 return m_mat1.GetCols();
940}
941
942template <typename T, size_t Rows, size_t Cols, typename M1>
944{
945 if (i != j)
946 {
947 return m_mat1(i, j);
948 }
949
950 return T{};
951}
952
953template <typename T, size_t Rows, size_t Cols, typename M1>
955{
956 return m_mat1.GetRows();
957}
958
959template <typename T, size_t Rows, size_t Cols, typename M1>
961{
962 return m_mat1.GetCols();
963}
964
965template <typename T, size_t Rows, size_t Cols, typename M1>
967{
968 if (m_isUpper)
969 {
970 if (m_isStrict)
971 {
972 return (j > i) ? m_mat1(i, j) : 0;
973 }
974
975 return (j >= i) ? m_mat1(i, j) : 0;
976 }
977
978 if (m_isStrict)
979 {
980 return (j < i) ? m_mat1(i, j) : 0;
981 }
982
983 return (j <= i) ? m_mat1(i, j) : 0;
984}
985
986template <typename T, size_t Rows, size_t Cols, typename M1>
988{
989 return m_mat1.GetCols();
990}
991
992template <typename T, size_t Rows, size_t Cols, typename M1>
994{
995 return m_mat1.GetRows();
996}
997
998template <typename T, size_t Rows, size_t Cols, typename M1>
1000 size_t j) const
1001{
1002 return m_mat1(j, i);
1003}
1004
1005template <typename T, size_t Rows, size_t Cols, typename M1, typename UOp>
1007{
1008 return m_mat1.GetRows();
1009}
1010
1011template <typename T, size_t Rows, size_t Cols, typename M1, typename UOp>
1013{
1014 return m_mat1.GetCols();
1015}
1016
1017template <typename T, size_t Rows, size_t Cols, typename M1, typename UOp>
1019 size_t j) const
1020{
1021 return m_op(m_mat1(i, j));
1022}
1023
1024template <typename T, size_t Rows, size_t Cols, typename M1>
1029
1030template <typename T, size_t Rows, size_t Cols, typename M1>
1035
1036template <typename T, size_t Rows, size_t Cols, typename M1>
1041
1042template <typename T, size_t Rows, size_t Cols, typename E1, typename E2,
1043 typename BOp>
1045 const
1046{
1047 return m_mat1.GetRows();
1048}
1049
1050template <typename T, size_t Rows, size_t Cols, typename E1, typename E2,
1051 typename BOp>
1053 const
1054{
1055 return m_mat1.GetCols();
1056}
1057
1058template <typename T, size_t Rows, size_t Cols, typename E1, typename E2,
1059 typename BOp>
1061 size_t i, size_t j) const
1062{
1063 return m_op(m_mat1(i, j), m_mat2(i, j));
1064}
1065
1066template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1074
1075template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1083
1084template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1092
1093template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1101
1102template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1110
1111template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1119
1120template <typename T, size_t Rows, size_t Cols, typename M1, typename BOp>
1122 const
1123{
1124 return m_mat1.GetRows();
1125}
1126
1127template <typename T, size_t Rows, size_t Cols, typename M1, typename BOp>
1129 const
1130{
1131 return m_mat1.GetCols();
1132}
1133
1134template <typename T, size_t Rows, size_t Cols, typename M1, typename BOp>
1136 size_t i, size_t j) const
1137{
1138 return m_op(m_mat1(i, j), m_scalar2);
1139}
1140
1141template <typename T, size_t Rows, size_t Cols, typename M1>
1143 const T& b)
1144{
1146 b };
1147}
1148
1149template <typename T, size_t Rows, size_t Cols, typename M1>
1151 const T& b)
1152{
1154 b };
1155}
1156
1157template <typename T, size_t Rows, size_t Cols, typename M1>
1159 const T& b)
1160{
1162 b };
1163}
1164
1165template <typename T, size_t Rows, size_t Cols, typename M1>
1167 const T& b)
1168{
1170 b };
1171}
1172
1173template <typename T, size_t Rows, size_t Cols, typename M2, typename BOp>
1175 const
1176{
1177 return m_mat2.GetRows();
1178}
1179
1180template <typename T, size_t Rows, size_t Cols, typename M2, typename BOp>
1182 const
1183{
1184 return m_mat2.GetCols();
1185}
1186
1187template <typename T, size_t Rows, size_t Cols, typename M2, typename BOp>
1189 size_t i, size_t j) const
1190{
1191 return m_op(m_scalar1, m_mat2(i, j));
1192}
1193
1194template <typename T, size_t Rows, size_t Cols, typename M2>
1195constexpr auto operator+(const T& a,
1197{
1199 b.GetDerived() };
1200}
1201
1202template <typename T, size_t Rows, size_t Cols, typename M2>
1203constexpr auto operator-(const T& a,
1205{
1207 b.GetDerived() };
1208}
1209
1210template <typename T, size_t Rows, size_t Cols, typename M2>
1211constexpr auto operator*(const T& a,
1213{
1215 b.GetDerived() };
1216}
1217
1218template <typename T, size_t Rows, size_t Cols, typename M2>
1219constexpr auto operator/(const T& a,
1221{
1223 b.GetDerived() };
1224}
1225
1226template <typename T, size_t Rows, size_t Cols, typename M1, typename M2,
1227 typename M3, typename TOp>
1229 const
1230{
1231 return m_mat1.GetRows();
1232}
1233
1234template <typename T, size_t Rows, size_t Cols, typename M1, typename M2,
1235 typename M3, typename TOp>
1237 const
1238{
1239 return m_mat1.GetCols();
1240}
1241
1242template <typename T, size_t Rows, size_t Cols, typename M1, typename M2,
1243 typename M3, typename TOp>
1245 size_t i, size_t j) const
1246{
1247 return m_op(m_mat1(i, j), m_mat2(i, j), m_mat3(i, j));
1248}
1249
1250template <typename T, size_t Rows, size_t Cols, typename M1, typename M2,
1251 typename M3>
1263
1264template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1266{
1267 return m_mat1.GetRows();
1268}
1269
1270template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1272{
1273 return m_mat2.GetCols();
1274}
1275
1276template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1278{
1279 T sum = m_mat1(i, 0) * m_mat2(0, j);
1280
1281 for (size_t k = 1; k < m_mat1.GetCols(); ++k)
1282 {
1283 sum += m_mat1(i, k) * m_mat2(k, j);
1284 }
1285
1286 return sum;
1287}
1288
1289template <typename T, size_t R1, size_t C1, size_t R2, size_t C2, typename M1,
1290 typename M2>
1299} // namespace CubbyFlow
1300
1301#endif
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:890
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:896
constexpr T operator()(size_t, size_t) const
Definition MatrixExpression-Impl.hpp:902
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:908
T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:920
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:914
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1052
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:1044
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1060
Base class for matrix expression.
Definition MatrixExpression.hpp:94
ValueType Determinant() const
Definition MatrixExpression-Impl.hpp:198
std::enable_if_t<(IsMatrixSizeDynamic< Rows, Cols >()||((Rows==2||Rows==3) &&Cols==1)) &&(IsMatrixSizeDynamic< R, C >()||((R==2||R==3) &&C==1)), Matrix< U, Rows, 1 > Projected(const MatrixExpression< T, R, C, E > &normal) const
Returns the projected vector to the surface with given surface normal.
std::enable_if_t<(IsMatrixSizeDynamic< Rows, Cols >()||(Rows==2 &&Cols==1)) &&(IsMatrixSizeDynamic< R, C >()||(R==2 &&C==1)), U > Cross(const MatrixExpression< T, R, C, E > &expression) const
Definition MatrixExpression-Impl.hpp:412
bool IsSimilar(const MatrixExpression< T, R, C, E > &m, double tol=std::numeric_limits< double >::epsilon()) const
Definition MatrixExpression-Impl.hpp:46
Matrix< T, Rows, Cols > Inverse() const
Returns inverse matrix.
Definition MatrixExpression-Impl.hpp:371
std::enable_if_t<(IsMatrixSizeDynamic< Rows, Cols >()||(Rows==3 &&Cols==1)), std::tuple< Matrix< U, 3, 1 >, Matrix< U, 3, 1 > > Tangentials() const
Returns the tangential vectors for this vector.
constexpr size_t GetRows() const
Returns the number of rows.
Definition MatrixExpression-Impl.hpp:21
ValueType AbsMin() const
Definition MatrixExpression-Impl.hpp:141
ValueType Avg() const
Definition MatrixExpression-Impl.hpp:93
ValueType Sum() const
Definition MatrixExpression-Impl.hpp:77
size_t SubdominantAxis() const
Definition MatrixExpression-Impl.hpp:228
MatrixTri< T, Rows, Cols, const Derived & > StrictLowerTri() const
Returns strictly lower triangle part of this matrix.
Definition MatrixExpression-Impl.hpp:337
ValueType Length() const
Definition MatrixExpression-Impl.hpp:278
ValueType NormSquared() const
Definition MatrixExpression-Impl.hpp:256
ValueType FrobeniusNorm() const
Definition MatrixExpression-Impl.hpp:272
constexpr size_t GetCols() const
Returns the number of columns.
Definition MatrixExpression-Impl.hpp:27
std::enable_if_t<(IsMatrixSizeDynamic< Rows, Cols >()||(Rows==2 &&Cols==1)), Matrix< U, 2, 1 > Tangential() const
Returns the tangential vector for this vector.
ValueType DistanceTo(const MatrixExpression< T, R, C, E > &other) const
Returns the distance to the other vector.
MatrixTri< T, Rows, Cols, const Derived & > UpperTri() const
Returns upper triangle part of this matrix (including the diagonal).
Definition MatrixExpression-Impl.hpp:358
MatrixDiagonal< T, Rows, Cols, const Derived & > Diagonal() const
Returns diagonal part of this matrix.
Definition MatrixExpression-Impl.hpp:323
MatrixUnaryOp< U, Rows, Cols, const Derived &, TypeCast< T, U > > CastTo() const
ValueType Min() const
Definition MatrixExpression-Impl.hpp:99
MatrixTranspose< T, Rows, Cols, const Derived & > Transposed() const
Definition MatrixExpression-Impl.hpp:365
T Eval(size_t i, size_t j) const
Returns the evaluated value for (i, j).
Definition MatrixExpression-Impl.hpp:33
ValueType LengthSquared() const
Definition MatrixExpression-Impl.hpp:286
constexpr bool IsSquare() const
Returns true if this matrix is a square matrix.
Definition MatrixExpression-Impl.hpp:71
ValueType AbsMax() const
Definition MatrixExpression-Impl.hpp:162
MatrixTri< T, Rows, Cols, const Derived & > LowerTri() const
Returns lower triangle part of this matrix (including the diagonal).
Definition MatrixExpression-Impl.hpp:351
ValueType Norm() const
Definition MatrixExpression-Impl.hpp:250
ValueType DistanceSquaredTo(const MatrixExpression< T, R, C, E > &other) const
Returns the squared distance to the other vector.
size_t DominantAxis() const
Definition MatrixExpression-Impl.hpp:206
ValueType Max() const
Definition MatrixExpression-Impl.hpp:120
Matrix< T, Rows, Cols > Eval() const
Definition MatrixExpression-Impl.hpp:39
std::enable_if_t<(IsMatrixSizeDynamic< Rows, Cols >()||((Rows==2||Rows==3) &&Cols==1)) &&(IsMatrixSizeDynamic< R, C >()||((R==2||R==3) &&C==1)), Matrix< U, Rows, 1 > Reflected(const MatrixExpression< T, R, C, E > &normal) const
Returns the reflection vector to the surface with given surface normal.
Derived & GetDerived()
Returns actual implementation (the subclass).
Definition MatrixExpression-Impl.hpp:509
MatrixScalarElemWiseBinaryOp< T, Rows, Cols, const Derived &, std::divides< T > > Normalized() const
Definition MatrixExpression-Impl.hpp:315
MatrixOffDiagonal< T, Rows, Cols, const Derived & > OffDiagonal() const
Returns off-diagonal part of this matrix.
Definition MatrixExpression-Impl.hpp:330
MatrixTri< T, Rows, Cols, const Derived & > StrictUpperTri() const
Returns strictly upper triangle part of this matrix.
Definition MatrixExpression-Impl.hpp:344
ValueType Trace() const
Definition MatrixExpression-Impl.hpp:183
Definition Matrix.hpp:30
constexpr size_t GetCols() const
Definition Matrix-Impl.hpp:266
constexpr size_t GetRows() const
Definition Matrix-Impl.hpp:260
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:1265
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1271
T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1277
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:937
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:931
T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:943
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1128
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1135
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:1121
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:1228
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1244
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1236
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:999
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:993
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:987
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:960
T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:966
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:954
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1012
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:1006
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1018
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1188
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:1174
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1181
Definition pybind11Utils.hpp:21
MatrixCSR< T > operator-(const MatrixCSR< T > &a)
Definition MatrixCSR-Impl.hpp:1031
constexpr auto Max(const MatrixExpression< T, Rows, Cols, M1 > &a, const MatrixExpression< T, Rows, Cols, M2 > &b)
Definition MatrixExpression-Impl.hpp:1112
constexpr auto Ceil(const MatrixExpression< T, Rows, Cols, M1 > &a)
Definition MatrixExpression-Impl.hpp:1025
constexpr auto Min(const MatrixExpression< T, Rows, Cols, M1 > &a, const MatrixExpression< T, Rows, Cols, M2 > &b)
Definition MatrixExpression-Impl.hpp:1103
constexpr auto ElemMul(const MatrixExpression< T, Rows, Cols, M1 > &a, const MatrixExpression< T, Rows, Cols, M2 > &b)
Definition MatrixExpression-Impl.hpp:1085
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 > Clamp(T val, T low, T high)
Returns the clamped value.
Definition MathUtils-Impl.hpp:166
constexpr auto Floor(const MatrixExpression< T, Rows, Cols, M1 > &a)
Definition MatrixExpression-Impl.hpp:1031
Matrix< T, Rows, 1 > Vector
Definition Matrix.hpp:738
MatrixCSR< T > operator+(const MatrixCSR< T > &a, const MatrixCSR< T > &b)
Definition MatrixCSR-Impl.hpp:1037
constexpr auto ElemDiv(const MatrixExpression< T, Rows, Cols, M1 > &a, const MatrixExpression< T, Rows, Cols, M2 > &b)
Definition MatrixExpression-Impl.hpp:1094
MatrixCSR< T > operator/(const MatrixCSR< T > &a, T b)
Definition MatrixCSR-Impl.hpp:1092
Vector< T, 3 > operator*(const Quaternion< T > &q, const Vector< T, 3 > &v)
Returns quaternion q * vector v.
Definition Quaternion-Impl.hpp:543
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