mirror of
https://gitlab.com/libeigen/eigen.git
synced 2024-12-27 07:29:52 +08:00
Fix cost evaluation. (chain product for integral power)
This commit is contained in:
parent
446d14f6ad
commit
dd8034bd1c
@ -157,7 +157,7 @@ typename MatrixType::RealScalar MatrixPower<MatrixType>::modfAndInit(RealScalar
|
|||||||
*intpart = std::floor(x);
|
*intpart = std::floor(x);
|
||||||
RealScalar res = x - *intpart;
|
RealScalar res = x - *intpart;
|
||||||
|
|
||||||
if (!m_init && res) { // !init && res
|
if (!m_init && res) {
|
||||||
const ComplexSchur<MatrixType> schurOfA(m_A);
|
const ComplexSchur<MatrixType> schurOfA(m_A);
|
||||||
m_T = schurOfA.matrixT();
|
m_T = schurOfA.matrixT();
|
||||||
m_U = schurOfA.matrixU();
|
m_U = schurOfA.matrixU();
|
||||||
@ -209,29 +209,41 @@ template<typename MatrixType>
|
|||||||
template<typename PlainObject, typename ResultType>
|
template<typename PlainObject, typename ResultType>
|
||||||
void MatrixPower<MatrixType>::computeIntPower(const PlainObject& b, ResultType& res, RealScalar p)
|
void MatrixPower<MatrixType>::computeIntPower(const PlainObject& b, ResultType& res, RealScalar p)
|
||||||
{
|
{
|
||||||
if (b.cols() > m_A.cols()) {
|
if (b.cols() >= m_A.cols()) {
|
||||||
m_tmp2 = MatrixType::Identity(m_A.rows(),m_A.cols());
|
m_tmp2 = MatrixType::Identity(m_A.rows(),m_A.cols());
|
||||||
computeIntPower(m_tmp2, p);
|
computeIntPower(m_tmp2, p);
|
||||||
res.noalias() = m_tmp2 * b;
|
res.noalias() = m_tmp2 * b;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
RealScalar pp = std::abs(p);
|
RealScalar pp = std::abs(p);
|
||||||
int cost = internal::binary_powering_cost(pp);
|
int squarings, applyings = internal::binary_powering_cost(pp, &squarings);
|
||||||
bool init = false;
|
bool init = false;
|
||||||
|
|
||||||
if (p==0) {
|
if (p==0) {
|
||||||
res = b;
|
res = b;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (p<0) m_tmp1 = m_A.inverse();
|
else if (p>0) {
|
||||||
else m_tmp1 = m_A;
|
m_tmp1 = m_A;
|
||||||
|
}
|
||||||
|
else if (b.cols() * (pp - applyings) <= m_A.cols() * squarings) {
|
||||||
|
PartialPivLU<MatrixType> A(m_A);
|
||||||
|
res = A.solve(b);
|
||||||
|
for (--pp; pp >= 1; --pp)
|
||||||
|
res = A.solve(res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_tmp1 = m_A.inverse();
|
||||||
|
}
|
||||||
|
|
||||||
while (b.cols()*pp > m_A.cols()*cost) {
|
while (b.cols() * (pp - applyings) > m_A.cols() * squarings) {
|
||||||
if (std::fmod(pp, 2) >= 1) {
|
if (std::fmod(pp, 2) >= 1) {
|
||||||
apply(b, res, init);
|
apply(b, res, init);
|
||||||
--cost;
|
--applyings;
|
||||||
}
|
}
|
||||||
m_tmp1 *= m_tmp1;
|
m_tmp1 *= m_tmp1;
|
||||||
--cost;
|
--squarings;
|
||||||
pp /= 2;
|
pp /= 2;
|
||||||
}
|
}
|
||||||
for (; pp >= 1; --pp)
|
for (; pp >= 1; --pp)
|
||||||
|
@ -34,15 +34,18 @@ struct traits<MatrixPowerProductBase<Derived> > : traits<Derived>
|
|||||||
{ };
|
{ };
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline int binary_powering_cost(T p)
|
inline int binary_powering_cost(T p, int* squarings)
|
||||||
{
|
{
|
||||||
int cost, tmp;
|
int applyings=0, tmp;
|
||||||
frexp(p, &cost);
|
|
||||||
|
if (frexp(p, squarings) != 0.5);
|
||||||
|
--*squarings;
|
||||||
|
|
||||||
while (std::frexp(p, &tmp), tmp > 0) {
|
while (std::frexp(p, &tmp), tmp > 0) {
|
||||||
p -= std::ldexp(static_cast<T>(0.5), tmp);
|
p -= std::ldexp(static_cast<T>(0.5), tmp);
|
||||||
++cost;
|
++applyings;
|
||||||
}
|
}
|
||||||
return cost;
|
return applyings;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int matrix_power_get_pade_degree(float normIminusT)
|
inline int matrix_power_get_pade_degree(float normIminusT)
|
||||||
@ -145,7 +148,7 @@ void MatrixPowerTriangularAtomic<MatrixType,UpLo>::computePade(int degree, const
|
|||||||
RealScalar p) const
|
RealScalar p) const
|
||||||
{
|
{
|
||||||
int i = degree<<1;
|
int i = degree<<1;
|
||||||
res = (p-(i>>1)) / ((i-1)<<1) * IminusT;
|
res = (p-degree) / ((i-1)<<1) * IminusT;
|
||||||
for (--i; i; --i) {
|
for (--i; i; --i) {
|
||||||
res = (MatrixType::Identity(m_T.rows(), m_T.cols()) + res).template triangularView<UpLo>()
|
res = (MatrixType::Identity(m_T.rows(), m_T.cols()) + res).template triangularView<UpLo>()
|
||||||
.solve((i==1 ? -p : i&1 ? (-p-(i>>1))/(i<<1) : (p-(i>>1))/((i-1)<<1)) * IminusT).eval();
|
.solve((i==1 ? -p : i&1 ? (-p-(i>>1))/(i<<1) : (p-(i>>1))/((i-1)<<1)) * IminusT).eval();
|
||||||
@ -166,9 +169,11 @@ void MatrixPowerTriangularAtomic<MatrixType,UpLo>::compute2x2(MatrixType& res, R
|
|||||||
res(i,i) = pow(m_T(i,i), p);
|
res(i,i) = pow(m_T(i,i), p);
|
||||||
if (m_T(i-1,i-1) == m_T(i,i)) {
|
if (m_T(i-1,i-1) == m_T(i,i)) {
|
||||||
res(i-1,i) = p * pow(m_T(i-1,i), p-1);
|
res(i-1,i) = p * pow(m_T(i-1,i), p-1);
|
||||||
} else if (2*abs(m_T(i-1,i-1)) < abs(m_T(i,i)) || 2*abs(m_T(i,i)) < abs(m_T(i-1,i-1))) {
|
}
|
||||||
|
else if (2*abs(m_T(i-1,i-1)) < abs(m_T(i,i)) || 2*abs(m_T(i,i)) < abs(m_T(i-1,i-1))) {
|
||||||
res(i-1,i) = m_T(i-1,i) * (res(i,i)-res(i-1,i-1)) / (m_T(i,i)-m_T(i-1,i-1));
|
res(i-1,i) = m_T(i-1,i) * (res(i,i)-res(i-1,i-1)) / (m_T(i,i)-m_T(i-1,i-1));
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// computation in previous branch is inaccurate if abs(m_T(i,i)) \approx abs(m_T(i-1,i-1))
|
// computation in previous branch is inaccurate if abs(m_T(i,i)) \approx abs(m_T(i-1,i-1))
|
||||||
int unwindingNumber = std::ceil(((logTdiag[i]-logTdiag[i-1]).imag() - M_PI) / (2*M_PI));
|
int unwindingNumber = std::ceil(((logTdiag[i]-logTdiag[i-1]).imag() - M_PI) / (2*M_PI));
|
||||||
Scalar w = internal::atanh2(m_T(i,i)-m_T(i-1,i-1), m_T(i,i)+m_T(i-1,i-1)) + Scalar(0, M_PI*unwindingNumber);
|
Scalar w = internal::atanh2(m_T(i,i)-m_T(i-1,i-1), m_T(i,i)+m_T(i-1,i-1)) + Scalar(0, M_PI*unwindingNumber);
|
||||||
@ -187,9 +192,9 @@ void MatrixPowerTriangularAtomic<MatrixType,UpLo>::computeBig(MatrixType& res, R
|
|||||||
digits <= 64? 2.4471944416607995472e-1L: // extended precision
|
digits <= 64? 2.4471944416607995472e-1L: // extended precision
|
||||||
digits <= 106? 1.1016843812851143391275867258512e-01: // double-double
|
digits <= 106? 1.1016843812851143391275867258512e-01: // double-double
|
||||||
9.134603732914548552537150753385375e-02; // quadruple precision
|
9.134603732914548552537150753385375e-02; // quadruple precision
|
||||||
int degree, degree2, numberOfSquareRoots=0, numberOfExtraSquareRoots=0;
|
|
||||||
MatrixType IminusT, sqrtT, T=m_T;
|
MatrixType IminusT, sqrtT, T=m_T;
|
||||||
RealScalar normIminusT;
|
RealScalar normIminusT;
|
||||||
|
int degree, degree2, numberOfSquareRoots=0, numberOfExtraSquareRoots=0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
IminusT = MatrixType::Identity(m_T.rows(), m_T.cols()) - T;
|
IminusT = MatrixType::Identity(m_T.rows(), m_T.cols()) - T;
|
||||||
|
Loading…
Reference in New Issue
Block a user