37 #ifndef VIGRA_EIGENSYSTEM_HXX 
   38 #define VIGRA_EIGENSYSTEM_HXX 
   43 #include "array_vector.hxx" 
   44 #include "polynomial.hxx" 
   57 template <
class T, 
class C1, 
class C2>
 
   63         "housholderTridiagonalization(): matrix must be square.");
 
   65         "housholderTridiagonalization(): matrix size mismatch.");
 
   77     for(
int i = n-1; i > 0; --i)
 
   83         for(
int k = 0; k < i; ++k)
 
   85             scale = scale + 
abs(d(k));
 
   90             for(
int j = 0; j < i; ++j)
 
  101             for(
int k = 0; k < i; ++k)
 
  114             for(
int j = 0; j < i; ++j)
 
  121             for(
int j = 0; j < i; ++j)
 
  125                g = e(j) + a(j, j) * f;
 
  126                for(
int k = j+1; k <= i-1; ++k)
 
  134             for(
int j = 0; j < i; ++j)
 
  140             for(
int j = 0; j < i; ++j)
 
  144             for(
int j = 0; j < i; ++j)
 
  148                 for(
int k = j; k <= i-1; ++k)
 
  150                     a(k, j) -= (f * e(k) + g * d(k));
 
  170                 d(k) = a(k, i+1) / h;
 
  177                     g += a(k, i+1) * a(k, j);
 
  201 template <
class T, 
class C1, 
class C2>
 
  207         "tridiagonalMatrixEigensystem(): matrix must be square.");
 
  209         "tridiagonalMatrixEigensystem(): matrix size mismatch.");
 
  221     T eps = VIGRA_CSTD::pow(2.0,-52.0);
 
  226         tst1 = std::max(tst1, 
abs(d(l)) + 
abs(e(l)));
 
  232             if(
abs(e(m)) <= eps*tst1)
 
  251                 T p = (d(l+1) - g) / (2.0 * e(l));
 
  257                 d(l) = e(l) / (p + r);
 
  258                 d(l+1) = e(l) * (p + r);
 
  276                 for(
int i = m-1; i >= (int)l; --i)
 
  287                     p = c * d(i) - s * g;
 
  288                     d(i+1) = h + s * (c * g + s * d(i));
 
  295                          z(k, i+1) = s * z(k, i) + c * h;
 
  296                         z(k, i) = c * z(k, i) - s * h;
 
  299                 p = -s * s2 * c3 * el1 * e(l) / dl1;
 
  305             } 
while(
abs(e(l)) > eps*tst1);
 
  328             std::swap(d(k), d(i));
 
  331                 std::swap(z(j, i), z(j, k));
 
  340 template <
class T, 
class C1, 
class C2>
 
  353     for(
int m = low+1; m <= high-1; ++m)
 
  358         for(
int i = m; i <= high; ++i)
 
  360             scale = scale + 
abs(H(i, m-1));
 
  368             for(
int i = high; i >= m; --i)
 
  370                 ort[i] = H(i, m-1)/scale;
 
  384             for(
int j = m; j < n; ++j)
 
  387                 for(
int i = high; i >= m; --i)
 
  392                 for(
int i = m; i <= high; ++i)
 
  398             for(
int i = 0; i <= high; ++i)
 
  401                 for(
int j = high; j >= m; --j)
 
  406                 for(
int j = m; j <= high; ++j)
 
  411             ort[m] = scale*ort[m];
 
  418     for(
int i = 0; i < n; ++i)
 
  420         for(
int j = 0; j < n; ++j)
 
  422             V(i, j) = (i == j ? 1.0 : 0.0);
 
  426     for(
int m = high-1; m >= low+1; --m)
 
  430             for(
int i = m+1; i <= high; ++i)
 
  434             for(
int j = m; j <= high; ++j)
 
  437                 for(
int i = m; i <= high; ++i)
 
  439                     g += ort[i] * V(i, j);
 
  442                 g = (g / ort[m]) / H(m, m-1);
 
  443                 for(
int i = m; i <= high; ++i)
 
  445                     V(i, j) += g * ort[i];
 
  456 void cdiv(T xr, T xi, T yr, T yi, T & cdivr, T & cdivi)
 
  463         cdivr = (xr + r*xi)/d;
 
  464         cdivi = (xi - r*xr)/d;
 
  470         cdivr = (r*xr + xi)/d;
 
  471         cdivi = (r*xi - xr)/d;
 
  475 template <
