31 #include <TooN/TooN.h> 57 template<
int M,
int N = M,
class Precision = DefaultPrecision,
bool WANT_U = 1,
bool WANT_V = 1>
64 static const int BigDim = M>N?M:N;
65 static const int SmallDim = M<N?M:N;
71 Precision get_largest_singular_value();
72 Precision get_smallest_singular_value();
73 int get_smallest_singular_value_index();
82 Precision dMax = get_largest_singular_value();
83 for(
int i=0; i<N; ++i)
84 inv_diag[i] = (vDiagonal[i] * condition > dMax) ?
85 static_cast<Precision
>(1)/vDiagonal[i] : 0;
92 template <
int Rows2,
int Cols2,
typename P2,
typename B2>
98 return (get_V() * diagmult(inv_diag, (get_U().T() * rhs)));
105 template <
int Size,
typename P2,
typename B2>
111 return (get_V() * diagmult(inv_diag, (get_U().T() * rhs)));
119 return diagmult(get_V(),inv_diag) * get_U().T();
126 void Bidiagonalize();
127 void Accumulate_RHS();
128 void Accumulate_LHS();
130 bool Diagonalize_SubLoop(
int k, Precision &z);
144 template<
int M,
int N,
class Precision,
bool WANT_U,
bool WANT_V>
145 template<
class Precision2,
class Base>
156 template<
int M,
int N,
class Precision,
bool WANT_U,
bool WANT_V>
164 Precision scale = 0.0;
166 for(
int i=0; i<N; ++i)
169 vOffDiagonal[i] = scale * g;
175 for(
int k=i; k<M; ++k)
176 scale += abs(mU[k][i]);
179 for(
int k=i; k<M; ++k)
182 s += mU[k][i] * mU[k][i];
184 Precision f = mU[i][i];
186 Precision h = f * g - s;
190 for(
int j=l; j<N; ++j)
193 for(
int k=i; k<M; ++k)
194 s += mU[k][i] * mU[k][j];
196 for(
int k=i; k<M; ++k)
197 mU[k][j] += f * mU[k][i];
200 for(
int k=i; k<M; ++k)
204 vDiagonal[i] = scale * g;
208 if(!(i >= M || i == (N-1)))
210 for(
int k=l; k<N; ++k)
211 scale += abs(mU[i][k]);
214 for(
int k=l; k<N; k++)
217 s += mU[i][k] * mU[i][k];
219 Precision f = mU[i][l];
221 Precision h = f * g - s;
223 for(
int k=l; k<N; ++k)
224 vOffDiagonal[k] = mU[i][k] / h;
227 for(
int j=l; j<M; ++j)
230 for(
int k=l; k<N; ++k)
231 s += mU[j][k] * mU[i][k];
232 for(
int k=l; k<N; ++k)
233 mU[j][k] += s * vOffDiagonal[k];
236 for(
int k=l; k<N; ++k)
240 anorm = max(anorm, abs(vDiagonal[i]) + abs(vOffDiagonal[i]));
246 template<
int M,
int N,
class Precision,
bool WANT_U,
bool WANT_V>
252 mV[N-1][N-1] =
static_cast<Precision
>(1);
253 Precision g = vOffDiagonal[N-1];
256 for(
int i=N-2; i>=0; --i)
261 for(
int j=l; j<N; ++j)
262 mV[j][i] = (mU[i][j] / mU[i][l]) / g;
263 for(
int j=l; j<N; ++j)
266 for(
int k=l; k<N; ++k)
267 s += mU[i][k] * mV[k][j];
268 for(
int k=l; k<N; ++k)
269 mV[k][j] += s * mV[k][i];
272 for(
int j=l; j<N; ++j)
273 mV[i][j] = mV[j][i] = 0;
274 mV[i][i] =
static_cast<Precision
>(1);
279 template<
int M,
int N,
class Precision,
bool WANT_U,
bool WANT_V>
284 for(
int i=SmallDim-1; i>=0; --i)
287 Precision g = vDiagonal[i];
290 for(
int j=l; j<N; ++j)
293 for(
int j=i; j<M; ++j)
298 Precision inv_g =
static_cast<Precision
>(1) / g;
299 if(i != (SmallDim-1))
301 for(
int j=l; j<N; ++j)
304 for(
int k=l; k<M; ++k)
305 s += mU[k][i] * mU[k][j];
306 Precision f = (s / mU[i][i]) * inv_g;
307 for(
int k=i; k<M; ++k)
308 mU[k][j] += f * mU[k][i];
311 for(
int j=i; j<M; ++j)
314 mU[i][i] +=
static_cast<Precision
>(1);
318 template<
int M,
int N,
class Precision,
bool WANT_U,
bool WANT_V>
322 for(
int k=N-1; k>=0; --k)
326 bool bConverged_Or_Error =
false;
328 bConverged_Or_Error = Diagonalize_SubLoop(k, z);
329 while(!bConverged_Or_Error);
338 for(
int j=0; j<N; ++j)
339 mV[j][k] = -mV[j][k];
345 template<
int M,
int N,
class Precision,
bool WANT_U,
bool WANT_V>
352 for(
int l=k; l>=0; --l)
355 if((abs(vOffDiagonal[l]) + anorm) == anorm)
357 if((abs(vDiagonal[l1]) + anorm) == anorm)
365 for(
int i=l; i<=k; ++i)
367 Precision f = s * vOffDiagonal[i];
368 vOffDiagonal[i] *= c;
369 if((abs(f) + anorm) == anorm)
371 Precision g = vDiagonal[i];
372 Precision h =
sqrt(f * f + g * g);
377 for(
int j=0; j<M; ++j)
379 Precision y = mU[j][l1];
380 Precision z = mU[j][i];
381 mU[j][l1] = y*c + z*s;
382 mU[j][i] = -y*s + z*c;
393 if(nIterations == 30)
399 Precision x = vDiagonal[l];
400 Precision y = vDiagonal[k1];
401 Precision g = vOffDiagonal[k1];
402 Precision h = vOffDiagonal[k];
403 Precision f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2.0*h*y);
405 Precision signed_g = (f>=0)?g:-g;
406 f = ((x-z)*(x+z) + h*(y/(f + signed_g) - h)) / x;
411 for(
int i1 = l; i1<=k1; ++i1)
419 vOffDiagonal[i1] = z;
427 for(
int j=0; j<N; ++j)
429 Precision xx = mV[j][i1];
430 Precision zz = mV[j][i];
431 mV[j][i1] = xx*c + zz*s;
432 mV[j][i] = -xx*s + zz*c;
444 for(
int j=0; j<M; ++j)
446 Precision yy = mU[j][i1];
447 Precision zz = mU[j][i];
448 mU[j][i1] = yy*c + zz*s;
449 mU[j][i] = -yy*s + zz*c;
465 template<
int M,
int N,
class Precision,
bool WANT_U,
bool WANT_V>
469 Precision d = vDiagonal[0];
470 for(
int i=1; i<N; ++i) d = max(d, vDiagonal[i]);
474 template<
int M,
int N,
class Precision,
bool WANT_U,
bool WANT_V>
478 Precision d = vDiagonal[0];
479 for(
int i=1; i<N; ++i) d = min(d, vDiagonal[i]);
483 template<
int M,
int N,
class Precision,
bool WANT_U,
bool WANT_V>
488 Precision d = vDiagonal[0];
489 for(
int i=1; i<N; ++i)
498 template<
int M,
int N,
class Precision,
bool WANT_U,
bool WANT_V>
501 std::vector<std::pair<Precision, unsigned int> > vSort;
503 for(
unsigned int i=0; i<N; ++i)
504 vSort.push_back(std::make_pair(-vDiagonal[i], i));
505 std::sort(vSort.begin(), vSort.end());
506 for(
unsigned int i=0; i<N; ++i)
507 vDiagonal[i] = -vSort[i].first;
511 for(
unsigned int i=0; i<N; ++i)
512 mU.T()[i] = mU_copy.T()[vSort[i].second];
517 for(
unsigned int i=0; i<N; ++i)
518 mV.T()[i] = mV_copy.T()[vSort[i].second];
Vector< N, typename Internal::MultiplyType< Precision, P2 >::type > backsub(const Vector< Size, P2, B2 > &rhs, const Precision condition=1e9)
Calculate result of multiplying the (pseudo-)inverse of M by a vector.
Definition: GR_SVD.h:107
Pretty generic SFINAE introspection generator.
Definition: vec_test.cc:21
A matrix.
Definition: matrix.hh:105
Performs SVD and back substitute to solve equations.
Definition: GR_SVD.h:58
void get_inv_diag(Vector< N > &inv_diag, const Precision condition)
Return the pesudo-inverse diagonal.
Definition: GR_SVD.h:80
Matrix< N, Cols2, typename Internal::MultiplyType< Precision, P2 >::type > backsub(const Matrix< Rows2, Cols2, P2, B2 > &rhs, const Precision condition=1e9)
Calculate result of multiplying the (pseudo-)inverse of M by another matrix.
Definition: GR_SVD.h:94
Matrix< R, C, P > sqrt(const Matrix< R, C, P, B > &m)
computes a matrix square root of a matrix m by the product form of the Denman and Beavers iteration a...
Definition: helpers.h:350
void reorder()
Reorder the components so the singular values are in descending order.
Definition: GR_SVD.h:499
Matrix< N, M, Precision > get_pinv(const Precision condition=1e9)
Get the pseudo-inverse .
Definition: GR_SVD.h:115