mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Apply clang-format
This commit is contained in:
@@ -13,108 +13,86 @@
|
||||
// IWYU pragma: private
|
||||
#include "./InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const typename Derived::Scalar bruteforce_det3_helper
|
||||
(const MatrixBase<Derived>& matrix, int a, int b, int c)
|
||||
{
|
||||
return matrix.coeff(0,a)
|
||||
* (matrix.coeff(1,b) * matrix.coeff(2,c) - matrix.coeff(1,c) * matrix.coeff(2,b));
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC inline const typename Derived::Scalar bruteforce_det3_helper(const MatrixBase<Derived>& matrix, int a,
|
||||
int b, int c) {
|
||||
return matrix.coeff(0, a) * (matrix.coeff(1, b) * matrix.coeff(2, c) - matrix.coeff(1, c) * matrix.coeff(2, b));
|
||||
}
|
||||
|
||||
template<typename Derived,
|
||||
int DeterminantType = Derived::RowsAtCompileTime
|
||||
> struct determinant_impl
|
||||
{
|
||||
static inline typename traits<Derived>::Scalar run(const Derived& m)
|
||||
{
|
||||
if(Derived::ColsAtCompileTime==Dynamic && m.rows()==0)
|
||||
return typename traits<Derived>::Scalar(1);
|
||||
template <typename Derived, int DeterminantType = Derived::RowsAtCompileTime>
|
||||
struct determinant_impl {
|
||||
static inline typename traits<Derived>::Scalar run(const Derived& m) {
|
||||
if (Derived::ColsAtCompileTime == Dynamic && m.rows() == 0) return typename traits<Derived>::Scalar(1);
|
||||
return m.partialPivLu().determinant();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived> struct determinant_impl<Derived, 1>
|
||||
{
|
||||
static inline EIGEN_DEVICE_FUNC
|
||||
typename traits<Derived>::Scalar run(const Derived& m)
|
||||
{
|
||||
return m.coeff(0,0);
|
||||
template <typename Derived>
|
||||
struct determinant_impl<Derived, 1> {
|
||||
static inline EIGEN_DEVICE_FUNC typename traits<Derived>::Scalar run(const Derived& m) { return m.coeff(0, 0); }
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
struct determinant_impl<Derived, 2> {
|
||||
static inline EIGEN_DEVICE_FUNC typename traits<Derived>::Scalar run(const Derived& m) {
|
||||
return m.coeff(0, 0) * m.coeff(1, 1) - m.coeff(1, 0) * m.coeff(0, 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived> struct determinant_impl<Derived, 2>
|
||||
{
|
||||
static inline EIGEN_DEVICE_FUNC
|
||||
typename traits<Derived>::Scalar run(const Derived& m)
|
||||
{
|
||||
return m.coeff(0,0) * m.coeff(1,1) - m.coeff(1,0) * m.coeff(0,1);
|
||||
template <typename Derived>
|
||||
struct determinant_impl<Derived, 3> {
|
||||
static inline EIGEN_DEVICE_FUNC typename traits<Derived>::Scalar run(const Derived& m) {
|
||||
return bruteforce_det3_helper(m, 0, 1, 2) - bruteforce_det3_helper(m, 1, 0, 2) + bruteforce_det3_helper(m, 2, 0, 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived> struct determinant_impl<Derived, 3>
|
||||
{
|
||||
static inline EIGEN_DEVICE_FUNC
|
||||
typename traits<Derived>::Scalar run(const Derived& m)
|
||||
{
|
||||
return bruteforce_det3_helper(m,0,1,2)
|
||||
- bruteforce_det3_helper(m,1,0,2)
|
||||
+ bruteforce_det3_helper(m,2,0,1);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived> struct determinant_impl<Derived, 4>
|
||||
{
|
||||
template <typename Derived>
|
||||
struct determinant_impl<Derived, 4> {
|
||||
typedef typename traits<Derived>::Scalar Scalar;
|
||||
static EIGEN_DEVICE_FUNC
|
||||
Scalar run(const Derived& m)
|
||||
{
|
||||
static EIGEN_DEVICE_FUNC Scalar run(const Derived& m) {
|
||||
Scalar d2_01 = det2(m, 0, 1);
|
||||
Scalar d2_02 = det2(m, 0, 2);
|
||||
Scalar d2_03 = det2(m, 0, 3);
|
||||
Scalar d2_12 = det2(m, 1, 2);
|
||||
Scalar d2_13 = det2(m, 1, 3);
|
||||
Scalar d2_23 = det2(m, 2, 3);
|
||||
Scalar d3_0 = det3(m, 1,d2_23, 2,d2_13, 3,d2_12);
|
||||
Scalar d3_1 = det3(m, 0,d2_23, 2,d2_03, 3,d2_02);
|
||||
Scalar d3_2 = det3(m, 0,d2_13, 1,d2_03, 3,d2_01);
|
||||
Scalar d3_3 = det3(m, 0,d2_12, 1,d2_02, 2,d2_01);
|
||||
return internal::pmadd(static_cast<Scalar>(-m(0,3)),d3_0, static_cast<Scalar>(m(1,3)*d3_1)) +
|
||||
internal::pmadd(static_cast<Scalar>(-m(2,3)),d3_2, static_cast<Scalar>(m(3,3)*d3_3));
|
||||
}
|
||||
protected:
|
||||
static EIGEN_DEVICE_FUNC
|
||||
Scalar det2(const Derived& m, Index i0, Index i1)
|
||||
{
|
||||
return m(i0,0) * m(i1,1) - m(i1,0) * m(i0,1);
|
||||
Scalar d3_0 = det3(m, 1, d2_23, 2, d2_13, 3, d2_12);
|
||||
Scalar d3_1 = det3(m, 0, d2_23, 2, d2_03, 3, d2_02);
|
||||
Scalar d3_2 = det3(m, 0, d2_13, 1, d2_03, 3, d2_01);
|
||||
Scalar d3_3 = det3(m, 0, d2_12, 1, d2_02, 2, d2_01);
|
||||
return internal::pmadd(static_cast<Scalar>(-m(0, 3)), d3_0, static_cast<Scalar>(m(1, 3) * d3_1)) +
|
||||
internal::pmadd(static_cast<Scalar>(-m(2, 3)), d3_2, static_cast<Scalar>(m(3, 3) * d3_3));
|
||||
}
|
||||
|
||||
static EIGEN_DEVICE_FUNC
|
||||
Scalar det3(const Derived& m, Index i0, const Scalar& d0, Index i1, const Scalar& d1, Index i2, const Scalar& d2)
|
||||
{
|
||||
return internal::pmadd(m(i0,2), d0, internal::pmadd(static_cast<Scalar>(-m(i1,2)), d1, static_cast<Scalar>(m(i2,2)*d2)));
|
||||
protected:
|
||||
static EIGEN_DEVICE_FUNC Scalar det2(const Derived& m, Index i0, Index i1) {
|
||||
return m(i0, 0) * m(i1, 1) - m(i1, 0) * m(i0, 1);
|
||||
}
|
||||
|
||||
static EIGEN_DEVICE_FUNC Scalar det3(const Derived& m, Index i0, const Scalar& d0, Index i1, const Scalar& d1,
|
||||
Index i2, const Scalar& d2) {
|
||||
return internal::pmadd(m(i0, 2), d0,
|
||||
internal::pmadd(static_cast<Scalar>(-m(i1, 2)), d1, static_cast<Scalar>(m(i2, 2) * d2)));
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
/** \lu_module
|
||||
*
|
||||
* \returns the determinant of this matrix
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline typename internal::traits<Derived>::Scalar MatrixBase<Derived>::determinant() const
|
||||
{
|
||||
*
|
||||
* \returns the determinant of this matrix
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Scalar MatrixBase<Derived>::determinant() const {
|
||||
eigen_assert(rows() == cols());
|
||||
typedef typename internal::nested_eval<Derived,Base::RowsAtCompileTime>::type Nested;
|
||||
typedef typename internal::nested_eval<Derived, Base::RowsAtCompileTime>::type Nested;
|
||||
return internal::determinant_impl<internal::remove_all_t<Nested>>::run(derived());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_DETERMINANT_H
|
||||
#endif // EIGEN_DETERMINANT_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@
|
||||
// IWYU pragma: private
|
||||
#include "./InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -22,51 +22,40 @@ namespace internal {
|
||||
*** General case implementation ***
|
||||
**********************************/
|
||||
|
||||
template<typename MatrixType, typename ResultType, int Size = MatrixType::RowsAtCompileTime>
|
||||
struct compute_inverse
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(const MatrixType& matrix, ResultType& result)
|
||||
{
|
||||
template <typename MatrixType, typename ResultType, int Size = MatrixType::RowsAtCompileTime>
|
||||
struct compute_inverse {
|
||||
EIGEN_DEVICE_FUNC static inline void run(const MatrixType& matrix, ResultType& result) {
|
||||
result = matrix.partialPivLu().inverse();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename MatrixType, typename ResultType, int Size = MatrixType::RowsAtCompileTime>
|
||||
struct compute_inverse_and_det_with_check { /* nothing! general case not supported. */ };
|
||||
template <typename MatrixType, typename ResultType, int Size = MatrixType::RowsAtCompileTime>
|
||||
struct compute_inverse_and_det_with_check { /* nothing! general case not supported. */
|
||||
};
|
||||
|
||||
/****************************
|
||||
*** Size 1 implementation ***
|
||||
****************************/
|
||||
|
||||
template<typename MatrixType, typename ResultType>
|
||||
struct compute_inverse<MatrixType, ResultType, 1>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(const MatrixType& matrix, ResultType& result)
|
||||
{
|
||||
template <typename MatrixType, typename ResultType>
|
||||
struct compute_inverse<MatrixType, ResultType, 1> {
|
||||
EIGEN_DEVICE_FUNC static inline void run(const MatrixType& matrix, ResultType& result) {
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
internal::evaluator<MatrixType> matrixEval(matrix);
|
||||
result.coeffRef(0,0) = Scalar(1) / matrixEval.coeff(0,0);
|
||||
result.coeffRef(0, 0) = Scalar(1) / matrixEval.coeff(0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_and_det_with_check<MatrixType, ResultType, 1>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(
|
||||
const MatrixType& matrix,
|
||||
const typename MatrixType::RealScalar& absDeterminantThreshold,
|
||||
ResultType& result,
|
||||
typename ResultType::Scalar& determinant,
|
||||
bool& invertible
|
||||
)
|
||||
{
|
||||
template <typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_and_det_with_check<MatrixType, ResultType, 1> {
|
||||
EIGEN_DEVICE_FUNC static inline void run(const MatrixType& matrix,
|
||||
const typename MatrixType::RealScalar& absDeterminantThreshold,
|
||||
ResultType& result, typename ResultType::Scalar& determinant,
|
||||
bool& invertible) {
|
||||
using std::abs;
|
||||
determinant = matrix.coeff(0,0);
|
||||
determinant = matrix.coeff(0, 0);
|
||||
invertible = abs(determinant) > absDeterminantThreshold;
|
||||
if(invertible) result.coeffRef(0,0) = typename ResultType::Scalar(1) / determinant;
|
||||
if (invertible) result.coeffRef(0, 0) = typename ResultType::Scalar(1) / determinant;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -74,48 +63,37 @@ struct compute_inverse_and_det_with_check<MatrixType, ResultType, 1>
|
||||
*** Size 2 implementation ***
|
||||
****************************/
|
||||
|
||||
template<typename MatrixType, typename ResultType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline void compute_inverse_size2_helper(
|
||||
const MatrixType& matrix, const typename ResultType::Scalar& invdet,
|
||||
ResultType& result)
|
||||
{
|
||||
typename ResultType::Scalar temp = matrix.coeff(0,0);
|
||||
result.coeffRef(0,0) = matrix.coeff(1,1) * invdet;
|
||||
result.coeffRef(1,0) = -matrix.coeff(1,0) * invdet;
|
||||
result.coeffRef(0,1) = -matrix.coeff(0,1) * invdet;
|
||||
result.coeffRef(1,1) = temp * invdet;
|
||||
template <typename MatrixType, typename ResultType>
|
||||
EIGEN_DEVICE_FUNC inline void compute_inverse_size2_helper(const MatrixType& matrix,
|
||||
const typename ResultType::Scalar& invdet,
|
||||
ResultType& result) {
|
||||
typename ResultType::Scalar temp = matrix.coeff(0, 0);
|
||||
result.coeffRef(0, 0) = matrix.coeff(1, 1) * invdet;
|
||||
result.coeffRef(1, 0) = -matrix.coeff(1, 0) * invdet;
|
||||
result.coeffRef(0, 1) = -matrix.coeff(0, 1) * invdet;
|
||||
result.coeffRef(1, 1) = temp * invdet;
|
||||
}
|
||||
|
||||
template<typename MatrixType, typename ResultType>
|
||||
struct compute_inverse<MatrixType, ResultType, 2>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(const MatrixType& matrix, ResultType& result)
|
||||
{
|
||||
template <typename MatrixType, typename ResultType>
|
||||
struct compute_inverse<MatrixType, ResultType, 2> {
|
||||
EIGEN_DEVICE_FUNC static inline void run(const MatrixType& matrix, ResultType& result) {
|
||||
typedef typename ResultType::Scalar Scalar;
|
||||
const Scalar invdet = typename MatrixType::Scalar(1) / matrix.determinant();
|
||||
compute_inverse_size2_helper(matrix, invdet, result);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_and_det_with_check<MatrixType, ResultType, 2>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(
|
||||
const MatrixType& matrix,
|
||||
const typename MatrixType::RealScalar& absDeterminantThreshold,
|
||||
ResultType& inverse,
|
||||
typename ResultType::Scalar& determinant,
|
||||
bool& invertible
|
||||
)
|
||||
{
|
||||
template <typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_and_det_with_check<MatrixType, ResultType, 2> {
|
||||
EIGEN_DEVICE_FUNC static inline void run(const MatrixType& matrix,
|
||||
const typename MatrixType::RealScalar& absDeterminantThreshold,
|
||||
ResultType& inverse, typename ResultType::Scalar& determinant,
|
||||
bool& invertible) {
|
||||
using std::abs;
|
||||
typedef typename ResultType::Scalar Scalar;
|
||||
determinant = matrix.determinant();
|
||||
invertible = abs(determinant) > absDeterminantThreshold;
|
||||
if(!invertible) return;
|
||||
if (!invertible) return;
|
||||
const Scalar invdet = Scalar(1) / determinant;
|
||||
compute_inverse_size2_helper(matrix, invdet, inverse);
|
||||
}
|
||||
@@ -125,79 +103,58 @@ struct compute_inverse_and_det_with_check<MatrixType, ResultType, 2>
|
||||
*** Size 3 implementation ***
|
||||
****************************/
|
||||
|
||||
template<typename MatrixType, int i, int j>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline typename MatrixType::Scalar cofactor_3x3(const MatrixType& m)
|
||||
{
|
||||
enum {
|
||||
i1 = (i+1) % 3,
|
||||
i2 = (i+2) % 3,
|
||||
j1 = (j+1) % 3,
|
||||
j2 = (j+2) % 3
|
||||
};
|
||||
return m.coeff(i1, j1) * m.coeff(i2, j2)
|
||||
- m.coeff(i1, j2) * m.coeff(i2, j1);
|
||||
template <typename MatrixType, int i, int j>
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixType::Scalar cofactor_3x3(const MatrixType& m) {
|
||||
enum { i1 = (i + 1) % 3, i2 = (i + 2) % 3, j1 = (j + 1) % 3, j2 = (j + 2) % 3 };
|
||||
return m.coeff(i1, j1) * m.coeff(i2, j2) - m.coeff(i1, j2) * m.coeff(i2, j1);
|
||||
}
|
||||
|
||||
template<typename MatrixType, typename ResultType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline void compute_inverse_size3_helper(
|
||||
const MatrixType& matrix,
|
||||
const typename ResultType::Scalar& invdet,
|
||||
const Matrix<typename ResultType::Scalar,3,1>& cofactors_col0,
|
||||
ResultType& result)
|
||||
{
|
||||
template <typename MatrixType, typename ResultType>
|
||||
EIGEN_DEVICE_FUNC inline void compute_inverse_size3_helper(
|
||||
const MatrixType& matrix, const typename ResultType::Scalar& invdet,
|
||||
const Matrix<typename ResultType::Scalar, 3, 1>& cofactors_col0, ResultType& result) {
|
||||
// Compute cofactors in a way that avoids aliasing issues.
|
||||
typedef typename ResultType::Scalar Scalar;
|
||||
const Scalar c01 = cofactor_3x3<MatrixType,0,1>(matrix) * invdet;
|
||||
const Scalar c11 = cofactor_3x3<MatrixType,1,1>(matrix) * invdet;
|
||||
const Scalar c02 = cofactor_3x3<MatrixType,0,2>(matrix) * invdet;
|
||||
result.coeffRef(1,2) = cofactor_3x3<MatrixType,2,1>(matrix) * invdet;
|
||||
result.coeffRef(2,1) = cofactor_3x3<MatrixType,1,2>(matrix) * invdet;
|
||||
result.coeffRef(2,2) = cofactor_3x3<MatrixType,2,2>(matrix) * invdet;
|
||||
result.coeffRef(1,0) = c01;
|
||||
result.coeffRef(1,1) = c11;
|
||||
result.coeffRef(2,0) = c02;
|
||||
const Scalar c01 = cofactor_3x3<MatrixType, 0, 1>(matrix) * invdet;
|
||||
const Scalar c11 = cofactor_3x3<MatrixType, 1, 1>(matrix) * invdet;
|
||||
const Scalar c02 = cofactor_3x3<MatrixType, 0, 2>(matrix) * invdet;
|
||||
result.coeffRef(1, 2) = cofactor_3x3<MatrixType, 2, 1>(matrix) * invdet;
|
||||
result.coeffRef(2, 1) = cofactor_3x3<MatrixType, 1, 2>(matrix) * invdet;
|
||||
result.coeffRef(2, 2) = cofactor_3x3<MatrixType, 2, 2>(matrix) * invdet;
|
||||
result.coeffRef(1, 0) = c01;
|
||||
result.coeffRef(1, 1) = c11;
|
||||
result.coeffRef(2, 0) = c02;
|
||||
result.row(0) = cofactors_col0 * invdet;
|
||||
}
|
||||
|
||||
template<typename MatrixType, typename ResultType>
|
||||
struct compute_inverse<MatrixType, ResultType, 3>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(const MatrixType& matrix, ResultType& result)
|
||||
{
|
||||
template <typename MatrixType, typename ResultType>
|
||||
struct compute_inverse<MatrixType, ResultType, 3> {
|
||||
EIGEN_DEVICE_FUNC static inline void run(const MatrixType& matrix, ResultType& result) {
|
||||
typedef typename ResultType::Scalar Scalar;
|
||||
Matrix<typename MatrixType::Scalar,3,1> cofactors_col0;
|
||||
cofactors_col0.coeffRef(0) = cofactor_3x3<MatrixType,0,0>(matrix);
|
||||
cofactors_col0.coeffRef(1) = cofactor_3x3<MatrixType,1,0>(matrix);
|
||||
cofactors_col0.coeffRef(2) = cofactor_3x3<MatrixType,2,0>(matrix);
|
||||
Matrix<typename MatrixType::Scalar, 3, 1> cofactors_col0;
|
||||
cofactors_col0.coeffRef(0) = cofactor_3x3<MatrixType, 0, 0>(matrix);
|
||||
cofactors_col0.coeffRef(1) = cofactor_3x3<MatrixType, 1, 0>(matrix);
|
||||
cofactors_col0.coeffRef(2) = cofactor_3x3<MatrixType, 2, 0>(matrix);
|
||||
const Scalar det = (cofactors_col0.cwiseProduct(matrix.col(0))).sum();
|
||||
const Scalar invdet = Scalar(1) / det;
|
||||
compute_inverse_size3_helper(matrix, invdet, cofactors_col0, result);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_and_det_with_check<MatrixType, ResultType, 3>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(
|
||||
const MatrixType& matrix,
|
||||
const typename MatrixType::RealScalar& absDeterminantThreshold,
|
||||
ResultType& inverse,
|
||||
typename ResultType::Scalar& determinant,
|
||||
bool& invertible
|
||||
)
|
||||
{
|
||||
template <typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_and_det_with_check<MatrixType, ResultType, 3> {
|
||||
EIGEN_DEVICE_FUNC static inline void run(const MatrixType& matrix,
|
||||
const typename MatrixType::RealScalar& absDeterminantThreshold,
|
||||
ResultType& inverse, typename ResultType::Scalar& determinant,
|
||||
bool& invertible) {
|
||||
typedef typename ResultType::Scalar Scalar;
|
||||
Matrix<Scalar,3,1> cofactors_col0;
|
||||
cofactors_col0.coeffRef(0) = cofactor_3x3<MatrixType,0,0>(matrix);
|
||||
cofactors_col0.coeffRef(1) = cofactor_3x3<MatrixType,1,0>(matrix);
|
||||
cofactors_col0.coeffRef(2) = cofactor_3x3<MatrixType,2,0>(matrix);
|
||||
Matrix<Scalar, 3, 1> cofactors_col0;
|
||||
cofactors_col0.coeffRef(0) = cofactor_3x3<MatrixType, 0, 0>(matrix);
|
||||
cofactors_col0.coeffRef(1) = cofactor_3x3<MatrixType, 1, 0>(matrix);
|
||||
cofactors_col0.coeffRef(2) = cofactor_3x3<MatrixType, 2, 0>(matrix);
|
||||
determinant = (cofactors_col0.cwiseProduct(matrix.col(0))).sum();
|
||||
invertible = Eigen::numext::abs(determinant) > absDeterminantThreshold;
|
||||
if(!invertible) return;
|
||||
if (!invertible) return;
|
||||
const Scalar invdet = Scalar(1) / determinant;
|
||||
compute_inverse_size3_helper(matrix, invdet, cofactors_col0, inverse);
|
||||
}
|
||||
@@ -207,84 +164,59 @@ struct compute_inverse_and_det_with_check<MatrixType, ResultType, 3>
|
||||
*** Size 4 implementation ***
|
||||
****************************/
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const typename Derived::Scalar general_det3_helper
|
||||
(const MatrixBase<Derived>& matrix, int i1, int i2, int i3, int j1, int j2, int j3)
|
||||
{
|
||||
return matrix.coeff(i1,j1)
|
||||
* (matrix.coeff(i2,j2) * matrix.coeff(i3,j3) - matrix.coeff(i2,j3) * matrix.coeff(i3,j2));
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC inline const typename Derived::Scalar general_det3_helper(const MatrixBase<Derived>& matrix, int i1,
|
||||
int i2, int i3, int j1, int j2, int j3) {
|
||||
return matrix.coeff(i1, j1) *
|
||||
(matrix.coeff(i2, j2) * matrix.coeff(i3, j3) - matrix.coeff(i2, j3) * matrix.coeff(i3, j2));
|
||||
}
|
||||
|
||||
template<typename MatrixType, int i, int j>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline typename MatrixType::Scalar cofactor_4x4(const MatrixType& matrix)
|
||||
{
|
||||
enum {
|
||||
i1 = (i+1) % 4,
|
||||
i2 = (i+2) % 4,
|
||||
i3 = (i+3) % 4,
|
||||
j1 = (j+1) % 4,
|
||||
j2 = (j+2) % 4,
|
||||
j3 = (j+3) % 4
|
||||
};
|
||||
return general_det3_helper(matrix, i1, i2, i3, j1, j2, j3)
|
||||
+ general_det3_helper(matrix, i2, i3, i1, j1, j2, j3)
|
||||
+ general_det3_helper(matrix, i3, i1, i2, j1, j2, j3);
|
||||
template <typename MatrixType, int i, int j>
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixType::Scalar cofactor_4x4(const MatrixType& matrix) {
|
||||
enum { i1 = (i + 1) % 4, i2 = (i + 2) % 4, i3 = (i + 3) % 4, j1 = (j + 1) % 4, j2 = (j + 2) % 4, j3 = (j + 3) % 4 };
|
||||
return general_det3_helper(matrix, i1, i2, i3, j1, j2, j3) + general_det3_helper(matrix, i2, i3, i1, j1, j2, j3) +
|
||||
general_det3_helper(matrix, i3, i1, i2, j1, j2, j3);
|
||||
}
|
||||
|
||||
template<int Arch, typename Scalar, typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_size4
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static void run(const MatrixType& matrix, ResultType& result)
|
||||
{
|
||||
result.coeffRef(0,0) = cofactor_4x4<MatrixType,0,0>(matrix);
|
||||
result.coeffRef(1,0) = -cofactor_4x4<MatrixType,0,1>(matrix);
|
||||
result.coeffRef(2,0) = cofactor_4x4<MatrixType,0,2>(matrix);
|
||||
result.coeffRef(3,0) = -cofactor_4x4<MatrixType,0,3>(matrix);
|
||||
result.coeffRef(0,2) = cofactor_4x4<MatrixType,2,0>(matrix);
|
||||
result.coeffRef(1,2) = -cofactor_4x4<MatrixType,2,1>(matrix);
|
||||
result.coeffRef(2,2) = cofactor_4x4<MatrixType,2,2>(matrix);
|
||||
result.coeffRef(3,2) = -cofactor_4x4<MatrixType,2,3>(matrix);
|
||||
result.coeffRef(0,1) = -cofactor_4x4<MatrixType,1,0>(matrix);
|
||||
result.coeffRef(1,1) = cofactor_4x4<MatrixType,1,1>(matrix);
|
||||
result.coeffRef(2,1) = -cofactor_4x4<MatrixType,1,2>(matrix);
|
||||
result.coeffRef(3,1) = cofactor_4x4<MatrixType,1,3>(matrix);
|
||||
result.coeffRef(0,3) = -cofactor_4x4<MatrixType,3,0>(matrix);
|
||||
result.coeffRef(1,3) = cofactor_4x4<MatrixType,3,1>(matrix);
|
||||
result.coeffRef(2,3) = -cofactor_4x4<MatrixType,3,2>(matrix);
|
||||
result.coeffRef(3,3) = cofactor_4x4<MatrixType,3,3>(matrix);
|
||||
template <int Arch, typename Scalar, typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_size4 {
|
||||
EIGEN_DEVICE_FUNC static void run(const MatrixType& matrix, ResultType& result) {
|
||||
result.coeffRef(0, 0) = cofactor_4x4<MatrixType, 0, 0>(matrix);
|
||||
result.coeffRef(1, 0) = -cofactor_4x4<MatrixType, 0, 1>(matrix);
|
||||
result.coeffRef(2, 0) = cofactor_4x4<MatrixType, 0, 2>(matrix);
|
||||
result.coeffRef(3, 0) = -cofactor_4x4<MatrixType, 0, 3>(matrix);
|
||||
result.coeffRef(0, 2) = cofactor_4x4<MatrixType, 2, 0>(matrix);
|
||||
result.coeffRef(1, 2) = -cofactor_4x4<MatrixType, 2, 1>(matrix);
|
||||
result.coeffRef(2, 2) = cofactor_4x4<MatrixType, 2, 2>(matrix);
|
||||
result.coeffRef(3, 2) = -cofactor_4x4<MatrixType, 2, 3>(matrix);
|
||||
result.coeffRef(0, 1) = -cofactor_4x4<MatrixType, 1, 0>(matrix);
|
||||
result.coeffRef(1, 1) = cofactor_4x4<MatrixType, 1, 1>(matrix);
|
||||
result.coeffRef(2, 1) = -cofactor_4x4<MatrixType, 1, 2>(matrix);
|
||||
result.coeffRef(3, 1) = cofactor_4x4<MatrixType, 1, 3>(matrix);
|
||||
result.coeffRef(0, 3) = -cofactor_4x4<MatrixType, 3, 0>(matrix);
|
||||
result.coeffRef(1, 3) = cofactor_4x4<MatrixType, 3, 1>(matrix);
|
||||
result.coeffRef(2, 3) = -cofactor_4x4<MatrixType, 3, 2>(matrix);
|
||||
result.coeffRef(3, 3) = cofactor_4x4<MatrixType, 3, 3>(matrix);
|
||||
result /= (matrix.col(0).cwiseProduct(result.row(0).transpose())).sum();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename MatrixType, typename ResultType>
|
||||
template <typename MatrixType, typename ResultType>
|
||||
struct compute_inverse<MatrixType, ResultType, 4>
|
||||
: compute_inverse_size4<Architecture::Target, typename MatrixType::Scalar,
|
||||
MatrixType, ResultType>
|
||||
{
|
||||
};
|
||||
: compute_inverse_size4<Architecture::Target, typename MatrixType::Scalar, MatrixType, ResultType> {};
|
||||
|
||||
template<typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_and_det_with_check<MatrixType, ResultType, 4>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(
|
||||
const MatrixType& matrix,
|
||||
const typename MatrixType::RealScalar& absDeterminantThreshold,
|
||||
ResultType& inverse,
|
||||
typename ResultType::Scalar& determinant,
|
||||
bool& invertible
|
||||
)
|
||||
{
|
||||
template <typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_and_det_with_check<MatrixType, ResultType, 4> {
|
||||
EIGEN_DEVICE_FUNC static inline void run(const MatrixType& matrix,
|
||||
const typename MatrixType::RealScalar& absDeterminantThreshold,
|
||||
ResultType& inverse, typename ResultType::Scalar& determinant,
|
||||
bool& invertible) {
|
||||
using std::abs;
|
||||
determinant = matrix.determinant();
|
||||
invertible = abs(determinant) > absDeterminantThreshold;
|
||||
if(invertible && extract_data(matrix) != extract_data(inverse)) {
|
||||
if (invertible && extract_data(matrix) != extract_data(inverse)) {
|
||||
compute_inverse<MatrixType, ResultType>::run(matrix, inverse);
|
||||
}
|
||||
else if(invertible) {
|
||||
} else if (invertible) {
|
||||
MatrixType matrix_t = matrix;
|
||||
compute_inverse<MatrixType, ResultType>::run(matrix_t, inverse);
|
||||
}
|
||||
@@ -295,141 +227,127 @@ struct compute_inverse_and_det_with_check<MatrixType, ResultType, 4>
|
||||
*** MatrixBase methods ***
|
||||
*************************/
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Specialization for "dense = dense_xpr.inverse()"
|
||||
template<typename DstXprType, typename XprType>
|
||||
struct Assignment<DstXprType, Inverse<XprType>, internal::assign_op<typename DstXprType::Scalar,typename XprType::Scalar>, Dense2Dense>
|
||||
{
|
||||
template <typename DstXprType, typename XprType>
|
||||
struct Assignment<DstXprType, Inverse<XprType>,
|
||||
internal::assign_op<typename DstXprType::Scalar, typename XprType::Scalar>, Dense2Dense> {
|
||||
typedef Inverse<XprType> SrcXprType;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename XprType::Scalar> &)
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static void run(DstXprType& dst, const SrcXprType& src,
|
||||
const internal::assign_op<typename DstXprType::Scalar, typename XprType::Scalar>&) {
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
|
||||
|
||||
const int Size = plain_enum_min(XprType::ColsAtCompileTime, DstXprType::ColsAtCompileTime);
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(Size);
|
||||
eigen_assert(( (Size<=1) || (Size>4) || (extract_data(src.nestedExpression())!=extract_data(dst)))
|
||||
&& "Aliasing problem detected in inverse(), you need to do inverse().eval() here.");
|
||||
eigen_assert(((Size <= 1) || (Size > 4) || (extract_data(src.nestedExpression()) != extract_data(dst))) &&
|
||||
"Aliasing problem detected in inverse(), you need to do inverse().eval() here.");
|
||||
|
||||
typedef typename internal::nested_eval<XprType, XprType::ColsAtCompileTime>::type ActualXprType;
|
||||
typedef internal::remove_all_t<ActualXprType> ActualXprTypeCleanded;
|
||||
|
||||
typedef typename internal::nested_eval<XprType,XprType::ColsAtCompileTime>::type ActualXprType;
|
||||
typedef internal::remove_all_t<ActualXprType> ActualXprTypeCleanded;
|
||||
|
||||
ActualXprType actual_xpr(src.nestedExpression());
|
||||
|
||||
|
||||
compute_inverse<ActualXprTypeCleanded, DstXprType>::run(actual_xpr, dst);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
/** \lu_module
|
||||
*
|
||||
* \returns the matrix inverse of this matrix.
|
||||
*
|
||||
* For small fixed sizes up to 4x4, this method uses cofactors.
|
||||
* In the general case, this method uses class PartialPivLU.
|
||||
*
|
||||
* \note This matrix must be invertible, otherwise the result is undefined. If you need an
|
||||
* invertibility check, do the following:
|
||||
* \li for fixed sizes up to 4x4, use computeInverseAndDetWithCheck().
|
||||
* \li for the general case, use class FullPivLU.
|
||||
*
|
||||
* Example: \include MatrixBase_inverse.cpp
|
||||
* Output: \verbinclude MatrixBase_inverse.out
|
||||
*
|
||||
* \sa computeInverseAndDetWithCheck()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Inverse<Derived> MatrixBase<Derived>::inverse() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsInteger,THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES)
|
||||
*
|
||||
* \returns the matrix inverse of this matrix.
|
||||
*
|
||||
* For small fixed sizes up to 4x4, this method uses cofactors.
|
||||
* In the general case, this method uses class PartialPivLU.
|
||||
*
|
||||
* \note This matrix must be invertible, otherwise the result is undefined. If you need an
|
||||
* invertibility check, do the following:
|
||||
* \li for fixed sizes up to 4x4, use computeInverseAndDetWithCheck().
|
||||
* \li for the general case, use class FullPivLU.
|
||||
*
|
||||
* Example: \include MatrixBase_inverse.cpp
|
||||
* Output: \verbinclude MatrixBase_inverse.out
|
||||
*
|
||||
* \sa computeInverseAndDetWithCheck()
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC inline const Inverse<Derived> MatrixBase<Derived>::inverse() const {
|
||||
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsInteger, THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES)
|
||||
eigen_assert(rows() == cols());
|
||||
return Inverse<Derived>(derived());
|
||||
}
|
||||
|
||||
/** \lu_module
|
||||
*
|
||||
* Computation of matrix inverse and determinant, with invertibility check.
|
||||
*
|
||||
* This is only for fixed-size square matrices of size up to 4x4.
|
||||
*
|
||||
* Notice that it will trigger a copy of input matrix when trying to do the inverse in place.
|
||||
*
|
||||
* \param inverse Reference to the matrix in which to store the inverse.
|
||||
* \param determinant Reference to the variable in which to store the determinant.
|
||||
* \param invertible Reference to the bool variable in which to store whether the matrix is invertible.
|
||||
* \param absDeterminantThreshold Optional parameter controlling the invertibility check.
|
||||
* The matrix will be declared invertible if the absolute value of its
|
||||
* determinant is greater than this threshold.
|
||||
*
|
||||
* Example: \include MatrixBase_computeInverseAndDetWithCheck.cpp
|
||||
* Output: \verbinclude MatrixBase_computeInverseAndDetWithCheck.out
|
||||
*
|
||||
* \sa inverse(), computeInverseWithCheck()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename ResultType>
|
||||
inline void MatrixBase<Derived>::computeInverseAndDetWithCheck(
|
||||
ResultType& inverse,
|
||||
typename ResultType::Scalar& determinant,
|
||||
bool& invertible,
|
||||
const RealScalar& absDeterminantThreshold
|
||||
) const
|
||||
{
|
||||
*
|
||||
* Computation of matrix inverse and determinant, with invertibility check.
|
||||
*
|
||||
* This is only for fixed-size square matrices of size up to 4x4.
|
||||
*
|
||||
* Notice that it will trigger a copy of input matrix when trying to do the inverse in place.
|
||||
*
|
||||
* \param inverse Reference to the matrix in which to store the inverse.
|
||||
* \param determinant Reference to the variable in which to store the determinant.
|
||||
* \param invertible Reference to the bool variable in which to store whether the matrix is invertible.
|
||||
* \param absDeterminantThreshold Optional parameter controlling the invertibility check.
|
||||
* The matrix will be declared invertible if the absolute value of its
|
||||
* determinant is greater than this threshold.
|
||||
*
|
||||
* Example: \include MatrixBase_computeInverseAndDetWithCheck.cpp
|
||||
* Output: \verbinclude MatrixBase_computeInverseAndDetWithCheck.out
|
||||
*
|
||||
* \sa inverse(), computeInverseWithCheck()
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename ResultType>
|
||||
inline void MatrixBase<Derived>::computeInverseAndDetWithCheck(ResultType& inverse,
|
||||
typename ResultType::Scalar& determinant,
|
||||
bool& invertible,
|
||||
const RealScalar& absDeterminantThreshold) const {
|
||||
// i'd love to put some static assertions there, but SFINAE means that they have no effect...
|
||||
eigen_assert(rows() == cols());
|
||||
// for 2x2, it's worth giving a chance to avoid evaluating.
|
||||
// for larger sizes, evaluating has negligible cost and limits code size.
|
||||
typedef std::conditional_t<
|
||||
RowsAtCompileTime == 2,
|
||||
internal::remove_all_t<typename internal::nested_eval<Derived, 2>::type>,
|
||||
PlainObject
|
||||
> MatrixType;
|
||||
internal::compute_inverse_and_det_with_check<MatrixType, ResultType>::run
|
||||
(derived(), absDeterminantThreshold, inverse, determinant, invertible);
|
||||
typedef std::conditional_t<RowsAtCompileTime == 2,
|
||||
internal::remove_all_t<typename internal::nested_eval<Derived, 2>::type>, PlainObject>
|
||||
MatrixType;
|
||||
internal::compute_inverse_and_det_with_check<MatrixType, ResultType>::run(derived(), absDeterminantThreshold, inverse,
|
||||
determinant, invertible);
|
||||
}
|
||||
|
||||
/** \lu_module
|
||||
*
|
||||
* Computation of matrix inverse, with invertibility check.
|
||||
*
|
||||
* This is only for fixed-size square matrices of size up to 4x4.
|
||||
*
|
||||
* Notice that it will trigger a copy of input matrix when trying to do the inverse in place.
|
||||
*
|
||||
* \param inverse Reference to the matrix in which to store the inverse.
|
||||
* \param invertible Reference to the bool variable in which to store whether the matrix is invertible.
|
||||
* \param absDeterminantThreshold Optional parameter controlling the invertibility check.
|
||||
* The matrix will be declared invertible if the absolute value of its
|
||||
* determinant is greater than this threshold.
|
||||
*
|
||||
* Example: \include MatrixBase_computeInverseWithCheck.cpp
|
||||
* Output: \verbinclude MatrixBase_computeInverseWithCheck.out
|
||||
*
|
||||
* \sa inverse(), computeInverseAndDetWithCheck()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename ResultType>
|
||||
inline void MatrixBase<Derived>::computeInverseWithCheck(
|
||||
ResultType& inverse,
|
||||
bool& invertible,
|
||||
const RealScalar& absDeterminantThreshold
|
||||
) const
|
||||
{
|
||||
*
|
||||
* Computation of matrix inverse, with invertibility check.
|
||||
*
|
||||
* This is only for fixed-size square matrices of size up to 4x4.
|
||||
*
|
||||
* Notice that it will trigger a copy of input matrix when trying to do the inverse in place.
|
||||
*
|
||||
* \param inverse Reference to the matrix in which to store the inverse.
|
||||
* \param invertible Reference to the bool variable in which to store whether the matrix is invertible.
|
||||
* \param absDeterminantThreshold Optional parameter controlling the invertibility check.
|
||||
* The matrix will be declared invertible if the absolute value of its
|
||||
* determinant is greater than this threshold.
|
||||
*
|
||||
* Example: \include MatrixBase_computeInverseWithCheck.cpp
|
||||
* Output: \verbinclude MatrixBase_computeInverseWithCheck.out
|
||||
*
|
||||
* \sa inverse(), computeInverseAndDetWithCheck()
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename ResultType>
|
||||
inline void MatrixBase<Derived>::computeInverseWithCheck(ResultType& inverse, bool& invertible,
|
||||
const RealScalar& absDeterminantThreshold) const {
|
||||
Scalar determinant;
|
||||
// i'd love to put some static assertions there, but SFINAE means that they have no effect...
|
||||
eigen_assert(rows() == cols());
|
||||
computeInverseAndDetWithCheck(inverse,determinant,invertible,absDeterminantThreshold);
|
||||
computeInverseAndDetWithCheck(inverse, determinant, invertible, absDeterminantThreshold);
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_INVERSE_IMPL_H
|
||||
#endif // EIGEN_INVERSE_IMPL_H
|
||||
|
||||
@@ -17,426 +17,385 @@
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
template<typename MatrixType_, typename PermutationIndex_> struct traits<PartialPivLU<MatrixType_, PermutationIndex_> >
|
||||
: traits<MatrixType_>
|
||||
{
|
||||
template <typename MatrixType_, typename PermutationIndex_>
|
||||
struct traits<PartialPivLU<MatrixType_, PermutationIndex_> > : traits<MatrixType_> {
|
||||
typedef MatrixXpr XprKind;
|
||||
typedef SolverStorage StorageKind;
|
||||
typedef PermutationIndex_ StorageIndex;
|
||||
typedef traits<MatrixType_> BaseTraits;
|
||||
enum {
|
||||
Flags = BaseTraits::Flags & RowMajorBit,
|
||||
CoeffReadCost = Dynamic
|
||||
};
|
||||
enum { Flags = BaseTraits::Flags & RowMajorBit, CoeffReadCost = Dynamic };
|
||||
};
|
||||
|
||||
template<typename T,typename Derived>
|
||||
template <typename T, typename Derived>
|
||||
struct enable_if_ref;
|
||||
// {
|
||||
// typedef Derived type;
|
||||
// };
|
||||
|
||||
template<typename T,typename Derived>
|
||||
struct enable_if_ref<Ref<T>,Derived> {
|
||||
template <typename T, typename Derived>
|
||||
struct enable_if_ref<Ref<T>, Derived> {
|
||||
typedef Derived type;
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
/** \ingroup LU_Module
|
||||
*
|
||||
* \class PartialPivLU
|
||||
*
|
||||
* \brief LU decomposition of a matrix with partial pivoting, and related features
|
||||
*
|
||||
* \tparam MatrixType_ the type of the matrix of which we are computing the LU decomposition
|
||||
*
|
||||
* This class represents a LU decomposition of a \b square \b invertible matrix, with partial pivoting: the matrix A
|
||||
* is decomposed as A = PLU where L is unit-lower-triangular, U is upper-triangular, and P
|
||||
* is a permutation matrix.
|
||||
*
|
||||
* Typically, partial pivoting LU decomposition is only considered numerically stable for square invertible
|
||||
* matrices. Thus LAPACK's dgesv and dgesvx require the matrix to be square and invertible. The present class
|
||||
* does the same. It will assert that the matrix is square, but it won't (actually it can't) check that the
|
||||
* matrix is invertible: it is your task to check that you only use this decomposition on invertible matrices.
|
||||
*
|
||||
* The guaranteed safe alternative, working for all matrices, is the full pivoting LU decomposition, provided
|
||||
* by class FullPivLU.
|
||||
*
|
||||
* This is \b not a rank-revealing LU decomposition. Many features are intentionally absent from this class,
|
||||
* such as rank computation. If you need these features, use class FullPivLU.
|
||||
*
|
||||
* This LU decomposition is suitable to invert invertible matrices. It is what MatrixBase::inverse() uses
|
||||
* in the general case.
|
||||
* On the other hand, it is \b not suitable to determine whether a given matrix is invertible.
|
||||
*
|
||||
* The data of the LU decomposition can be directly accessed through the methods matrixLU(), permutationP().
|
||||
*
|
||||
* This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
|
||||
*
|
||||
* \sa MatrixBase::partialPivLu(), MatrixBase::determinant(), MatrixBase::inverse(), MatrixBase::computeInverse(), class FullPivLU
|
||||
*/
|
||||
template<typename MatrixType_, typename PermutationIndex_> class PartialPivLU
|
||||
: public SolverBase<PartialPivLU<MatrixType_, PermutationIndex_> >
|
||||
{
|
||||
public:
|
||||
*
|
||||
* \class PartialPivLU
|
||||
*
|
||||
* \brief LU decomposition of a matrix with partial pivoting, and related features
|
||||
*
|
||||
* \tparam MatrixType_ the type of the matrix of which we are computing the LU decomposition
|
||||
*
|
||||
* This class represents a LU decomposition of a \b square \b invertible matrix, with partial pivoting: the matrix A
|
||||
* is decomposed as A = PLU where L is unit-lower-triangular, U is upper-triangular, and P
|
||||
* is a permutation matrix.
|
||||
*
|
||||
* Typically, partial pivoting LU decomposition is only considered numerically stable for square invertible
|
||||
* matrices. Thus LAPACK's dgesv and dgesvx require the matrix to be square and invertible. The present class
|
||||
* does the same. It will assert that the matrix is square, but it won't (actually it can't) check that the
|
||||
* matrix is invertible: it is your task to check that you only use this decomposition on invertible matrices.
|
||||
*
|
||||
* The guaranteed safe alternative, working for all matrices, is the full pivoting LU decomposition, provided
|
||||
* by class FullPivLU.
|
||||
*
|
||||
* This is \b not a rank-revealing LU decomposition. Many features are intentionally absent from this class,
|
||||
* such as rank computation. If you need these features, use class FullPivLU.
|
||||
*
|
||||
* This LU decomposition is suitable to invert invertible matrices. It is what MatrixBase::inverse() uses
|
||||
* in the general case.
|
||||
* On the other hand, it is \b not suitable to determine whether a given matrix is invertible.
|
||||
*
|
||||
* The data of the LU decomposition can be directly accessed through the methods matrixLU(), permutationP().
|
||||
*
|
||||
* This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
|
||||
*
|
||||
* \sa MatrixBase::partialPivLu(), MatrixBase::determinant(), MatrixBase::inverse(), MatrixBase::computeInverse(), class
|
||||
* FullPivLU
|
||||
*/
|
||||
template <typename MatrixType_, typename PermutationIndex_>
|
||||
class PartialPivLU : public SolverBase<PartialPivLU<MatrixType_, PermutationIndex_> > {
|
||||
public:
|
||||
typedef MatrixType_ MatrixType;
|
||||
typedef SolverBase<PartialPivLU> Base;
|
||||
friend class SolverBase<PartialPivLU>;
|
||||
|
||||
typedef MatrixType_ MatrixType;
|
||||
typedef SolverBase<PartialPivLU> Base;
|
||||
friend class SolverBase<PartialPivLU>;
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(PartialPivLU)
|
||||
enum {
|
||||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
|
||||
};
|
||||
using PermutationIndex = PermutationIndex_;
|
||||
typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime, PermutationIndex> PermutationType;
|
||||
typedef Transpositions<RowsAtCompileTime, MaxRowsAtCompileTime, PermutationIndex> TranspositionType;
|
||||
typedef typename MatrixType::PlainObject PlainObject;
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(PartialPivLU)
|
||||
enum {
|
||||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
|
||||
};
|
||||
using PermutationIndex = PermutationIndex_;
|
||||
typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime, PermutationIndex> PermutationType;
|
||||
typedef Transpositions<RowsAtCompileTime, MaxRowsAtCompileTime, PermutationIndex> TranspositionType;
|
||||
typedef typename MatrixType::PlainObject PlainObject;
|
||||
/**
|
||||
* \brief Default Constructor.
|
||||
*
|
||||
* The default constructor is useful in cases in which the user intends to
|
||||
* perform decompositions via PartialPivLU::compute(const MatrixType&).
|
||||
*/
|
||||
PartialPivLU();
|
||||
|
||||
/**
|
||||
* \brief Default Constructor.
|
||||
*
|
||||
* The default constructor is useful in cases in which the user intends to
|
||||
* perform decompositions via PartialPivLU::compute(const MatrixType&).
|
||||
*/
|
||||
PartialPivLU();
|
||||
/** \brief Default Constructor with memory preallocation
|
||||
*
|
||||
* Like the default constructor but with preallocation of the internal data
|
||||
* according to the specified problem \a size.
|
||||
* \sa PartialPivLU()
|
||||
*/
|
||||
explicit PartialPivLU(Index size);
|
||||
|
||||
/** \brief Default Constructor with memory preallocation
|
||||
*
|
||||
* Like the default constructor but with preallocation of the internal data
|
||||
* according to the specified problem \a size.
|
||||
* \sa PartialPivLU()
|
||||
*/
|
||||
explicit PartialPivLU(Index size);
|
||||
/** Constructor.
|
||||
*
|
||||
* \param matrix the matrix of which to compute the LU decomposition.
|
||||
*
|
||||
* \warning The matrix should have full rank (e.g. if it's square, it should be invertible).
|
||||
* If you need to deal with non-full rank, use class FullPivLU instead.
|
||||
*/
|
||||
template <typename InputType>
|
||||
explicit PartialPivLU(const EigenBase<InputType>& matrix);
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* \param matrix the matrix of which to compute the LU decomposition.
|
||||
*
|
||||
* \warning The matrix should have full rank (e.g. if it's square, it should be invertible).
|
||||
* If you need to deal with non-full rank, use class FullPivLU instead.
|
||||
*/
|
||||
template<typename InputType>
|
||||
explicit PartialPivLU(const EigenBase<InputType>& matrix);
|
||||
/** Constructor for \link InplaceDecomposition inplace decomposition \endlink
|
||||
*
|
||||
* \param matrix the matrix of which to compute the LU decomposition.
|
||||
*
|
||||
* \warning The matrix should have full rank (e.g. if it's square, it should be invertible).
|
||||
* If you need to deal with non-full rank, use class FullPivLU instead.
|
||||
*/
|
||||
template <typename InputType>
|
||||
explicit PartialPivLU(EigenBase<InputType>& matrix);
|
||||
|
||||
/** Constructor for \link InplaceDecomposition inplace decomposition \endlink
|
||||
*
|
||||
* \param matrix the matrix of which to compute the LU decomposition.
|
||||
*
|
||||
* \warning The matrix should have full rank (e.g. if it's square, it should be invertible).
|
||||
* If you need to deal with non-full rank, use class FullPivLU instead.
|
||||
*/
|
||||
template<typename InputType>
|
||||
explicit PartialPivLU(EigenBase<InputType>& matrix);
|
||||
template <typename InputType>
|
||||
PartialPivLU& compute(const EigenBase<InputType>& matrix) {
|
||||
m_lu = matrix.derived();
|
||||
compute();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputType>
|
||||
PartialPivLU& compute(const EigenBase<InputType>& matrix) {
|
||||
m_lu = matrix.derived();
|
||||
compute();
|
||||
return *this;
|
||||
}
|
||||
/** \returns the LU decomposition matrix: the upper-triangular part is U, the
|
||||
* unit-lower-triangular part is L (at least for square matrices; in the non-square
|
||||
* case, special care is needed, see the documentation of class FullPivLU).
|
||||
*
|
||||
* \sa matrixL(), matrixU()
|
||||
*/
|
||||
inline const MatrixType& matrixLU() const {
|
||||
eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
|
||||
return m_lu;
|
||||
}
|
||||
|
||||
/** \returns the LU decomposition matrix: the upper-triangular part is U, the
|
||||
* unit-lower-triangular part is L (at least for square matrices; in the non-square
|
||||
* case, special care is needed, see the documentation of class FullPivLU).
|
||||
*
|
||||
* \sa matrixL(), matrixU()
|
||||
*/
|
||||
inline const MatrixType& matrixLU() const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
|
||||
return m_lu;
|
||||
}
|
||||
/** \returns the permutation matrix P.
|
||||
*/
|
||||
inline const PermutationType& permutationP() const {
|
||||
eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
|
||||
return m_p;
|
||||
}
|
||||
|
||||
/** \returns the permutation matrix P.
|
||||
*/
|
||||
inline const PermutationType& permutationP() const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
|
||||
return m_p;
|
||||
}
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** This method returns the solution x to the equation Ax=b, where A is the matrix of which
|
||||
* *this is the LU decomposition.
|
||||
*
|
||||
* \param b the right-hand-side of the equation to solve. Can be a vector or a matrix,
|
||||
* the only requirement in order for the equation to make sense is that
|
||||
* b.rows()==A.rows(), where A is the matrix of which *this is the LU decomposition.
|
||||
*
|
||||
* \returns the solution.
|
||||
*
|
||||
* Example: \include PartialPivLU_solve.cpp
|
||||
* Output: \verbinclude PartialPivLU_solve.out
|
||||
*
|
||||
* Since this PartialPivLU class assumes anyway that the matrix A is invertible, the solution
|
||||
* theoretically exists and is unique regardless of b.
|
||||
*
|
||||
* \sa TriangularView::solve(), inverse(), computeInverse()
|
||||
*/
|
||||
template <typename Rhs>
|
||||
inline const Solve<PartialPivLU, Rhs> solve(const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** This method returns the solution x to the equation Ax=b, where A is the matrix of which
|
||||
* *this is the LU decomposition.
|
||||
*
|
||||
* \param b the right-hand-side of the equation to solve. Can be a vector or a matrix,
|
||||
* the only requirement in order for the equation to make sense is that
|
||||
* b.rows()==A.rows(), where A is the matrix of which *this is the LU decomposition.
|
||||
*
|
||||
* \returns the solution.
|
||||
*
|
||||
* Example: \include PartialPivLU_solve.cpp
|
||||
* Output: \verbinclude PartialPivLU_solve.out
|
||||
*
|
||||
* Since this PartialPivLU class assumes anyway that the matrix A is invertible, the solution
|
||||
* theoretically exists and is unique regardless of b.
|
||||
*
|
||||
* \sa TriangularView::solve(), inverse(), computeInverse()
|
||||
*/
|
||||
template<typename Rhs>
|
||||
inline const Solve<PartialPivLU, Rhs>
|
||||
solve(const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
/** \returns an estimate of the reciprocal condition number of the matrix of which \c *this is
|
||||
the LU decomposition.
|
||||
*/
|
||||
inline RealScalar rcond() const {
|
||||
eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
|
||||
return internal::rcond_estimate_helper(m_l1_norm, *this);
|
||||
}
|
||||
|
||||
/** \returns an estimate of the reciprocal condition number of the matrix of which \c *this is
|
||||
the LU decomposition.
|
||||
*/
|
||||
inline RealScalar rcond() const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
|
||||
return internal::rcond_estimate_helper(m_l1_norm, *this);
|
||||
}
|
||||
/** \returns the inverse of the matrix of which *this is the LU decomposition.
|
||||
*
|
||||
* \warning The matrix being decomposed here is assumed to be invertible. If you need to check for
|
||||
* invertibility, use class FullPivLU instead.
|
||||
*
|
||||
* \sa MatrixBase::inverse(), LU::inverse()
|
||||
*/
|
||||
inline const Inverse<PartialPivLU> inverse() const {
|
||||
eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
|
||||
return Inverse<PartialPivLU>(*this);
|
||||
}
|
||||
|
||||
/** \returns the inverse of the matrix of which *this is the LU decomposition.
|
||||
*
|
||||
* \warning The matrix being decomposed here is assumed to be invertible. If you need to check for
|
||||
* invertibility, use class FullPivLU instead.
|
||||
*
|
||||
* \sa MatrixBase::inverse(), LU::inverse()
|
||||
*/
|
||||
inline const Inverse<PartialPivLU> inverse() const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
|
||||
return Inverse<PartialPivLU>(*this);
|
||||
}
|
||||
/** \returns the determinant of the matrix of which
|
||||
* *this is the LU decomposition. It has only linear complexity
|
||||
* (that is, O(n) where n is the dimension of the square matrix)
|
||||
* as the LU decomposition has already been computed.
|
||||
*
|
||||
* \note For fixed-size matrices of size up to 4, MatrixBase::determinant() offers
|
||||
* optimized paths.
|
||||
*
|
||||
* \warning a determinant can be very big or small, so for matrices
|
||||
* of large enough dimension, there is a risk of overflow/underflow.
|
||||
*
|
||||
* \sa MatrixBase::determinant()
|
||||
*/
|
||||
Scalar determinant() const;
|
||||
|
||||
/** \returns the determinant of the matrix of which
|
||||
* *this is the LU decomposition. It has only linear complexity
|
||||
* (that is, O(n) where n is the dimension of the square matrix)
|
||||
* as the LU decomposition has already been computed.
|
||||
*
|
||||
* \note For fixed-size matrices of size up to 4, MatrixBase::determinant() offers
|
||||
* optimized paths.
|
||||
*
|
||||
* \warning a determinant can be very big or small, so for matrices
|
||||
* of large enough dimension, there is a risk of overflow/underflow.
|
||||
*
|
||||
* \sa MatrixBase::determinant()
|
||||
*/
|
||||
Scalar determinant() const;
|
||||
MatrixType reconstructedMatrix() const;
|
||||
|
||||
MatrixType reconstructedMatrix() const;
|
||||
EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_lu.rows(); }
|
||||
EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_lu.cols(); }
|
||||
|
||||
EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_lu.rows(); }
|
||||
EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_lu.cols(); }
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template <typename RhsType, typename DstType>
|
||||
EIGEN_DEVICE_FUNC void _solve_impl(const RhsType& rhs, DstType& dst) const {
|
||||
/* The decomposition PA = LU can be rewritten as A = P^{-1} L U.
|
||||
* So we proceed as follows:
|
||||
* Step 1: compute c = Pb.
|
||||
* Step 2: replace c by the solution x to Lx = c.
|
||||
* Step 3: replace c by the solution x to Ux = c.
|
||||
*/
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename RhsType, typename DstType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void _solve_impl(const RhsType &rhs, DstType &dst) const {
|
||||
/* The decomposition PA = LU can be rewritten as A = P^{-1} L U.
|
||||
* So we proceed as follows:
|
||||
* Step 1: compute c = Pb.
|
||||
* Step 2: replace c by the solution x to Lx = c.
|
||||
* Step 3: replace c by the solution x to Ux = c.
|
||||
*/
|
||||
// Step 1
|
||||
dst = permutationP() * rhs;
|
||||
|
||||
// Step 1
|
||||
dst = permutationP() * rhs;
|
||||
// Step 2
|
||||
m_lu.template triangularView<UnitLower>().solveInPlace(dst);
|
||||
|
||||
// Step 2
|
||||
m_lu.template triangularView<UnitLower>().solveInPlace(dst);
|
||||
// Step 3
|
||||
m_lu.template triangularView<Upper>().solveInPlace(dst);
|
||||
}
|
||||
|
||||
// Step 3
|
||||
m_lu.template triangularView<Upper>().solveInPlace(dst);
|
||||
}
|
||||
template <bool Conjugate, typename RhsType, typename DstType>
|
||||
EIGEN_DEVICE_FUNC void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const {
|
||||
/* The decomposition PA = LU can be rewritten as A^T = U^T L^T P.
|
||||
* So we proceed as follows:
|
||||
* Step 1: compute c as the solution to L^T c = b
|
||||
* Step 2: replace c by the solution x to U^T x = c.
|
||||
* Step 3: update c = P^-1 c.
|
||||
*/
|
||||
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const {
|
||||
/* The decomposition PA = LU can be rewritten as A^T = U^T L^T P.
|
||||
* So we proceed as follows:
|
||||
* Step 1: compute c as the solution to L^T c = b
|
||||
* Step 2: replace c by the solution x to U^T x = c.
|
||||
* Step 3: update c = P^-1 c.
|
||||
*/
|
||||
eigen_assert(rhs.rows() == m_lu.cols());
|
||||
|
||||
eigen_assert(rhs.rows() == m_lu.cols());
|
||||
// Step 1
|
||||
dst = m_lu.template triangularView<Upper>().transpose().template conjugateIf<Conjugate>().solve(rhs);
|
||||
// Step 2
|
||||
m_lu.template triangularView<UnitLower>().transpose().template conjugateIf<Conjugate>().solveInPlace(dst);
|
||||
// Step 3
|
||||
dst = permutationP().transpose() * dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Step 1
|
||||
dst = m_lu.template triangularView<Upper>().transpose()
|
||||
.template conjugateIf<Conjugate>().solve(rhs);
|
||||
// Step 2
|
||||
m_lu.template triangularView<UnitLower>().transpose()
|
||||
.template conjugateIf<Conjugate>().solveInPlace(dst);
|
||||
// Step 3
|
||||
dst = permutationP().transpose() * dst;
|
||||
}
|
||||
#endif
|
||||
protected:
|
||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||
|
||||
protected:
|
||||
void compute();
|
||||
|
||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||
|
||||
void compute();
|
||||
|
||||
MatrixType m_lu;
|
||||
PermutationType m_p;
|
||||
TranspositionType m_rowsTranspositions;
|
||||
RealScalar m_l1_norm;
|
||||
signed char m_det_p;
|
||||
bool m_isInitialized;
|
||||
MatrixType m_lu;
|
||||
PermutationType m_p;
|
||||
TranspositionType m_rowsTranspositions;
|
||||
RealScalar m_l1_norm;
|
||||
signed char m_det_p;
|
||||
bool m_isInitialized;
|
||||
};
|
||||
|
||||
template<typename MatrixType, typename PermutationIndex>
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
PartialPivLU<MatrixType, PermutationIndex>::PartialPivLU()
|
||||
: m_lu(),
|
||||
m_p(),
|
||||
m_rowsTranspositions(),
|
||||
m_l1_norm(0),
|
||||
m_det_p(0),
|
||||
m_isInitialized(false)
|
||||
{
|
||||
}
|
||||
: m_lu(), m_p(), m_rowsTranspositions(), m_l1_norm(0), m_det_p(0), m_isInitialized(false) {}
|
||||
|
||||
template<typename MatrixType, typename PermutationIndex>
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
PartialPivLU<MatrixType, PermutationIndex>::PartialPivLU(Index size)
|
||||
: m_lu(size, size),
|
||||
m_p(size),
|
||||
m_rowsTranspositions(size),
|
||||
m_l1_norm(0),
|
||||
m_det_p(0),
|
||||
m_isInitialized(false)
|
||||
{
|
||||
}
|
||||
: m_lu(size, size), m_p(size), m_rowsTranspositions(size), m_l1_norm(0), m_det_p(0), m_isInitialized(false) {}
|
||||
|
||||
template<typename MatrixType, typename PermutationIndex>
|
||||
template<typename InputType>
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
template <typename InputType>
|
||||
PartialPivLU<MatrixType, PermutationIndex>::PartialPivLU(const EigenBase<InputType>& matrix)
|
||||
: m_lu(matrix.rows(),matrix.cols()),
|
||||
m_p(matrix.rows()),
|
||||
m_rowsTranspositions(matrix.rows()),
|
||||
m_l1_norm(0),
|
||||
m_det_p(0),
|
||||
m_isInitialized(false)
|
||||
{
|
||||
: m_lu(matrix.rows(), matrix.cols()),
|
||||
m_p(matrix.rows()),
|
||||
m_rowsTranspositions(matrix.rows()),
|
||||
m_l1_norm(0),
|
||||
m_det_p(0),
|
||||
m_isInitialized(false) {
|
||||
compute(matrix.derived());
|
||||
}
|
||||
|
||||
template<typename MatrixType, typename PermutationIndex>
|
||||
template<typename InputType>
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
template <typename InputType>
|
||||
PartialPivLU<MatrixType, PermutationIndex>::PartialPivLU(EigenBase<InputType>& matrix)
|
||||
: m_lu(matrix.derived()),
|
||||
m_p(matrix.rows()),
|
||||
m_rowsTranspositions(matrix.rows()),
|
||||
m_l1_norm(0),
|
||||
m_det_p(0),
|
||||
m_isInitialized(false)
|
||||
{
|
||||
: m_lu(matrix.derived()),
|
||||
m_p(matrix.rows()),
|
||||
m_rowsTranspositions(matrix.rows()),
|
||||
m_l1_norm(0),
|
||||
m_det_p(0),
|
||||
m_isInitialized(false) {
|
||||
compute();
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
/** \internal This is the blocked version of fullpivlu_unblocked() */
|
||||
template<typename Scalar, int StorageOrder, typename PivIndex, int SizeAtCompileTime=Dynamic>
|
||||
struct partial_lu_impl
|
||||
{
|
||||
template <typename Scalar, int StorageOrder, typename PivIndex, int SizeAtCompileTime = Dynamic>
|
||||
struct partial_lu_impl {
|
||||
static constexpr int UnBlockedBound = 16;
|
||||
static constexpr bool UnBlockedAtCompileTime = SizeAtCompileTime!=Dynamic && SizeAtCompileTime<=UnBlockedBound;
|
||||
static constexpr bool UnBlockedAtCompileTime = SizeAtCompileTime != Dynamic && SizeAtCompileTime <= UnBlockedBound;
|
||||
static constexpr int ActualSizeAtCompileTime = UnBlockedAtCompileTime ? SizeAtCompileTime : Dynamic;
|
||||
// Remaining rows and columns at compile-time:
|
||||
static constexpr int RRows = SizeAtCompileTime==2 ? 1 : Dynamic;
|
||||
static constexpr int RCols = SizeAtCompileTime==2 ? 1 : Dynamic;
|
||||
static constexpr int RRows = SizeAtCompileTime == 2 ? 1 : Dynamic;
|
||||
static constexpr int RCols = SizeAtCompileTime == 2 ? 1 : Dynamic;
|
||||
typedef Matrix<Scalar, ActualSizeAtCompileTime, ActualSizeAtCompileTime, StorageOrder> MatrixType;
|
||||
typedef Ref<MatrixType> MatrixTypeRef;
|
||||
typedef Ref<Matrix<Scalar, Dynamic, Dynamic, StorageOrder> > BlockType;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
|
||||
/** \internal performs the LU decomposition in-place of the matrix \a lu
|
||||
* using an unblocked algorithm.
|
||||
*
|
||||
* In addition, this function returns the row transpositions in the
|
||||
* vector \a row_transpositions which must have a size equal to the number
|
||||
* of columns of the matrix \a lu, and an integer \a nb_transpositions
|
||||
* which returns the actual number of transpositions.
|
||||
*
|
||||
* \returns The index of the first pivot which is exactly zero if any, or a negative number otherwise.
|
||||
*/
|
||||
static Index unblocked_lu(MatrixTypeRef& lu, PivIndex* row_transpositions, PivIndex& nb_transpositions)
|
||||
{
|
||||
* using an unblocked algorithm.
|
||||
*
|
||||
* In addition, this function returns the row transpositions in the
|
||||
* vector \a row_transpositions which must have a size equal to the number
|
||||
* of columns of the matrix \a lu, and an integer \a nb_transpositions
|
||||
* which returns the actual number of transpositions.
|
||||
*
|
||||
* \returns The index of the first pivot which is exactly zero if any, or a negative number otherwise.
|
||||
*/
|
||||
static Index unblocked_lu(MatrixTypeRef& lu, PivIndex* row_transpositions, PivIndex& nb_transpositions) {
|
||||
typedef scalar_score_coeff_op<Scalar> Scoring;
|
||||
typedef typename Scoring::result_type Score;
|
||||
const Index rows = lu.rows();
|
||||
const Index cols = lu.cols();
|
||||
const Index size = (std::min)(rows,cols);
|
||||
const Index size = (std::min)(rows, cols);
|
||||
// For small compile-time matrices it is worth processing the last row separately:
|
||||
// speedup: +100% for 2x2, +10% for others.
|
||||
const Index endk = UnBlockedAtCompileTime ? size-1 : size;
|
||||
const Index endk = UnBlockedAtCompileTime ? size - 1 : size;
|
||||
nb_transpositions = 0;
|
||||
Index first_zero_pivot = -1;
|
||||
for(Index k = 0; k < endk; ++k)
|
||||
{
|
||||
int rrows = internal::convert_index<int>(rows-k-1);
|
||||
int rcols = internal::convert_index<int>(cols-k-1);
|
||||
for (Index k = 0; k < endk; ++k) {
|
||||
int rrows = internal::convert_index<int>(rows - k - 1);
|
||||
int rcols = internal::convert_index<int>(cols - k - 1);
|
||||
|
||||
Index row_of_biggest_in_col;
|
||||
Score biggest_in_corner
|
||||
= lu.col(k).tail(rows-k).unaryExpr(Scoring()).maxCoeff(&row_of_biggest_in_col);
|
||||
Score biggest_in_corner = lu.col(k).tail(rows - k).unaryExpr(Scoring()).maxCoeff(&row_of_biggest_in_col);
|
||||
row_of_biggest_in_col += k;
|
||||
|
||||
row_transpositions[k] = PivIndex(row_of_biggest_in_col);
|
||||
|
||||
if(!numext::is_exactly_zero(biggest_in_corner))
|
||||
{
|
||||
if(k != row_of_biggest_in_col)
|
||||
{
|
||||
if (!numext::is_exactly_zero(biggest_in_corner)) {
|
||||
if (k != row_of_biggest_in_col) {
|
||||
lu.row(k).swap(lu.row(row_of_biggest_in_col));
|
||||
++nb_transpositions;
|
||||
}
|
||||
|
||||
lu.col(k).tail(fix<RRows>(rrows)) /= lu.coeff(k,k);
|
||||
}
|
||||
else if(first_zero_pivot==-1)
|
||||
{
|
||||
lu.col(k).tail(fix<RRows>(rrows)) /= lu.coeff(k, k);
|
||||
} else if (first_zero_pivot == -1) {
|
||||
// the pivot is exactly zero, we record the index of the first pivot which is exactly 0,
|
||||
// and continue the factorization such we still have A = PLU
|
||||
first_zero_pivot = k;
|
||||
}
|
||||
|
||||
if(k<rows-1)
|
||||
lu.bottomRightCorner(fix<RRows>(rrows),fix<RCols>(rcols)).noalias() -= lu.col(k).tail(fix<RRows>(rrows)) * lu.row(k).tail(fix<RCols>(rcols));
|
||||
if (k < rows - 1)
|
||||
lu.bottomRightCorner(fix<RRows>(rrows), fix<RCols>(rcols)).noalias() -=
|
||||
lu.col(k).tail(fix<RRows>(rrows)) * lu.row(k).tail(fix<RCols>(rcols));
|
||||
}
|
||||
|
||||
// special handling of the last entry
|
||||
if(UnBlockedAtCompileTime)
|
||||
{
|
||||
if (UnBlockedAtCompileTime) {
|
||||
Index k = endk;
|
||||
row_transpositions[k] = PivIndex(k);
|
||||
if (numext::is_exactly_zero(Scoring()(lu(k, k))) && first_zero_pivot == -1)
|
||||
first_zero_pivot = k;
|
||||
if (numext::is_exactly_zero(Scoring()(lu(k, k))) && first_zero_pivot == -1) first_zero_pivot = k;
|
||||
}
|
||||
|
||||
return first_zero_pivot;
|
||||
}
|
||||
|
||||
/** \internal performs the LU decomposition in-place of the matrix represented
|
||||
* by the variables \a rows, \a cols, \a lu_data, and \a lu_stride using a
|
||||
* recursive, blocked algorithm.
|
||||
*
|
||||
* In addition, this function returns the row transpositions in the
|
||||
* vector \a row_transpositions which must have a size equal to the number
|
||||
* of columns of the matrix \a lu, and an integer \a nb_transpositions
|
||||
* which returns the actual number of transpositions.
|
||||
*
|
||||
* \returns The index of the first pivot which is exactly zero if any, or a negative number otherwise.
|
||||
*
|
||||
* \note This very low level interface using pointers, etc. is to:
|
||||
* 1 - reduce the number of instantiations to the strict minimum
|
||||
* 2 - avoid infinite recursion of the instantiations with Block<Block<Block<...> > >
|
||||
*/
|
||||
static Index blocked_lu(Index rows, Index cols, Scalar* lu_data, Index luStride, PivIndex* row_transpositions, PivIndex& nb_transpositions, Index maxBlockSize=256)
|
||||
{
|
||||
MatrixTypeRef lu = MatrixType::Map(lu_data,rows, cols, OuterStride<>(luStride));
|
||||
* by the variables \a rows, \a cols, \a lu_data, and \a lu_stride using a
|
||||
* recursive, blocked algorithm.
|
||||
*
|
||||
* In addition, this function returns the row transpositions in the
|
||||
* vector \a row_transpositions which must have a size equal to the number
|
||||
* of columns of the matrix \a lu, and an integer \a nb_transpositions
|
||||
* which returns the actual number of transpositions.
|
||||
*
|
||||
* \returns The index of the first pivot which is exactly zero if any, or a negative number otherwise.
|
||||
*
|
||||
* \note This very low level interface using pointers, etc. is to:
|
||||
* 1 - reduce the number of instantiations to the strict minimum
|
||||
* 2 - avoid infinite recursion of the instantiations with Block<Block<Block<...> > >
|
||||
*/
|
||||
static Index blocked_lu(Index rows, Index cols, Scalar* lu_data, Index luStride, PivIndex* row_transpositions,
|
||||
PivIndex& nb_transpositions, Index maxBlockSize = 256) {
|
||||
MatrixTypeRef lu = MatrixType::Map(lu_data, rows, cols, OuterStride<>(luStride));
|
||||
|
||||
const Index size = (std::min)(rows,cols);
|
||||
const Index size = (std::min)(rows, cols);
|
||||
|
||||
// if the matrix is too small, no blocking:
|
||||
if(UnBlockedAtCompileTime || size<=UnBlockedBound)
|
||||
{
|
||||
if (UnBlockedAtCompileTime || size <= UnBlockedBound) {
|
||||
return unblocked_lu(lu, row_transpositions, nb_transpositions);
|
||||
}
|
||||
|
||||
@@ -444,51 +403,46 @@ struct partial_lu_impl
|
||||
// of the matrix so that there is enough sub blocks:
|
||||
Index blockSize;
|
||||
{
|
||||
blockSize = size/8;
|
||||
blockSize = (blockSize/16)*16;
|
||||
blockSize = (std::min)((std::max)(blockSize,Index(8)), maxBlockSize);
|
||||
blockSize = size / 8;
|
||||
blockSize = (blockSize / 16) * 16;
|
||||
blockSize = (std::min)((std::max)(blockSize, Index(8)), maxBlockSize);
|
||||
}
|
||||
|
||||
nb_transpositions = 0;
|
||||
Index first_zero_pivot = -1;
|
||||
for(Index k = 0; k < size; k+=blockSize)
|
||||
{
|
||||
Index bs = (std::min)(size-k,blockSize); // actual size of the block
|
||||
Index trows = rows - k - bs; // trailing rows
|
||||
Index tsize = size - k - bs; // trailing size
|
||||
for (Index k = 0; k < size; k += blockSize) {
|
||||
Index bs = (std::min)(size - k, blockSize); // actual size of the block
|
||||
Index trows = rows - k - bs; // trailing rows
|
||||
Index tsize = size - k - bs; // trailing size
|
||||
|
||||
// partition the matrix:
|
||||
// A00 | A01 | A02
|
||||
// lu = A_0 | A_1 | A_2 = A10 | A11 | A12
|
||||
// A20 | A21 | A22
|
||||
BlockType A_0 = lu.block(0,0,rows,k);
|
||||
BlockType A_2 = lu.block(0,k+bs,rows,tsize);
|
||||
BlockType A11 = lu.block(k,k,bs,bs);
|
||||
BlockType A12 = lu.block(k,k+bs,bs,tsize);
|
||||
BlockType A21 = lu.block(k+bs,k,trows,bs);
|
||||
BlockType A22 = lu.block(k+bs,k+bs,trows,tsize);
|
||||
BlockType A_0 = lu.block(0, 0, rows, k);
|
||||
BlockType A_2 = lu.block(0, k + bs, rows, tsize);
|
||||
BlockType A11 = lu.block(k, k, bs, bs);
|
||||
BlockType A12 = lu.block(k, k + bs, bs, tsize);
|
||||
BlockType A21 = lu.block(k + bs, k, trows, bs);
|
||||
BlockType A22 = lu.block(k + bs, k + bs, trows, tsize);
|
||||
|
||||
PivIndex nb_transpositions_in_panel;
|
||||
// recursively call the blocked LU algorithm on [A11^T A21^T]^T
|
||||
// with a very small blocking size:
|
||||
Index ret = blocked_lu(trows+bs, bs, &lu.coeffRef(k,k), luStride,
|
||||
row_transpositions+k, nb_transpositions_in_panel, 16);
|
||||
if(ret>=0 && first_zero_pivot==-1)
|
||||
first_zero_pivot = k+ret;
|
||||
Index ret = blocked_lu(trows + bs, bs, &lu.coeffRef(k, k), luStride, row_transpositions + k,
|
||||
nb_transpositions_in_panel, 16);
|
||||
if (ret >= 0 && first_zero_pivot == -1) first_zero_pivot = k + ret;
|
||||
|
||||
nb_transpositions += nb_transpositions_in_panel;
|
||||
// update permutations and apply them to A_0
|
||||
for(Index i=k; i<k+bs; ++i)
|
||||
{
|
||||
for (Index i = k; i < k + bs; ++i) {
|
||||
Index piv = (row_transpositions[i] += internal::convert_index<PivIndex>(k));
|
||||
A_0.row(i).swap(A_0.row(piv));
|
||||
}
|
||||
|
||||
if(trows)
|
||||
{
|
||||
if (trows) {
|
||||
// apply permutations to A_2
|
||||
for(Index i=k;i<k+bs; ++i)
|
||||
A_2.row(i).swap(A_2.row(row_transpositions[i]));
|
||||
for (Index i = k; i < k + bs; ++i) A_2.row(i).swap(A_2.row(row_transpositions[i]));
|
||||
|
||||
// A12 = A11^-1 A12
|
||||
A11.template triangularView<UnitLower>().solveInPlace(A12);
|
||||
@@ -501,33 +455,33 @@ struct partial_lu_impl
|
||||
};
|
||||
|
||||
/** \internal performs the LU decomposition with partial pivoting in-place.
|
||||
*/
|
||||
template<typename MatrixType, typename TranspositionType>
|
||||
void partial_lu_inplace(MatrixType& lu, TranspositionType& row_transpositions, typename TranspositionType::StorageIndex& nb_transpositions)
|
||||
{
|
||||
*/
|
||||
template <typename MatrixType, typename TranspositionType>
|
||||
void partial_lu_inplace(MatrixType& lu, TranspositionType& row_transpositions,
|
||||
typename TranspositionType::StorageIndex& nb_transpositions) {
|
||||
// Special-case of zero matrix.
|
||||
if (lu.rows() == 0 || lu.cols() == 0) {
|
||||
nb_transpositions = 0;
|
||||
return;
|
||||
}
|
||||
eigen_assert(lu.cols() == row_transpositions.size());
|
||||
eigen_assert(row_transpositions.size() < 2 || (&row_transpositions.coeffRef(1)-&row_transpositions.coeffRef(0)) == 1);
|
||||
eigen_assert(row_transpositions.size() < 2 ||
|
||||
(&row_transpositions.coeffRef(1) - &row_transpositions.coeffRef(0)) == 1);
|
||||
|
||||
partial_lu_impl
|
||||
< typename MatrixType::Scalar, MatrixType::Flags&RowMajorBit?RowMajor:ColMajor,
|
||||
typename TranspositionType::StorageIndex,
|
||||
internal::min_size_prefer_fixed(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime)>
|
||||
::blocked_lu(lu.rows(), lu.cols(), &lu.coeffRef(0,0), lu.outerStride(), &row_transpositions.coeffRef(0), nb_transpositions);
|
||||
partial_lu_impl<typename MatrixType::Scalar, MatrixType::Flags & RowMajorBit ? RowMajor : ColMajor,
|
||||
typename TranspositionType::StorageIndex,
|
||||
internal::min_size_prefer_fixed(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime)>::
|
||||
blocked_lu(lu.rows(), lu.cols(), &lu.coeffRef(0, 0), lu.outerStride(), &row_transpositions.coeffRef(0),
|
||||
nb_transpositions);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
template<typename MatrixType, typename PermutationIndex>
|
||||
void PartialPivLU<MatrixType, PermutationIndex>::compute()
|
||||
{
|
||||
eigen_assert(m_lu.rows()<NumTraits<PermutationIndex>::highest());
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
void PartialPivLU<MatrixType, PermutationIndex>::compute() {
|
||||
eigen_assert(m_lu.rows() < NumTraits<PermutationIndex>::highest());
|
||||
|
||||
if(m_lu.cols()>0)
|
||||
if (m_lu.cols() > 0)
|
||||
m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff();
|
||||
else
|
||||
m_l1_norm = RealScalar(0);
|
||||
@@ -539,16 +493,16 @@ void PartialPivLU<MatrixType, PermutationIndex>::compute()
|
||||
|
||||
typename TranspositionType::StorageIndex nb_transpositions;
|
||||
internal::partial_lu_inplace(m_lu, m_rowsTranspositions, nb_transpositions);
|
||||
m_det_p = (nb_transpositions%2) ? -1 : 1;
|
||||
m_det_p = (nb_transpositions % 2) ? -1 : 1;
|
||||
|
||||
m_p = m_rowsTranspositions;
|
||||
|
||||
m_isInitialized = true;
|
||||
}
|
||||
|
||||
template<typename MatrixType, typename PermutationIndex>
|
||||
typename PartialPivLU<MatrixType, PermutationIndex>::Scalar PartialPivLU<MatrixType, PermutationIndex>::determinant() const
|
||||
{
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
typename PartialPivLU<MatrixType, PermutationIndex>::Scalar PartialPivLU<MatrixType, PermutationIndex>::determinant()
|
||||
const {
|
||||
eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
|
||||
return Scalar(m_det_p) * m_lu.diagonal().prod();
|
||||
}
|
||||
@@ -556,13 +510,11 @@ typename PartialPivLU<MatrixType, PermutationIndex>::Scalar PartialPivLU<MatrixT
|
||||
/** \returns the matrix represented by the decomposition,
|
||||
* i.e., it returns the product: P^{-1} L U.
|
||||
* This function is provided for debug purpose. */
|
||||
template<typename MatrixType, typename PermutationIndex>
|
||||
MatrixType PartialPivLU<MatrixType, PermutationIndex>::reconstructedMatrix() const
|
||||
{
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
MatrixType PartialPivLU<MatrixType, PermutationIndex>::reconstructedMatrix() const {
|
||||
eigen_assert(m_isInitialized && "LU is not initialized.");
|
||||
// LU
|
||||
MatrixType res = m_lu.template triangularView<UnitLower>().toDenseMatrix()
|
||||
* m_lu.template triangularView<Upper>();
|
||||
MatrixType res = m_lu.template triangularView<UnitLower>().toDenseMatrix() * m_lu.template triangularView<Upper>();
|
||||
|
||||
// P^{-1}(LU)
|
||||
res = m_p.inverse() * res;
|
||||
@@ -575,50 +527,49 @@ MatrixType PartialPivLU<MatrixType, PermutationIndex>::reconstructedMatrix() con
|
||||
namespace internal {
|
||||
|
||||
/***** Implementation of inverse() *****************************************************/
|
||||
template<typename DstXprType, typename MatrixType, typename PermutationIndex>
|
||||
struct Assignment<DstXprType, Inverse<PartialPivLU<MatrixType, PermutationIndex> >, internal::assign_op<typename DstXprType::Scalar,typename PartialPivLU<MatrixType, PermutationIndex>::Scalar>, Dense2Dense>
|
||||
{
|
||||
template <typename DstXprType, typename MatrixType, typename PermutationIndex>
|
||||
struct Assignment<
|
||||
DstXprType, Inverse<PartialPivLU<MatrixType, PermutationIndex> >,
|
||||
internal::assign_op<typename DstXprType::Scalar, typename PartialPivLU<MatrixType, PermutationIndex>::Scalar>,
|
||||
Dense2Dense> {
|
||||
typedef PartialPivLU<MatrixType, PermutationIndex> LuType;
|
||||
typedef Inverse<LuType> SrcXprType;
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename LuType::Scalar> &)
|
||||
{
|
||||
static void run(DstXprType& dst, const SrcXprType& src,
|
||||
const internal::assign_op<typename DstXprType::Scalar, typename LuType::Scalar>&) {
|
||||
dst = src.nestedExpression().solve(MatrixType::Identity(src.rows(), src.cols()));
|
||||
}
|
||||
};
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
/******** MatrixBase methods *******/
|
||||
|
||||
/** \lu_module
|
||||
*
|
||||
* \return the partial-pivoting LU decomposition of \c *this.
|
||||
*
|
||||
* \sa class PartialPivLU
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename PermutationIndex>
|
||||
*
|
||||
* \return the partial-pivoting LU decomposition of \c *this.
|
||||
*
|
||||
* \sa class PartialPivLU
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename PermutationIndex>
|
||||
inline const PartialPivLU<typename MatrixBase<Derived>::PlainObject, PermutationIndex>
|
||||
MatrixBase<Derived>::partialPivLu() const
|
||||
{
|
||||
MatrixBase<Derived>::partialPivLu() const {
|
||||
return PartialPivLU<PlainObject, PermutationIndex>(eval());
|
||||
}
|
||||
|
||||
/** \lu_module
|
||||
*
|
||||
* Synonym of partialPivLu().
|
||||
*
|
||||
* \return the partial-pivoting LU decomposition of \c *this.
|
||||
*
|
||||
* \sa class PartialPivLU
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename PermutationIndex>
|
||||
inline const PartialPivLU<typename MatrixBase<Derived>::PlainObject, PermutationIndex>
|
||||
MatrixBase<Derived>::lu() const
|
||||
{
|
||||
*
|
||||
* Synonym of partialPivLu().
|
||||
*
|
||||
* \return the partial-pivoting LU decomposition of \c *this.
|
||||
*
|
||||
* \sa class PartialPivLU
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename PermutationIndex>
|
||||
inline const PartialPivLU<typename MatrixBase<Derived>::PlainObject, PermutationIndex> MatrixBase<Derived>::lu() const {
|
||||
return PartialPivLU<PlainObject, PermutationIndex>(eval());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_PARTIALLU_H
|
||||
#endif // EIGEN_PARTIALLU_H
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
// IWYU pragma: private
|
||||
#include "./InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -45,15 +45,14 @@ namespace lapacke_helpers {
|
||||
// Generic lapacke partial lu implementation that converts arguments and dispatches to the function above
|
||||
// -------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
template<typename Scalar, int StorageOrder>
|
||||
template <typename Scalar, int StorageOrder>
|
||||
struct lapacke_partial_lu {
|
||||
/** \internal performs the LU decomposition in-place of the matrix represented */
|
||||
static lapack_int blocked_lu(Index rows, Index cols, Scalar* lu_data, Index luStride, lapack_int* row_transpositions,
|
||||
lapack_int& nb_transpositions, lapack_int maxBlockSize=256)
|
||||
{
|
||||
lapack_int& nb_transpositions, lapack_int maxBlockSize = 256) {
|
||||
EIGEN_UNUSED_VARIABLE(maxBlockSize);
|
||||
// Set up parameters for getrf
|
||||
lapack_int matrix_order = StorageOrder==RowMajor ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR;
|
||||
lapack_int matrix_order = StorageOrder == RowMajor ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR;
|
||||
lapack_int lda = to_lapack(luStride);
|
||||
Scalar* a = lu_data;
|
||||
lapack_int* ipiv = row_transpositions;
|
||||
@@ -61,10 +60,10 @@ struct lapacke_partial_lu {
|
||||
lapack_int n = to_lapack(cols);
|
||||
nb_transpositions = 0;
|
||||
|
||||
lapack_int info = getrf(matrix_order, m, n, to_lapack(a), lda, ipiv );
|
||||
lapack_int info = getrf(matrix_order, m, n, to_lapack(a), lda, ipiv);
|
||||
eigen_assert(info >= 0);
|
||||
|
||||
for(int i=0; i<m; i++) {
|
||||
for (int i = 0; i < m; i++) {
|
||||
ipiv[i]--;
|
||||
if (ipiv[i] != i) nb_transpositions++;
|
||||
}
|
||||
@@ -72,16 +71,17 @@ struct lapacke_partial_lu {
|
||||
return first_zero_pivot;
|
||||
}
|
||||
};
|
||||
} // end namespace lapacke_helpers
|
||||
} // end namespace lapacke_helpers
|
||||
|
||||
/*
|
||||
* Here, we just put the generic implementation from lapacke_partial_lu into a partial specialization of the partial_lu_impl
|
||||
* type. This specialization is more specialized than the generic implementations that Eigen implements, so if the
|
||||
* Scalar type matches they will be chosen.
|
||||
* Here, we just put the generic implementation from lapacke_partial_lu into a partial specialization of the
|
||||
* partial_lu_impl type. This specialization is more specialized than the generic implementations that Eigen implements,
|
||||
* so if the Scalar type matches they will be chosen.
|
||||
*/
|
||||
#define EIGEN_LAPACKE_PARTIAL_LU(EIGTYPE) \
|
||||
template<int StorageOrder> \
|
||||
struct partial_lu_impl<EIGTYPE, StorageOrder, lapack_int, Dynamic> : public lapacke_helpers::lapacke_partial_lu<EIGTYPE, StorageOrder> {};
|
||||
#define EIGEN_LAPACKE_PARTIAL_LU(EIGTYPE) \
|
||||
template <int StorageOrder> \
|
||||
struct partial_lu_impl<EIGTYPE, StorageOrder, lapack_int, Dynamic> \
|
||||
: public lapacke_helpers::lapacke_partial_lu<EIGTYPE, StorageOrder> {};
|
||||
|
||||
EIGEN_LAPACKE_PARTIAL_LU(double)
|
||||
EIGEN_LAPACKE_PARTIAL_LU(float)
|
||||
@@ -90,8 +90,8 @@ EIGEN_LAPACKE_PARTIAL_LU(std::complex<float>)
|
||||
|
||||
#undef EIGEN_LAPACKE_PARTIAL_LU
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_PARTIALLU_LAPACK_H
|
||||
#endif // EIGEN_PARTIALLU_LAPACK_H
|
||||
|
||||
@@ -42,49 +42,43 @@
|
||||
// These routines requires bit manipulation of the sign, which is not compatible
|
||||
// with fastmath.
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("no-fast-math")
|
||||
#pragma GCC optimize("no-fast-math")
|
||||
#endif
|
||||
|
||||
namespace Eigen
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
template <typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_size4<Architecture::Target, float, MatrixType, ResultType>
|
||||
{
|
||||
enum
|
||||
{
|
||||
struct compute_inverse_size4<Architecture::Target, float, MatrixType, ResultType> {
|
||||
enum {
|
||||
MatrixAlignment = traits<MatrixType>::Alignment,
|
||||
ResultAlignment = traits<ResultType>::Alignment,
|
||||
StorageOrdersMatch = (MatrixType::Flags & RowMajorBit) == (ResultType::Flags & RowMajorBit)
|
||||
};
|
||||
typedef std::conditional_t<(MatrixType::Flags & LinearAccessBit), MatrixType const &, typename MatrixType::PlainObject> ActualMatrixType;
|
||||
typedef std::conditional_t<(MatrixType::Flags & LinearAccessBit), MatrixType const &,
|
||||
typename MatrixType::PlainObject>
|
||||
ActualMatrixType;
|
||||
|
||||
static void run(const MatrixType &mat, ResultType &result)
|
||||
{
|
||||
static void run(const MatrixType &mat, ResultType &result) {
|
||||
ActualMatrixType matrix(mat);
|
||||
|
||||
const float* data = matrix.data();
|
||||
const float *data = matrix.data();
|
||||
const Index stride = matrix.innerStride();
|
||||
Packet4f L1 = ploadt<Packet4f,MatrixAlignment>(data);
|
||||
Packet4f L2 = ploadt<Packet4f,MatrixAlignment>(data + stride*4);
|
||||
Packet4f L3 = ploadt<Packet4f,MatrixAlignment>(data + stride*8);
|
||||
Packet4f L4 = ploadt<Packet4f,MatrixAlignment>(data + stride*12);
|
||||
Packet4f L1 = ploadt<Packet4f, MatrixAlignment>(data);
|
||||
Packet4f L2 = ploadt<Packet4f, MatrixAlignment>(data + stride * 4);
|
||||
Packet4f L3 = ploadt<Packet4f, MatrixAlignment>(data + stride * 8);
|
||||
Packet4f L4 = ploadt<Packet4f, MatrixAlignment>(data + stride * 12);
|
||||
|
||||
// Four 2x2 sub-matrices of the input matrix
|
||||
// input = [[A, B],
|
||||
// [C, D]]
|
||||
Packet4f A, B, C, D;
|
||||
|
||||
if (!StorageOrdersMatch)
|
||||
{
|
||||
if (!StorageOrdersMatch) {
|
||||
A = vec4f_unpacklo(L1, L2);
|
||||
B = vec4f_unpacklo(L3, L4);
|
||||
C = vec4f_unpackhi(L1, L2);
|
||||
D = vec4f_unpackhi(L3, L4);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
A = vec4f_movelh(L1, L2);
|
||||
B = vec4f_movehl(L2, L1);
|
||||
C = vec4f_movelh(L3, L4);
|
||||
@@ -175,21 +169,17 @@ struct compute_inverse_size4<Architecture::Target, float, MatrixType, ResultType
|
||||
// same algorithm as above, except that each operand is split into
|
||||
// halves for two registers to hold.
|
||||
template <typename MatrixType, typename ResultType>
|
||||
struct compute_inverse_size4<Architecture::Target, double, MatrixType, ResultType>
|
||||
{
|
||||
enum
|
||||
{
|
||||
struct compute_inverse_size4<Architecture::Target, double, MatrixType, ResultType> {
|
||||
enum {
|
||||
MatrixAlignment = traits<MatrixType>::Alignment,
|
||||
ResultAlignment = traits<ResultType>::Alignment,
|
||||
StorageOrdersMatch = (MatrixType::Flags & RowMajorBit) == (ResultType::Flags & RowMajorBit)
|
||||
};
|
||||
typedef std::conditional_t<(MatrixType::Flags & LinearAccessBit),
|
||||
MatrixType const &,
|
||||
typename MatrixType::PlainObject>
|
||||
typedef std::conditional_t<(MatrixType::Flags & LinearAccessBit), MatrixType const &,
|
||||
typename MatrixType::PlainObject>
|
||||
ActualMatrixType;
|
||||
|
||||
static void run(const MatrixType &mat, ResultType &result)
|
||||
{
|
||||
static void run(const MatrixType &mat, ResultType &result) {
|
||||
ActualMatrixType matrix(mat);
|
||||
|
||||
// Four 2x2 sub-matrices of the input matrix, each is further divided into upper and lower
|
||||
@@ -201,26 +191,23 @@ struct compute_inverse_size4<Architecture::Target, double, MatrixType, ResultTyp
|
||||
|
||||
Packet2d A1, A2, B1, B2, C1, C2, D1, D2;
|
||||
|
||||
const double* data = matrix.data();
|
||||
const double *data = matrix.data();
|
||||
const Index stride = matrix.innerStride();
|
||||
if (StorageOrdersMatch)
|
||||
{
|
||||
A1 = ploadt<Packet2d,MatrixAlignment>(data + stride*0);
|
||||
B1 = ploadt<Packet2d,MatrixAlignment>(data + stride*2);
|
||||
A2 = ploadt<Packet2d,MatrixAlignment>(data + stride*4);
|
||||
B2 = ploadt<Packet2d,MatrixAlignment>(data + stride*6);
|
||||
C1 = ploadt<Packet2d,MatrixAlignment>(data + stride*8);
|
||||
D1 = ploadt<Packet2d,MatrixAlignment>(data + stride*10);
|
||||
C2 = ploadt<Packet2d,MatrixAlignment>(data + stride*12);
|
||||
D2 = ploadt<Packet2d,MatrixAlignment>(data + stride*14);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (StorageOrdersMatch) {
|
||||
A1 = ploadt<Packet2d, MatrixAlignment>(data + stride * 0);
|
||||
B1 = ploadt<Packet2d, MatrixAlignment>(data + stride * 2);
|
||||
A2 = ploadt<Packet2d, MatrixAlignment>(data + stride * 4);
|
||||
B2 = ploadt<Packet2d, MatrixAlignment>(data + stride * 6);
|
||||
C1 = ploadt<Packet2d, MatrixAlignment>(data + stride * 8);
|
||||
D1 = ploadt<Packet2d, MatrixAlignment>(data + stride * 10);
|
||||
C2 = ploadt<Packet2d, MatrixAlignment>(data + stride * 12);
|
||||
D2 = ploadt<Packet2d, MatrixAlignment>(data + stride * 14);
|
||||
} else {
|
||||
Packet2d temp;
|
||||
A1 = ploadt<Packet2d,MatrixAlignment>(data + stride*0);
|
||||
C1 = ploadt<Packet2d,MatrixAlignment>(data + stride*2);
|
||||
A2 = ploadt<Packet2d,MatrixAlignment>(data + stride*4);
|
||||
C2 = ploadt<Packet2d,MatrixAlignment>(data + stride*6);
|
||||
A1 = ploadt<Packet2d, MatrixAlignment>(data + stride * 0);
|
||||
C1 = ploadt<Packet2d, MatrixAlignment>(data + stride * 2);
|
||||
A2 = ploadt<Packet2d, MatrixAlignment>(data + stride * 4);
|
||||
C2 = ploadt<Packet2d, MatrixAlignment>(data + stride * 6);
|
||||
temp = A1;
|
||||
A1 = vec2d_unpacklo(A1, A2);
|
||||
A2 = vec2d_unpackhi(temp, A2);
|
||||
@@ -229,10 +216,10 @@ struct compute_inverse_size4<Architecture::Target, double, MatrixType, ResultTyp
|
||||
C1 = vec2d_unpacklo(C1, C2);
|
||||
C2 = vec2d_unpackhi(temp, C2);
|
||||
|
||||
B1 = ploadt<Packet2d,MatrixAlignment>(data + stride*8);
|
||||
D1 = ploadt<Packet2d,MatrixAlignment>(data + stride*10);
|
||||
B2 = ploadt<Packet2d,MatrixAlignment>(data + stride*12);
|
||||
D2 = ploadt<Packet2d,MatrixAlignment>(data + stride*14);
|
||||
B1 = ploadt<Packet2d, MatrixAlignment>(data + stride * 8);
|
||||
D1 = ploadt<Packet2d, MatrixAlignment>(data + stride * 10);
|
||||
B2 = ploadt<Packet2d, MatrixAlignment>(data + stride * 12);
|
||||
D2 = ploadt<Packet2d, MatrixAlignment>(data + stride * 14);
|
||||
|
||||
temp = B1;
|
||||
B1 = vec2d_unpacklo(B1, B2);
|
||||
@@ -356,8 +343,8 @@ struct compute_inverse_size4<Architecture::Target, double, MatrixType, ResultTyp
|
||||
}
|
||||
};
|
||||
#endif
|
||||
} // namespace internal
|
||||
} // namespace Eigen
|
||||
} // namespace internal
|
||||
} // namespace Eigen
|
||||
|
||||
#if EIGEN_COMP_GNUC_STRICT
|
||||
#pragma GCC pop_options
|
||||
|
||||
Reference in New Issue
Block a user