42 #ifndef GNSSTK_MATRIX_FUNCTORS_HPP
43 #define GNSSTK_MATRIX_FUNCTORS_HPP
107 template <
class BaseClass>
110 const T eps=T(8)*std::numeric_limits<T>::epsilon();
118 size_t n(
U.cols()), m(
U.rows());
119 size_t i, j, k, l, nm, jj;
120 T anorm(0), scale(0), g(0), s, f, h, c, x,
y, z;
126 for (i = 0; i < n; i++) {
129 g = s = scale = T(0);
131 for(k = i; k < m; k++) scale +=
ABS(
U(k, i));
133 for(k = i; k < m; k++) {
135 s +=
U(k, i) *
U(k, i);
141 for(j = l; j < n; j++) {
142 for(s = T(0), k = i; k < m; k++) s +=
U(k, i) *
U(k, j);
144 for(k = i; k < m; k++)
U(k, j) += f *
U(k, i);
146 for(k = i; k < m; k++)
U(k, i) *= scale;
150 g = s = scale = T(0);
151 if ( (i < m) && (i != n-1) ) {
152 for(k = l; k < n; k++) scale +=
ABS(
U(i, k));
154 for(k = l; k < n; k++) {
156 s +=
U(i, k) *
U(i, k);
162 for(k = l; k < n; k++) B[k] =
U(i, k) / h;
163 for(j = l; j < m; j++) {
164 for(s = T(0), k = l; k < n; k++) s +=
U(j, k) *
U(i, k);
165 for(k = l; k < n; k++)
U(j, k) += s * B[k];
167 for(k = l; k < n; k++)
U(i, k) *= scale;
172 for(i = n - 1; ; i--) {
175 for(j = l; j < n; j++)
V(j, i) = (
U(i, j) /
U(i, l)) / g;
176 for(j = l; j < n; j++) {
177 for(s = T(0), k = l; k < n; k++) s +=
U(i, k) *
V(k, j);
178 for(k = l; k < n; k++)
V(k, j) += s *
V(k, i);
181 for(j = l; j < n; j++)
V(j, i) =
V(i, j) = T(0);
188 for(i = ( (m-1 < n-1) ? m-1 : n-1); ; i--) {
191 for(j=l; j<n; j++)
U(i, j) = T(0);
194 for(j = l; j < n; j++) {
195 for(s = T(0), k = l; k < m; k++) s +=
U(k,i) *
U(k,j);
196 f = (s /
U(i,i)) * g;
197 for(k=i; k<m; k++)
U(k,j) += f *
U(k,i);
199 for(j = i; j < m; j++)
U(j,i) *= g;
202 for(j=i; j<m; j++)
U(j,i) = T(0);
207 for(k = n - 1; ; k--) {
213 if (
ABS(B[l])/
MAX(
ABS(B[l]),anorm) < eps) {
218 MatrixException e(
"SVD algorithm has nm==-1");
227 for(i = l; i <= k; i++) {
230 if (
ABS(f)/
MAX(
ABS(f),anorm) < eps)
break;
237 for(j = 0; j < m; j++) {
240 U(j, nm) =
y * c + z * s;
241 U(j,i) = z * c -
y * s;
249 for(j = 0; j < n; j++)
V(j,k) = -
V(j,k);
255 MatrixException e(
"SVD algorithm did not converge");
260 MatrixException e(
"SVD algorithm has k==0");
267 f = ( (
y-z) * (
y+z) + (g-h) * (g+h)) / (T(2) * h *
y);
269 f = ( (x-z) * (x+z) + h * ((
y/(f +
SIGN(g,f))) - h)) / x;
271 for(j = l; j <= nm; j++) {
285 for(jj = 0; jj < n; jj++) {
288 V(jj, j) = x * c + z * s;
289 V(jj, i) = z * c - x * s;
300 for(jj = 0; jj < m; jj++) {
303 U(jj, j) =
y * c + z * s;
304 U(jj, i) = z * c -
y * s;
314 if(
U.cols() >
U.rows()) {
315 for(i=1; i<
S.size(); i++) {
331 S.resize(Temp.
rows());
354 template <
class BaseClass>
357 if(b.
size() !=
U.rows())
359 MatrixException e(
"SVD::BackSub called with unequal dimensions");
363 size_t i, n=
V.cols(), m=
U.rows();
365 for(i=0; i<
S.size(); i++) W(i,i)=(
S(i)==T(0)?T(0):T(1)/
S(i));
378 void sort(
bool descending=
true)
382 for(i=1; i<
S.size(); i++) {
387 if(descending && sv < svj)
break;
388 if(!descending && sv > svj)
break;
405 for(
size_t i=0; i<
S.size(); i++) d *=
S(i);
442 template <
class BaseClass>
446 MatrixException e(
"LUDecomp requires a square, non-trivial matrix");
450 size_t N=m.
rows(),i,j,k,imax;
466 SingularMatrixException e(
"singular matrix!");
475 for(k=0; k<i; k++) t -=
LU(i,k)*
LU(k,j);
481 for(k=0; k<j; k++) t -=
LU(i,k)*
LU(k,j);
499 SingularMatrixException e(
"singular matrix!");
504 for(i=j+1; i<N; i++)
LU(i,j) *= d;
513 template <
class BaseClass2>
516 if(
LU.rows() != v.
size()) {
517 MatrixException e(
"Vector size does not match dimension of LUDecomp");
522 size_t N=
LU.rows(),i,j,ii(0);
529 if(first &&
sum != T(0)) {
533 else for(j=ii; j<i; j++)
sum -=
LU(i,j)*v(j);
539 for(j=i+1; j<N; j++)
sum -=
LU(i,j)*v(j);
540 v(i) =
sum /
LU(i,i);
550 T d(
static_cast<T
>(
parity));
551 for(
size_t i=0; i<
LU.rows(); i++) d *=
LU(i,i);
599 template <
class BaseClass>
603 MatrixException e(
"Cholesky requires a square matrix");
607 size_t N=m.
rows(),i,j,k;
614 MatrixException e(
"Cholesky fails - eigenvalue <= 0");
620 for(k=0; k<j; k++)
U(k,j)=d*
P(k,j);
623 P(i,k) -=
U(k,j)*
U(i,j);
630 for(j=0; j<=N-1; j++) {
632 MatrixException e(
"Cholesky fails - eigenvalue <= 0");
638 for(k=j+1; k<N; k++)
L(k,j)=d*
P(k,j);
639 for(k=j+1; k<N; k++) {
641 P(i,k) -=
L(i,j)*
L(k,j);
655 template <
class BaseClass2>
658 if (
L.rows() != b.
size())
660 MatrixException e(
"Vector size does not match dimension of Cholesky");
663 size_t i,j,N=
L.rows();
669 for(j=0; j<i; j++)
y(i)-=
L(i,j)*
y(j);
673 b(N-1) =
y(N-1)/
L(N-1,N-1);
676 for(j=i+1; j<N; j++) b(i)-=
L(j,i)*b(j);
706 template <
class BaseClass>
710 MatrixException e(
"CholeskyCrout requires a square matrix");
714 int N = m.
rows(), i, j, k;
720 for(k=0; k<j; k++ )
sum -= (*this).L(j,k)*(*this).L(j,k);
724 MatrixException e(
"CholeskyCrout fails - eigenvalue <= 0");
728 for(i=j+1; i<N; i++){
730 for(k=0; k<j; k++)
sum -= (*this).L(i,k)*(*this).L(j,k);
731 (*this).L(i,j) =
sum/(*this).L(j,j);
764 template <
class BaseClass>
773 const T EPS(1.e-200);
774 for(j=0; (j<
A.cols()-1 && j<
A.rows()-1); j++) {
777 for(i=j; i<
A.rows(); i++) {
783 if(
sum < EPS)
continue;
786 if(v(j) > T(0))
sum = -
sum;
792 for(k=j+1; k<
A.cols(); k++) {
795 for(i=j; i<
A.rows(); i++) {
796 alpha +=
A(i,k)*v(i);
799 if(alpha*alpha < EPS)
continue;
801 for(i=j; i<
A.rows(); i++) {
802 A(i,k) += alpha*v(i);