UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
ImplicitQRSVD.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4// HEADER_UNIT_SKIP - Bad include VectorTypes (living in GeometryCore)
5
6#include "Chaos/Matrix.h"
7#include "Chaos/Vector.h"
10
11
12namespace Chaos {
13
31 template <class T>
33 public:
34 int rowi;
35 int rowk;
36 T c;
37 T s;
38
39 inline GivensRotation() : rowi(0), rowk(0), c((T)0.), s((T)0.) {}
40
41 inline GivensRotation(int rowi_in, int rowk_in) : rowi(rowi_in), rowk(rowk_in), c(1), s(0) {}
42
43 inline GivensRotation(T a, T b, int rowi_in, int rowk_in) : rowi(rowi_in), rowk(rowk_in) {
44 Compute(a, b);
45 }
46
48
49 inline void TransposeInPlace() {
50 s = -s;
51 }
52
58 inline void Compute(const T a, const T b) {
59
60 T d = a * a + b * b;
61 c = 1;
62 s = 0;
63 if (d != 0) {
64 T t = T(1)/FMath::Sqrt(d);
65 c = a * t;
66 s = -b * t;
67 }
68 }
69
75 inline void ComputeUnconventional(const T a, const T b) {
76 T d = a * a + b * b;
77 c = 0;
78 s = 1;
79 if (d != 0) {
80 T t = T(1)/FMath::Sqrt(d);
81 s = a * t;
82 c = b * t;
83 }
84 }
88 //template <class T>
89 inline void Fill(const PMatrix<T, 2, 2>& R) const {
90 PMatrix<T, 2, 2>& A = const_cast<PMatrix<T, 2, 2>&>(R);
91 A = PMatrix<T, 2, 2>((FReal)1., (FReal)0., (FReal)0., (FReal)1.);
92 A.M[rowi*2+rowi] = c;
93 A.M[rowi * 2 + rowk] = -s;
94 A.M[rowk * 2 + rowi] = s;
95 A.M[rowk * 2 + rowk] = c;
96 }
97
105 //template <class T>
106 inline void RowRotation(PMatrix<T, 2, 2>& A) const {
107 for (int j = 0; j < 2; j++) {
108 T tau1 = A.M[j*2+rowi];
109 T tau2 = A.M[j*2+rowk];
110 A.M[j*2+rowi] = c * tau1 - s * tau2;
111 A.M[j*2+rowk] = s * tau1 + c * tau2;
112 }
113 }
114
115 //template <class T>
116 inline void RowRotation(PMatrix<T, 3, 3>& A) const {
117 for (int j = 0; j < 3; j++) {
118 T tau1 = A.M[j][rowi];
119 T tau2 = A.M[j][rowk];
120 A.M[j][rowi] = c * tau1 - s * tau2;
121 A.M[j][rowk] = s * tau1 + c * tau2;
122 }
123 }
124
132 //template <class T>
133 inline void ColumnRotation(PMatrix<T, 2, 2>& A) const {
134 for (int j = 0; j < 2; j++) {
135 T tau1 = A.M[rowi*2+j];
136 T tau2 = A.M[rowk*2+j];
137 A.M[rowi*2+j] = c * tau1 - s * tau2;
138 A.M[rowk*2+j]= s * tau1 + c * tau2;
139 }
140 }
141
142 //template <class T>
143 inline void ColumnRotation(PMatrix<T, 3, 3>& A) const {
144 for (int j = 0; j < 3; j++) {
145 T tau1 = A.M[rowi][j];
146 T tau2 = A.M[rowk][j];
147 A.M[rowi][j] = c * tau1 - s * tau2;
148 A.M[rowk][j] = s * tau1 + c * tau2;
149 }
150 }
151
155 inline void operator*=(const GivensRotation<T>& A) {
156 T new_c = c * A.c - s * A.s;
157 T new_s = s * A.c + c * A.s;
158 c = new_c;
159 s = new_s;
160 }
161
166 GivensRotation<T> r(*this);
167 r *= A;
168 return r;
169 }
170 };
171
182 template <class T>
190 GivensRotation<T> r1(H.M[0][0], H.M[0][1], 0, 1);
199 GivensRotation<T> r2(1, 2);
200 if (H.M[0][1] != (T)0.)
201 r2.Compute(H.M[0][0] * H.M[1][0] + H.M[0][1] * H.M[1][1], H.M[0][0] * H.M[2][0] + H.M[0][1] * H.M[2][1]);
202 else
203 r2.Compute(H.M[1][0], H.M[2][0]);
204
205 r1.RowRotation(H);
206
207 r2.ColumnRotation(H);
208 r2.ColumnRotation(V);
209
216 GivensRotation<T> r3(H.M[1][1], H.M[1][2], 1, 2);
217 r3.RowRotation(H);
218
219
220 r1.ColumnRotation(U);
221 r3.ColumnRotation(U);
222 }
223
234 template <class T>
236 U = PMatrix<T, 3, 3>(1, 1, 1);
237 V = PMatrix<T, 3, 3>(1, 1, 1);
238
246 GivensRotation<T> r(H.M[0][1], H.M[0][2], 1, 2);
247 r.RowRotation(H);
248 r.ColumnRotation(U);
249 ZeroChase(H, U, V);
250 }
251
262 template <class T>
264 U = PMatrix<T, 3, 3>(1, 1, 1);
265 V = PMatrix<T, 3, 3>(1, 1, 1);
266
274 GivensRotation<T> r1(H.M[1][0], H.M[2][0], 1, 2);
275 r1.ColumnRotation(H);
276 r1.ColumnRotation(V);
277
285 r1.ComputeUnconventional(H.M[2][1], H.M[2][2]);
286 r1.RowRotation(H);
287 r1.ColumnRotation(U);
288
296 GivensRotation<T> r2(H.M[0][2], H.M[1][2], 0, 1);
297 r2.ColumnRotation(H);
298 r2.ColumnRotation(V);
299
306 r2.ComputeUnconventional(H.M[1][0], H.M[1][1]);
307 r2.RowRotation(H);
308 r2.ColumnRotation(U);
309 }
310
322 template <class T>
324 PMatrix<T, 2, 2>& A_copy = const_cast<PMatrix<T, 2, 2>&>(A);
325 TVector<T, 2> x(A_copy.M[0*2+0] + A_copy.M[1*2+1], A_copy.M[0*2+1] - A_copy.M[1*2+0]);
326 T denominator = x.Size();
327 R.c = (T)1.;
328 R.s = (T)0.;
329 if (denominator != 0) {
330 /*
331 No need to use a tolerance here because x(0) and x(1) always have
332 smaller magnitude then denominator, therefore overflow never happens.
333 */
334 R.c = x[0] / denominator;
335 R.s = -x[1] / denominator;
336 }
337 S_Sym = A;
338 R.RowRotation(S_Sym);
339 }
340
352 template <class T>
358
366 template < class T>
368 const T tol = std::numeric_limits<T>::epsilon()) {
369
370 TVector<T, 2>& sigma = const_cast<TVector<T, 2>&>(Sigma);
371
372 PMatrix<T, 2, 2> S_Sym((T)0., (T)0., (T)0.);
374 T cosine, sine;
375 T x = S_Sym.M[0*2+0];
376 T y = S_Sym.M[1*2+0];
377 T z = S_Sym.M[3];
379 // S is already diagonal
380 cosine = (T)1.;
381 sine = (T)0.;
382 sigma[0] = x;
383 sigma[1] = z;
384 }
385 else {
386 T tau = (T)0.5 * (x - z);
387 T w = FMath::Sqrt(tau * tau + y * y);
388 // w > y > 0
389 T t;
390 if (tau > 0) {
391 // tau + w > w > y > 0 ==> division is safe
392 t = y / (tau + w);
393 }
394 else {
395 // tau - w < -w < -y < 0 ==> division is safe
396 t = y / (tau - w);
397 }
398 cosine = (T)1. / FMath::Sqrt(t * t + (T)1.);
399 sine = -t * cosine;
400 /*
401 V = [cosine -sine; sine cosine]
402 Sigma = V'SV. Only Compute the diagonals for efficiency.
403 Also utilize symmetry of S and don't form V yet.
404 */
405 T c2 = cosine * cosine;
406 T csy = 2 * cosine * sine * y;
407 T s2 = sine * sine;
408 sigma[0] = c2 * x - csy + s2 * z;
409 sigma[1] = s2 * x + csy + c2 * z;
410 }
411
412 // Sorting
413 // Polar already guarantees negative sign is on the small magnitude singular value.
414 if (sigma[0] < sigma[1]) {
415 Swap(sigma[0], sigma[1]);
416 V.c = -sine;
417 V.s = cosine;
418 }
419 else {
420 V.c = cosine;
421 V.s = sine;
422 }
423 U *= V;
424 }
432 template <class T>
434 const PMatrix<T, 2, 2>& A, const PMatrix<T, 2, 2>& U, const TVector<T, 2>& Sigma, const PMatrix<T, 2, 2>& V,
435 const T tol = std::numeric_limits<T>::epsilon()) {
436 //using T = ScalarType<TA>;
437 GivensRotation<T> gv(0, 1);
438 GivensRotation<T> gu(0, 1);
440
441 gu.Fill(U);
442 gv.Fill(V);
443 }
444
453 template <class T>
454 T WilkinsonShift(const T a1, const T b1, const T a2) {
455
456 T d = (T)0.5 * (a1 - a2);
457 T bs = b1 * b1;
458
459 //T mu = a2 - copysign(bs / (FGenericPlatformMath::Abs(d) + FMath::Sqrt(d * d + bs)), d);
460 T mu = a2 - (T)FMath::Sign(d) * bs / ((FGenericPlatformMath::Abs(d) + FMath::Sqrt(d * d + bs)));
461 return mu;
462 }
463
467 template <int t, class T>
469 int other = (t == 1) ? 0 : 2;
470 GivensRotation<T> u(0, 1);
471 GivensRotation<T> v(0, 1);
472 sigma[other] = B.M[other][other];
473 const PMatrix<T, 2, 2> B_sub(B.M[t][t], B.M[t][t+1], B.M[t+1][t], B.M[t+1][t+1]);
474 const TVector<T, 2> sigma_sub(sigma[t], sigma[t + 1]);
476 sigma[t] = sigma_sub[0];
477 sigma[t + 1] = sigma_sub[1];
478 B.M[t][t] = B_sub.M[0];
479 B.M[t][t + 1] = B_sub.M[1];
480 B.M[t + 1][t] = B_sub.M[2];
481 B.M[t + 1][t + 1] = B_sub.M[3];
482 u.rowi += t;
483 u.rowk += t;
484 v.rowi += t;
485 v.rowk += t;
486 u.ColumnRotation(U);
487 v.ColumnRotation(V);
488 }
489
493 template <class T>
494 inline void FlipSign(int i, PMatrix<T, 3, 3>& U, TVector<T, 3>& sigma) {
495 sigma[i] = -sigma[i];
496 U.SetColumn(i, -U.GetColumn(i));
497 }
498
499 //IMPORTANT: test this function before testing polar:
500 template <class T>
501 inline void SwapCols(PMatrix<T, 3, 3>& A, const int i1, const int i2) {
502 auto OtherCol = A.GetColumn(i1);
503 A.SetColumn(i1, A.GetColumn(i2));
504 A.SetColumn(i2, OtherCol);
505 }
506
507
511 template <class T>
513
514 // Case: sigma(0) > |sigma(1)| >= |sigma(2)|
516 if (sigma[1] < (T)0.) {
517 FlipSign(1, U, sigma);
518 FlipSign(2, U, sigma);
519 }
520 return;
521 }
522
523 // fix sign of sigma for both cases
524 if (sigma[2] < (T)0.) {
525 FlipSign(1, U, sigma);
526 FlipSign(2, U, sigma);
527 }
528
529 // swap sigma(1) and sigma(2) for both cases
530 Swap(sigma[1], sigma[2]);
531 SwapCols(U, 1, 2);
532 SwapCols(V, 1, 2);
533
534 // Case: |sigma(2)| >= sigma(0) > |simga(1)|
535 if (sigma[1] > sigma[0]) {
536 Swap(sigma[0], sigma[1]);
537 SwapCols(U, 0, 1);
538 SwapCols(V, 0, 1);
539 }
540
541 // Case: sigma(0) >= |sigma(2)| > |simga(1)|
542 else {
543 U.SetColumn(2, -U.GetColumn(2));
544 V.SetColumn(2, -V.GetColumn(2));
545
546 }
547 }
548
552 template <class T>
554
555 // Case: |sigma(0)| >= sigma(1) > |sigma(2)|
556 if (FGenericPlatformMath::Abs(sigma[0]) >= sigma[1]) {
557 if (sigma[0] < (T)0.) {
558 FlipSign(0, U, sigma);
559 FlipSign(2, U, sigma);
560 }
561 return;
562 }
563
564 // swap sigma(0) and sigma(1) for both cases
565 Swap(sigma[0], sigma[1]);
566 SwapCols(U, 0, 1);
567 SwapCols(V, 0, 1);
568
569 // Case: sigma(1) > |sigma(2)| >= |sigma(0)|
571 Swap(sigma[1], sigma[2]);
572 SwapCols(U, 1, 2);
573 SwapCols(V, 1, 2);
574 }
575
576 // Case: sigma(1) >= |sigma(0)| > |sigma(2)|
577 else {
578 U.SetColumn(1, -U.GetColumn(1));
579 V.SetColumn(1, -V.GetColumn(1));
580 }
581
582 // fix sign for both cases
583 if (sigma[1] < (T)0.) {
584 FlipSign(1, U, sigma);
585 FlipSign(2, U, sigma);
586 }
587 }
588
596 template <class T>
598 T tol = std::numeric_limits<T>::epsilon())
599 {
600 sigma[0] = T(0.);
601 sigma[1] = T(0.);
602 sigma[2] = T(0.);
603
605 U = PMatrix<T, 3, 3>(1, 1, 1);
606 V = PMatrix<T, 3, 3>(1, 1, 1);
607
608 MakeUpperBidiag(B, U, V);
609
610 int count = 0;
611 T mu = (T)0;
612 GivensRotation<T> r(0, 1);
613
614 T alpha_1 = B.M[0][0];
615 T beta_1 = B.M[1][0];
616 T alpha_2 = B.M[1][1];
617 T alpha_3 = B.M[2][2];
618 T beta_2 = B.M[2][1];
619 T gamma_1 = alpha_1 * beta_1;
620 T gamma_2 = alpha_2 * beta_2;
621 tol *= FMath::Max((T)0.5 * FMath::Sqrt(alpha_1 * alpha_1 + alpha_2 * alpha_2 + alpha_3 * alpha_3 + beta_1 * beta_1 + beta_2 * beta_2), (T)1);
622
629
631 r.ColumnRotation(B);
632
633 r.ColumnRotation(V);
634 ZeroChase(B, U, V);
635
636 alpha_1 = B.M[0][0];
637 beta_1 = B.M[1][0];
638 alpha_2 = B.M[1][1];
639 alpha_3 = B.M[2][2];
640 beta_2 = B.M[2][1];
643 count++;
644 }
656 Process<0>(B, U, sigma, V);
657 Sort0(U, sigma, V);
658 }
665 else if (FGenericPlatformMath::Abs(beta_1) <= tol) {
666 Process<1>(B, U, sigma, V);
667 Sort1(U, sigma, V);
668 }
682 GivensRotation<T> r1(1, 2);
683 r1.ComputeUnconventional(B.M[2][1], B.M[2][2]);
684 r1.RowRotation(B);
685 r1.ColumnRotation(U);
686
687 Process<0>(B, U, sigma, V);
688 Sort0(U, sigma, V);
689 }
703 GivensRotation<T> r1(1, 2);
704 r1.Compute(B.M[1][1], B.M[2][1]);
705 r1.ColumnRotation(B);
706 r1.ColumnRotation(V);
713 GivensRotation<T> r2(0, 2);
714 r2.Compute(B.M[0][0], B.M[2][0]);
715 r2.ColumnRotation(B);
716 r2.ColumnRotation(V);
717
718 Process<0>(B, U, sigma, V);
719 Sort0(U, sigma, V);
720 }
734 GivensRotation<T> r1(0, 1);
735 r1.ComputeUnconventional(B.M[1][0], B.M[1][1]);
736 r1.RowRotation(B);
737 r1.ColumnRotation(U);
738
745 GivensRotation<T> r2(0, 2);
746 r2.ComputeUnconventional(B.M[2][0], B.M[2][2]);
747 r2.RowRotation(B);
748 r2.ColumnRotation(U);
749
750 Process<1>(B, U, sigma, V);
751 Sort1(U, sigma, V);
752 }
753
754 return count;
755 }
756
768 template <class T>
773
775 R = V.GetTransposed() * U;
776 S_Sym = V.GetTransposed() * PMatrix<T, 3, 3>(sigma) * V;
777 }
778
779 // 3X3 version of dRdF
780 // indexing of diff: dRdF[9*(i*3+j)+(m*3+n)] = dR.GetAt(m, n) /dF.GetAt (i, j):
781 template <class T>
785 PMatrix<T, 3, 3> D = (S.M[0][0] + S.M[1][1] + S.M[2][2]) * PMatrix<T, 3, 3>(1, 1, 1) - S;
786 Dinv = D.Inverse();
787
788 dRdF[0 * 9 + 0] = (-R.GetAt(0, 1) * Dinv.GetAt(2, 1) * R.GetAt(0, 2) + R.GetAt(0, 1) * Dinv.GetAt(2, 2) * R.GetAt(0, 1) + R.GetAt(0, 2) * Dinv.GetAt(1, 1) * R.GetAt(0, 2) - R.GetAt(0, 2) * Dinv.GetAt(1, 2) * R.GetAt(0, 1));
789 dRdF[1 * 9 + 0] = (R.GetAt(0, 1) * Dinv.GetAt(2, 0) * R.GetAt(0, 2) - R.GetAt(0, 1) * Dinv.GetAt(2, 2) * R.GetAt(0, 0) - R.GetAt(0, 2) * Dinv.GetAt(1, 0) * R.GetAt(0, 2) + R.GetAt(0, 2) * Dinv.GetAt(1, 2) * R.GetAt(0, 0));
790 dRdF[2 * 9 + 0] = (-R.GetAt(0, 1) * Dinv.GetAt(2, 0) * R.GetAt(0, 1) + R.GetAt(0, 1) * Dinv.GetAt(2, 1) * R.GetAt(0, 0) + R.GetAt(0, 2) * Dinv.GetAt(1, 0) * R.GetAt(0, 1) - R.GetAt(0, 2) * Dinv.GetAt(1, 1) * R.GetAt(0, 0));
791 dRdF[3 * 9 + 0] = (-R.GetAt(0, 1) * Dinv.GetAt(2, 1) * R.GetAt(1, 2) + R.GetAt(0, 1) * Dinv.GetAt(2, 2) * R.GetAt(1, 1) + R.GetAt(0, 2) * Dinv.GetAt(1, 1) * R.GetAt(1, 2) - R.GetAt(0, 2) * Dinv.GetAt(1, 2) * R.GetAt(1, 1));
792 dRdF[4 * 9 + 0] = (R.GetAt(0, 1) * Dinv.GetAt(2, 0) * R.GetAt(1, 2) - R.GetAt(0, 1) * Dinv.GetAt(2, 2) * R.GetAt(1, 0) - R.GetAt(0, 2) * Dinv.GetAt(1, 0) * R.GetAt(1, 2) + R.GetAt(0, 2) * Dinv.GetAt(1, 2) * R.GetAt(1, 0));
793 dRdF[5 * 9 + 0] = (-R.GetAt(0, 1) * Dinv.GetAt(2, 0) * R.GetAt(1, 1) + R.GetAt(0, 1) *Dinv.GetAt(2, 1) * R.GetAt(1, 0) + R.GetAt(0, 2) * Dinv.GetAt(1, 0) * R.GetAt(1, 1) - R.GetAt(0, 2) * Dinv.GetAt(1, 1) * R.GetAt(1, 0));
794 dRdF[6 * 9 + 0] = (-R.GetAt(0, 1) * Dinv.GetAt(2, 1) * R.GetAt(2, 2) + R.GetAt(0, 1) * Dinv.GetAt(2, 2) * R.GetAt(2, 1) + R.GetAt(0, 2) * Dinv.GetAt(1, 1) * R.GetAt(2, 2) - R.GetAt(0, 2) * Dinv.GetAt(1, 2) * R.GetAt(2, 1));
795 dRdF[7 * 9 + 0] = (R.GetAt(0, 1) * Dinv.GetAt(2, 0) * R.GetAt(2, 2) - R.GetAt(0, 1) * Dinv.GetAt(2, 2) * R.GetAt(2, 0) - R.GetAt(0, 2) * Dinv.GetAt(1, 0) * R.GetAt(2, 2) + R.GetAt(0, 2) * Dinv.GetAt(1, 2) * R.GetAt(2, 0));
796 dRdF[8 * 9 + 0] = (-R.GetAt(0, 1) * Dinv.GetAt(2, 0) * R.GetAt(2, 1) + R.GetAt(0, 1) * Dinv.GetAt(2, 1) * R.GetAt(2, 0) + R.GetAt(0, 2) * Dinv.GetAt(1, 0) * R.GetAt(2, 1) - R.GetAt(0, 2) * Dinv.GetAt(1, 1) * R.GetAt(2, 0));
797 dRdF[0 * 9 + 1] = (R.GetAt(0, 0) * Dinv.GetAt(2, 1) * R.GetAt(0, 2) - R.GetAt(0, 0) * Dinv.GetAt(2, 2) * R.GetAt(0, 1) - R.GetAt(0, 2) * Dinv.GetAt(0, 1) * R.GetAt(0, 2) + R.GetAt(0, 2) * Dinv.GetAt(0, 2) * R.GetAt(0, 1));
798 dRdF[1 * 9 + 1] = (-R.GetAt(0, 0) * Dinv.GetAt(2, 0) * R.GetAt(0, 2) + R.GetAt(0, 0) * Dinv.GetAt(2, 2) * R.GetAt(0, 0) + R.GetAt(0, 2) * Dinv.GetAt(0, 0) * R.GetAt(0, 2) - R.GetAt(0, 2) * Dinv.GetAt(0, 2) * R.GetAt(0, 0));
799 dRdF[2 * 9 + 1] = (R.GetAt(0, 0) * Dinv.GetAt(2, 0) * R.GetAt(0, 1) - R.GetAt(0, 0) * Dinv.GetAt(2, 1) * R.GetAt(0, 0) - R.GetAt(0, 2) * Dinv.GetAt(0, 0) * R.GetAt(0, 1) + R.GetAt(0, 2) * Dinv.GetAt(0, 1) * R.GetAt(0, 0));
800 dRdF[3 * 9 + 1] = (R.GetAt(0, 0) * Dinv.GetAt(2, 1) * R.GetAt(1, 2) - R.GetAt(0, 0) * Dinv.GetAt(2, 2) * R.GetAt(1, 1) - R.GetAt(0, 2) * Dinv.GetAt(0, 1) * R.GetAt(1, 2) + R.GetAt(0, 2) * Dinv.GetAt(0, 2) * R.GetAt(1, 1));
801 dRdF[4 * 9 + 1] = (-R.GetAt(0, 0) * Dinv.GetAt(2, 0) * R.GetAt(1, 2) + R.GetAt(0, 0) * Dinv.GetAt(2, 2) * R.GetAt(1, 0) + R.GetAt(0, 2) * Dinv.GetAt(0, 0) * R.GetAt(1, 2) - R.GetAt(0, 2) * Dinv.GetAt(0, 2) * R.GetAt(1, 0));
802 dRdF[5 * 9 + 1] = (R.GetAt(0, 0) * Dinv.GetAt(2, 0) * R.GetAt(1, 1) - R.GetAt(0, 0) * Dinv.GetAt(2, 1) * R.GetAt(1, 0) - R.GetAt(0, 2) * Dinv.GetAt(0, 0) * R.GetAt(1, 1) + R.GetAt(0, 2) * Dinv.GetAt(0, 1) * R.GetAt(1, 0));
803 dRdF[6 * 9 + 1] = (R.GetAt(0, 0) * Dinv.GetAt(2, 1) * R.GetAt(2, 2) - R.GetAt(0, 0) * Dinv.GetAt(2, 2) * R.GetAt(2, 1) - R.GetAt(0, 2) * Dinv.GetAt(0, 1) * R.GetAt(2, 2) + R.GetAt(0, 2) * Dinv.GetAt(0, 2) * R.GetAt(2, 1));
804 dRdF[7 * 9 + 1] = (-R.GetAt(0, 0) * Dinv.GetAt(2, 0) * R.GetAt(2, 2) + R.GetAt(0, 0) * Dinv.GetAt(2, 2) * R.GetAt(2, 0) + R.GetAt(0, 2) * Dinv.GetAt(0, 0) * R.GetAt(2, 2) - R.GetAt(0, 2) * Dinv.GetAt(0, 2) * R.GetAt(2, 0));
805 dRdF[8 * 9 + 1] = (R.GetAt(0, 0) * Dinv.GetAt(2, 0) * R.GetAt(2, 1) - R.GetAt(0, 0) * Dinv.GetAt(2, 1) * R.GetAt(2, 0) - R.GetAt(0, 2) * Dinv.GetAt(0, 0) * R.GetAt(2, 1) + R.GetAt(0, 2) * Dinv.GetAt(0, 1) * R.GetAt(2, 0));
806 dRdF[0 * 9 + 2] = (-R.GetAt(0, 0) * Dinv.GetAt(1, 1) * R.GetAt(0, 2) + R.GetAt(0, 0) * Dinv.GetAt(1, 2) * R.GetAt(0, 1) + R.GetAt(0, 1) * Dinv.GetAt(0, 1) * R.GetAt(0, 2) - R.GetAt(0, 1) * Dinv.GetAt(0, 2) * R.GetAt(0, 1));
807 dRdF[1 * 9 + 2] = (R.GetAt(0, 0) * Dinv.GetAt(1, 0) * R.GetAt(0, 2) - R.GetAt(0, 0) * Dinv.GetAt(1, 2) * R.GetAt(0, 0) - R.GetAt(0, 1) * Dinv.GetAt(0, 0) * R.GetAt(0, 2) + R.GetAt(0, 1) * Dinv.GetAt(0, 2) * R.GetAt(0, 0));
808 dRdF[2 * 9 + 2] = (-R.GetAt(0, 0) * Dinv.GetAt(1, 0) * R.GetAt(0, 1) + R.GetAt(0, 0) * Dinv.GetAt(1, 1) * R.GetAt(0, 0) + R.GetAt(0, 1) * Dinv.GetAt(0, 0) * R.GetAt(0, 1) - R.GetAt(0, 1) * Dinv.GetAt(0, 1) * R.GetAt(0, 0));
809 dRdF[3 * 9 + 2] = (-R.GetAt(0, 0) * Dinv.GetAt(1, 1) * R.GetAt(1, 2) + R.GetAt(0, 0) * Dinv.GetAt(1, 2) * R.GetAt(1, 1) + R.GetAt(0, 1) * Dinv.GetAt(0, 1) * R.GetAt(1, 2) - R.GetAt(0, 1) * Dinv.GetAt(0, 2) * R.GetAt(1, 1));
810 dRdF[4 * 9 + 2] = (R.GetAt(0, 0) * Dinv.GetAt(1, 0) * R.GetAt(1, 2) - R.GetAt(0, 0) * Dinv.GetAt(1, 2) * R.GetAt(1, 0) - R.GetAt(0, 1) * Dinv.GetAt(0, 0) * R.GetAt(1, 2) + R.GetAt(0, 1) * Dinv.GetAt(0, 2) * R.GetAt(1, 0));
811 dRdF[5 * 9 + 2] = (-R.GetAt(0, 0) * Dinv.GetAt(1, 0) * R.GetAt(1, 1) + R.GetAt(0, 0) * Dinv.GetAt(1, 1) * R.GetAt(1, 0) + R.GetAt(0, 1) * Dinv.GetAt(0, 0) * R.GetAt(1, 1) - R.GetAt(0, 1) * Dinv.GetAt(0, 1) * R.GetAt(1, 0));
812 dRdF[6 * 9 + 2] = (-R.GetAt(0, 0) * Dinv.GetAt(1, 1) * R.GetAt(2, 2) + R.GetAt(0, 0) * Dinv.GetAt(1, 2) * R.GetAt(2, 1) + R.GetAt(0, 1) * Dinv.GetAt(0, 1) * R.GetAt(2, 2) - R.GetAt(0, 1) * Dinv.GetAt(0, 2) * R.GetAt(2, 1));
813 dRdF[7 * 9 + 2] = (R.GetAt(0, 0) * Dinv.GetAt(1, 0) * R.GetAt(2, 2) - R.GetAt(0, 0) * Dinv.GetAt(1, 2) * R.GetAt(2, 0) - R.GetAt(0, 1) * Dinv.GetAt(0, 0) * R.GetAt(2, 2) + R.GetAt(0, 1) * Dinv.GetAt(0, 2) * R.GetAt(2, 0));
814 dRdF[8 * 9 + 2] = (-R.GetAt(0, 0) * Dinv.GetAt(1, 0) * R.GetAt(2, 1) + R.GetAt(0, 0) * Dinv.GetAt(1, 1) * R.GetAt(2, 0) + R.GetAt(0, 1) * Dinv.GetAt(0, 0) * R.GetAt(2, 1) - R.GetAt(0, 1) * Dinv.GetAt(0, 1) * R.GetAt(2, 0));
815 dRdF[0 * 9 + 3] = (-R.GetAt(1, 1) * Dinv.GetAt(2, 1) * R.GetAt(0, 2) + R.GetAt(1, 1) * Dinv.GetAt(2, 2) * R.GetAt(0, 1) + R.GetAt(1, 2) * Dinv.GetAt(1, 1) * R.GetAt(0, 2) - R.GetAt(1, 2) * Dinv.GetAt(1, 2) * R.GetAt(0, 1));
816 dRdF[1 * 9 + 3] = (R.GetAt(1, 1) * Dinv.GetAt(2, 0) * R.GetAt(0, 2) - R.GetAt(1, 1) * Dinv.GetAt(2, 2) * R.GetAt(0, 0) - R.GetAt(1, 2) * Dinv.GetAt(1, 0) * R.GetAt(0, 2) + R.GetAt(1, 2) * Dinv.GetAt(1, 2) * R.GetAt(0, 0));
817 dRdF[2 * 9 + 3] = (-R.GetAt(1, 1) * Dinv.GetAt(2, 0) * R.GetAt(0, 1) + R.GetAt(1, 1) * Dinv.GetAt(2, 1) * R.GetAt(0, 0) + R.GetAt(1, 2) * Dinv.GetAt(1, 0) * R.GetAt(0, 1) - R.GetAt(1, 2) * Dinv.GetAt(1, 1) * R.GetAt(0, 0));
818 dRdF[3 * 9 + 3] = (-R.GetAt(1, 1) * Dinv.GetAt(2, 1) * R.GetAt(1, 2) + R.GetAt(1, 1) * Dinv.GetAt(2, 2) * R.GetAt(1, 1) + R.GetAt(1, 2) * Dinv.GetAt(1, 1) * R.GetAt(1, 2) - R.GetAt(1, 2) * Dinv.GetAt(1, 2) * R.GetAt(1, 1));
819 dRdF[4 * 9 + 3] = (R.GetAt(1, 1) * Dinv.GetAt(2, 0) * R.GetAt(1, 2) - R.GetAt(1, 1) * Dinv.GetAt(2, 2) * R.GetAt(1, 0) - R.GetAt(1, 2) * Dinv.GetAt(1, 0) * R.GetAt(1, 2) + R.GetAt(1, 2) * Dinv.GetAt(1, 2) * R.GetAt(1, 0));
820 dRdF[5 * 9 + 3] = (-R.GetAt(1, 1) * Dinv.GetAt(2, 0) * R.GetAt(1, 1) + R.GetAt(1, 1) * Dinv.GetAt(2, 1) * R.GetAt(1, 0) + R.GetAt(1, 2) * Dinv.GetAt(1, 0) * R.GetAt(1, 1) - R.GetAt(1, 2) * Dinv.GetAt(1, 1) * R.GetAt(1, 0));
821 dRdF[6 * 9 + 3] = (-R.GetAt(1, 1) * Dinv.GetAt(2, 1) * R.GetAt(2, 2) + R.GetAt(1, 1) * Dinv.GetAt(2, 2) * R.GetAt(2, 1) + R.GetAt(1, 2) * Dinv.GetAt(1, 1) * R.GetAt(2, 2) - R.GetAt(1, 2) * Dinv.GetAt(1, 2) * R.GetAt(2, 1));
822 dRdF[7 * 9 + 3] = (R.GetAt(1, 1) * Dinv.GetAt(2, 0) * R.GetAt(2, 2) - R.GetAt(1, 1) * Dinv.GetAt(2, 2) * R.GetAt(2, 0) - R.GetAt(1, 2) * Dinv.GetAt(1, 0) * R.GetAt(2, 2) + R.GetAt(1, 2) * Dinv.GetAt(1, 2) * R.GetAt(2, 0));
823 dRdF[8 * 9 + 3] = (-R.GetAt(1, 1) * Dinv.GetAt(2, 0) * R.GetAt(2, 1) + R.GetAt(1, 1) * Dinv.GetAt(2, 1) * R.GetAt(2, 0) + R.GetAt(1, 2) * Dinv.GetAt(1, 0) * R.GetAt(2, 1) - R.GetAt(1, 2) * Dinv.GetAt(1, 1) * R.GetAt(2, 0));
824 dRdF[0 * 9 + 4] = (R.GetAt(1, 0) * Dinv.GetAt(2, 1) * R.GetAt(0, 2) - R.GetAt(1, 0) * Dinv.GetAt(2, 2) * R.GetAt(0, 1) - R.GetAt(1, 2) * Dinv.GetAt(0, 1) * R.GetAt(0, 2) + R.GetAt(1, 2) * Dinv.GetAt(0, 2) * R.GetAt(0, 1));
825 dRdF[1 * 9 + 4] = (-R.GetAt(1, 0) * Dinv.GetAt(2, 0) * R.GetAt(0, 2) + R.GetAt(1, 0) * Dinv.GetAt(2, 2) * R.GetAt(0, 0) + R.GetAt(1, 2) * Dinv.GetAt(0, 0) * R.GetAt(0, 2) - R.GetAt(1, 2) * Dinv.GetAt(0, 2) * R.GetAt(0, 0));
826 dRdF[2 * 9 + 4] = (R.GetAt(1, 0) * Dinv.GetAt(2, 0) * R.GetAt(0, 1) - R.GetAt(1, 0) * Dinv.GetAt(2, 1) * R.GetAt(0, 0) - R.GetAt(1, 2) * Dinv.GetAt(0, 0) * R.GetAt(0, 1) + R.GetAt(1, 2) * Dinv.GetAt(0, 1) * R.GetAt(0, 0));
827 dRdF[3 * 9 + 4] = (R.GetAt(1, 0) * Dinv.GetAt(2, 1) * R.GetAt(1, 2) - R.GetAt(1, 0) * Dinv.GetAt(2, 2) * R.GetAt(1, 1) - R.GetAt(1, 2) * Dinv.GetAt(0, 1) * R.GetAt(1, 2) + R.GetAt(1, 2) * Dinv.GetAt(0, 2) * R.GetAt(1, 1));
828 dRdF[4 * 9 + 4] = (-R.GetAt(1, 0) * Dinv.GetAt(2, 0) * R.GetAt(1, 2) + R.GetAt(1, 0) * Dinv.GetAt(2, 2) * R.GetAt(1, 0) + R.GetAt(1, 2) * Dinv.GetAt(0, 0) * R.GetAt(1, 2) - R.GetAt(1, 2) * Dinv.GetAt(0, 2) * R.GetAt(1, 0));
829 dRdF[5 * 9 + 4] = (R.GetAt(1, 0) * Dinv.GetAt(2, 0) * R.GetAt(1, 1) - R.GetAt(1, 0) * Dinv.GetAt(2, 1) * R.GetAt(1, 0) - R.GetAt(1, 2) * Dinv.GetAt(0, 0) * R.GetAt(1, 1) + R.GetAt(1, 2) * Dinv.GetAt(0, 1) * R.GetAt(1, 0));
830 dRdF[6 * 9 + 4] = (R.GetAt(1, 0) * Dinv.GetAt(2, 1) * R.GetAt(2, 2) - R.GetAt(1, 0) * Dinv.GetAt(2, 2) * R.GetAt(2, 1) - R.GetAt(1, 2) * Dinv.GetAt(0, 1) * R.GetAt(2, 2) + R.GetAt(1, 2) * Dinv.GetAt(0, 2) * R.GetAt(2, 1));
831 dRdF[7 * 9 + 4] = (-R.GetAt(1, 0) * Dinv.GetAt(2, 0) * R.GetAt(2, 2) + R.GetAt(1, 0) * Dinv.GetAt(2, 2) * R.GetAt(2, 0) + R.GetAt(1, 2) * Dinv.GetAt(0, 0) * R.GetAt(2, 2) - R.GetAt(1, 2) * Dinv.GetAt(0, 2) * R.GetAt(2, 0));
832 dRdF[8 * 9 + 4] = (R.GetAt(1, 0) * Dinv.GetAt(2, 0) * R.GetAt(2, 1) - R.GetAt(1, 0) * Dinv.GetAt(2, 1) * R.GetAt(2, 0) - R.GetAt(1, 2) * Dinv.GetAt(0, 0) * R.GetAt(2, 1) + R.GetAt(1, 2) * Dinv.GetAt(0, 1) * R.GetAt(2, 0));
833 dRdF[0 * 9 + 5] = (-R.GetAt(1, 0) * Dinv.GetAt(1, 1) * R.GetAt(0, 2) + R.GetAt(1, 0) * Dinv.GetAt(1, 2) * R.GetAt(0, 1) + R.GetAt(1, 1) * Dinv.GetAt(0, 1) * R.GetAt(0, 2) - R.GetAt(1, 1) * Dinv.GetAt(0, 2) * R.GetAt(0, 1));
834 dRdF[1 * 9 + 5] = (R.GetAt(1, 0) * Dinv.GetAt(1, 0) * R.GetAt(0, 2) - R.GetAt(1, 0) * Dinv.GetAt(1, 2) * R.GetAt(0, 0) - R.GetAt(1, 1) * Dinv.GetAt(0, 0) * R.GetAt(0, 2) + R.GetAt(1, 1) * Dinv.GetAt(0, 2) * R.GetAt(0, 0));
835 dRdF[2 * 9 + 5] = (-R.GetAt(1, 0) * Dinv.GetAt(1, 0) * R.GetAt(0, 1) + R.GetAt(1, 0) * Dinv.GetAt(1, 1) * R.GetAt(0, 0) + R.GetAt(1, 1) * Dinv.GetAt(0, 0) * R.GetAt(0, 1) - R.GetAt(1, 1) * Dinv.GetAt(0, 1) * R.GetAt(0, 0));
836 dRdF[3 * 9 + 5] = (-R.GetAt(1, 0) * Dinv.GetAt(1, 1) * R.GetAt(1, 2) + R.GetAt(1, 0) * Dinv.GetAt(1, 2) * R.GetAt(1, 1) + R.GetAt(1, 1) * Dinv.GetAt(0, 1) * R.GetAt(1, 2) - R.GetAt(1, 1) * Dinv.GetAt(0, 2) * R.GetAt(1, 1));
837 dRdF[4 * 9 + 5] = (R.GetAt(1, 0) * Dinv.GetAt(1, 0) * R.GetAt(1, 2) - R.GetAt(1, 0) * Dinv.GetAt(1, 2) * R.GetAt(1, 0) - R.GetAt(1, 1) * Dinv.GetAt(0, 0) * R.GetAt(1, 2) + R.GetAt(1, 1) * Dinv.GetAt(0, 2) * R.GetAt(1, 0));
838 dRdF[5 * 9 + 5] = (-R.GetAt(1, 0) * Dinv.GetAt(1, 0) * R.GetAt(1, 1) + R.GetAt(1, 0) * Dinv.GetAt(1, 1) * R.GetAt(1, 0) + R.GetAt(1, 1) * Dinv.GetAt(0, 0) * R.GetAt(1, 1) - R.GetAt(1, 1) * Dinv.GetAt(0, 1) * R.GetAt(1, 0));
839 dRdF[6 * 9 + 5] = (-R.GetAt(1, 0) * Dinv.GetAt(1, 1) * R.GetAt(2, 2) + R.GetAt(1, 0) * Dinv.GetAt(1, 2) * R.GetAt(2, 1) + R.GetAt(1, 1) * Dinv.GetAt(0, 1) * R.GetAt(2, 2) - R.GetAt(1, 1) * Dinv.GetAt(0, 2) * R.GetAt(2, 1));
840 dRdF[7 * 9 + 5] = (R.GetAt(1, 0) * Dinv.GetAt(1, 0) * R.GetAt(2, 2) - R.GetAt(1, 0) * Dinv.GetAt(1, 2) * R.GetAt(2, 0) - R.GetAt(1, 1) * Dinv.GetAt(0, 0) * R.GetAt(2, 2) + R.GetAt(1, 1) * Dinv.GetAt(0, 2) * R.GetAt(2, 0));
841 dRdF[8 * 9 + 5] = (-R.GetAt(1, 0) * Dinv.GetAt(1, 0) * R.GetAt(2, 1) + R.GetAt(1, 0) * Dinv.GetAt(1, 1) * R.GetAt(2, 0) + R.GetAt(1, 1) * Dinv.GetAt(0, 0) * R.GetAt(2, 1) - R.GetAt(1, 1) * Dinv.GetAt(0, 1) * R.GetAt(2, 0));
842 dRdF[0 * 9 + 6] = (-R.GetAt(2, 1) * Dinv.GetAt(2, 1) * R.GetAt(0, 2) + R.GetAt(2, 1) * Dinv.GetAt(2, 2) * R.GetAt(0, 1) + R.GetAt(2, 2) * Dinv.GetAt(1, 1) * R.GetAt(0, 2) - R.GetAt(2, 2) * Dinv.GetAt(1, 2) * R.GetAt(0, 1));
843 dRdF[1 * 9 + 6] = (R.GetAt(2, 1) * Dinv.GetAt(2, 0) * R.GetAt(0, 2) - R.GetAt(2, 1) * Dinv.GetAt(2, 2) * R.GetAt(0, 0) - R.GetAt(2, 2) * Dinv.GetAt(1, 0) * R.GetAt(0, 2) + R.GetAt(2, 2) * Dinv.GetAt(1, 2) * R.GetAt(0, 0));
844 dRdF[2 * 9 + 6] = (-R.GetAt(2, 1) * Dinv.GetAt(2, 0) * R.GetAt(0, 1) + R.GetAt(2, 1) * Dinv.GetAt(2, 1) * R.GetAt(0, 0) + R.GetAt(2, 2) * Dinv.GetAt(1, 0) * R.GetAt(0, 1) - R.GetAt(2, 2) * Dinv.GetAt(1, 1) * R.GetAt(0, 0));
845 dRdF[3 * 9 + 6] = (-R.GetAt(2, 1) * Dinv.GetAt(2, 1) * R.GetAt(1, 2) + R.GetAt(2, 1) * Dinv.GetAt(2, 2) * R.GetAt(1, 1) + R.GetAt(2, 2) * Dinv.GetAt(1, 1) * R.GetAt(1, 2) - R.GetAt(2, 2) * Dinv.GetAt(1, 2) * R.GetAt(1, 1));
846 dRdF[4 * 9 + 6] = (R.GetAt(2, 1) * Dinv.GetAt(2, 0) * R.GetAt(1, 2) - R.GetAt(2, 1) * Dinv.GetAt(2, 2) * R.GetAt(1, 0) - R.GetAt(2, 2) * Dinv.GetAt(1, 0) * R.GetAt(1, 2) + R.GetAt(2, 2) * Dinv.GetAt(1, 2) * R.GetAt(1, 0));
847 dRdF[5 * 9 + 6] = (-R.GetAt(2, 1) * Dinv.GetAt(2, 0) * R.GetAt(1, 1) + R.GetAt(2, 1) * Dinv.GetAt(2, 1) * R.GetAt(1, 0) + R.GetAt(2, 2) * Dinv.GetAt(1, 0) * R.GetAt(1, 1) - R.GetAt(2, 2) * Dinv.GetAt(1, 1) * R.GetAt(1, 0));
848 dRdF[6 * 9 + 6] = (-R.GetAt(2, 1) * Dinv.GetAt(2, 1) * R.GetAt(2, 2) + R.GetAt(2, 1) * Dinv.GetAt(2, 2) * R.GetAt(2, 1) + R.GetAt(2, 2) * Dinv.GetAt(1, 1) * R.GetAt(2, 2) - R.GetAt(2, 2) * Dinv.GetAt(1, 2) * R.GetAt(2, 1));
849 dRdF[7 * 9 + 6] = (R.GetAt(2, 1) * Dinv.GetAt(2, 0) * R.GetAt(2, 2) - R.GetAt(2, 1) * Dinv.GetAt(2, 2) * R.GetAt(2, 0) - R.GetAt(2, 2) * Dinv.GetAt(1, 0) * R.GetAt(2, 2) + R.GetAt(2, 2) * Dinv.GetAt(1, 2) * R.GetAt(2, 0));
850 dRdF[8 * 9 + 6] = (-R.GetAt(2, 1) * Dinv.GetAt(2, 0) * R.GetAt(2, 1) + R.GetAt(2, 1) * Dinv.GetAt(2, 1) * R.GetAt(2, 0) + R.GetAt(2, 2) * Dinv.GetAt(1, 0) * R.GetAt(2, 1) - R.GetAt(2, 2) * Dinv.GetAt(1, 1) * R.GetAt(2, 0));
851 dRdF[0 * 9 + 7] = (R.GetAt(2, 0) * Dinv.GetAt(2, 1) * R.GetAt(0, 2) - R.GetAt(2, 0) * Dinv.GetAt(2, 2) * R.GetAt(0, 1) - R.GetAt(2, 2) * Dinv.GetAt(0, 1) * R.GetAt(0, 2) + R.GetAt(2, 2) * Dinv.GetAt(0, 2) * R.GetAt(0, 1));
852 dRdF[1 * 9 + 7] = (-R.GetAt(2, 0) * Dinv.GetAt(2, 0) * R.GetAt(0, 2) + R.GetAt(2, 0) * Dinv.GetAt(2, 2) * R.GetAt(0, 0) + R.GetAt(2, 2) * Dinv.GetAt(0, 0) * R.GetAt(0, 2) - R.GetAt(2, 2) * Dinv.GetAt(0, 2) * R.GetAt(0, 0));
853 dRdF[2 * 9 + 7] = (R.GetAt(2, 0) * Dinv.GetAt(2, 0) * R.GetAt(0, 1) - R.GetAt(2, 0) * Dinv.GetAt(2, 1) * R.GetAt(0, 0) - R.GetAt(2, 2) * Dinv.GetAt(0, 0) * R.GetAt(0, 1) + R.GetAt(2, 2) * Dinv.GetAt(0, 1) * R.GetAt(0, 0));
854 dRdF[3 * 9 + 7] = (R.GetAt(2, 0) * Dinv.GetAt(2, 1) * R.GetAt(1, 2) - R.GetAt(2, 0) * Dinv.GetAt(2, 2) * R.GetAt(1, 1) - R.GetAt(2, 2) * Dinv.GetAt(0, 1) * R.GetAt(1, 2) + R.GetAt(2, 2) * Dinv.GetAt(0, 2) * R.GetAt(1, 1));
855 dRdF[4 * 9 + 7] = (-R.GetAt(2, 0) * Dinv.GetAt(2, 0) * R.GetAt(1, 2) + R.GetAt(2, 0) * Dinv.GetAt(2, 2) * R.GetAt(1, 0) + R.GetAt(2, 2) * Dinv.GetAt(0, 0) * R.GetAt(1, 2) - R.GetAt(2, 2) * Dinv.GetAt(0, 2) * R.GetAt(1, 0));
856 dRdF[5 * 9 + 7] = (R.GetAt(2, 0) * Dinv.GetAt(2, 0) * R.GetAt(1, 1) - R.GetAt(2, 0) * Dinv.GetAt(2, 1) * R.GetAt(1, 0) - R.GetAt(2, 2) * Dinv.GetAt(0, 0) * R.GetAt(1, 1) + R.GetAt(2, 2) * Dinv.GetAt(0, 1) * R.GetAt(1, 0));
857 dRdF[6 * 9 + 7] = (R.GetAt(2, 0) * Dinv.GetAt(2, 1) * R.GetAt(2, 2) - R.GetAt(2, 0) * Dinv.GetAt(2, 2) * R.GetAt(2, 1) - R.GetAt(2, 2) * Dinv.GetAt(0, 1) * R.GetAt(2, 2) + R.GetAt(2, 2) * Dinv.GetAt(0, 2) * R.GetAt(2, 1));
858 dRdF[7 * 9 + 7] = (-R.GetAt(2, 0) * Dinv.GetAt(2, 0) * R.GetAt(2, 2) + R.GetAt(2, 0) * Dinv.GetAt(2, 2) * R.GetAt(2, 0) + R.GetAt(2, 2) * Dinv.GetAt(0, 0) * R.GetAt(2, 2) - R.GetAt(2, 2) * Dinv.GetAt(0, 2) * R.GetAt(2, 0));
859 dRdF[8 * 9 + 7] = (R.GetAt(2, 0) * Dinv.GetAt(2, 0) * R.GetAt(2, 1) - R.GetAt(2, 0) * Dinv.GetAt(2, 1) * R.GetAt(2, 0) - R.GetAt(2, 2) * Dinv.GetAt(0, 0) * R.GetAt(2, 1) + R.GetAt(2, 2) * Dinv.GetAt(0, 1) * R.GetAt(2, 0));
860 dRdF[0 * 9 + 8] = (-R.GetAt(2, 0) * Dinv.GetAt(1, 1) * R.GetAt(0, 2) + R.GetAt(2, 0) * Dinv.GetAt(1, 2) * R.GetAt(0, 1) + R.GetAt(2, 1) * Dinv.GetAt(0, 1) * R.GetAt(0, 2) - R.GetAt(2, 1) * Dinv.GetAt(0, 2) * R.GetAt(0, 1));
861 dRdF[1 * 9 + 8] = (R.GetAt(2, 0) * Dinv.GetAt(1, 0) * R.GetAt(0, 2) - R.GetAt(2, 0) * Dinv.GetAt(1, 2) * R.GetAt(0, 0) - R.GetAt(2, 1) * Dinv.GetAt(0, 0) * R.GetAt(0, 2) + R.GetAt(2, 1) * Dinv.GetAt(0, 2) * R.GetAt(0, 0));
862 dRdF[2 * 9 + 8] = (-R.GetAt(2, 0) * Dinv.GetAt(1, 0) * R.GetAt(0, 1) + R.GetAt(2, 0) * Dinv.GetAt(1, 1) * R.GetAt(0, 0) + R.GetAt(2, 1) * Dinv.GetAt(0, 0) * R.GetAt(0, 1) - R.GetAt(2, 1) * Dinv.GetAt(0, 1) * R.GetAt(0, 0));
863 dRdF[3 * 9 + 8] = (-R.GetAt(2, 0) * Dinv.GetAt(1, 1) * R.GetAt(1, 2) + R.GetAt(2, 0) * Dinv.GetAt(1, 2) * R.GetAt(1, 1) + R.GetAt(2, 1) * Dinv.GetAt(0, 1) * R.GetAt(1, 2) - R.GetAt(2, 1) * Dinv.GetAt(0, 2) * R.GetAt(1, 1));
864 dRdF[4 * 9 + 8] = (R.GetAt(2, 0) * Dinv.GetAt(1, 0) * R.GetAt(1, 2) - R.GetAt(2, 0) * Dinv.GetAt(1, 2) * R.GetAt(1, 0) - R.GetAt(2, 1) * Dinv.GetAt(0, 0) * R.GetAt(1, 2) + R.GetAt(2, 1) * Dinv.GetAt(0, 2) * R.GetAt(1, 0));
865 dRdF[5 * 9 + 8] = (-R.GetAt(2, 0) * Dinv.GetAt(1, 0) * R.GetAt(1, 1) + R.GetAt(2, 0) * Dinv.GetAt(1, 1) * R.GetAt(1, 0) + R.GetAt(2, 1) * Dinv.GetAt(0, 0) * R.GetAt(1, 1) - R.GetAt(2, 1) * Dinv.GetAt(0, 1) * R.GetAt(1, 0));
866 dRdF[6 * 9 + 8] = (-R.GetAt(2, 0) * Dinv.GetAt(1, 1) * R.GetAt(2, 2) + R.GetAt(2, 0) * Dinv.GetAt(1, 2) * R.GetAt(2, 1) + R.GetAt(2, 1) * Dinv.GetAt(0, 1) * R.GetAt(2, 2) - R.GetAt(2, 1) * Dinv.GetAt(0, 2) * R.GetAt(2, 1));
867 dRdF[7 * 9 + 8] = (R.GetAt(2, 0) * Dinv.GetAt(1, 0) * R.GetAt(2, 2) - R.GetAt(2, 0) * Dinv.GetAt(1, 2) * R.GetAt(2, 0) - R.GetAt(2, 1) * Dinv.GetAt(0, 0) * R.GetAt(2, 2) + R.GetAt(2, 1) * Dinv.GetAt(0, 2) * R.GetAt(2, 0));
868 dRdF[8 * 9 + 8] = (-R.GetAt(2, 0) * Dinv.GetAt(1, 0) * R.GetAt(2, 1) + R.GetAt(2, 0) * Dinv.GetAt(1, 1) * R.GetAt(2, 0) + R.GetAt(2, 1) * Dinv.GetAt(0, 0) * R.GetAt(2, 1) - R.GetAt(2, 1) * Dinv.GetAt(0, 1) * R.GetAt(2, 0));
869 }
870
871} // namespace Chaos
872
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
@ Compute
Definition MetalRHIPrivate.h:232
Definition ImplicitQRSVD.h:32
int rowk
Definition ImplicitQRSVD.h:35
GivensRotation< T > operator*(const GivensRotation< T > &A) const
Definition ImplicitQRSVD.h:165
GivensRotation(int rowi_in, int rowk_in)
Definition ImplicitQRSVD.h:41
int rowi
Definition ImplicitQRSVD.h:34
void ComputeUnconventional(const T a, const T b)
Definition ImplicitQRSVD.h:75
T s
Definition ImplicitQRSVD.h:37
void RowRotation(PMatrix< T, 2, 2 > &A) const
Definition ImplicitQRSVD.h:106
GivensRotation(T a, T b, int rowi_in, int rowk_in)
Definition ImplicitQRSVD.h:43
T c
Definition ImplicitQRSVD.h:36
void Fill(const PMatrix< T, 2, 2 > &R) const
Definition ImplicitQRSVD.h:89
void operator*=(const GivensRotation< T > &A)
Definition ImplicitQRSVD.h:155
GivensRotation()
Definition ImplicitQRSVD.h:39
~GivensRotation()
Definition ImplicitQRSVD.h:47
void ColumnRotation(PMatrix< T, 3, 3 > &A) const
Definition ImplicitQRSVD.h:143
void ColumnRotation(PMatrix< T, 2, 2 > &A) const
Definition ImplicitQRSVD.h:133
void RowRotation(PMatrix< T, 3, 3 > &A) const
Definition ImplicitQRSVD.h:116
void TransposeInPlace()
Definition ImplicitQRSVD.h:49
void Compute(const T a, const T b)
Definition ImplicitQRSVD.h:58
Definition Matrix.h:21
Definition Vector.h:41
Definition SkeletalMeshComponent.h:307
void SingularValueDecomposition(const PMatrix< T, 2, 2 > &A, GivensRotation< T > &U, const TVector< T, 2 > &Sigma, GivensRotation< T > &V, const T tol=std::numeric_limits< T >::epsilon())
2x2 SVD (singular value decomposition) A=USV'
Definition ImplicitQRSVD.h:367
void dRdFCorotated(const PMatrix< T, 3, 3 > &F, TVector< T, 81 > &dRdF)
Definition ImplicitQRSVD.h:782
void MakeLambdaShape(PMatrix< T, 3, 3 > &H, PMatrix< T, 3, 3 > &U, PMatrix< T, 3, 3 > &V)
make a 3X3 matrix to lambda shape original form of H: x x x x x x x x x after : x 0 0 x x 0 x 0 x
Definition ImplicitQRSVD.h:263
void FlipSign(int i, PMatrix< T, 3, 3 > &U, TVector< T, 3 > &sigma)
Helper function of 3X3 SVD for flipping signs due to flipping signs of sigma.
Definition ImplicitQRSVD.h:494
void Sort0(PMatrix< T, 3, 3 > &U, TVector< T, 3 > &sigma, PMatrix< T, 3, 3 > &V)
Helper function of 3X3 SVD for sorting singular values.
Definition ImplicitQRSVD.h:512
void PolarDecomposition(const PMatrix< T, 2, 2 > &A, GivensRotation< T > &R, PMatrix< T, 2, 2 > &S_Sym)
2x2 polar decomposition.
Definition ImplicitQRSVD.h:323
void SwapCols(PMatrix< T, 3, 3 > &A, const int i1, const int i2)
Definition ImplicitQRSVD.h:501
FRealDouble FReal
Definition Real.h:22
void ZeroChase(PMatrix< T, 3, 3 > &H, PMatrix< T, 3, 3 > &U, PMatrix< T, 3, 3 > &V)
zero chasing the 3X3 matrix to bidiagonal form original form of H: x x 0 x x x 0 0 x after zero chase...
Definition ImplicitQRSVD.h:183
void MakeUpperBidiag(PMatrix< T, 3, 3 > &H, PMatrix< T, 3, 3 > &U, PMatrix< T, 3, 3 > &V)
make a 3X3 matrix to upper bidiagonal form original form of H: x x x x x x x x x after zero chase: x ...
Definition ImplicitQRSVD.h:235
T WilkinsonShift(const T a1, const T b1, const T a2)
Compute WilkinsonShift of the block a1 b1 b1 a2 based on the WilkinsonShift formula mu = c + d - sign...
Definition ImplicitQRSVD.h:454
void Sort1(PMatrix< T, 3, 3 > &U, TVector< T, 3 > &sigma, PMatrix< T, 3, 3 > &V)
Helper function of 3X3 SVD for Sorting singular values.
Definition ImplicitQRSVD.h:553
float v
Definition radaudio_mdct.cpp:62
static constexpr UE_FORCEINLINE_HINT T Abs(const T A)
Definition GenericPlatformMath.h:949