mirror of
https://gitlab.com/libeigen/eigen.git
synced 2024-12-15 07:10:37 +08:00
bug #1403: more scalar conversions fixes in BDCSVD
This commit is contained in:
parent
1bbcf19029
commit
731c8c704d
@ -552,10 +552,10 @@ void ColPivHouseholderQR<MatrixType>::computeInPlace()
|
||||
// http://www.netlib.org/lapack/lawnspdf/lawn176.pdf
|
||||
// and used in LAPACK routines xGEQPF and xGEQP3.
|
||||
// See lines 278-297 in http://www.netlib.org/lapack/explore-html/dc/df4/sgeqpf_8f_source.html
|
||||
if (m_colNormsUpdated.coeffRef(j) != 0) {
|
||||
if (m_colNormsUpdated.coeffRef(j) != RealScalar(0)) {
|
||||
RealScalar temp = abs(m_qr.coeffRef(k, j)) / m_colNormsUpdated.coeffRef(j);
|
||||
temp = (RealScalar(1) + temp) * (RealScalar(1) - temp);
|
||||
temp = temp < 0 ? RealScalar(0) : temp;
|
||||
temp = temp < RealScalar(0) ? RealScalar(0) : temp;
|
||||
RealScalar temp2 = temp * numext::abs2<RealScalar>(m_colNormsUpdated.coeffRef(j) /
|
||||
m_colNormsDirect.coeffRef(j));
|
||||
if (temp2 <= norm_downdate_threshold) {
|
||||
|
@ -77,6 +77,7 @@ public:
|
||||
typedef _MatrixType MatrixType;
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
typedef typename NumTraits<RealScalar>::Literal Literal;
|
||||
enum {
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||
@ -259,7 +260,7 @@ BDCSVD<MatrixType>& BDCSVD<MatrixType>::compute(const MatrixType& matrix, unsign
|
||||
|
||||
//**** step 0 - Copy the input matrix and apply scaling to reduce over/under-flows
|
||||
RealScalar scale = matrix.cwiseAbs().maxCoeff();
|
||||
if(scale==RealScalar(0)) scale = RealScalar(1);
|
||||
if(scale==Literal(0)) scale = Literal(1);
|
||||
MatrixX copy;
|
||||
if (m_isTranspose) copy = matrix.adjoint()/scale;
|
||||
else copy = matrix/scale;
|
||||
@ -351,13 +352,13 @@ void BDCSVD<MatrixType>::structured_update(Block<MatrixXr,Dynamic,Dynamic> A, co
|
||||
Index k1=0, k2=0;
|
||||
for(Index j=0; j<n; ++j)
|
||||
{
|
||||
if( (A.col(j).head(n1).array()!=0).any() )
|
||||
if( (A.col(j).head(n1).array()!=Literal(0)).any() )
|
||||
{
|
||||
A1.col(k1) = A.col(j).head(n1);
|
||||
B1.row(k1) = B.row(j);
|
||||
++k1;
|
||||
}
|
||||
if( (A.col(j).tail(n2).array()!=0).any() )
|
||||
if( (A.col(j).tail(n2).array()!=Literal(0)).any() )
|
||||
{
|
||||
A2.col(k2) = A.col(j).tail(n2);
|
||||
B2.row(k2) = B.row(j);
|
||||
@ -449,11 +450,11 @@ void BDCSVD<MatrixType>::divide (Index firstCol, Index lastCol, Index firstRowW,
|
||||
l = m_naiveU.row(1).segment(firstCol, k);
|
||||
f = m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1);
|
||||
}
|
||||
if (m_compV) m_naiveV(firstRowW+k, firstColW) = 1;
|
||||
if (m_compV) m_naiveV(firstRowW+k, firstColW) = Literal(1);
|
||||
if (r0<considerZero)
|
||||
{
|
||||
c0 = 1;
|
||||
s0 = 0;
|
||||
c0 = Literal(1);
|
||||
s0 = Literal(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -574,7 +575,7 @@ void BDCSVD<MatrixType>::computeSVDofM(Index firstCol, Index n, MatrixXr& U, Vec
|
||||
ArrayRef col0 = m_computed.col(firstCol).segment(firstCol, n);
|
||||
m_workspace.head(n) = m_computed.block(firstCol, firstCol, n, n).diagonal();
|
||||
ArrayRef diag = m_workspace.head(n);
|
||||
diag(0) = 0;
|
||||
diag(0) = Literal(0);
|
||||
|
||||
// Allocate space for singular values and vectors
|
||||
singVals.resize(n);
|
||||
@ -590,7 +591,7 @@ void BDCSVD<MatrixType>::computeSVDofM(Index firstCol, Index n, MatrixXr& U, Vec
|
||||
// but others are interleaved and we must ignore them at this stage.
|
||||
// To this end, let's compute a permutation skipping them:
|
||||
Index actual_n = n;
|
||||
while(actual_n>1 && diag(actual_n-1)==0) --actual_n;
|
||||
while(actual_n>1 && diag(actual_n-1)==Literal(0)) --actual_n;
|
||||
Index m = 0; // size of the deflated problem
|
||||
for(Index k=0;k<actual_n;++k)
|
||||
if(abs(col0(k))>considerZero)
|
||||
@ -691,7 +692,7 @@ template <typename MatrixType>
|
||||
typename BDCSVD<MatrixType>::RealScalar BDCSVD<MatrixType>::secularEq(RealScalar mu, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const ArrayRef& diagShifted, RealScalar shift)
|
||||
{
|
||||
Index m = perm.size();
|
||||
RealScalar res = 1;
|
||||
RealScalar res = Literal(1);
|
||||
for(Index i=0; i<m; ++i)
|
||||
{
|
||||
Index j = perm(i);
|
||||
@ -710,16 +711,16 @@ void BDCSVD<MatrixType>::computeSingVals(const ArrayRef& col0, const ArrayRef& d
|
||||
|
||||
Index n = col0.size();
|
||||
Index actual_n = n;
|
||||
while(actual_n>1 && col0(actual_n-1)==0) --actual_n;
|
||||
while(actual_n>1 && col0(actual_n-1)==Literal(0)) --actual_n;
|
||||
|
||||
for (Index k = 0; k < n; ++k)
|
||||
{
|
||||
if (col0(k) == 0 || actual_n==1)
|
||||
if (col0(k) == Literal(0) || actual_n==1)
|
||||
{
|
||||
// if col0(k) == 0, then entry is deflated, so singular value is on diagonal
|
||||
// if actual_n==1, then the deflated problem is already diagonalized
|
||||
singVals(k) = k==0 ? col0(0) : diag(k);
|
||||
mus(k) = 0;
|
||||
mus(k) = Literal(0);
|
||||
shifts(k) = k==0 ? col0(0) : diag(k);
|
||||
continue;
|
||||
}
|
||||
@ -733,13 +734,13 @@ void BDCSVD<MatrixType>::computeSingVals(const ArrayRef& col0, const ArrayRef& d
|
||||
{
|
||||
// Skip deflated singular values
|
||||
Index l = k+1;
|
||||
while(col0(l)==0) { ++l; eigen_internal_assert(l<actual_n); }
|
||||
while(col0(l)==Literal(0)) { ++l; eigen_internal_assert(l<actual_n); }
|
||||
right = diag(l);
|
||||
}
|
||||
|
||||
// first decide whether it's closer to the left end or the right end
|
||||
RealScalar mid = left + (right-left) / 2;
|
||||
RealScalar fMid = secularEq(mid, col0, diag, perm, diag, 0);
|
||||
RealScalar mid = left + (right-left) / Literal(2);
|
||||
RealScalar fMid = secularEq(mid, col0, diag, perm, diag, Literal(0));
|
||||
#ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
|
||||
std::cout << right-left << "\n";
|
||||
std::cout << "fMid = " << fMid << " " << secularEq(mid-left, col0, diag, perm, diag-left, left) << " " << secularEq(mid-right, col0, diag, perm, diag-right, right) << "\n";
|
||||
@ -755,7 +756,7 @@ void BDCSVD<MatrixType>::computeSingVals(const ArrayRef& col0, const ArrayRef& d
|
||||
<< " " << secularEq(0.8*(left+right), col0, diag, perm, diag, 0)
|
||||
<< " " << secularEq(0.9*(left+right), col0, diag, perm, diag, 0) << "\n";
|
||||
#endif
|
||||
RealScalar shift = (k == actual_n-1 || fMid > 0) ? left : right;
|
||||
RealScalar shift = (k == actual_n-1 || fMid > Literal(0)) ? left : right;
|
||||
|
||||
// measure everything relative to shift
|
||||
Map<ArrayXr> diagShifted(m_workspace.data()+4*n, n);
|
||||
@ -785,13 +786,13 @@ void BDCSVD<MatrixType>::computeSingVals(const ArrayRef& col0, const ArrayRef& d
|
||||
|
||||
// rational interpolation: fit a function of the form a / mu + b through the two previous
|
||||
// iterates and use its zero to compute the next iterate
|
||||
bool useBisection = fPrev*fCur>0;
|
||||
while (fCur!=0 && abs(muCur - muPrev) > 8 * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(muCur), abs(muPrev)) && abs(fCur - fPrev)>NumTraits<RealScalar>::epsilon() && !useBisection)
|
||||
bool useBisection = fPrev*fCur>Literal(0);
|
||||
while (fCur!=Literal(0) && abs(muCur - muPrev) > Literal(8) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(muCur), abs(muPrev)) && abs(fCur - fPrev)>NumTraits<RealScalar>::epsilon() && !useBisection)
|
||||
{
|
||||
++m_numIters;
|
||||
|
||||
// Find a and b such that the function f(mu) = a / mu + b matches the current and previous samples.
|
||||
RealScalar a = (fCur - fPrev) / (1/muCur - 1/muPrev);
|
||||
RealScalar a = (fCur - fPrev) / (Literal(1)/muCur - Literal(1)/muPrev);
|
||||
RealScalar b = fCur - a / muCur;
|
||||
// And find mu such that f(mu)==0:
|
||||
RealScalar muZero = -a/b;
|
||||
@ -803,8 +804,8 @@ void BDCSVD<MatrixType>::computeSingVals(const ArrayRef& col0, const ArrayRef& d
|
||||
fCur = fZero;
|
||||
|
||||
|
||||
if (shift == left && (muCur < 0 || muCur > right - left)) useBisection = true;
|
||||
if (shift == right && (muCur < -(right - left) || muCur > 0)) useBisection = true;
|
||||
if (shift == left && (muCur < Literal(0) || muCur > right - left)) useBisection = true;
|
||||
if (shift == right && (muCur < -(right - left) || muCur > Literal(0))) useBisection = true;
|
||||
if (abs(fCur)>abs(fPrev)) useBisection = true;
|
||||
}
|
||||
|
||||
@ -841,13 +842,13 @@ void BDCSVD<MatrixType>::computeSingVals(const ArrayRef& col0, const ArrayRef& d
|
||||
std::cout << k << " : " << fLeft << " * " << fRight << " == " << fLeft * fRight << " ; " << left << " - " << right << " -> " << leftShifted << " " << rightShifted << " shift=" << shift << "\n";
|
||||
}
|
||||
#endif
|
||||
eigen_internal_assert(fLeft * fRight < 0);
|
||||
eigen_internal_assert(fLeft * fRight < Literal(0));
|
||||
|
||||
while (rightShifted - leftShifted > 2 * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(leftShifted), abs(rightShifted)))
|
||||
while (rightShifted - leftShifted > Literal(2) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(abs(leftShifted), abs(rightShifted)))
|
||||
{
|
||||
RealScalar midShifted = (leftShifted + rightShifted) / 2;
|
||||
RealScalar midShifted = (leftShifted + rightShifted) / Literal(2);
|
||||
fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift);
|
||||
if (fLeft * fMid < 0)
|
||||
if (fLeft * fMid < Literal(0))
|
||||
{
|
||||
rightShifted = midShifted;
|
||||
}
|
||||
@ -858,7 +859,7 @@ void BDCSVD<MatrixType>::computeSingVals(const ArrayRef& col0, const ArrayRef& d
|
||||
}
|
||||
}
|
||||
|
||||
muCur = (leftShifted + rightShifted) / 2;
|
||||
muCur = (leftShifted + rightShifted) / Literal(2);
|
||||
}
|
||||
|
||||
singVals[k] = shift + muCur;
|
||||
@ -892,8 +893,8 @@ void BDCSVD<MatrixType>::perturbCol0
|
||||
// The offset permits to skip deflated entries while computing zhat
|
||||
for (Index k = 0; k < n; ++k)
|
||||
{
|
||||
if (col0(k) == 0) // deflated
|
||||
zhat(k) = 0;
|
||||
if (col0(k) == Literal(0)) // deflated
|
||||
zhat(k) = Literal(0);
|
||||
else
|
||||
{
|
||||
// see equation (3.6)
|
||||
@ -918,7 +919,7 @@ void BDCSVD<MatrixType>::perturbCol0
|
||||
std::cout << "zhat(" << k << ") = sqrt( " << prod << ") ; " << (singVals(last) + dk) << " * " << mus(last) + shifts(last) << " - " << dk << "\n";
|
||||
#endif
|
||||
RealScalar tmp = sqrt(prod);
|
||||
zhat(k) = col0(k) > 0 ? tmp : -tmp;
|
||||
zhat(k) = col0(k) > Literal(0) ? tmp : -tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -934,7 +935,7 @@ void BDCSVD<MatrixType>::computeSingVecs
|
||||
|
||||
for (Index k = 0; k < n; ++k)
|
||||
{
|
||||
if (zhat(k) == 0)
|
||||
if (zhat(k) == Literal(0))
|
||||
{
|
||||
U.col(k) = VectorType::Unit(n+1, k);
|
||||
if (m_compV) V.col(k) = VectorType::Unit(n, k);
|
||||
@ -947,7 +948,7 @@ void BDCSVD<MatrixType>::computeSingVecs
|
||||
Index i = perm(l);
|
||||
U(i,k) = zhat(i)/(((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k]));
|
||||
}
|
||||
U(n,k) = 0;
|
||||
U(n,k) = Literal(0);
|
||||
U.col(k).normalize();
|
||||
|
||||
if (m_compV)
|
||||
@ -958,7 +959,7 @@ void BDCSVD<MatrixType>::computeSingVecs
|
||||
Index i = perm(l);
|
||||
V(i,k) = diag(i) * zhat(i) / (((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k]));
|
||||
}
|
||||
V(0,k) = -1;
|
||||
V(0,k) = Literal(-1);
|
||||
V.col(k).normalize();
|
||||
}
|
||||
}
|
||||
@ -980,14 +981,14 @@ void BDCSVD<MatrixType>::deflation43(Index firstCol, Index shift, Index i, Index
|
||||
RealScalar c = m_computed(start, start);
|
||||
RealScalar s = m_computed(start+i, start);
|
||||
RealScalar r = sqrt(numext::abs2(c) + numext::abs2(s));
|
||||
if (r == 0)
|
||||
if (r == Literal(0))
|
||||
{
|
||||
m_computed(start+i, start+i) = 0;
|
||||
m_computed(start+i, start+i) = Literal(0);
|
||||
return;
|
||||
}
|
||||
m_computed(start,start) = r;
|
||||
m_computed(start+i, start) = 0;
|
||||
m_computed(start+i, start+i) = 0;
|
||||
m_computed(start+i, start) = Literal(0);
|
||||
m_computed(start+i, start+i) = Literal(0);
|
||||
|
||||
JacobiRotation<RealScalar> J(c/r,-s/r);
|
||||
if (m_compU) m_naiveU.middleRows(firstCol, size+1).applyOnTheRight(firstCol, firstCol+i, J);
|
||||
@ -1020,7 +1021,7 @@ void BDCSVD<MatrixType>::deflation44(Index firstColu , Index firstColm, Index fi
|
||||
<< m_computed(firstColm + i+1, firstColm+i+1) << " "
|
||||
<< m_computed(firstColm + i+2, firstColm+i+2) << "\n";
|
||||
#endif
|
||||
if (r==0)
|
||||
if (r==Literal(0))
|
||||
{
|
||||
m_computed(firstColm + i, firstColm + i) = m_computed(firstColm + j, firstColm + j);
|
||||
return;
|
||||
@ -1029,7 +1030,7 @@ void BDCSVD<MatrixType>::deflation44(Index firstColu , Index firstColm, Index fi
|
||||
s/=r;
|
||||
m_computed(firstColm + i, firstColm) = r;
|
||||
m_computed(firstColm + j, firstColm + j) = m_computed(firstColm + i, firstColm + i);
|
||||
m_computed(firstColm + j, firstColm) = 0;
|
||||
m_computed(firstColm + j, firstColm) = Literal(0);
|
||||
|
||||
JacobiRotation<RealScalar> J(c,-s);
|
||||
if (m_compU) m_naiveU.middleRows(firstColu, size+1).applyOnTheRight(firstColu + i, firstColu + j, J);
|
||||
@ -1053,7 +1054,7 @@ void BDCSVD<MatrixType>::deflation(Index firstCol, Index lastCol, Index k, Index
|
||||
const RealScalar considerZero = (std::numeric_limits<RealScalar>::min)();
|
||||
RealScalar maxDiag = diag.tail((std::max)(Index(1),length-1)).cwiseAbs().maxCoeff();
|
||||
RealScalar epsilon_strict = numext::maxi<RealScalar>(considerZero,NumTraits<RealScalar>::epsilon() * maxDiag);
|
||||
RealScalar epsilon_coarse = 8 * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(col0.cwiseAbs().maxCoeff(), maxDiag);
|
||||
RealScalar epsilon_coarse = Literal(8) * NumTraits<RealScalar>::epsilon() * numext::maxi<RealScalar>(col0.cwiseAbs().maxCoeff(), maxDiag);
|
||||
|
||||
#ifdef EIGEN_BDCSVD_SANITY_CHECKS
|
||||
assert(m_naiveU.allFinite());
|
||||
@ -1081,7 +1082,7 @@ void BDCSVD<MatrixType>::deflation(Index firstCol, Index lastCol, Index k, Index
|
||||
#ifdef EIGEN_BDCSVD_DEBUG_VERBOSE
|
||||
std::cout << "deflation 4.2, set z(" << i << ") to zero because " << abs(col0(i)) << " < " << epsilon_strict << " (diag(" << i << ")=" << diag(i) << ")\n";
|
||||
#endif
|
||||
col0(i) = 0;
|
||||
col0(i) = Literal(0);
|
||||
}
|
||||
|
||||
//condition 4.3
|
||||
|
@ -159,6 +159,8 @@ void upperbidiagonalization_blocked_helper(MatrixType& A,
|
||||
traits<MatrixType>::Flags & RowMajorBit> > Y)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
typedef typename NumTraits<RealScalar>::Literal Literal;
|
||||
enum { StorageOrder = traits<MatrixType>::Flags & RowMajorBit };
|
||||
typedef InnerStride<int(StorageOrder) == int(ColMajor) ? 1 : Dynamic> ColInnerStride;
|
||||
typedef InnerStride<int(StorageOrder) == int(ColMajor) ? Dynamic : 1> RowInnerStride;
|
||||
@ -263,7 +265,7 @@ void upperbidiagonalization_blocked_helper(MatrixType& A,
|
||||
SubMatType A10( A.block(bs,0, brows-bs,bs) );
|
||||
SubMatType A01( A.block(0,bs, bs,bcols-bs) );
|
||||
Scalar tmp = A01(bs-1,0);
|
||||
A01(bs-1,0) = 1;
|
||||
A01(bs-1,0) = Literal(1);
|
||||
A11.noalias() -= A10 * Y.topLeftCorner(bcols,bs).bottomRows(bcols-bs).adjoint();
|
||||
A11.noalias() -= X.topLeftCorner(brows,bs).bottomRows(brows-bs) * A01;
|
||||
A01(bs-1,0) = tmp;
|
||||
|
Loading…
Reference in New Issue
Block a user