mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-08-13 12:19:12 +08:00
bug #206 - part 4: Removes heap allocations from JacobiSVD and its preconditioners
This commit is contained in:
parent
5e431779f3
commit
4477843bdd
@ -562,7 +562,7 @@ public:
|
|||||||
// and v_k is the k-th Householder vector [1,m_qr(k+1,k), m_qr(k+2,k), ...]
|
// and v_k is the k-th Householder vector [1,m_qr(k+1,k), m_qr(k+2,k), ...]
|
||||||
const Index rows = m_qr.rows();
|
const Index rows = m_qr.rows();
|
||||||
const Index cols = m_qr.cols();
|
const Index cols = m_qr.cols();
|
||||||
const Index size = std::min(rows, cols);
|
const Index size = (std::min)(rows, cols);
|
||||||
workspace.resize(rows);
|
workspace.resize(rows);
|
||||||
result.setIdentity(rows, rows);
|
result.setIdentity(rows, rows);
|
||||||
for (Index k = size-1; k >= 0; k--)
|
for (Index k = size-1; k >= 0; k--)
|
||||||
|
@ -61,9 +61,12 @@ template<typename MatrixType, int QRPreconditioner, int Case,
|
|||||||
> struct qr_preconditioner_impl {};
|
> struct qr_preconditioner_impl {};
|
||||||
|
|
||||||
template<typename MatrixType, int QRPreconditioner, int Case>
|
template<typename MatrixType, int QRPreconditioner, int Case>
|
||||||
struct qr_preconditioner_impl<MatrixType, QRPreconditioner, Case, false>
|
class qr_preconditioner_impl<MatrixType, QRPreconditioner, Case, false>
|
||||||
{
|
{
|
||||||
static bool run(JacobiSVD<MatrixType, QRPreconditioner>&, const MatrixType&)
|
public:
|
||||||
|
typedef typename MatrixType::Index Index;
|
||||||
|
void allocate(const JacobiSVD<MatrixType, QRPreconditioner>&) {}
|
||||||
|
bool run(JacobiSVD<MatrixType, QRPreconditioner>&, const MatrixType&)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -72,134 +75,279 @@ struct qr_preconditioner_impl<MatrixType, QRPreconditioner, Case, false>
|
|||||||
/*** preconditioner using FullPivHouseholderQR ***/
|
/*** preconditioner using FullPivHouseholderQR ***/
|
||||||
|
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
struct qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
|
class qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
|
||||||
{
|
{
|
||||||
static bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
public:
|
||||||
|
typedef typename MatrixType::Index Index;
|
||||||
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||||
|
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime
|
||||||
|
};
|
||||||
|
typedef Matrix<Scalar, 1, RowsAtCompileTime, RowMajor, 1, MaxRowsAtCompileTime> WorkspaceType;
|
||||||
|
|
||||||
|
void allocate(const JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd)
|
||||||
|
{
|
||||||
|
if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
|
||||||
|
{
|
||||||
|
m_qr = FullPivHouseholderQR<MatrixType>(svd.rows(), svd.cols());
|
||||||
|
}
|
||||||
|
if (svd.m_computeFullU) m_workspace.resize(svd.rows());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
||||||
{
|
{
|
||||||
if(matrix.rows() > matrix.cols())
|
if(matrix.rows() > matrix.cols())
|
||||||
{
|
{
|
||||||
FullPivHouseholderQR<MatrixType> qr(matrix);
|
m_qr.compute(matrix);
|
||||||
svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
|
svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
|
||||||
if(svd.m_computeFullU) svd.m_matrixU = qr.matrixQ();
|
if(svd.m_computeFullU) m_qr.matrixQ().evalTo(svd.m_matrixU, m_workspace);
|
||||||
if(svd.computeV()) svd.m_matrixV = qr.colsPermutation();
|
if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
FullPivHouseholderQR<MatrixType> m_qr;
|
||||||
|
WorkspaceType m_workspace;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
struct qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
|
class qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
|
||||||
{
|
{
|
||||||
static bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
public:
|
||||||
|
typedef typename MatrixType::Index Index;
|
||||||
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||||
|
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||||
|
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||||
|
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
|
||||||
|
Options = MatrixType::Options
|
||||||
|
};
|
||||||
|
typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
|
||||||
|
TransposeTypeWithSameStorageOrder;
|
||||||
|
|
||||||
|
void allocate(const JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd)
|
||||||
|
{
|
||||||
|
if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
|
||||||
|
{
|
||||||
|
m_qr = FullPivHouseholderQR<TransposeTypeWithSameStorageOrder>(svd.cols(), svd.rows());
|
||||||
|
}
|
||||||
|
m_adjoint.resize(svd.cols(), svd.rows());
|
||||||
|
if (svd.m_computeFullV) m_workspace.resize(svd.cols());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
||||||
{
|
{
|
||||||
if(matrix.cols() > matrix.rows())
|
if(matrix.cols() > matrix.rows())
|
||||||
{
|
{
|
||||||
typedef Matrix<typename MatrixType::Scalar, MatrixType::ColsAtCompileTime, MatrixType::RowsAtCompileTime,
|
m_adjoint = matrix.adjoint();
|
||||||
MatrixType::Options, MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime>
|
m_qr.compute(m_adjoint);
|
||||||
TransposeTypeWithSameStorageOrder;
|
svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
|
||||||
FullPivHouseholderQR<TransposeTypeWithSameStorageOrder> qr(matrix.adjoint());
|
if(svd.m_computeFullV) m_qr.matrixQ().evalTo(svd.m_matrixV, m_workspace);
|
||||||
svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
|
if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
|
||||||
if(svd.m_computeFullV) svd.m_matrixV = qr.matrixQ();
|
|
||||||
if(svd.computeU()) svd.m_matrixU = qr.colsPermutation();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
FullPivHouseholderQR<TransposeTypeWithSameStorageOrder> m_qr;
|
||||||
|
TransposeTypeWithSameStorageOrder m_adjoint;
|
||||||
|
typename internal::plain_row_type<MatrixType>::type m_workspace;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*** preconditioner using ColPivHouseholderQR ***/
|
/*** preconditioner using ColPivHouseholderQR ***/
|
||||||
|
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
struct qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
|
class qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
|
||||||
{
|
{
|
||||||
static bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
public:
|
||||||
|
typedef typename MatrixType::Index Index;
|
||||||
|
|
||||||
|
void allocate(const JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd)
|
||||||
|
{
|
||||||
|
if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
|
||||||
|
{
|
||||||
|
m_qr = ColPivHouseholderQR<MatrixType>(svd.rows(), svd.cols());
|
||||||
|
}
|
||||||
|
if (svd.m_computeFullU) m_workspace.resize(svd.rows());
|
||||||
|
else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
||||||
{
|
{
|
||||||
if(matrix.rows() > matrix.cols())
|
if(matrix.rows() > matrix.cols())
|
||||||
{
|
{
|
||||||
ColPivHouseholderQR<MatrixType> qr(matrix);
|
m_qr.compute(matrix);
|
||||||
svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
|
svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
|
||||||
if(svd.m_computeFullU) svd.m_matrixU = qr.householderQ();
|
if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
|
||||||
else if(svd.m_computeThinU) {
|
else if(svd.m_computeThinU)
|
||||||
|
{
|
||||||
svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
|
svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
|
||||||
qr.householderQ().applyThisOnTheLeft(svd.m_matrixU);
|
m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
|
||||||
}
|
}
|
||||||
if(svd.computeV()) svd.m_matrixV = qr.colsPermutation();
|
if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ColPivHouseholderQR<MatrixType> m_qr;
|
||||||
|
typename internal::plain_col_type<MatrixType>::type m_workspace;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
struct qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
|
class qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
|
||||||
{
|
{
|
||||||
static bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
public:
|
||||||
|
typedef typename MatrixType::Index Index;
|
||||||
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||||
|
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||||
|
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||||
|
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
|
||||||
|
Options = MatrixType::Options
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
|
||||||
|
TransposeTypeWithSameStorageOrder;
|
||||||
|
|
||||||
|
void allocate(const JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd)
|
||||||
|
{
|
||||||
|
if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
|
||||||
|
{
|
||||||
|
m_qr = ColPivHouseholderQR<TransposeTypeWithSameStorageOrder>(svd.cols(), svd.rows());
|
||||||
|
}
|
||||||
|
if (svd.m_computeFullV) m_workspace.resize(svd.cols());
|
||||||
|
else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
|
||||||
|
m_adjoint.resize(svd.cols(), svd.rows());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
||||||
{
|
{
|
||||||
if(matrix.cols() > matrix.rows())
|
if(matrix.cols() > matrix.rows())
|
||||||
{
|
{
|
||||||
typedef Matrix<typename MatrixType::Scalar, MatrixType::ColsAtCompileTime, MatrixType::RowsAtCompileTime,
|
m_adjoint = matrix.adjoint();
|
||||||
MatrixType::Options, MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime>
|
m_qr.compute(m_adjoint);
|
||||||
TransposeTypeWithSameStorageOrder;
|
|
||||||
ColPivHouseholderQR<TransposeTypeWithSameStorageOrder> qr(matrix.adjoint());
|
svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
|
||||||
svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
|
if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
|
||||||
if(svd.m_computeFullV) svd.m_matrixV = qr.householderQ();
|
else if(svd.m_computeThinV)
|
||||||
else if(svd.m_computeThinV) {
|
{
|
||||||
svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
|
svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
|
||||||
qr.householderQ().applyThisOnTheLeft(svd.m_matrixV);
|
m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
|
||||||
}
|
}
|
||||||
if(svd.computeU()) svd.m_matrixU = qr.colsPermutation();
|
if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ColPivHouseholderQR<TransposeTypeWithSameStorageOrder> m_qr;
|
||||||
|
TransposeTypeWithSameStorageOrder m_adjoint;
|
||||||
|
typename internal::plain_row_type<MatrixType>::type m_workspace;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*** preconditioner using HouseholderQR ***/
|
/*** preconditioner using HouseholderQR ***/
|
||||||
|
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
struct qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
|
class qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
|
||||||
{
|
{
|
||||||
static bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
public:
|
||||||
|
typedef typename MatrixType::Index Index;
|
||||||
|
|
||||||
|
void allocate(const JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd)
|
||||||
|
{
|
||||||
|
if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
|
||||||
|
{
|
||||||
|
m_qr = HouseholderQR<MatrixType>(svd.rows(), svd.cols());
|
||||||
|
}
|
||||||
|
if (svd.m_computeFullU) m_workspace.resize(svd.rows());
|
||||||
|
else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
||||||
{
|
{
|
||||||
if(matrix.rows() > matrix.cols())
|
if(matrix.rows() > matrix.cols())
|
||||||
{
|
{
|
||||||
HouseholderQR<MatrixType> qr(matrix);
|
m_qr.compute(matrix);
|
||||||
svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
|
svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
|
||||||
if(svd.m_computeFullU) svd.m_matrixU = qr.householderQ();
|
if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace);
|
||||||
else if(svd.m_computeThinU) {
|
else if(svd.m_computeThinU)
|
||||||
|
{
|
||||||
svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
|
svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
|
||||||
qr.householderQ().applyThisOnTheLeft(svd.m_matrixU);
|
m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace);
|
||||||
}
|
}
|
||||||
if(svd.computeV()) svd.m_matrixV.setIdentity(matrix.cols(), matrix.cols());
|
if(svd.computeV()) svd.m_matrixV.setIdentity(matrix.cols(), matrix.cols());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
HouseholderQR<MatrixType> m_qr;
|
||||||
|
typename internal::plain_col_type<MatrixType>::type m_workspace;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
struct qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
|
class qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
|
||||||
{
|
{
|
||||||
static bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
public:
|
||||||
|
typedef typename MatrixType::Index Index;
|
||||||
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||||
|
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||||
|
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||||
|
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
|
||||||
|
Options = MatrixType::Options
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Matrix<Scalar, ColsAtCompileTime, RowsAtCompileTime, Options, MaxColsAtCompileTime, MaxRowsAtCompileTime>
|
||||||
|
TransposeTypeWithSameStorageOrder;
|
||||||
|
|
||||||
|
void allocate(const JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd)
|
||||||
|
{
|
||||||
|
if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
|
||||||
|
{
|
||||||
|
m_qr = HouseholderQR<TransposeTypeWithSameStorageOrder>(svd.cols(), svd.rows());
|
||||||
|
}
|
||||||
|
if (svd.m_computeFullV) m_workspace.resize(svd.cols());
|
||||||
|
else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
|
||||||
|
m_adjoint.resize(svd.cols(), svd.rows());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
|
||||||
{
|
{
|
||||||
if(matrix.cols() > matrix.rows())
|
if(matrix.cols() > matrix.rows())
|
||||||
{
|
{
|
||||||
typedef Matrix<typename MatrixType::Scalar, MatrixType::ColsAtCompileTime, MatrixType::RowsAtCompileTime,
|
m_adjoint = matrix.adjoint();
|
||||||
MatrixType::Options, MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime>
|
m_qr.compute(m_adjoint);
|
||||||
TransposeTypeWithSameStorageOrder;
|
|
||||||
HouseholderQR<TransposeTypeWithSameStorageOrder> qr(matrix.adjoint());
|
svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
|
||||||
svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
|
if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace);
|
||||||
if(svd.m_computeFullV) svd.m_matrixV = qr.householderQ();
|
else if(svd.m_computeThinV)
|
||||||
else if(svd.m_computeThinV) {
|
{
|
||||||
svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
|
svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
|
||||||
qr.householderQ().applyThisOnTheLeft(svd.m_matrixV);
|
m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace);
|
||||||
}
|
}
|
||||||
if(svd.computeU()) svd.m_matrixU.setIdentity(matrix.rows(), matrix.rows());
|
if(svd.computeU()) svd.m_matrixU.setIdentity(matrix.rows(), matrix.rows());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
HouseholderQR<TransposeTypeWithSameStorageOrder> m_qr;
|
||||||
|
TransposeTypeWithSameStorageOrder m_adjoint;
|
||||||
|
typename internal::plain_row_type<MatrixType>::type m_workspace;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*** 2x2 SVD implementation
|
/*** 2x2 SVD implementation
|
||||||
@ -535,6 +683,9 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
|
|||||||
friend struct internal::svd_precondition_2x2_block_to_be_real;
|
friend struct internal::svd_precondition_2x2_block_to_be_real;
|
||||||
template<typename __MatrixType, int _QRPreconditioner, int _Case, bool _DoAnything>
|
template<typename __MatrixType, int _QRPreconditioner, int _Case, bool _DoAnything>
|
||||||
friend struct internal::qr_preconditioner_impl;
|
friend struct internal::qr_preconditioner_impl;
|
||||||
|
|
||||||
|
internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreColsThanRows> m_qr_precond_morecols;
|
||||||
|
internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreRowsThanCols> m_qr_precond_morerows;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename MatrixType, int QRPreconditioner>
|
template<typename MatrixType, int QRPreconditioner>
|
||||||
@ -578,6 +729,9 @@ void JacobiSVD<MatrixType, QRPreconditioner>::allocate(Index rows, Index cols, u
|
|||||||
: m_computeThinV ? m_diagSize
|
: m_computeThinV ? m_diagSize
|
||||||
: 0);
|
: 0);
|
||||||
m_workMatrix.resize(m_diagSize, m_diagSize);
|
m_workMatrix.resize(m_diagSize, m_diagSize);
|
||||||
|
|
||||||
|
m_qr_precond_morecols.allocate(*this);
|
||||||
|
m_qr_precond_morerows.allocate(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename MatrixType, int QRPreconditioner>
|
template<typename MatrixType, int QRPreconditioner>
|
||||||
@ -595,8 +749,7 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
|
|||||||
|
|
||||||
/*** step 1. The R-SVD step: we use a QR decomposition to reduce to the case of a square matrix */
|
/*** step 1. The R-SVD step: we use a QR decomposition to reduce to the case of a square matrix */
|
||||||
|
|
||||||
if(!internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreColsThanRows>::run(*this, matrix)
|
if(!m_qr_precond_morecols.run(*this, matrix) && !m_qr_precond_morerows.run(*this, matrix))
|
||||||
&& !internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreRowsThanCols>::run(*this, matrix))
|
|
||||||
{
|
{
|
||||||
m_workMatrix = matrix.block(0,0,m_diagSize,m_diagSize);
|
m_workMatrix = matrix.block(0,0,m_diagSize,m_diagSize);
|
||||||
if(m_computeFullU) m_matrixU.setIdentity(m_rows,m_rows);
|
if(m_computeFullU) m_matrixU.setIdentity(m_rows,m_rows);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user