1#ifndef IRLBA_WRAPPERS_HPP
2#define IRLBA_WRAPPERS_HPP
24template<
class Matrix_,
typename =
int>
29 typedef typename Matrix_::Workspace
type;
37template<
class Matrix_>
38struct get_workspace<Matrix_, decltype((void) std::declval<typename Matrix_::Index>(), 0)> {
52template<
class Matrix_>
60template<
class Matrix_>
62 if constexpr(std::is_same<WrappedWorkspace<Matrix_>,
bool>::value) {
65 return matrix.workspace();
73template<
class Matrix_,
typename =
int>
78 typedef typename Matrix_::AdjointWorkspace
type;
86template<
class Matrix_>
101template<
class Matrix_>
109template<
class Matrix_>
111 if constexpr(std::is_same<WrappedAdjointWorkspace<Matrix_>,
bool>::value) {
114 return matrix.adjoint_workspace();
123template<
class Matrix_,
typename =
int>
125 static constexpr bool value =
false;
128template<
class Matrix_>
129struct is_eigen<Matrix_, decltype((void) std::declval<typename Matrix_::Index>(), 0)> {
130 static constexpr bool value =
true;
149template<
class Matrix_,
class Right_,
class EigenVector_>
151 if constexpr(internal::is_eigen<Matrix_>::value) {
152 out.noalias() = matrix * rhs;
154 matrix.multiply(rhs, work, out);
169template<
class Matrix_,
class Right_,
class EigenVector_>
171 if constexpr(internal::is_eigen<Matrix_>::value) {
172 out.noalias() = matrix.adjoint() * rhs;
174 matrix.adjoint_multiply(rhs, work, out);
184template<
class EigenMatrix_,
class Matrix_>
186 if constexpr(internal::is_eigen<Matrix_>::value) {
187 return EigenMatrix_(matrix);
189 return matrix.template realize<EigenMatrix_>();
204template<
class Matrix_,
class EigenVector_>
212 Centered(
const Matrix_& matrix,
const EigenVector_& center) : my_matrix(matrix), my_center(center) {}
218 Eigen::Index rows()
const {
return my_matrix.rows(); }
220 Eigen::Index cols()
const {
return my_matrix.cols(); }
224 Workspace(WrappedWorkspace<Matrix_> i) : inner(std::move(i)) {}
225 WrappedWorkspace<Matrix_> inner;
229 Workspace workspace()
const {
233 struct AdjointWorkspace {
234 AdjointWorkspace(WrappedAdjointWorkspace<Matrix_> i) : inner(std::move(i)) {}
235 WrappedAdjointWorkspace<Matrix_> inner;
239 AdjointWorkspace adjoint_workspace()
const {
244 template<
class Right_>
245 void multiply(
const Right_& rhs, Workspace& work, EigenVector_& out)
const {
246 const auto& realized_rhs = internal::realize_rhs(rhs, work.buffer);
248 auto beta = realized_rhs.dot(my_center);
249 for (
auto& o : out) {
255 template<
class Right_>
256 void adjoint_multiply(
const Right_& rhs, AdjointWorkspace& work, EigenVector_& out)
const {
257 const auto& realized_rhs = internal::realize_rhs(rhs, work.buffer);
259 auto beta = realized_rhs.sum();
260 out -= beta * (my_center);
264 template<
class EigenMatrix_>
265 Eigen::MatrixXd realize()
const {
267 output.array().rowwise() -= my_center.adjoint().array();
275 const Matrix_& my_matrix;
276 const EigenVector_& my_center;
293template<
bool column_,
class Matrix_,
class EigenVector_>
302 Scaled(
const Matrix_& matrix,
const EigenVector_& scale,
bool divide) :
303 my_matrix(matrix), my_scale(scale), my_divide(divide) {}
309 Eigen::Index rows()
const {
return my_matrix.rows(); }
311 Eigen::Index cols()
const {
return my_matrix.cols(); }
314 template<
template<
class>
class Wrapper_>
315 struct BufferedWorkspace {
316 BufferedWorkspace(
size_t n, Wrapper_<Matrix_> c) : buffer(n), child(std::move(c)) {}
318 Wrapper_<Matrix_> child;
321 typedef typename std::conditional<column_, BufferedWorkspace<WrappedWorkspace>,
WrappedWorkspace<Matrix_> >::type Workspace;
323 Workspace workspace()
const {
324 if constexpr(column_) {
325 return BufferedWorkspace<WrappedWorkspace>(my_matrix.cols(),
wrapped_workspace(my_matrix));
331 typedef typename std::conditional<column_, WrappedAdjointWorkspace<Matrix_>, BufferedWorkspace<WrappedAdjointWorkspace> >::type AdjointWorkspace;
333 AdjointWorkspace adjoint_workspace()
const {
334 if constexpr(column_) {
342 template<
class Right_>
343 void multiply(
const Right_& rhs, Workspace& work, EigenVector_& out)
const {
344 if constexpr(column_) {
350 work.buffer = rhs.cwiseQuotient(my_scale);
352 work.buffer = rhs.cwiseProduct(my_scale);
359 out.array() /= my_scale.array();
361 out.array() *= my_scale.array();
366 template<
class Right_>
367 void adjoint_multiply(
const Right_& rhs, AdjointWorkspace& work, EigenVector_& out)
const {
368 if constexpr(column_) {
371 out.array() /= my_scale.array();
373 out.array() *= my_scale.array();
378 work.buffer = rhs.cwiseQuotient(my_scale);
380 work.buffer = rhs.cwiseProduct(my_scale);
386 template<
class EigenMatrix_>
387 EigenMatrix_ realize()
const {
390 if constexpr(column_) {
392 output.array().rowwise() /= my_scale.adjoint().array();
394 output.array().rowwise() *= my_scale.adjoint().array();
398 output.array().colwise() /= my_scale.array();
400 output.array().colwise() *= my_scale.array();
411 const Matrix_& my_matrix;
412 const EigenVector_& my_scale;
431template<
bool column_,
class Matrix_,
class EigenVector_>
Wrapper for a centered matrix.
Definition wrappers.hpp:205
Centered(const Matrix_ &matrix, const EigenVector_ ¢er)
Definition wrappers.hpp:212
Wrapper for a scaled matrix.
Definition wrappers.hpp:294
Scaled(const Matrix_ &matrix, const EigenVector_ &scale, bool divide)
Definition wrappers.hpp:302
Implements IRLBA for approximate SVD.
Definition compute.hpp:18
Scaled< column_, Matrix_, EigenVector_ > make_Scaled(const Matrix_ &matrix, const EigenVector_ &scale, bool divide)
Definition wrappers.hpp:432
void wrapped_adjoint_multiply(const Matrix_ &matrix, const Right_ &rhs, WrappedAdjointWorkspace< Matrix_ > &work, EigenVector_ &out)
Definition wrappers.hpp:170
WrappedWorkspace< Matrix_ > wrapped_workspace(const Matrix_ &matrix)
Definition wrappers.hpp:61
void wrapped_multiply(const Matrix_ &matrix, const Right_ &rhs, WrappedWorkspace< Matrix_ > &work, EigenVector_ &out)
Definition wrappers.hpp:150
WrappedAdjointWorkspace< Matrix_ > wrapped_adjoint_workspace(const Matrix_ &matrix)
Definition wrappers.hpp:110
typename get_adjoint_workspace< Matrix_ >::type WrappedAdjointWorkspace
Definition wrappers.hpp:102
EigenMatrix_ wrapped_realize(const Matrix_ &matrix)
Definition wrappers.hpp:185
typename get_workspace< Matrix_ >::type WrappedWorkspace
Definition wrappers.hpp:53
bool type
Definition wrappers.hpp:91
Get the type of workspace for wrapped_adjoint_multiply().
Definition wrappers.hpp:74
Matrix_::AdjointWorkspace type
Definition wrappers.hpp:78
bool type
Definition wrappers.hpp:42
Get the type of workspace for wrapped_multiply().
Definition wrappers.hpp:25
Matrix_::Workspace type
Definition wrappers.hpp:29