6 #ifndef ACA_HPP_INCLUDED
7 #define ACA_HPP_INCLUDED
10 #include <type_traits>
17 template <
class Scalar>
33 template <
class UType,
class VType>
34 LowRank(
int row0,
int col0, Eigen::MatrixBase<UType>
const &U, Eigen::DenseBase<VType>
const &V)
35 : row0(row0), col0(col0), U(U), V(V)
40 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>
const &
getU(
void)
const
46 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>
const &
getV(
void)
const
66 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> U;
67 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> V;
76 template <
class Matrix>
81 typedef typename std::decay<Matrix>::type::Scalar Scalar;
87 Block(Matrix M,
int row0,
int col0)
88 : M(std::forward<Matrix>(M)), row0(row0), col0(col0)
96 Scalar operator()(
int i,
int j)
const
98 return M(row0+i, col0+j);
113 template <
class Matrix>
115 createBlock(Matrix &&M,
int row0,
int col0)
117 return Block<Matrix>(std::forward<Matrix>(M), row0, col0);
134 template <
class Matrix,
class Result>
136 Eigen::DenseBase<Result> &U, Eigen::DenseBase<Result> &V)
145 auto magest = std::abs(M(nRows/2,nCols/2));
154 for (
int k = 0; k < R; ++k)
157 for (
int s = 0; s < nCols; ++s)
161 V.col(r) -= V.leftCols(r) * U.block(i,0,1,r).transpose();
165 for (
int s = 1; s < nCols; ++s)
166 if (std::abs(V(s,r)) > std::abs(V(j,r)))
170 if (std::abs(V(j,r)) / magest < 1e-10)
174 for (
int s = 0; s < nRows; ++s)
178 U.col(r) -= U.leftCols(r) * V.block(j,0,1,r).transpose();
186 S2 = S2 + U.col(r-1).squaredNorm() * V.col(r-1).squaredNorm();
187 for (
int s = 0; s < r-1; ++s)
188 S2 += 2.0 * std::real(U.col(s).dot(U.col(r-1)) * V.col(s).dot(V.col(r-1)));
191 double err = U.col(r-1).norm() * V.col(r-1).norm() / std::sqrt(S2);
216 template <
class Matrix,
class RowArray,
class ColumnArray,
class BlockArray,
class Input,
class Output,
class Ranks>
218 Eigen::DenseBase<RowArray>
const &rowClusters, Eigen::DenseBase<ColumnArray>
const &colClusters,
219 Eigen::DenseBase<BlockArray>
const &blocks,
220 Input
const &input, Output &output,
221 double eps,
int maxRank,
224 typedef typename Matrix::Scalar Scalar;
227 int nMaxRows = rowClusters.col(1).maxCoeff(), nMaxCols = colClusters.col(1).maxCoeff();
230 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> U(nMaxRows, maxRank), V(nMaxCols, maxRank);
231 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Z(maxRank,1);
234 m_nEval = m_matrixSize = 0;
237 for (
int iBlock = 0; iBlock < blocks.rows(); ++iBlock)
239 auto rowCluster(rowClusters.row(blocks(iBlock,0)));
240 auto colCluster(colClusters.row(blocks(iBlock,1)));
243 int row0 = rowCluster(0), nRows = rowCluster(1);
244 int col0 = colCluster(0), nCols = colCluster(1);
246 auto u(U.topRows(nRows));
247 auto v(V.topRows(nCols));
250 int r =
low_rank_approx(createBlock(M, row0, col0), nRows, nCols, eps, maxRank, u, v);
252 m_nEval += (nRows+nCols)*r;
253 m_matrixSize += nRows*nCols;
256 auto vv(V.leftCols(r));
257 auto uu(U.leftCols(r));
258 auto z(Z.topRows(r));
264 for (
int j = 0; j < nCols; ++j)
265 z += vv.row(j).transpose() * input( col0+j , 0);
267 for (
int i = 0; i < nRows; ++i)
268 output( row0+i, 0 ) += (uu.row(i)*z)(0,0);
270 outRanks(iBlock,0) = r;
284 template <
class Matrix,
class RowArray,
class ColumnArray,
class BlockArray>
285 static std::vector<LowRank<typename Matrix::Scalar> >
decompose(Matrix
const &M,
286 Eigen::DenseBase<RowArray>
const &rowClusters, Eigen::DenseBase<ColumnArray>
const &colClusters,
287 Eigen::DenseBase<BlockArray>
const &blocks,
288 double eps,
int maxRank)
290 typedef typename Matrix::Scalar Scalar;
291 typedef std::vector<LowRank<Scalar> > ReturnType;
294 ret.reserve(blocks.rows());
297 int nMaxRows = rowClusters.col(1).maxCoeff(), nMaxCols = colClusters.col(1).maxCoeff();
300 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> U(nMaxRows, maxRank), V(nMaxCols, maxRank);
301 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Z(maxRank,1);
304 for (
int iBlock = 0; iBlock < blocks.rows(); ++iBlock)
306 auto rowCluster(rowClusters.row(blocks(iBlock,0)));
307 auto colCluster(colClusters.row(blocks(iBlock,1)));
310 int row0 = rowCluster(0), nRows = rowCluster(1);
311 int col0 = colCluster(0), nCols = colCluster(1);
313 auto u(U.topRows(nRows));
314 auto v(V.topRows(nCols));
317 int r =
low_rank_approx(createBlock(M, row0, col0), nRows, nCols, eps, maxRank, u, v);
319 ret.push_back(
LowRank<Scalar>(row0, col0, U.leftCols(r), V.leftCols(r)));
347 #endif // ACA_HPP_INCLUDED