class T, 
class C>
 
  477              T & p, T & q, T & r, T & s, T & w, T & x, T & y, T & z)
 
  485         p = (r * s - w) / H(m+1, m) + H(m, m+1);
 
  486         q = H(m+1, m+1) - z - r - s;
 
  497             eps * (
abs(p) * (
abs(H(m-1, m-1)) + 
abs(z) +
 
  511 template <
class T, 
class C1, 
class C2, 
class C3>
 
  529     T eps = VIGRA_CSTD::pow(2.0, 
sizeof(T) == 
sizeof(
float)
 
  533     T p=0,q=0,r=0,s=0,z=0,t,w,x,y;
 
  545             s = 
abs(H(l-1, l-1)) + 
abs(H(l, l));
 
  550             if(
abs(H(l, l-1)) < eps * s)
 
  561             H(n, n) = H(n, n) + exshift;
 
  572             w = H(n, n-1) * H(n-1, n);
 
  573             p = (H(n-1, n-1) - H(n, n)) / 2.0;
 
  576             H(n, n) = H(n, n) + exshift;
 
  577             H(n-1, n-1) = H(n-1, n-1) + exshift;
 
  610                 for(
int j = n-1; j < nn; ++j)
 
  613                     H(n-1, j) = q * z + p * H(n, j);
 
  614                     H(n, j) = q * H(n, j) - p * z;
 
  619                 for(
int i = 0; i <= n; ++i)
 
  622                     H(i, n-1) = q * z + p * H(i, n);
 
  623                     H(i, n) = q * H(i, n) - p * z;
 
  628                 for(
int i = low; i <= high; ++i)
 
  631                     V(i, n-1) = q * z + p * V(i, n);
 
  632                     V(i, n) = q * V(i, n) - p * z;
 
  662                 w = H(n, n-1) * H(n-1, n);
 
  670                 for(
int i = low; i <= n; ++i)
 
  674                 s = 
abs(H(n, n-1)) + 
abs(H(n-1, n-2));
 
  692                       s = x - w / ((y - x) / 2.0 + s);
 
  693                       for(
int i = low; i <= n; ++i)
 
  707             int m = hessenbergQrDecompositionHelper(H, n, l, eps, p, q, r, s, w, x, y, z);
 
  708             for(
int i = m+2; i <= n; ++i)
 
  719             for(
int k = m; k <= n-1; ++k)
 
  721                 int notlast = (k != n-1);
 
  725                     r = (notlast ? H(k+2, k-1) : 0.0);
 
  751                         H(k, k-1) = -H(k, k-1);
 
  762                     for(
int j = k; j < nn; ++j)
 
  764                         p = H(k, j) + q * H(k+1, j);
 
  767                             p = p + r * H(k+2, j);
 
  768                             H(k+2, j) = H(k+2, j) - p * z;
 
  770                         H(k, j) = H(k, j) - p * x;
 
  771                         H(k+1, j) = H(k+1, j) - p * y;
 
  776                     for(
int i = 0; i <= std::min(n,k+3); ++i)
 
  778                         p = x * H(i, k) + y * H(i, k+1);
 
  781                             p = p + z * H(i, k+2);
 
  782                             H(i, k+2) = H(i, k+2) - p * r;
 
  784                         H(i, k) = H(i, k) - p;
 
  785                         H(i, k+1) = H(i, k+1) - p * q;
 
  790                     for(
int i = low; i <= high; ++i)
 
  792                         p = x * V(i, k) + y * V(i, k+1);
 
  795                             p = p + z * V(i, k+2);
 
  796                             V(i, k+2) = V(i, k+2) - p * r;
 
  798                         V(i, k) = V(i, k) - p;
 
  799                         V(i, k+1) = V(i, k+1) - p * q;
 
  813     for(n = nn-1; n >= 0; --n)
 
  824             for(
int i = n-1; i >= 0; --i)
 
  828                 for(
int j = l; j <= n; ++j)
 
  830                     r = r + H(i, j) * H(j, n);
 
  848                             H(i, n) = -r / (eps * 
norm);
 
  858                         q = (d(i) - p) * (d(i) - p) + e(i) * e(i);
 
  859                         t = (x * s - z * r) / q;
 
  863                             H(i+1, n) = (-r - w * t) / x;
 
  867                             H(i+1, n) = (-s - y * t) / z;
 
  874                     if((eps * t) * t > 1)
 
  876                         for(
int j = i; j <= n; ++j)
 
  878                             H(j, n) = H(j, n) / t;
 
  893             if(
abs(H(n, n-1)) > 
abs(H(n-1, n)))
 
  895                 H(n-1, n-1) = q / H(n, n-1);
 
  896                 H(n-1, n) = -(H(n, n) - p) / H(n, n-1);
 
  900                 cdiv(0.0,-H(n-1, n),H(n-1, n-1)-p,q, H(n-1, n-1), H(n-1, n));
 
  904             for(
int i = n-2; i >= 0; --i)
 
  909                 for(
int j = l; j <= n; ++j)
 
  911                     ra = ra + H(j, n-1) * H(i, j);
 
  912                     sa = sa + H(j, n) * H(i, j);
 
  927                         cdiv(-ra,-sa,w,q, H(i, n-1), H(i, n));
 
  935                         vr = (d(i) - p) * (d(i) - p) + e(i) * e(i) - q * q;
 
  936                         vi = (d(i) - p) * 2.0 * q;
 
  937                         if((vr == 0.0) && (vi == 0.0))
 
  939                             vr = eps * norm * (
abs(w) + 
abs(q) +
 
  942                         cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi, H(i, n-1), H(i, n));
 
  945                             H(i+1, n-1) = (-ra - w * H(i, n-1) + q * H(i, n)) / x;
 
  946                             H(i+1, n) = (-sa - w * H(i, n) - q * H(i, n-1)) / x;
 
  950                             cdiv(-r-y*H(i, n-1),-s-y*H(i, n),z,q, H(i+1, n-1), H(i+1, n));
 
  956                     t = std::max(
abs(H(i, n-1)),
abs(H(i, n)));
 
  957                     if((eps * t) * t > 1)
 
  959                         for(
int j = i; j <= n; ++j)
 
  961                             H(j, n-1) = H(j, n-1) / t;
 
  962                             H(j, n) = H(j, n) / t;
 
  972     for(
int j = nn-1; j >= low; --j)
 
  974         for(
int i = low; i <= high; ++i)
 
  977             for(
int k = low; k <= std::min(j,high); ++k)
 
  979                 z = z + V(i, k) * H(k, j);
 
 1006 template <
class T, 
class C1, 
class C2, 
class C3>
 
 1012         "symmetricEigensystem(): symmetric input matrix required.");
 
 1016         "symmetricEigensystem(): matrix shape mismatch.");
 
 1020     detail::housholderTridiagonalization(ev, de);
 
 1021     if(!detail::tridiagonalMatrixEigensystem(de, ev))
 
 1030 template <
class T, 
class C2, 
class C3>
 
 1032 symmetricEigensystem2x2(T a00, T a01, T a11,
 
 1035     double evec[2]={0,0};
 
 1039         if (fabs(a11)>fabs(a00)){
 
 1045         else if(fabs(a00)>fabs(a11)) {
 
 1052             evec[0]=.5* M_SQRT2;
 
 1053             evec[1]=.5* M_SQRT2;
 
 1059         double temp=a11-a00;
 
 1061         double coherence=
sqrt(temp*temp+4*a01*a01);
 
 1063         evec[1]=temp+coherence;
 
 1064         temp=
std::sqrt(evec[0]*evec[0]+evec[1]*evec[1]);
 
 1066             evec[0]=.5* M_SQRT2;
 
 1067             evec[1]=.5* M_SQRT2;
 
 1076             ew(0,0)=.5*(a00+a11+coherence);
 
 1077             ew(1,0)=.5*(a00+a11-coherence);
 
 1087 template <
class T, 
class C2, 
class C3>
 
 1089 symmetricEigensystem3x3(T a00, T a01, T a02, T a11, T a12, T a22,
 
 1090             MultiArrayView<2, T, C2> & ew, MultiArrayView<2, T, C3> & ev)
 
 1093                             &ew(0,0), &ew(1,0), &ew(2,0));
 
 1100     double b1=a00-ew(0,0),
 
 1124     double M = std::max(std::max(
abs(ew(0,0)), 
abs(ew(1,0))), 
abs(ew(2,0)));
 
 1125     double epsilon = 1e-12*M;
 
 1126     if(l0<epsilon) { 
return false; }
 
 1127     if(l1<epsilon) { 
return false; }
 
 1128     if(l2<epsilon) { 
return false; }
 
 1150 template <
class T, 
class C1, 
class C2, 
class C3>
 
 1156         "symmetricEigensystemNoniterative(): symmetric input matrix required.");
 
 1160         detail::symmetricEigensystem2x2(a(0,0), a(0,1), a(1,1), ew, ev);
 
 1166         if(detail::symmetricEigensystem3x3(a(0,0), a(0,1), a(0,2), a(1,1), a(1,2), a(2,2),
 
 1172     vigra_precondition(
false,
 
 1173         "symmetricEigensystemNoniterative(): can only handle 2x2 and 3x3 matrices.");
 
 1192 template <
class T, 
class C1, 
class C2, 
class C3>
 
 1198     vigra_precondition(acols == 
rowCount(a),
 
 1199         "nonsymmetricEigensystem(): square input matrix required.");
 
 1202         "nonsymmetricEigensystem(): matrix shape mismatch.");
 
 1206     detail::nonsymmetricHessenbergReduction(H, ev);
 
 1207     if(!detail::hessenbergQrDecomposition(H, ev, de))
 
 1212         ew(i,0) = std::complex<T>(de(i, 0), de(i, 1));
 
 1232 template <
class POLYNOMIAL, 
class VECTOR>
 
 1235     typedef typename POLYNOMIAL::value_type T;
 
 1236     typedef typename POLYNOMIAL::Real    Real;
 
 1237     typedef typename POLYNOMIAL::Complex Complex;
 
 1241     int const degree = poly.order();
 
 1242     double const eps = poly.epsilon();
 
 1244     TMatrix inMatrix(degree, degree);
 
 1245     for(
int i = 0; i < 
degree; ++i)
 
 1246         inMatrix(0, i) = -poly[degree - i - 1] / poly[
degree];
 
 1247     for(
int i = 0; i < degree - 1; ++i)
 
 1248         inMatrix(i + 1, i) = NumericTraits<T>::one();
 
 1249     ComplexMatrix ew(degree, 1);
 
 1250     TMatrix ev(degree, degree);
 
 1254     for(
int i = 0; i < 
degree; ++i)
 
 1257             vigra::detail::laguerre1Root(poly, ew(i,0), 1);
 
 1258         roots.push_back(vigra::detail::deleteBelowEpsilon(ew(i,0), eps));
 
 1260     std::sort(roots.begin(), roots.end(), vigra::detail::PolynomialRootCompare<Real>(eps));
 
 1264 template <
class POLYNOMIAL, 
class VECTOR>
 
 1287 template <
class POLYNOMIAL, 
class VECTOR>
 
 1290     typedef typename NumericTraits<typename VECTOR::value_type>::ComplexPromote Complex;
 
 1294     for(
unsigned int i = 0; i < croots.
size(); ++i)
 
 1295         if(croots[i].
imag() == 0.0)
 
 1296             roots.push_back(croots[i].
real());
 
 1300 template <
class POLYNOMIAL, 
class VECTOR>
 
 1319 #endif // VIGRA_EIGENSYSTEM_HXX 
vigra::GridGraph< N, DirectedTag >::degree_size_type degree(typename vigra::GridGraph< N, DirectedTag >::vertex_descriptor const &v, vigra::GridGraph< N, DirectedTag > const &g)
Return total number of edges (incoming and outgoing) of vertex v (API: boost). 
Definition: multi_gridgraph.hxx:2828
MultiArrayView< 2, T, C > columnVector(MultiArrayView< 2, T, C > const &m, MultiArrayIndex d)
Definition: matrix.hxx:727
R imag(const FFTWComplex< R > &a)
imaginary part 
Definition: fftw3.hxx:1023
MultiArrayIndex rowCount(const MultiArrayView< 2, T, C > &x)
Definition: matrix.hxx:671
linalg::TemporaryMatrix< T > sqrt(MultiArrayView< 2, T, C > const &v)
void symmetric3x3Eigenvalues(T a00, T a01, T a02, T a11, T a12, T a22, T *r0, T *r1, T *r2)
Compute the eigenvalues of a 3x3 real symmetric matrix. 
Definition: mathutil.hxx:754
bool symmetricEigensystemNoniterative(MultiArrayView< 2, T, C1 > const &a, MultiArrayView< 2, T, C2 > &ew, MultiArrayView< 2, T, C3 > &ev)
Definition: eigensystem.hxx:1152
R real(const FFTWComplex< R > &a)
real part 
Definition: fftw3.hxx:1016
bool isSymmetric(const MultiArrayView< 2, T, C > &v)
Definition: matrix.hxx:779
std::ptrdiff_t MultiArrayIndex
Definition: multi_fwd.hxx:60
FixedPoint16< IntBits, OverflowHandling > hypot(FixedPoint16< IntBits, OverflowHandling > v1, FixedPoint16< IntBits, OverflowHandling > v2)
Length of hypotenuse. 
Definition: fixedpoint.hxx:1640
bool polynomialRealRootsEigenvalueMethod(POLYNOMIAL const &p, VECTOR &roots, bool)
Definition: eigensystem.hxx:1288
FFTWComplex< R >::NormType norm(const FFTWComplex< R > &a)
norm (= magnitude) 
Definition: fftw3.hxx:1037
bool symmetricEigensystem(MultiArrayView< 2, T, C1 > const &a, MultiArrayView< 2, T, C2 > &ew, MultiArrayView< 2, T, C3 > &ev)
Definition: eigensystem.hxx:1008
linalg::TemporaryMatrix< T > sq(MultiArrayView< 2, T, C > const &v)
Matrix< T, ALLLOC >::NormType norm(const Matrix< T, ALLLOC > &a)
bool polynomialRootsEigenvalueMethod(POLYNOMIAL const &poly, VECTOR &roots, bool polishRoots)
Definition: eigensystem.hxx:1233
void copy(const MultiArrayView &rhs)
Definition: multi_array.hxx:1216
MultiArrayIndex columnCount(const MultiArrayView< 2, T, C > &x)
Definition: matrix.hxx:684
size_type size() const 
Definition: array_vector.hxx:358
linalg::TemporaryMatrix< T > abs(MultiArrayView< 2, T, C > const &v)
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root. 
Definition: fixedpoint.hxx:616
MultiArrayView< N-M, T, StrideTag > bindOuter(const TinyVector< Index, M > &d) const 
Definition: multi_array.hxx:2184
bool nonsymmetricEigensystem(MultiArrayView< 2, T, C1 > const &a, MultiArrayView< 2, std::complex< T >, C2 > &ew, MultiArrayView< 2, T, C3 > &ev)
Definition: eigensystem.hxx:1194