26 template <
typename Real>
45 int operator()(Real a00, Real a01, Real a02, Real a11, Real a12, Real a22,
46 bool aggressive,
int sortType, std::array<Real, 3>& eval,
47 std::array<std::array<Real, 3>, 3>& evec)
const;
51 void Update0(Real Q[3][3], Real
c, Real
s)
const;
54 void Update1(Real Q[3][3], Real c, Real s)
const;
57 void Update2(Real Q[3][3], Real c, Real s)
const;
60 void Update3(Real Q[3][3], Real c, Real s)
const;
70 void GetCosSin(Real u, Real
v, Real& cs, Real& sn)
const;
77 bool Converged(
bool aggressive, Real bDiag0, Real bDiag1,
84 bool Sort(std::array<Real, 3>
const& d,
int& i0,
int& i1,
int& i2)
const;
88 template <
typename Real>
96 void operator()(Real a00, Real a01, Real a02, Real a11, Real a12, Real a22,
97 std::array<Real, 3>& eval,
std::array<std::array<Real, 3>, 3>& evec)
const;
100 static std::array<Real, 3> Multiply(Real
s, std::array<Real, 3>
const& U);
101 static std::array<Real, 3> Subtract(std::array<Real, 3>
const& U, std::array<Real, 3>
const& V);
102 static std::array<Real, 3> Divide(std::array<Real, 3>
const& U, Real s);
103 static Real
Dot(std::array<Real, 3>
const& U, std::array<Real, 3>
const& V);
104 static std::array<Real, 3>
Cross(std::array<Real, 3>
const& U, std::array<Real, 3>
const& V);
107 std::array<Real, 3>& U, std::array<Real, 3>& V)
const;
109 void ComputeEigenvector0(Real a00, Real a01, Real a02, Real a11, Real a12, Real a22,
110 Real& eval0, std::array<Real, 3>& evec0)
const;
112 void ComputeEigenvector1(Real a00, Real a01, Real a02, Real a11, Real a12, Real a22,
113 std::array<Real, 3>
const& evec0, Real& eval1, std::array<Real, 3>& evec1)
const;
117 template <
typename Real>
119 Real a11, Real a12, Real a22,
bool aggressive,
int sortType,
120 std::array<Real, 3>& eval,
std::array<std::array<Real, 3>, 3>& evec)
const 123 Real
const zero = (Real)0, one = (Real)1, half = (Real)0.5;
124 bool isRotation =
false;
127 Real Q[3][3] = { {
c,
s, zero }, {
s, -
c, zero }, { zero, zero, one } };
128 Real term0 = c * a00 + s * a01;
129 Real term1 = c * a01 + s * a11;
130 Real b00 = c * term0 + s * term1;
131 Real b01 = s * term0 - c * term1;
132 term0 = s * a00 - c * a01;
133 term1 = s * a01 - c * a11;
134 Real b11 = s * term0 - c * term1;
135 Real b12 = s * a02 - c * a12;
139 int const maxIteration = 2 * (1 + std::numeric_limits<Real>::digits -
140 std::numeric_limits<Real>::min_exponent);
146 Real saveB00, saveB01, saveB11;
147 for (iteration = 0; iteration < maxIteration; ++iteration)
150 GetCosSin(half * (b00 - b11), b01, c2, s2);
151 s = sqrt(half * (one - c2));
156 isRotation = !isRotation;
163 term0 = c * saveB00 + s * saveB01;
164 term1 = c * saveB01 + s * saveB11;
165 b00 = c * term0 + s * term1;
167 term0 = c * saveB01 - s * saveB00;
168 term1 = c * saveB11 - s * saveB01;
169 b22 = c * term1 - s * term0;
173 if (
Converged(aggressive, b00, b11, b01))
176 GetCosSin(half * (b00 - b11), b01, c2, s2);
177 s = sqrt(half * (one - c2));
182 isRotation = !isRotation;
188 term0 = c * saveB00 + s * saveB01;
189 term1 = c * saveB01 + s * saveB11;
190 b00 = c * term0 + s * term1;
191 term0 = s * saveB00 - c * saveB01;
192 term1 = s * saveB01 - c * saveB11;
193 b11 = s * term0 - c * term1;
200 Real saveB11, saveB12, saveB22;
201 for (iteration = 0; iteration < maxIteration; ++iteration)
204 GetCosSin(half * (b22 - b11), b12, c2, s2);
205 s = sqrt(half * (one - c2));
210 isRotation = !isRotation;
217 term0 = c * saveB22 + s * saveB12;
218 term1 = c * saveB12 + s * saveB11;
219 b22 = c * term0 + s * term1;
221 term0 = c * saveB12 - s * saveB22;
222 term1 = c * saveB11 - s * saveB12;
223 b00 = c * term1 - s * term0;
227 if (
Converged(aggressive, b11, b22, b12))
230 GetCosSin(half * (b11 - b22), b12, c2, s2);
231 s = sqrt(half * (one - c2));
236 isRotation = !isRotation;
242 term0 = c * saveB11 + s * saveB12;
243 term1 = c * saveB12 + s * saveB22;
244 b11 = c * term0 + s * term1;
245 term0 = s * saveB11 - c * saveB12;
246 term1 = s * saveB12 - c * saveB22;
247 b22 = s * term0 - c * term1;
253 std::array<Real, 3> diagonal = { b00, b11, b22 };
258 bool isOdd =
Sort(diagonal, i0, i1, i2);
261 isRotation = !isRotation;
264 else if (sortType <= -1)
267 bool isOdd =
Sort(diagonal, i0, i1, i2);
271 isRotation = !isRotation;
281 eval[0] = diagonal[i0];
282 eval[1] = diagonal[i1];
283 eval[2] = diagonal[i2];
284 evec[0][0] = Q[0][i0];
285 evec[0][1] = Q[1][i0];
286 evec[0][2] = Q[2][i0];
287 evec[1][0] = Q[0][i1];
288 evec[1][1] = Q[1][i1];
289 evec[1][2] = Q[2][i1];
290 evec[2][0] = Q[0][i2];
291 evec[2][1] = Q[1][i2];
292 evec[2][2] = Q[2][i2];
297 for (
int j = 0; j < 3; ++j)
299 evec[2][j] = -evec[2][j];
306 template <
typename Real>
310 for (
int r = 0;
r < 3; ++
r)
312 Real tmp0 = c * Q[
r][0] + s * Q[
r][1];
314 Real tmp2 = c * Q[
r][1] - s * Q[
r][0];
321 template <
typename Real>
325 for (
int r = 0;
r < 3; ++
r)
327 Real tmp0 = c * Q[
r][1] - s * Q[
r][2];
329 Real tmp2 = c * Q[
r][2] + s * Q[
r][1];
336 template <
typename Real>
340 for (
int r = 0;
r < 3; ++
r)
342 Real tmp0 = c * Q[
r][0] + s * Q[
r][1];
343 Real tmp1 = s * Q[
r][0] - c * Q[
r][1];
349 template <
typename Real>
353 for (
int r = 0;
r < 3; ++
r)
355 Real tmp0 = c * Q[
r][1] + s * Q[
r][2];
356 Real tmp1 = s * Q[
r][1] - c * Q[
r][2];
362 template <
typename Real>
367 if (maxAbsComp > (Real)0)
371 Real
length = sqrt(u * u + v * v);
387 template <
typename Real>
389 Real bDiag1, Real bSuper)
const 393 return bSuper == (Real)0;
398 return sum +
std::abs(bSuper) == sum;
402 template <
typename Real>
404 int& i0,
int& i1,
int& i2)
const 411 i0 = 2; i1 = 0; i2 = 1; odd =
true;
413 else if (d[2] < d[1])
415 i0 = 0; i1 = 2; i2 = 1; odd =
false;
419 i0 = 0; i1 = 1; i2 = 2; odd =
true;
426 i0 = 2; i1 = 1; i2 = 0; odd =
false;
428 else if (d[2] < d[0])
430 i0 = 1; i1 = 2; i2 = 0; odd =
true;
434 i0 = 1; i1 = 0; i2 = 2; odd =
false;
441 template <
typename Real>
443 Real a11, Real a12, Real a22, std::array<Real, 3>& eval,
444 std::array<std::array<Real, 3>, 3>& evec)
const 449 Real max0 = std::max(fabs(a00), fabs(a01));
450 Real max1 = std::max(fabs(a02), fabs(a11));
451 Real max2 = std::max(fabs(a12), fabs(a22));
452 Real maxAbsElement = std::max(std::max(max0, max1), max2);
453 if (maxAbsElement == (Real)0)
459 evec[0] = { (Real)1, (Real)0, (Real)0 };
460 evec[1] = { (Real)0, (Real)1, (Real)0 };
461 evec[2] = { (Real)0, (Real)0, (Real)1 };
465 Real invMaxAbsElement = (Real)1 / maxAbsElement;
466 a00 *= invMaxAbsElement;
467 a01 *= invMaxAbsElement;
468 a02 *= invMaxAbsElement;
469 a11 *= invMaxAbsElement;
470 a12 *= invMaxAbsElement;
471 a22 *= invMaxAbsElement;
473 Real norm = a01 * a01 + a02 * a02 + a12 * a12;
480 Real traceDiv3 = (a00 + a11 + a22) / (Real)3;
481 Real b00 = a00 - traceDiv3;
482 Real b11 = a11 - traceDiv3;
483 Real b22 = a22 - traceDiv3;
484 Real denom = sqrt((b00 * b00 + b11 * b11 + b22 * b22 + norm * (Real)2) / (Real)6);
485 Real c00 = b11 * b22 - a12 * a12;
486 Real c01 = a01 * b22 - a12 * a02;
487 Real c02 = a01 * a12 - b11 * a02;
488 Real det = (b00 * c00 - a01 * c01 + a02 * c02) / (denom * denom * denom);
489 Real halfDet = det * (Real)0.5;
490 halfDet = std::min(std::max(halfDet, (Real)-1), (Real)1);
495 Real
angle = acos(halfDet) / (Real)3;
496 Real
const twoThirdsPi = (Real)2.09439510239319549;
497 Real beta2 = cos(angle) * (Real)2;
498 Real beta0 = cos(angle + twoThirdsPi) * (Real)2;
499 Real beta1 = -(beta0 + beta2);
502 eval[0] = traceDiv3 + denom * beta0;
503 eval[1] = traceDiv3 + denom * beta1;
504 eval[2] = traceDiv3 + denom * beta2;
511 if (halfDet >= (Real)0)
524 ComputeEigenvector0(a00, a01, a02, a11, a12, a22, eval[i0], evec[i0]);
525 ComputeEigenvector1(a00, a01, a02, a11, a12, a22, evec[i0], eval[i1], evec[i1]);
526 evec[i2] =
Cross(evec[i0], evec[i1]);
534 evec[0] = { (Real)1, (Real)0, (Real)0 };
535 evec[1] = { (Real)0, (Real)1, (Real)0 };
536 evec[2] = { (Real)0, (Real)0, (Real)1 };
541 eval[0] *= maxAbsElement;
542 eval[1] *= maxAbsElement;
543 eval[2] *= maxAbsElement;
546 template <
typename Real>
548 Real
s, std::array<Real, 3>
const& U)
550 std::array<Real, 3> product = { s * U[0], s * U[1], s * U[2] };
554 template <
typename Real>
556 std::array<Real, 3>
const& U, std::array<Real, 3>
const& V)
558 std::array<float, 3> difference = { U[0] - V[0], U[1] - V[1], U[2] - V[2] };
562 template <
typename Real>
564 std::array<Real, 3>
const& U, Real
s)
566 Real invS = (Real)1 / s;
567 std::array<Real, 3> division = { U[0] * invS, U[1] * invS, U[2] * invS };
571 template <
typename Real>
573 std::array<Real, 3>
const& V)
575 Real dot = U[0] * V[0] + U[1] * V[1] + U[2] * V[2];
579 template <
typename Real>
581 std::array<Real, 3>
const& V)
583 std::array<Real, 3> cross =
585 U[1] * V[2] - U[2] * V[1],
586 U[2] * V[0] - U[0] * V[2],
587 U[0] * V[1] - U[1] * V[0]
592 template <
typename Real>
594 std::array<Real, 3>
const& W, std::array<Real, 3>& U, std::array<Real, 3>& V)
const 600 if (fabs(W[0]) > fabs(W[1]))
603 invLength = (Real)1 / sqrt(W[0] * W[0] + W[2] * W[2]);
604 U = { -W[2] * invLength, (Real)0, +W[0] * invLength };
609 invLength = (Real)1 / sqrt(W[1] * W[1] + W[2] * W[2]);
610 U = { (Real)0, +W[2] * invLength, -W[1] * invLength };
615 template <
typename Real>
617 Real a02, Real a11, Real a12, Real a22, Real& eval0, std::array<Real, 3>& evec0)
const 623 std::array<Real, 3> row0 = { a00 - eval0, a01, a02 };
624 std::array<Real, 3> row1 = { a01, a11 - eval0, a12 };
625 std::array<Real, 3> row2 = { a02, a12, a22 - eval0 };
626 std::array<Real, 3> r0xr1 =
Cross(row0, row1);
627 std::array<Real, 3> r0xr2 =
Cross(row0, row2);
628 std::array<Real, 3> r1xr2 =
Cross(row1, row2);
629 Real d0 =
Dot(r0xr1, r0xr1);
630 Real d1 =
Dot(r0xr2, r0xr2);
631 Real d2 =
Dot(r1xr2, r1xr2);
647 evec0 = Divide(r0xr1, sqrt(d0));
651 evec0 = Divide(r0xr2, sqrt(d1));
655 evec0 = Divide(r1xr2, sqrt(d2));
659 template <
typename Real>
661 Real a02, Real a11, Real a12, Real a22, std::array<Real, 3>
const& evec0,
662 Real& eval1, std::array<Real, 3>& evec1)
const 665 std::array<Real, 3> U, V;
685 std::array<Real, 3> AU =
687 a00 * U[0] + a01 * U[1] + a02 * U[2],
688 a01 * U[0] + a11 * U[1] + a12 * U[2],
689 a02 * U[0] + a12 * U[1] + a22 * U[2]
692 std::array<Real, 3> AV =
694 a00 * V[0] + a01 * V[1] + a02 * V[2],
695 a01 * V[0] + a11 * V[1] + a12 * V[2],
696 a02 * V[0] + a12 * V[1] + a22 * V[2]
699 Real m00 = U[0] * AU[0] + U[1] * AU[1] + U[2] * AU[2] - eval1;
700 Real m01 = U[0] * AV[0] + U[1] * AV[1] + U[2] * AV[2];
701 Real m11 = V[0] * AV[0] + V[1] * AV[1] + V[2] * AV[2] - eval1;
708 Real absM00 = fabs(m00);
709 Real absM01 = fabs(m01);
710 Real absM11 = fabs(m11);
712 if (absM00 >= absM11)
714 maxAbsComp = std::max(absM00, absM01);
715 if (maxAbsComp > (Real)0)
717 if (absM00 >= absM01)
720 m00 = (Real)1 / sqrt((Real)1 + m01 * m01);
726 m01 = (Real)1 / sqrt((Real)1 + m00 * m00);
729 evec1 = Subtract(Multiply(m01, U), Multiply(m00, V));
738 maxAbsComp = std::max(absM11, absM01);
739 if (maxAbsComp > (Real)0)
741 if (absM11 >= absM01)
744 m11 = (Real)1 / sqrt((Real)1 + m01 * m01);
750 m01 = (Real)1 / sqrt((Real)1 + m11 * m11);
753 evec1 = Subtract(Multiply(m11, U), Multiply(m01, V));
void ComputeOrthogonalComplement(std::array< Real, 3 > const &W, std::array< Real, 3 > &U, std::array< Real, 3 > &V) const
static std::array< Real, 3 > Divide(std::array< Real, 3 > const &U, Real s)
void ComputeEigenvector1(Real a00, Real a01, Real a02, Real a11, Real a12, Real a22, std::array< Real, 3 > const &evec0, Real &eval1, std::array< Real, 3 > &evec1) const
static std::array< Real, 3 > Cross(std::array< Real, 3 > const &U, std::array< Real, 3 > const &V)
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
void operator()(Real a00, Real a01, Real a02, Real a11, Real a12, Real a22, std::array< Real, 3 > &eval, std::array< std::array< Real, 3 >, 3 > &evec) const
int operator()(Real a00, Real a01, Real a02, Real a11, Real a12, Real a22, bool aggressive, int sortType, std::array< Real, 3 > &eval, std::array< std::array< Real, 3 >, 3 > &evec) const
static Real Dot(std::array< Real, 3 > const &U, std::array< Real, 3 > const &V)
static std::array< Real, 3 > Subtract(std::array< Real, 3 > const &U, std::array< Real, 3 > const &V)
static std::array< Real, 3 > Multiply(Real s, std::array< Real, 3 > const &U)
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
void ComputeEigenvector0(Real a00, Real a01, Real a02, Real a11, Real a12, Real a22, Real &eval0, std::array< Real, 3 > &evec0) const
DualQuaternion< Real > Cross(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
void Update1(Real Q[3][3], Real c, Real s) const
bool Sort(std::array< Real, 3 > const &d, int &i0, int &i1, int &i2) const
GLuint GLsizei GLsizei * length
void Update0(Real Q[3][3], Real c, Real s) const
void Update2(Real Q[3][3], Real c, Real s) const
bool Converged(bool aggressive, Real bDiag0, Real bDiag1, Real bSuper) const
Real ComputeOrthogonalComplement(int numInputs, Vector2< Real > *v, bool robust=false)
void GetCosSin(Real u, Real v, Real &cs, Real &sn) const
void Update3(Real Q[3][3], Real c, Real s) const