GteSymmetricEigensolver2x2.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <GTEngineDEF.h>
11 #include <algorithm>
12 #include <array>
13 #include <cmath>
14 
15 namespace gte
16 {
17 
18 template <typename Real>
20 {
21 public:
22  // The input matrix must be symmetric, so only the unique elements must
23  // be specified: a00, a01, and a11.
24  //
25  // The order of the eigenvalues is specified by sortType: -1 (decreasing),
26  // 0 (no sorting), or +1 (increasing). When sorted, the eigenvectors are
27  // ordered accordingly, and {evec[0], evec[1]} is guaranteed to be a
28  // right-handed orthonormal set.
29 
30  void operator()(Real a00, Real a01, Real a11, int sortType,
31  std::array<Real, 2>& eval, std::array<std::array<Real, 2>, 2>& evec)
32  const;
33 };
34 
35 
36 template <typename Real>
37 void SymmetricEigensolver2x2<Real>::operator()(Real a00, Real a01, Real a11,
38  int sortType, std::array<Real, 2>& eval,
39  std::array<std::array<Real, 2>, 2>& evec) const
40 {
41  // Normalize (c2,s2) robustly, avoiding floating-point overflow in the
42  // sqrt call.
43  Real const zero = (Real)0, one = (Real)1, half = (Real)0.5;
44  Real c2 = half * (a00 - a11), s2 = a01;
45  Real maxAbsComp = std::max(std::abs(c2), std::abs(s2));
46  if (maxAbsComp > zero)
47  {
48  c2 /= maxAbsComp; // in [-1,1]
49  s2 /= maxAbsComp; // in [-1,1]
50  Real length = sqrt(c2 * c2 + s2 * s2);
51  c2 /= length;
52  s2 /= length;
53  if (c2 > zero)
54  {
55  c2 = -c2;
56  s2 = -s2;
57  }
58  }
59  else
60  {
61  c2 = -one;
62  s2 = zero;
63  }
64 
65  Real s = sqrt(half * (one - c2)); // >= 1/sqrt(2)
66  Real c = half * s2 / s;
67 
68  Real diagonal[2];
69  Real csqr = c * c, ssqr = s * s, mid = s2 * a01;
70  diagonal[0] = csqr * a00 + mid + ssqr * a11;
71  diagonal[1] = csqr * a11 - mid + ssqr * a00;
72 
73  if (sortType == 0 || sortType * diagonal[0] <= sortType * diagonal[1])
74  {
75  eval[0] = diagonal[0];
76  eval[1] = diagonal[1];
77  evec[0][0] = c;
78  evec[0][1] = s;
79  evec[1][0] = -s;
80  evec[1][1] = c;
81  }
82  else
83  {
84  eval[0] = diagonal[1];
85  eval[1] = diagonal[0];
86  evec[0][0] = s;
87  evec[0][1] = -c;
88  evec[1][0] = c;
89  evec[1][1] = s;
90  }
91 }
92 
93 
94 }
void operator()(Real a00, Real a01, Real a11, int sortType, std::array< Real, 2 > &eval, std::array< std::array< Real, 2 >, 2 > &evec) const
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
const GLubyte * c
Definition: glext.h:11671
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:790
GLenum array
Definition: glext.h:6669
GLdouble s
Definition: glext.h:231


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:01