1 #ifndef CEDRIC_ANALYSIS_SVD_H
2 #define CEDRIC_ANALYSIS_SVD_H
10 #include <boost/numeric/ublas/matrix.hpp>
11 #include <boost/numeric/ublas/vector.hpp>
19 template<
class ValueType>
23 typedef boost::numeric::ublas::matrix<ValueType>
Matrix;
24 typedef boost::numeric::ublas::vector<ValueType>
Vector;
62 #ifdef NRUTIL_REPLACEMENT
66 inline T
SQR( T arg ) {
return arg == 0.0 ? 0.0 : arg*arg; }
69 inline T
SIGN( T a, T b ) {
return b >= 0.0 ? fabs(a) : fabs(b); }
73 static double maxarg1,maxarg2;
74 #define FMAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\
75 (maxarg1) : (maxarg2))
76 static int iminarg1,iminarg2;
77 #define IMIN(a,b) (iminarg1=(a),iminarg2=(b),(iminarg1) < (iminarg2) ?\
78 (iminarg1) : (iminarg2))
79 #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
81 #define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)
93 return absa*sqrt(1.0+
SQR(absb/absa));
95 return (absb == 0.0 ? 0.0 : absb*sqrt(1.0+
SQR(absa/absb)));
98 template<
class Matrix,
class Vector>
void swap_columns( Matrix& M,
int i,
int j )
100 Vector v = boost::numeric::ublas::column(M,i);
101 boost::numeric::ublas::column(M,i) = boost::numeric::ublas::column(M,j);
102 boost::numeric::ublas::column(M,j) = v;
116 : m_rows( matrix.size1() ),
117 m_cols( matrix.size2() ),
119 m_V( m_cols, m_cols )
121 svdcmp( matrix, m_S, m_V );
125 for(
unsigned int run=0; run < m_S.size(); ++run )
129 for(
unsigned int i=0; i < m_S.size()-1; ++i )
131 if( m_S[i] < m_S[i+1] )
137 swap_columns<Matrix,Vector>( matrix, i, i+1 );
138 swap_columns<Matrix,Vector>( m_V, i, i+1 );
157 int flag,i,its,j,jj,k,l,nm;
159 double anorm,c,f,g,h,s,scale,x,y,z;
161 std::vector<double> rv1( n );
173 for (k=i;k<=m;k++) scale += fabs(a(k-1,i-1));
179 s += a(k-1,i-1)*a(k-1,i-1);
183 g = -
SIGN(sqrt(s),f);
189 for (s=0.0,k=i;k<=m;k++) s += a(k-1,i-1)*a(k-1,j-1);
191 for (k=i;k<=m;k++) a(k-1,j-1) += f*a(k-1,i-1);
194 for (k=i;k<=m;k++) a(k-1,i-1) *= scale;
201 if (i <= m && i != n)
203 for (k=l;k<=n;k++) scale += fabs(a(i-1,k-1));
209 s += a(i-1,k-1)*a(i-1,k-1);
213 g = -
SIGN(sqrt(s),f);
217 for (k=l;k<=n;k++) rv1[k-1]=a(i-1,k-1)/h;
221 for (s=0.0,k=l;k<=n;k++) s += a(j-1,k-1)*a(i-1,k-1);
222 for (k=l;k<=n;k++) a(j-1,k-1) += s*rv1[k-1];
225 for (k=l;k<=n;k++) a(i-1,k-1) *= scale;
229 #ifdef NRUTIL_REPLACEMENT
230 anorm=std::max(anorm,(fabs(w[i-1])+fabs(rv1[i-1])));
232 anorm=
FMAX(anorm,(fabs(w[i-1])+fabs(rv1[i])));
244 v(j-1,i-1)=(a(i-1,j-1)/a(i-1,l-1))/g;
248 for (s=0.0,k=l;k<=n;k++) s += a(i-1,k-1)*v(k-1,j-1);
249 for (k=l;k<=n;k++) v(k-1,j-1) += s*v(k-1,i-1);
253 for (j=l;j<=n;j++) v(i-1,j-1)=v(j-1,i-1)=0.0;
261 #ifdef NRUTIL_REPLACEMENT
262 for (i=std::min(m,n);i>=1;i--)
264 for (i=
IMIN(m,n);i>=1;i--)
270 for (j=l;j<=n;j++) a(i-1,j-1)=0.0;
278 for (s=0.0,k=l;k<=m;k++) s += a(k-1,i-1)*a(k-1,j-1);
280 for (k=i;k<=m;k++) a(k-1,j-1) += f*a(k-1,i-1);
283 for (j=i;j<=m;j++) a(j-1,i-1) *= g;
286 else for (j=i;j<=m;j++) a(j-1,i-1)=0.0;
295 for (its=1;its<=30;its++)
301 if ((
double)(fabs(rv1[l-1])+anorm) == anorm)
307 if ((
double)(fabs(w[nm-1])+anorm) == anorm)
break;
319 if ((
double)(fabs(f)+anorm) == anorm)
break;
344 for (j=1;j<=n;j++) v(j-1,k-1) = -v(j-1,k-1);
349 if (its == 30) assert(
false);
357 f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
359 f=((x-z)*(x+z)+h*((y/(f+
SIGN(g,f)))-h))/x;
377 for (jj=1;jj<=n;jj++)
398 for (jj=1;jj<=m;jj++)
414 #endif // CEDRIC_ANALYSIS_SVD_H
boost::numeric::ublas::vector< ValueType > Vector
Definition: SVD.h:24
const Vector & getSingularValues() const
Definition: SVD.h:37
void svdcmp(Matrix &a, Vector &w, Matrix &v)
Definition: SVD.h:152
SVD(Matrix &matrix)
Compute Singular Value Decomposition.
Definition: SVD.h:115
boost::numeric::ublas::matrix< ValueType > Matrix
Definition: SVD.h:23
const Matrix & getV() const
Definition: SVD.h:41
#define SQR(a)
Definition: SVD.h:81
#define FMAX(a, b)
Definition: SVD.h:74
Compute Singular Value Decomposition, Wrapper for super-old Numerical Recipes code.
Definition: SVD.h:20
#define SIGN(a, b)
Definition: SVD.h:79
#define IMIN(a, b)
Definition: SVD.h:77