bugged gaxpy level 2 algorithm without pivoting + use the template type instead of double for sum

This commit is contained in:
nojhan 2011-12-18 23:39:43 +01:00
commit 5b9e843dba
2 changed files with 84 additions and 11 deletions

View file

@ -133,8 +133,8 @@ protected:
* *
* Compute L such that V = L L^T * Compute L such that V = L L^T
* *
* When compiled in debug mode and called on ill-conditionned matrix, * When called on ill-conditionned matrix,
* will raise an assert before calling the square root on a negative number. * will raise an exception before calling the square root on a negative number.
*/ */
template< typename T > template< typename T >
class LLT : public Cholesky<T> class LLT : public Cholesky<T>
@ -148,24 +148,24 @@ public:
this->_L(0, 0) = sqrt( V(0, 0) ); this->_L(0, 0) = sqrt( V(0, 0) );
// end of the column // end of the column
for ( j = 1; j < N; ++j ) { for( j = 1; j < N; ++j ) {
this->_L(j, 0) = V(0, j) / this->_L(0, 0); this->_L(j, 0) = V(0, j) / this->_L(0, 0);
} }
// end of the matrix // end of the matrix
for ( i = 1; i < N; ++i ) { // each column for( i = 1; i < N; ++i ) { // each column
// diagonal // diagonal
double sum = 0.0; T sum = 0.0;
for ( k = 0; k < i; ++k) { for( k = 0; k < i; ++k) {
sum += this->_L(i, k) * this->_L(i, k); sum += this->_L(i, k) * this->_L(i, k);
} }
this->_L(i,i) = L_i_i( V, i, sum ); this->_L(i,i) = L_i_i( V, i, sum );
for ( j = i + 1; j < N; ++j ) { // rows for( j = i + 1; j < N; ++j ) { // rows
// one element // one element
sum = 0.0; sum = 0.0;
for ( k = 0; k < i; ++k ) { for( k = 0; k < i; ++k ) {
sum += this->_L(j, k) * this->_L(i, k); sum += this->_L(j, k) * this->_L(i, k);
} }
@ -176,7 +176,7 @@ public:
} }
/** The step of the standard LLT algorithm where round off errors may appear */ /** The step of the standard LLT algorithm where round off errors may appear */
inline virtual T L_i_i( const typename Cholesky<T>::CovarMat& V, const unsigned int& i, const double& sum ) const inline virtual T L_i_i( const typename Cholesky<T>::CovarMat& V, const unsigned int& i, const T& sum ) const
{ {
// round-off errors may appear here // round-off errors may appear here
if( V(i,i) - sum < 0 ) { if( V(i,i) - sum < 0 ) {
@ -202,7 +202,7 @@ template< typename T >
class LLTabs : public LLT<T> class LLTabs : public LLT<T>
{ {
public: public:
inline virtual T L_i_i( const typename Cholesky<T>::CovarMat& V, const unsigned int& i, const double& sum ) const inline virtual T L_i_i( const typename Cholesky<T>::CovarMat& V, const unsigned int& i, const T& sum ) const
{ {
/***** ugly hack *****/ /***** ugly hack *****/
return sqrt( fabs( V(i,i) - sum) ); return sqrt( fabs( V(i,i) - sum) );
@ -221,7 +221,7 @@ template< typename T >
class LLTzero : public LLT<T> class LLTzero : public LLT<T>
{ {
public: public:
inline virtual T L_i_i( const typename Cholesky<T>::CovarMat& V, const unsigned int& i, const double& sum ) const inline virtual T L_i_i( const typename Cholesky<T>::CovarMat& V, const unsigned int& i, const T& sum ) const
{ {
T Lii; T Lii;
if( V(i,i) - sum >= 0 ) { if( V(i,i) - sum >= 0 ) {
@ -296,4 +296,76 @@ public:
} }
}; };
/** Compute the LL^T Cholesky factorization of a matrix
*
* with the gaxpy level 2 algorithm without pivoting xPOTF2 used in LAPACK.
*
* Requires n^3/3 floating point operations.
*
* Reference:
* Craig Lucas, LAPACK-Style Codes for level 2 and 3 Pivoted Cholesky Factorizations, February 5, 2004
* Numerical Analysis Report, Manchester Centre for Computational Mathematics, Departements of Mathematics
* ISSN 1360-1725
*/
template< typename T >
class Gaxpy : public Cholesky<T>
{
public:
virtual void factorize( const typename Cholesky<T>::CovarMat& V )
{
unsigned int N = assert_properties( V );
this->_L = V;
for( unsigned int i=0; i<N; ++i) {
// Level 2 BLAS equivalent pseudo-code:
// L(i,i) = L(i,i) - L(i,1:i-1) L(i,1:i-1)^T
T sum = 0.0;
// for( unsigned int k=1; k<i-1; ++k) {
// for( unsigned int k=1; k<i; ++k) {
for( unsigned int k=0; k<i; ++k) {
// for( unsigned int k=0; k<i-1; ++k) {
sum += this->_L(i, k) * this->_L(i, k);
}
this->_L(i,i) = this->_L(i,i) - sum;
// L(i,i) = sqrt( L(i,i) )
this->_L(i,i) = L_i_i( this->_L(i,i) );
// if 0 < i < N
if( 0 < i && i < N ) {
// L(i+1:n,i) = L(i+1:n,i) - L(i+1:n,1:i-1) L(i,1:i-1)^T
for( unsigned int j = i+1; j < N; ++j ) {
sum = 0.0;
// for( unsigned int k = 1; k < i-1; ++k ) {
// for( unsigned int k = 1; k < i; ++k ) {
for( unsigned int k = 0; k < i; ++k ) {
// for( unsigned int k = 0; k < i-1; ++k ) {
sum += this->_L(j, k) * this->_L(i, k);
}
this->_L(j,i) = this->_L(j,i) - sum;
}
} // if 0 < i < N
if( i < N ) {
for( unsigned int j = i+1; j < N; ++j ) {
this->_L(j,i) = this->_L(j,i) / this->_L(i,i);
}
}
} // for i in N
}
/** The step of the standard LLT algorithm where round off errors may appear */
inline virtual T L_i_i( const T& lii ) const
{
// round-off errors may appear here
if( lii <= 0 ) {
std::ostringstream oss;
oss << "L(i,i)==" << lii;
throw NotDefinitePositive(oss.str());
}
return sqrt( lii );
}
};
} // namespace cholesky } // namespace cholesky

View file

@ -140,6 +140,7 @@ void test( unsigned int M, unsigned int N, unsigned int F, unsigned int R, unsig
algos["LLTa"] = new cholesky::LLTabs<T>; algos["LLTa"] = new cholesky::LLTabs<T>;
algos["LLTz"] = new cholesky::LLTzero<T>; algos["LLTz"] = new cholesky::LLTzero<T>;
algos["LDLT"] = new cholesky::LDLT<T>; algos["LDLT"] = new cholesky::LDLT<T>;
algos["Gaxpy"] = new cholesky::Gaxpy<T>;
// init data structures on the same keys than given algorithms // init data structures on the same keys than given algorithms
std::map<std::string,unsigned int> fails; std::map<std::string,unsigned int> fails;