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