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(((std::fabs(Eval(1, 0)) > 0 || std::fabs(Eval(2, 0)) > 0) ? V(1, 0, 0)
499 : V(0, 1, 0))
500 .Cross(*this)
501 .Normalized());
502 V b(this->Cross(a));
503
504 return std::make_tuple(a, b);
505}
506
507template <typename T, size_t Rows, size_t Cols, typename D>
509{
510 return static_cast<D&>(*this);
511}
512
513template <typename T, size_t Rows, size_t Cols, typename D>
515{
516 return static_cast<const D&>(*this);
517}
518
519template <typename T, size_t Rows, size_t Cols, typename D>
522{
523 return m.Eval(0, 0);
524}
525
526template <typename T, size_t Rows, size_t Cols, typename D>
529{
530 return m.Eval(0, 0) * m.Eval(1, 1) - m.Eval(1, 0) * m.Eval(0, 1);
531}
532
533template <typename T, size_t Rows, size_t Cols, typename D>
536{
537 return m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(2, 2) -
538 m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(2, 1) +
539 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(2, 0) -
540 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(2, 2) +
541 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(2, 1) -
542 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(2, 0);
543}
544
545template <typename T, size_t Rows, size_t Cols, typename D>
548{
549 return m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(2, 2) * m.Eval(3, 3) +
550 m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(2, 3) * m.Eval(3, 1) +
551 m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(2, 1) * m.Eval(3, 2) +
552 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(2, 3) * m.Eval(3, 2) +
553 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(2, 0) * m.Eval(3, 3) +
554 m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(2, 2) * m.Eval(3, 0) +
555 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(2, 1) * m.Eval(3, 3) +
556 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(2, 3) * m.Eval(3, 0) +
557 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(2, 0) * m.Eval(3, 1) +
558 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(2, 2) * m.Eval(3, 1) +
559 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(2, 0) * m.Eval(3, 2) +
560 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(2, 1) * m.Eval(3, 0) -
561 m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(2, 3) * m.Eval(3, 2) -
562 m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(2, 1) * m.Eval(3, 3) -
563 m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(2, 2) * m.Eval(3, 1) -
564 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(2, 2) * m.Eval(3, 3) -
565 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(2, 3) * m.Eval(3, 0) -
566 m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(2, 0) * m.Eval(3, 2) -
567 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(2, 3) * m.Eval(3, 1) -
568 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(2, 0) * m.Eval(3, 3) -
569 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(2, 1) * m.Eval(3, 0) -
570 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(2, 1) * m.Eval(3, 2) -
571 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(2, 2) * m.Eval(3, 0) -
572 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(2, 0) * m.Eval(3, 1);
573}
574
575template <typename T, size_t Rows, size_t Cols, typename D>
576template <typename U>
577std::enable_if_t<(Rows > 4 && Cols > 4) || IsMatrixSizeDynamic<Rows, Cols>(), U>
579{
580 // Computes inverse matrix using Gaussian elimination method.
581 // https://martin-thoma.com/solving-linear-equations-with-gaussian-elimination/
583
584 T result = 1;
585
586 for (size_t i = 0; i < m.GetRows(); ++i)
587 {
588 // Search for maximum in this column
589 T maxEl = std::fabs(a(i, i));
590 size_t maxRow = i;
591
592 for (size_t k = i + 1; k < m.GetRows(); ++k)
593 {
594 if (std::fabs(a(k, i)) > maxEl)
595 {
596 maxEl = std::fabs(a(k, i));
597 maxRow = k;
598 }
599 }
600
601 // Swap maximum row with current row (column by column)
602 if (maxRow != i)
603 {
604 for (size_t k = i; k < m.GetRows(); ++k)
605 {
606 std::swap(a(maxRow, k), a(i, k));
607 }
608 result *= -1;
609 }
610
611 // Make all rows below this one 0 in current column
612 for (size_t k = i + 1; k < m.GetRows(); ++k)
613 {
614 T c = -a(k, i) / a(i, i);
615
616 for (size_t j = i; j < m.GetRows(); ++j)
617 {
618 if (i == j)
619 {
620 a(k, j) = 0;
621 }
622 else
623 {
624 a(k, j) += c * a(i, j);
625 }
626 }
627 }
628 }
629
630 for (size_t i = 0; i < m.GetRows(); ++i)
631 {
632 result *= a(i, i);
633 }
634
635 return result;
636}
637
638template <typename T, size_t Rows, size_t Cols, typename D>
641{
642 result(0, 0) = 1 / m(0, 0);
643}
644
645template <typename T, size_t Rows, size_t Cols, typename D>
648{
649 T d = Determinant(m);
650
651 result(0, 0) = m.Eval(1, 1) / d;
652 result(0, 1) = -m.Eval(0, 1) / d;
653 result(1, 0) = -m.Eval(1, 0) / d;
654 result(1, 1) = m.Eval(0, 0) / d;
655}
656
657template <typename T, size_t Rows, size_t Cols, typename D>
660{
661 T d = Determinant(m);
662
663 result(0, 0) =
664 (m.Eval(1, 1) * m.Eval(2, 2) - m.Eval(1, 2) * m.Eval(2, 1)) / d;
665 result(0, 1) =
666 (m.Eval(0, 2) * m.Eval(2, 1) - m.Eval(0, 1) * m.Eval(2, 2)) / d;
667 result(0, 2) =
668 (m.Eval(0, 1) * m.Eval(1, 2) - m.Eval(0, 2) * m.Eval(1, 1)) / d;
669 result(1, 0) =
670 (m.Eval(1, 2) * m.Eval(2, 0) - m.Eval(1, 0) * m.Eval(2, 2)) / d;
671 result(1, 1) =
672 (m.Eval(0, 0) * m.Eval(2, 2) - m.Eval(0, 2) * m.Eval(2, 0)) / d;
673 result(1, 2) =
674 (m.Eval(0, 2) * m.Eval(1, 0) - m.Eval(0, 0) * m.Eval(1, 2)) / d;
675 result(2, 0) =
676 (m.Eval(1, 0) * m.Eval(2, 1) - m.Eval(1, 1) * m.Eval(2, 0)) / d;
677 result(2, 1) =
678 (m.Eval(0, 1) * m.Eval(2, 0) - m.Eval(0, 0) * m.Eval(2, 1)) / d;
679 result(2, 2) =
680 (m.Eval(0, 0) * m.Eval(1, 1) - m.Eval(0, 1) * m.Eval(1, 0)) / d;
681}
682
683template <typename T, size_t Rows, size_t Cols, typename D>
686{
687 T d = Determinant(m);
688
689 result(0, 0) = (m.Eval(1, 1) * m.Eval(2, 2) * m.Eval(3, 3) +
690 m.Eval(1, 2) * m.Eval(2, 3) * m.Eval(3, 1) +
691 m.Eval(1, 3) * m.Eval(2, 1) * m.Eval(3, 2) -
692 m.Eval(1, 1) * m.Eval(2, 3) * m.Eval(3, 2) -
693 m.Eval(1, 2) * m.Eval(2, 1) * m.Eval(3, 3) -
694 m.Eval(1, 3) * m.Eval(2, 2) * m.Eval(3, 1)) /
695 d;
696 result(0, 1) = (m.Eval(0, 1) * m.Eval(2, 3) * m.Eval(3, 2) +
697 m.Eval(0, 2) * m.Eval(2, 1) * m.Eval(3, 3) +
698 m.Eval(0, 3) * m.Eval(2, 2) * m.Eval(3, 1) -
699 m.Eval(0, 1) * m.Eval(2, 2) * m.Eval(3, 3) -
700 m.Eval(0, 2) * m.Eval(2, 3) * m.Eval(3, 1) -
701 m.Eval(0, 3) * m.Eval(2, 1) * m.Eval(3, 2)) /
702 d;
703 result(0, 2) = (m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(3, 3) +
704 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(3, 1) +
705 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(3, 2) -
706 m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(3, 2) -
707 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(3, 3) -
708 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(3, 1)) /
709 d;
710 result(0, 3) = (m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(2, 2) +
711 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(2, 3) +
712 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(2, 1) -
713 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(2, 3) -
714 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(2, 1) -
715 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(2, 2)) /
716 d;
717 result(1, 0) = (m.Eval(1, 0) * m.Eval(2, 3) * m.Eval(3, 2) +
718 m.Eval(1, 2) * m.Eval(2, 0) * m.Eval(3, 3) +
719 m.Eval(1, 3) * m.Eval(2, 2) * m.Eval(3, 0) -
720 m.Eval(1, 0) * m.Eval(2, 2) * m.Eval(3, 3) -
721 m.Eval(1, 2) * m.Eval(2, 3) * m.Eval(3, 0) -
722 m.Eval(1, 3) * m.Eval(2, 0) * m.Eval(3, 2)) /
723 d;
724 result(1, 1) = (m.Eval(0, 0) * m.Eval(2, 2) * m.Eval(3, 3) +
725 m.Eval(0, 2) * m.Eval(2, 3) * m.Eval(3, 0) +
726 m.Eval(0, 3) * m.Eval(2, 0) * m.Eval(3, 2) -
727 m.Eval(0, 0) * m.Eval(2, 3) * m.Eval(3, 2) -
728 m.Eval(0, 2) * m.Eval(2, 0) * m.Eval(3, 3) -
729 m.Eval(0, 3) * m.Eval(2, 2) * m.Eval(3, 0)) /
730 d;
731 result(1, 2) = (m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(3, 2) +
732 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(3, 3) +
733 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(3, 0) -
734 m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(3, 3) -
735 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(3, 0) -
736 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(3, 2)) /
737 d;
738 result(1, 3) = (m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(2, 3) +
739 m.Eval(0, 2) * m.Eval(1, 3) * m.Eval(2, 0) +
740 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(2, 2) -
741 m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(2, 2) -
742 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(2, 3) -
743 m.Eval(0, 3) * m.Eval(1, 2) * m.Eval(2, 0)) /
744 d;
745 result(2, 0) = (m.Eval(1, 0) * m.Eval(2, 1) * m.Eval(3, 3) +
746 m.Eval(1, 1) * m.Eval(2, 3) * m.Eval(3, 0) +
747 m.Eval(1, 3) * m.Eval(2, 0) * m.Eval(3, 1) -
748 m.Eval(1, 0) * m.Eval(2, 3) * m.Eval(3, 1) -
749 m.Eval(1, 1) * m.Eval(2, 0) * m.Eval(3, 3) -
750 m.Eval(1, 3) * m.Eval(2, 1) * m.Eval(3, 0)) /
751 d;
752 result(2, 1) = (m.Eval(0, 0) * m.Eval(2, 3) * m.Eval(3, 1) +
753 m.Eval(0, 1) * m.Eval(2, 0) * m.Eval(3, 3) +
754 m.Eval(0, 3) * m.Eval(2, 1) * m.Eval(3, 0) -
755 m.Eval(0, 0) * m.Eval(2, 1) * m.Eval(3, 3) -
756 m.Eval(0, 1) * m.Eval(2, 3) * m.Eval(3, 0) -
757 m.Eval(0, 3) * m.Eval(2, 0) * m.Eval(3, 1)) /
758 d;
759 result(2, 2) = (m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(3, 3) +
760 m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(3, 0) +
761 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(3, 1) -
762 m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(3, 1) -
763 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(3, 3) -
764 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(3, 0)) /
765 d;
766 result(2, 3) = (m.Eval(0, 0) * m.Eval(1, 3) * m.Eval(2, 1) +
767 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(2, 3) +
768 m.Eval(0, 3) * m.Eval(1, 1) * m.Eval(2, 0) -
769 m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(2, 3) -
770 m.Eval(0, 1) * m.Eval(1, 3) * m.Eval(2, 0) -
771 m.Eval(0, 3) * m.Eval(1, 0) * m.Eval(2, 1)) /
772 d;
773 result(3, 0) = (m.Eval(1, 0) * m.Eval(2, 2) * m.Eval(3, 1) +
774 m.Eval(1, 1) * m.Eval(2, 0) * m.Eval(3, 2) +
775 m.Eval(1, 2) * m.Eval(2, 1) * m.Eval(3, 0) -
776 m.Eval(1, 0) * m.Eval(2, 1) * m.Eval(3, 2) -
777 m.Eval(1, 1) * m.Eval(2, 2) * m.Eval(3, 0) -
778 m.Eval(1, 2) * m.Eval(2, 0) * m.Eval(3, 1)) /
779 d;
780 result(3, 1) = (m.Eval(0, 0) * m.Eval(2, 1) * m.Eval(3, 2) +
781 m.Eval(0, 1) * m.Eval(2, 2) * m.Eval(3, 0) +
782 m.Eval(0, 2) * m.Eval(2, 0) * m.Eval(3, 1) -
783 m.Eval(0, 0) * m.Eval(2, 2) * m.Eval(3, 1) -
784 m.Eval(0, 1) * m.Eval(2, 0) * m.Eval(3, 2) -
785 m.Eval(0, 2) * m.Eval(2, 1) * m.Eval(3, 0)) /
786 d;
787 result(3, 2) = (m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(3, 1) +
788 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(3, 2) +
789 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(3, 0) -
790 m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(3, 2) -
791 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(3, 0) -
792 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(3, 1)) /
793 d;
794 result(3, 3) = (m.Eval(0, 0) * m.Eval(1, 1) * m.Eval(2, 2) +
795 m.Eval(0, 1) * m.Eval(1, 2) * m.Eval(2, 0) +
796 m.Eval(0, 2) * m.Eval(1, 0) * m.Eval(2, 1) -
797 m.Eval(0, 0) * m.Eval(1, 2) * m.Eval(2, 1) -
798 m.Eval(0, 1) * m.Eval(1, 0) * m.Eval(2, 2) -
799 m.Eval(0, 2) * m.Eval(1, 1) * m.Eval(2, 0)) /
800 d;
801}
802
803template <typename T, size_t Rows, size_t Cols, typename Derived>
804template <typename M>
807 std::enable_if_t<
808 (Rows > 4 && Cols > 4) || IsMatrixSizeDynamic<Rows, Cols>(), M>& result)
809{
810 // Computes inverse matrix using Gaussian elimination method.
811 // https://martin-thoma.com/solving-linear-equations-with-gaussian-elimination/
813
815
817 a.GetRows(), a.GetCols(), 1 } };
818 const size_t n = m.GetRows();
819
820 for (size_t i = 0; i < n; ++i)
821 {
822 // Search for maximum in this column
823 T maxEl = std::fabs(a(i, i));
824 size_t maxRow = i;
825
826 for (size_t k = i + 1; k < n; ++k)
827 {
828 if (std::fabs(a(k, i)) > maxEl)
829 {
830 maxEl = std::fabs(a(k, i));
831 maxRow = k;
832 }
833 }
834
835 // Swap maximum row with current row (column by column)
836 if (maxRow != i)
837 {
838 for (size_t k = i; k < n; ++k)
839 {
840 std::swap(a(maxRow, k), a(i, k));
841 }
842
843 for (size_t k = 0; k < n; ++k)
844 {
845 std::swap(result(maxRow, k), result(i, k));
846 }
847 }
848
849 // Make all rows except this one 0 in current column
850 for (size_t k = 0; k < n; ++k)
851 {
852 if (k == i)
853 {
854 continue;
855 }
856
857 T c = -a(k, i) / a(i, i);
858
859 for (size_t j = 0; j < n; ++j)
860 {
861 result(k, j) += c * result(i, j);
862
863 if (i == j)
864 {
865 a(k, j) = 0;
866 }
867 else if (i < j)
868 {
869 a(k, j) += c * a(i, j);
870 }
871 }
872 }
873
874 // Scale
875 for (size_t k = 0; k < n; ++k)
876 {
877 T c = 1 / a(k, k);
878
879 for (size_t j = 0; j < n; ++j)
880 {
881 a(k, j) *= c;
882 result(k, j) *= c;
883 }
884 }
885 }
886}
887
888template <typename T, size_t Rows, size_t Cols>
890{
891 return m_rows;
892}
893
894template <typename T, size_t Rows, size_t Cols>
896{
897 return m_cols;
898}
899
900template <typename T, size_t Rows, size_t Cols>
901constexpr T MatrixConstant<T, Rows, Cols>::operator()(size_t, size_t) const
902{
903 return m_val;
904}
905
906template <typename T, size_t Rows, size_t Cols, typename M1>
908{
909 return m_mat1.GetRows();
910}
911
912template <typename T, size_t Rows, size_t Cols, typename M1>
914{
915 return m_mat1.GetCols();
916}
917
918template <typename T, size_t Rows, size_t Cols, typename M1>
920{
921 if (i == j)
922 {
923 return m_mat1(i, j);
924 }
925
926 return T{};
927}
928
929template <typename T, size_t Rows, size_t Cols, typename M1>
931{
932 return m_mat1.GetRows();
933}
934
935template <typename T, size_t Rows, size_t Cols, typename M1>
937{
938 return m_mat1.GetCols();
939}
940
941template <typename T, size_t Rows, size_t Cols, typename M1>
943{
944 if (i != j)
945 {
946 return m_mat1(i, j);
947 }
948
949 return T{};
950}
951
952template <typename T, size_t Rows, size_t Cols, typename M1>
954{
955 return m_mat1.GetRows();
956}
957
958template <typename T, size_t Rows, size_t Cols, typename M1>
960{
961 return m_mat1.GetCols();
962}
963
964template <typename T, size_t Rows, size_t Cols, typename M1>
966{
967 if (m_isUpper)
968 {
969 if (m_isStrict)
970 {
971 return (j > i) ? m_mat1(i, j) : 0;
972 }
973
974 return (j >= i) ? m_mat1(i, j) : 0;
975 }
976
977 if (m_isStrict)
978 {
979 return (j < i) ? m_mat1(i, j) : 0;
980 }
981
982 return (j <= i) ? m_mat1(i, j) : 0;
983}
984
985template <typename T, size_t Rows, size_t Cols, typename M1>
987{
988 return m_mat1.GetCols();
989}
990
991template <typename T, size_t Rows, size_t Cols, typename M1>
993{
994 return m_mat1.GetRows();
995}
996
997template <typename T, size_t Rows, size_t Cols, typename M1>
999 size_t j) const
1000{
1001 return m_mat1(j, i);
1002}
1003
1004template <typename T, size_t Rows, size_t Cols, typename M1, typename UOp>
1006{
1007 return m_mat1.GetRows();
1008}
1009
1010template <typename T, size_t Rows, size_t Cols, typename M1, typename UOp>
1012{
1013 return m_mat1.GetCols();
1014}
1015
1016template <typename T, size_t Rows, size_t Cols, typename M1, typename UOp>
1018 size_t j) const
1019{
1020 return m_op(m_mat1(i, j));
1021}
1022
1023template <typename T, size_t Rows, size_t Cols, typename M1>
1028
1029template <typename T, size_t Rows, size_t Cols, typename M1>
1034
1035template <typename T, size_t Rows, size_t Cols, typename M1>
1040
1041template <typename T, size_t Rows, size_t Cols, typename E1, typename E2,
1042 typename BOp>
1044 const
1045{
1046 return m_mat1.GetRows();
1047}
1048
1049template <typename T, size_t Rows, size_t Cols, typename E1, typename E2,
1050 typename BOp>
1052 const
1053{
1054 return m_mat1.GetCols();
1055}
1056
1057template <typename T, size_t Rows, size_t Cols, typename E1, typename E2,
1058 typename BOp>
1060 size_t i, size_t j) const
1061{
1062 return m_op(m_mat1(i, j), m_mat2(i, j));
1063}
1064
1065template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1073
1074template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1082
1083template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1091
1092template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1100
1101template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1109
1110template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1118
1119template <typename T, size_t Rows, size_t Cols, typename M1, typename BOp>
1121 const
1122{
1123 return m_mat1.GetRows();
1124}
1125
1126template <typename T, size_t Rows, size_t Cols, typename M1, typename BOp>
1128 const
1129{
1130 return m_mat1.GetCols();
1131}
1132
1133template <typename T, size_t Rows, size_t Cols, typename M1, typename BOp>
1135 size_t i, size_t j) const
1136{
1137 return m_op(m_mat1(i, j), m_scalar2);
1138}
1139
1140template <typename T, size_t Rows, size_t Cols, typename M1>
1142 const T& b)
1143{
1145 b };
1146}
1147
1148template <typename T, size_t Rows, size_t Cols, typename M1>
1150 const T& b)
1151{
1153 b };
1154}
1155
1156template <typename T, size_t Rows, size_t Cols, typename M1>
1158 const T& b)
1159{
1161 b };
1162}
1163
1164template <typename T, size_t Rows, size_t Cols, typename M1>
1166 const T& b)
1167{
1169 b };
1170}
1171
1172template <typename T, size_t Rows, size_t Cols, typename M2, typename BOp>
1174 const
1175{
1176 return m_mat2.GetRows();
1177}
1178
1179template <typename T, size_t Rows, size_t Cols, typename M2, typename BOp>
1181 const
1182{
1183 return m_mat2.GetCols();
1184}
1185
1186template <typename T, size_t Rows, size_t Cols, typename M2, typename BOp>
1188 size_t i, size_t j) const
1189{
1190 return m_op(m_scalar1, m_mat2(i, j));
1191}
1192
1193template <typename T, size_t Rows, size_t Cols, typename M2>
1194constexpr auto operator+(const T& a,
1196{
1198 b.GetDerived() };
1199}
1200
1201template <typename T, size_t Rows, size_t Cols, typename M2>
1202constexpr auto operator-(const T& a,
1204{
1206 b.GetDerived() };
1207}
1208
1209template <typename T, size_t Rows, size_t Cols, typename M2>
1210constexpr auto operator*(const T& a,
1212{
1214 b.GetDerived() };
1215}
1216
1217template <typename T, size_t Rows, size_t Cols, typename M2>
1218constexpr auto operator/(const T& a,
1220{
1222 b.GetDerived() };
1223}
1224
1225template <typename T, size_t Rows, size_t Cols, typename M1, typename M2,
1226 typename M3, typename TOp>
1228 const
1229{
1230 return m_mat1.GetRows();
1231}
1232
1233template <typename T, size_t Rows, size_t Cols, typename M1, typename M2,
1234 typename M3, typename TOp>
1236 const
1237{
1238 return m_mat1.GetCols();
1239}
1240
1241template <typename T, size_t Rows, size_t Cols, typename M1, typename M2,
1242 typename M3, typename TOp>
1244 size_t i, size_t j) const
1245{
1246 return m_op(m_mat1(i, j), m_mat2(i, j), m_mat3(i, j));
1247}
1248
1249template <typename T, size_t Rows, size_t Cols, typename M1, typename M2,
1250 typename M3>
1262
1263template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1265{
1266 return m_mat1.GetRows();
1267}
1268
1269template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1271{
1272 return m_mat2.GetCols();
1273}
1274
1275template <typename T, size_t Rows, size_t Cols, typename M1, typename M2>
1277{
1278 T sum = m_mat1(i, 0) * m_mat2(0, j);
1279
1280 for (size_t k = 1; k < m_mat1.GetCols(); ++k)
1281 {
1282 sum += m_mat1(i, k) * m_mat2(k, j);
1283 }
1284
1285 return sum;
1286}
1287
1288template <typename T, size_t R1, size_t C1, size_t R2, size_t C2, typename M1,
1289 typename M2>
1298} // namespace CubbyFlow
1299
1300#endif
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:889
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:895
constexpr T operator()(size_t, size_t) const
Definition MatrixExpression-Impl.hpp:901
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:907
T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:919
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:913
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1051
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:1043
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1059
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:508
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:1264
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1270
T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1276
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:936
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:930
T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:942
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1127
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1134
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:1120
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:1227
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1243
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1235
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:998
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:992
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:986
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:959
T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:965
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:953
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1011
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:1005
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1017
constexpr T operator()(size_t i, size_t j) const
Definition MatrixExpression-Impl.hpp:1187
constexpr size_t GetRows() const
Definition MatrixExpression-Impl.hpp:1173
constexpr size_t GetCols() const
Definition MatrixExpression-Impl.hpp:1180
Definition pybind11Utils.hpp:22
MatrixCSR< T > operator-(const MatrixCSR< T > &a)
Definition MatrixCSR-Impl.hpp:1029
constexpr auto Max(const MatrixExpression< T, Rows, Cols, M1 > &a, const MatrixExpression< T, Rows, Cols, M2 > &b)
Definition MatrixExpression-Impl.hpp:1111
constexpr auto Ceil(const MatrixExpression< T, Rows, Cols, M1 > &a)
Definition MatrixExpression-Impl.hpp:1024
constexpr auto Min(const MatrixExpression< T, Rows, Cols, M1 > &a, const MatrixExpression< T, Rows, Cols, M2 > &b)
Definition MatrixExpression-Impl.hpp:1102
constexpr auto ElemMul(const MatrixExpression< T, Rows, Cols, M1 > &a, const MatrixExpression< T, Rows, Cols, M2 > &b)
Definition MatrixExpression-Impl.hpp:1084
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:1030
Matrix< T, Rows, 1 > Vector
Definition Matrix.hpp:719
MatrixCSR< T > operator+(const MatrixCSR< T > &a, const MatrixCSR< T > &b)
Definition MatrixCSR-Impl.hpp:1035
constexpr auto ElemDiv(const MatrixExpression< T, Rows, Cols, M1 > &a, const MatrixExpression< T, Rows, Cols, M2 > &b)
Definition MatrixExpression-Impl.hpp:1093
MatrixCSR< T > operator/(const MatrixCSR< T > &a, T b)
Definition MatrixCSR-Impl.hpp:1090
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