74 #ifndef SLIP_LINEAR_ALGEBRA_SVD_HPP
75 #define SLIP_LINEAR_ALGEBRA_SVD_HPP
143 template<
typename Matrix1,
155 assert(X.rows() >= X.rows());
156 assert(U.rows() == X.rows());
157 assert(U.cols() == X.cols());
158 assert(V.rows() == V.cols());
159 assert(V.rows() == X.cols());
160 assert(d.
size() == X.cols());
161 assert((e.
size() + 1) == X.cols());
163 typedef typename Matrix1::value_type value_type;
165 std::size_t X_rows = X.rows();
166 std::size_t X_cols = X.cols();
168 std::fill(U.begin(),U.end(),value_type(0));
169 std::fill(V.begin(),V.end(),value_type(0));
178 for(std::size_t k=0;k<X_cols;++k)
180 if((k<X_cols-1)||(X_rows>X_cols))
182 slip::housegen(X.col_begin(k)+k,X.col_end(k),a.begin()+(k),a.end(),d[k]);
184 std::copy(a.begin()+(k),a.end(),X.col_begin(k)+k);
185 box.
set_coord(
int(k),
int(k+1),
int(X_rows-1),
int(X_cols-1));
188 X.upper_left(box),X.bottom_right(box));
198 box2.
set_coord(
int(k+1),
int(k+1),
int(X_rows-1),
int(X_cols-1));
201 X.upper_left(box2),X.bottom_right(box2));
208 e[X_cols-2]=X[X_cols-2][X_cols-1];
210 if((X_rows)==(X_cols))
212 d[X_cols-1]=X[X_cols-1][X_cols-1];
218 U.
fill(value_type(0));
219 std::size_t U_cols = X.cols();
220 for (std::size_t i = 0; i < U_cols; ++i)
222 U[i][i] = value_type(1);
225 std::size_t min_np=
std::min(X_cols-1,X_rows-2);
226 for(
int k=min_np;k>=0;k--)
228 std::copy(X.col_begin(k)+k,X.col_end(k),a.begin()+k);
229 box.
set_coord(
int(k),
int(k),
int(X.rows()-1),
int(X.cols()-1));
231 U.upper_left(box),U.bottom_right(box));
236 V.fill(value_type(0.0));
237 std::size_t V_cols = X.cols();
238 for (std::size_t i = 0; i < V_cols; ++i)
240 V[i][i] = value_type(1.0);
243 for(
int k=
int((X_cols-3));k>=0;k--)
246 box2.
set_coord(
int(k+1),
int(k+1),
int(X_cols-1),
int(X_cols-1));
248 V.upper_left(box2),V.bottom_right(box2));
276 template<
typename Matrix,
typename Vector>
287 std::size_t d_size = d.
size();
290 for(std::size_t k=0;k<d_size;k++)
303 if(k==(d_size-1))
break;
342 template<
typename Matrix,
typename Vector,
typename Real,
typename SizeType >
346 const SizeType& row1,
347 const SizeType& row2,
358 Real d1 = d[row1]/scl;
359 Real e1 = e[row1]/scl;
360 Real sig = sigma/scl;
361 Real f = (d1+sig) * (d1-sig);
363 SizeType row2_m1 = row2 - 1;
364 SizeType V_rows_m1 = V.
rows() - 1;
365 SizeType U_rows_m1 = U.
rows() - 1;
370 for (SizeType k = row1; k <= row2_m1; ++k)
377 f = (c*d[k]) + (s*e[k]);
378 e[k] = (c*e[k]) - (s*d[k]);
384 f = (c * e[k]) + (s * d[k+1]);
385 d[k+1] = (c * d[k+1]) - (s * e[k]);
417 template <
typename Real >
426 Real a = (ppq * ppq) + r2;
427 Real b = (pmq * pmq) + r2;
429 if(sigma_max != Real(0.0))
431 sigma = (
std::abs(p*q)) / sigma_max;
458 template<
typename Vector,
typename SizeType>
467 assert(l < d.
size());
468 assert(i1 < d.
size());
469 assert(i2 < d.
size());
472 value_type tau = value_type(0);
482 if(e[i1-1] != value_type(0.0))
484 tau = d[i1] * (tau/(tau +
std::abs(e[i1-1])));
490 e[i1-1] = value_type(0.0);
587 template<
typename Matrix1,
589 typename RandomAccessIterator,
593 RandomAccessIterator S_first,
594 RandomAccessIterator S_last,
596 const int max_it = 75)
599 assert(M.rows() >= M.cols());
600 assert(M.rows() == U.rows());
601 assert(M.cols() == U.cols());
602 assert(
int(M.cols()) ==
int((S_last-S_first)));
603 assert(V.rows() == M.cols());
605 typedef typename Matrix1::value_type value_type;
610 std::size_t X_cols = X.cols();
611 std::size_t X_cols_m1 = X_cols - 1;
630 std::size_t e1_size = e1.size();
631 for(std::size_t i = 0; i < e1_size; ++i)
633 d[i] = std::real(d1[i]);
634 e[i] = std::real(e1[i]);
637 d[e1_size] = std::real(d1[e1_size]);
643 std::size_t i2 = X_cols_m1;
645 real sigma =
real(0);
646 std::size_t oldi2 = 0;
675 for(std::size_t k = 0; k < X_cols; ++k)
681 real(-1),V.col_begin(k));
685 for(std::size_t k = 0; k < X_cols_m1; ++k)
693 std::swap_ranges(V.col_begin(k),V.col_end(k),V.col_begin(k+1));
694 std::swap_ranges(U.col_begin(k),U.col_end(k),U.col_begin(k+1));
773 template<
typename Matrix,
typename Matrix2>
778 const int max_it = 75)
783 assert(S.rows() == S.cols());
784 assert(X.
cols() == S.cols());
792 std::fill(S.begin(),S.end(),0);
834 template<
typename Matrix1,
typename RandomAccessIterator,
typename Matrix2,
typename Matrix3>
837 RandomAccessIterator S_first,
838 RandomAccessIterator S_last,
843 assert(X.rows() >= X.cols());
844 assert(V.rows() == V.cols());
845 assert(X.rows() == U.rows());
846 assert(X.cols() == U.cols());
847 assert(
int(S_last-S_first) ==
int(U.cols()));
848 assert(
int(S_last-S_first) ==
int(V.rows()));
849 assert(K <= U.cols());
851 std::size_t U_rows = U.rows();
853 std::size_t V_rows = V.rows();
854 for(std::size_t i = 0; i < U_rows; ++i)
856 for(std::size_t j = 0; j < V_rows; ++j)
859 for(std::size_t k = 0; k < K; ++k)
861 X[i][j] += S_first[k] * U[i][k] *
slip::conj(V[j][k]);
902 template <
class Matrix1,
class Matrix2,
class Matrix3,
class Matrix4>
944 template <
class Matrix1,
945 typename RandomAccessIterator1,
947 typename RandomAccessIterator2,
948 typename RandomAccessIterator3>
951 RandomAccessIterator1 W_first,
952 RandomAccessIterator1 W_last,
954 RandomAccessIterator2 B_first,
955 RandomAccessIterator2 B_last,
956 RandomAccessIterator3 X_first,
957 RandomAccessIterator3 X_last)
959 assert(U.rows() >= U.cols());
960 assert(
int(X_last - X_first) ==
int(U.cols()));
961 assert(
int(B_last - B_first) ==
int(U.rows()));
962 assert(
int(W_last - W_first) ==
int(U.cols()));
963 assert(V.rows() == U.cols());
964 typedef typename Matrix1::value_type value_type;
967 std::size_t U_cols = U.cols();
971 for (std::size_t j = 0; j < U_cols; ++j)
974 value_type s = value_type(0.0);
977 if (W_first[j] !=
real(0.0))
980 B_first,value_type(0.0));
1031 template <
class Matrix1,
1032 typename RandomAccessIterator1,
1033 typename RandomAccessIterator2>
1036 RandomAccessIterator1 X_first,
1037 RandomAccessIterator1 X_last,
1038 RandomAccessIterator2 B_first,
1039 RandomAccessIterator2 B_last)
1041 assert(A.rows() >= A.cols());
1042 assert(
int(X_last - X_first) ==
int(A.cols()));
1043 assert(
int(B_last - B_first) ==
int(A.rows()));
1045 typedef typename Matrix1::value_type value_type;
1061 real Smin = Smax * slip::epsilon<value_type>();
1062 std::replace_if(S.begin(),S.end(),std::bind2nd(std::less<real>(), Smin),
real(0));
1110 template <
class Matrix1,
1143 template <
class Matrix1,
1144 typename RandomAccessIterator1,
1149 RandomAccessIterator1 W_first,
1150 RandomAccessIterator1 W_last,
1155 typedef typename Matrix1::value_type value_type;
1157 std::size_t U_rows = U.rows();
1158 std::size_t U_cols = U.cols();
1163 real Wmax = *W_first;
1164 real Wmin = Wmax * slip::epsilon<value_type>();
1165 std::replace_if(W_first,W_last,std::bind2nd(std::less<real>(), Wmin),
real(0));
1169 RandomAccessIterator1 it = std::find(W_first,W_last,
real(0));
1170 std::size_t K = std::size_t(it - W_first);
1173 for(std::size_t i = 0; i < U_cols; ++i)
1175 for(std::size_t j = 0; j < U_rows; ++j)
1179 for(std::size_t k = 0; k < K; ++k)
1182 Ainv[i][j] += (
real(1)/W_first[k]) *
slip::conj(U[j][k]) * V[i][k];
1218 template <
class Matrix1,
1224 typedef typename Matrix1::value_type value_type;
1271 template <
class Matrix1,
1282 #endif //SLIP_LINEAR_ALGEBRA_SVD_HPP
Provides a class to manipulate 2d dynamic and generic arrays.
bool is_complex(const T &val)
Test if an element is complex.
void set_coord(const CoordType &x11, const CoordType &x12, const CoordType &x21, const CoordType &x22)
Mutator of the coordinates of the Box2d.
void right_householder_update(RandomAccessIterator V_first, RandomAccessIterator V_last, MatrixIterator1 M_up, MatrixIterator1 M_bot)
right multiplies the matrix M with the Householder matrix P:
void set_diagonal(RandomAccessIterator1 diag_first, RandomAccessIterator1 diag_last, Container2d &container, const int diag_number=0)
Set the diagonal [diag_first,diag_last) in the diagonal diag_number of a 2d container.
void svd_inv(const Matrix1 &U, RandomAccessIterator1 W_first, RandomAccessIterator1 W_last, const Matrix2 &V, Matrix3 &Ainv)
Singular Value inverse of a matrix from its Singular Value Decomposition given by U...
void pinv(const Matrix1 &A, Matrix2 &Ainv)
Pseudo inverse of a matrix.
iterator end()
Returns a read/write iterator that points one past the last element in the Vector. Iteration is done in ordinary element order.
T & min(const GrayscaleImage< T > &M1)
Returns the min element of a GrayscaleImage.
iterator begin()
Returns a read/write iterator that points to the first element in the Matrix. Iteration is done in or...
slip::lin_alg_traits< T >::value_type epsilon()
Returns the epsilon value of a real or a complex.
void rotgen(Real &a, Real &b, Real &cos, Real &sin)
Computes the Givens sinus and cosinus.
void shift(Real &p, Real &r, Real &q, Real &sigma)
Given a matrix compute the smallest singular value of this matrix.
void BiReduce(Matrix1 &X, Vector &d, Vector &e, Matrix2 &U, Matrix3 &V)
BiReduce. Given an n*p matrix X with n>=p Bireduce reduce X to an upper bidiagola form The tranformat...
size_type cols() const
Returns the number of columns (second dimension size) in the Matrix.
void matrix_vector_multiplies(RandomAccessIterator2d M_upper_left, RandomAccessIterator2d M_bottom_right, RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 result_first, RandomAccessIterator2 result_last)
Computes the multiplication of a Matrix and a Vector: Result=MV.
void svd_solve(const Matrix1 &U, RandomAccessIterator1 W_first, RandomAccessIterator1 W_last, const Matrix2 &V, RandomAccessIterator2 B_first, RandomAccessIterator2 B_last, RandomAccessIterator3 X_first, RandomAccessIterator3 X_last)
Solve Linear (USV^H).X = B where U, S and V are provided by a svd decomposition.
Provides common linear algebra algorithms.
col_iterator col_end(const size_type col)
Returns a read/write iterator that points one past the end element of the column column in the Matrix...
void real(const Matrix1 &C, Matrix2 &R)
Extract the real Matrix of a complex Matrix. .
HyperVolume< T > abs(const HyperVolume< T > &M)
void left_householder_update(RandomAccessIterator V_first, RandomAccessIterator V_last, MatrixIterator1 M_up, MatrixIterator1 M_bot)
Left multiplies the Householder matrix P with the matrix M: .
void BiQR(Vector &d, Vector &e, Real &sigma, const SizeType &row1, const SizeType &row2, Matrix &U, Matrix &V)
BiQR Given an upper bidiagonal matrix B and a shift sigma, BiQR performs a QR step between rows row1 ...
void right_givens(Matrix &M, const SizeType &col1, const SizeType &col2, const Real &sinus, const Real &cosinus, const SizeType &row1, const SizeType &row2)
Apply right Givens rotation multiplication.
size_type size() const
Returns the number of elements in the Vector.
void fill(const T &value)
Fills the container range [begin(),begin()+size()) with copies of value.
void vector_scalar_multiplies(RandomAccessIterator1 V_first, RandomAccessIterator1 V_last, const T &scal, RandomAccessIterator2 result_first)
Computes the multiplication of a vector V by a scalar scal.
void Bi_complex_to_real(Vector &d, Vector &e, Matrix &U, Matrix &V)
BiQR Given an upper bidiagonal matrix B, Bi_complex_to_real transforms the complex bidiagonal form in...
void copy(_II first, _II last, _OI output_first)
Copy algorithm optimized for slip iterators.
Provides some macros which are used for using complex as real.
Numerical Vector class. This container statisfies the RandomAccessContainer concepts of the Standard ...
void housegen(VectorIterator1 a_begin, VectorIterator1 a_end, VectorIterator2 u_begin, VectorIterator2 u_end, typename std::iterator_traits< VectorIterator1 >::value_type &nu)
Compute the Householder vector u of a vector a.
Provides some mathematical functors and constants.
HyperVolume< T > sqrt(const HyperVolume< T > &M)
Numerical matrix class. This container statisfies the BidirectionnalContainer concepts of the STL...
size_type rows() const
Returns the number of rows (first dimension size) in the Matrix.
std::iterator_traits< RandomAccessIterator1 >::value_type hermitian_inner_product(RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, typename std::iterator_traits< RandomAccessIterator1 >::value_type init)
Computes the hermitian inner-product of two ranges X and Y: .
col_iterator col_begin(const size_type col)
Returns a read/write iterator that points to the first element of the column column in the Matrix...
void svd(const Matrix1 &M, Matrix2 &U, RandomAccessIterator S_first, RandomAccessIterator S_last, Matrix3 &V, const int max_it=75)
(thin) Singular Value Decomposition Given a matrix M, this function computes its singular value decom...
void get_diagonal(const Container2d &container, RandomAccessIterator1 diag_first, RandomAccessIterator1 diag_last, const int diag_number=0)
Get the diagonal diag_number of a 2d container.
void BdBacksearch(Vector &d, Vector &e, const typename slip::lin_alg_traits< typename Vector::value_type >::value_type tol, SizeType &l, SizeType &i1, SizeType &i2)
Back searching a bidiagonal Matrix this algorithm takes a bidiagobal matrix B, a tolerance tol and an...
This is a linear (one-dimensional) dynamic template container. This container statisfies the RandomAc...
void svd_approx(const Matrix1 &U, RandomAccessIterator S_first, RandomAccessIterator S_last, const Matrix2 &V, const std::size_t K, Matrix3 &X)
Singular Value Approximation of a matrix from its Singular Value Decomposition given by U...
Provides a class to manipulate numerical vectors.
This is a two-dimensional dynamic and generic container. This container statisfies the Bidirectionnal...
T & max(const GrayscaleImage< T > &M1)
Returns the max element of a GrayscaleImage.
iterator begin()
Returns a read/write iterator that points to the first element in the Vector. Iteration is done in or...
Provides some algorithms to compute norms.