32 #ifndef __VMML__MATRIX_PSEUDOINVERSE__HPP__
33 #define __VMML__MATRIX_PSEUDOINVERSE__HPP__
36 #include <vmmlib/matrix.hpp>
37 #include <vmmlib/vector.hpp>
40 #include <vmmlib/lapack_svd.hpp>
41 #include <vmmlib/blas_dgemm.hpp>
55 template<
typename T,
typename T
internal =
double >
58 typedef typename T::value_type Texternal;
97 void operator()(
const T& input, T& pseudoinverse_transposed) {
100 if (T::ROWS < T::COLS) {
102 compute_inv(input, pseudoinverse_transposed);
105 compute(input, pseudoinverse_transposed);
109 void compute_inv(
const T& input, T& pseudoinverse_transposed,
110 typename T::value_type tolerance = std::numeric_limits< typename T::value_type >::epsilon()) {
111 if (_work_inv == 0) {
112 _work_inv =
new tmp_matrices_inv();
118 matrix_nm_type& U = _work_inv->U;
119 vec_m_type& sigmas = _work_inv->sigmas;
120 matrix_mm_type& Vt = _work_inv->Vt;
121 matrix_nm_type& in_data = _work_inv->input;
122 in_data.cast_from(transpose(input));
124 bool svd_ok = svd.compute(in_data, U, sigmas, Vt);
127 VMMLIB_ERROR(
"matrix compute_pseudoinverse - problem with lapack svd.", VMMLIB_HERE);
135 typename vector< T::ROWS, Tinternal >::const_iterator it = sigmas.begin(), it_end = sigmas.end();
136 size_t num_sigmas = 0;
137 for (; it != it_end; ++it) {
138 if (*it >= tolerance)
145 matrix_mn_type& result = _work_inv->result;
148 matrix_mn_type& tmp = _work_inv->tmp;
150 sigmas.reciprocal_safe();
154 blas_type_inv blas_dgemm1;
156 if (num_sigmas >= 1) {
159 for (
size_t i = 0; i < num_sigmas && it != it_end; ++it, ++i) {
161 U.get_column(i, u_i);
162 blas_dgemm1.compute_vv_outer(vt_i, u_i, tmp);
168 pseudoinverse_transposed.cast_from(result);
171 pseudoinverse_transposed.zero();
175 void compute(
const T& input, T& pseudoinverse_transposed,
176 typename T::value_type tolerance = std::numeric_limits< typename T::value_type >::epsilon()) {
178 _work =
new tmp_matrices();
184 matrix_mn_type& U = _work->U;
185 vec_n_type& sigmas = _work->sigmas;
186 matrix_nn_type& Vt = _work->Vt;
187 matrix_mn_type& in_data = _work->input;
188 in_data.cast_from(input);
190 bool svd_ok = svd.compute(in_data, U, sigmas, Vt);
193 VMMLIB_ERROR(
"matrix compute_pseudoinverse - problem with lapack svd.", VMMLIB_HERE);
202 typename vector< T::COLS, Tinternal >::const_iterator it = sigmas.begin(), it_end = sigmas.end();
203 size_t num_sigmas = 0;
204 for (; it != it_end; ++it) {
205 if (*it >= tolerance)
212 matrix_nm_type& result = _work->result;
215 pinv_type& pseudoinverse = _work->pseudoinverse;
216 matrix_nm_type& tmp = _work->tmp;
218 sigmas.reciprocal_safe();
223 blas_type blas_dgemm1;
225 if (num_sigmas >= 1) {
228 for (
size_t i = 0; i < num_sigmas && it != it_end; ++it, ++i) {
230 U.get_column(i, u_i);
231 blas_dgemm1.compute_vv_outer(vt_i, u_i, tmp);
237 pseudoinverse.cast_from(result);
238 pseudoinverse.transpose_to(pseudoinverse_transposed);
241 pseudoinverse_transposed.zero();
245 compute_pseudoinverse()
246 : _work(0), _work_inv(0) {
249 compute_pseudoinverse(
const compute_pseudoinverse& )
250 : _work(0), _work_inv(0) {
253 ~compute_pseudoinverse() {
261 tmp_matrices_inv* _work_inv;