Apply clang-format

This commit is contained in:
Tobias Wood
2023-11-29 11:12:48 +00:00
parent 9ea520fc45
commit f38e16c193
534 changed files with 103368 additions and 116934 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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