Skip to content

Commit

Permalink
Debugged recent modifications to tridiagonalization and reimplemented…
Browse files Browse the repository at this point in the history
… correctness checks.

--HG--
rename : src/lapack/Tridiag/ColReflector.cpp => src/lapack/Reflector/ColReflector.cpp
rename : src/lapack/Tridiag/Reflector.cpp => src/lapack/Reflector/Reflector.cpp
rename : src/lapack/Tridiag/RowReflector.cpp => src/lapack/Reflector/RowReflector.cpp
  • Loading branch information
poulson committed Jul 7, 2010
1 parent 169647f commit e368a99
Show file tree
Hide file tree
Showing 15 changed files with 458 additions and 259 deletions.
6 changes: 3 additions & 3 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ Authors of Elemental

Jack Poulson <jack.poulson@gmail.com>:
The entire library, with the exception of basing the files
{ ColReflector.cpp, RowReflector.cpp } on the LAPACK source code
for real and complex Householder reflectors, { dlarfg.f, zlarfg.f }
ColReflector.cpp, RowReflector.cpp, and Reflector.cpp on the LAPACK source
for real and complex Householder reflectors, dlarfg.f and zlarfg.f.

Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.:
The serial code for generating Householder reflectors, { dlarfg.f, zlarfg.f }.
The serial code for generating Householder reflectors, dlarfg.f and zlarfg.f.

6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,12 @@ lapackfiles = Chol/Chol.cpp \
LU/PanelLU.cpp \
QR/PanelQR.cpp \
QR/QR.cpp \
Tridiag/ColReflector.cpp \
Reflector/ColReflector.cpp \
Reflector/RowReflector.cpp \
Reflector/Reflector.cpp \
Tridiag/LocalTridiag.cpp \
Tridiag/PanelTridiagL.cpp \
Tridiag/PanelTridiagU.cpp \
Tridiag/Reflector.cpp \
Tridiag/RowReflector.cpp \
Tridiag/Tridiag.cpp \
Tridiag/TridiagL.cpp \
Tridiag/TridiagU.cpp \
Expand Down
19 changes: 19 additions & 0 deletions include/elemental/lapack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,25 @@ QR( DistMatrix<std::complex<R>,MC,MR >& A,
DistMatrix<std::complex<R>,MD,Star>& t );
#endif

//----------------------------------------------------------------------------//
// Reflector (Householder reflector): //
//----------------------------------------------------------------------------//

// Serial version for real datatypes
template<typename R>
R
Reflector( Matrix<R>& chi, Matrix<R>& x );

// Serial version for complex datatypes
template<typename R>
std::complex<R>
Reflector( Matrix< std::complex<R> >& chi, Matrix< std::complex<R> >& x );

// Parallel version
template<typename T>
T
Reflector( DistMatrix<T,MC,MR>& chi, DistMatrix<T,MC,MR>& x );

//----------------------------------------------------------------------------//
// Tridiag (Householder tridiagonalization): //
// //
Expand Down
9 changes: 4 additions & 5 deletions include/elemental/lapack_internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,12 +279,8 @@ PanelQR( DistMatrix<std::complex<R>,MC,MR >& A,
#endif

//----------------------------------------------------------------------------//
// Tridiag //
// Reflector //
//----------------------------------------------------------------------------//
template<typename T>
T
Reflector( DistMatrix<T,MC,MR>& chi, DistMatrix<T,MC,MR>& x );

template<typename R>
R
ColReflector( DistMatrix<R,MC,MR>& chi, DistMatrix<R,MC,MR>& x );
Expand All @@ -309,6 +305,9 @@ RowReflector
DistMatrix<std::complex<R>,MC,MR>& x );
#endif

//----------------------------------------------------------------------------//
// Tridiag //
//----------------------------------------------------------------------------//
template<typename R>
void
PanelTridiagL
Expand Down
4 changes: 2 additions & 2 deletions src/lapack/QR/PanelQR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ elemental::lapack::internal::PanelQR
Z_MR_Star.AlignWith( ARightPan );
Z_MR_Star.ResizeTo( ARightPan.Width(), 1 );
//--------------------------------------------------------------------//
R tau = lapack::internal::Reflector( alpha11, a21 );
R tau = lapack::Reflector( alpha11, a21 );

bool myDiagonalEntry = ( g.MCRank() == alpha11.ColAlignment() &&
g.MRRank() == alpha11.RowAlignment() );
Expand Down Expand Up @@ -169,7 +169,7 @@ elemental::lapack::internal::PanelQR
Z_MR_Star.AlignWith( ARightPan );
Z_MR_Star.ResizeTo( ARightPan.Width(), 1 );
//--------------------------------------------------------------------//
C tau = lapack::internal::Reflector( alpha11, a21 );
C tau = lapack::Reflector( alpha11, a21 );
tau1.Set( 0, 0, tau );

bool myDiagonalEntry = ( g.MCRank() == alpha11.ColAlignment() &&
Expand Down
File renamed without changes.
205 changes: 205 additions & 0 deletions src/lapack/Reflector/Reflector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/*
This file is part of Elemental, a library for distributed-memory dense
linear algebra.
Copyright (c) 1992-2008 The University of Tennessee
All rights reserved.
Copyright (c) 2009-2010 Jack Poulson <jack.poulson@gmail.com>.
All rights reserved.
This file is released under the terms of the license contained in the file
LICENSE-LAPACK-DERIV as it is a derivative work of the LAPACK routines
dlarfg.f and zlarfg.f.
*/
#include "elemental/lapack_internal.hpp"
using namespace std;
using namespace elemental;

template<typename R>
R
elemental::lapack::Reflector
( Matrix<R>& chi, Matrix<R>& x )
{
#ifndef RELEASE
PushCallStack("lapack::Reflector");
#endif
if( x.Height() == 0 )
{
chi(0,0) *= (R)-1;
#ifndef RELEASE
PopCallStack();
#endif
return (R)2;
}

R norm = blas::Nrm2( x );
R alpha = chi(0,0);

R beta;
if( alpha <= 0 )
beta = wrappers::lapack::SafeNorm( alpha, norm );
else
beta = -wrappers::lapack::SafeNorm( alpha, norm );

R safeMin = numeric_limits<R>::min() / numeric_limits<R>::epsilon();
int count = 0;
if( Abs( beta ) < safeMin )
{
R invOfSafeMin = static_cast<R>(1) / safeMin;
do
{
++count;
blas::Scal( invOfSafeMin, x );
alpha *= invOfSafeMin;
beta *= invOfSafeMin;
} while( Abs( beta ) < safeMin );

norm = blas::Nrm2( x );
if( alpha <= 0 )
beta = wrappers::lapack::SafeNorm( alpha, norm );
else
beta = -wrappers::lapack::SafeNorm( alpha, norm );
}

R tau = ( beta - alpha ) / beta;
blas::Scal( static_cast<R>(1)/(alpha-beta), x );

for( int j=0; j<count; ++j )
beta *= safeMin;
chi(0,0) = beta;
#ifndef RELEASE
PopCallStack();
#endif
return tau;
}

#ifndef WITHOUT_COMPLEX
template<typename R>
complex<R>
elemental::lapack::Reflector
( Matrix< complex<R> >& chi, Matrix< complex<R> >& x )
{
#ifndef RELEASE
PushCallStack("lapack::Reflector");
#endif
typedef complex<R> C;

R norm = blas::Nrm2( x );
C alpha = chi(0,0);

if( norm == 0 && imag(alpha) == (R)0 )
{
chi(0,0) *= (R)-1;
#ifndef RELEASE
PopCallStack();
#endif
return (C)2;
}

R beta;
if( real(alpha) <= 0 )
beta = wrappers::lapack::SafeNorm( real(alpha), imag(alpha), norm );
else
beta = -wrappers::lapack::SafeNorm( real(alpha), imag(alpha), norm );

R safeMin = numeric_limits<R>::min() / numeric_limits<R>::epsilon();
int count = 0;
if( Abs( beta ) < safeMin )
{
R invOfSafeMin = static_cast<R>(1) / safeMin;
do
{
++count;
blas::Scal( (C)invOfSafeMin, x );
alpha *= invOfSafeMin;
beta *= invOfSafeMin;
} while( Abs( beta ) < safeMin );

norm = blas::Nrm2( x );
if( real(alpha) <= 0 )
beta = wrappers::lapack::SafeNorm
( real(alpha), imag(alpha), norm );
else
beta = -wrappers::lapack::SafeNorm
( real(alpha), imag(alpha), norm );
}

C tau = C( (beta-real(alpha))/beta, -imag(alpha)/beta );
blas::Scal( static_cast<C>(1)/(alpha-beta), x );

for( int j=0; j<count; ++j )
beta *= safeMin;
chi(0,0) = beta;
#ifndef RELEASE
PopCallStack();
#endif
return tau;
}
#endif // WITHOUT_COMPLEX

template<typename T>
T
elemental::lapack::Reflector
( DistMatrix<T,MC,MR>& chi, DistMatrix<T,MC,MR>& x )
{
#ifndef RELEASE
PushCallStack("lapack::Reflector");
if( chi.GetGrid() != x.GetGrid() )
throw logic_error( "chi and x must be distributed over the same grid" );
if( chi.Height() != 1 || chi.Width() != 1 )
throw logic_error( "chi must be a scalar." );
if( x.Height() != 1 && x.Width() != 1 )
throw logic_error( "x must be a vector." );
#endif
if( max( x.Height(), x.Width() ) == 0 )
return (T)0;

const Grid& g = x.GetGrid();
T tau;
if( x.Width() == 1 )
{
const bool thisIsMyColumn = ( g.MRRank() == x.RowAlignment() );
if( thisIsMyColumn )
tau = lapack::internal::ColReflector( chi, x );
wrappers::mpi::Broadcast( &tau, 1, x.RowAlignment(), g.MRComm() );
}
else
{
const bool thisIsMyRow = ( g.MCRank() == x.ColAlignment() );
if( thisIsMyRow )
tau = lapack::internal::RowReflector( chi, x );
wrappers::mpi::Broadcast( &tau, 1, x.ColAlignment(), g.MCComm() );
}
#ifndef RELEASE
PopCallStack();
#endif
return tau;
}

template float elemental::lapack::Reflector
( Matrix<float>& chi, Matrix<float>& x );

template float elemental::lapack::Reflector
( DistMatrix<float,MC,MR>& chi, DistMatrix<float,MC,MR>& x );

template double elemental::lapack::Reflector
( Matrix<double>& chi, Matrix<double>& x );

template double elemental::lapack::Reflector
( DistMatrix<double,MC,MR>& chi, DistMatrix<double,MC,MR>& x );

#ifndef WITHOUT_COMPLEX
template scomplex elemental::lapack::Reflector
( Matrix<scomplex>& chi, Matrix<scomplex>& x );

template scomplex elemental::lapack::Reflector
( DistMatrix<scomplex,MC,MR>& chi, DistMatrix<scomplex,MC,MR>& x );

template dcomplex elemental::lapack::Reflector
( Matrix<dcomplex>& chi, Matrix<dcomplex>& x );

template dcomplex elemental::lapack::Reflector
( DistMatrix<dcomplex,MC,MR>& chi, DistMatrix<dcomplex,MC,MR>& x );
#endif

File renamed without changes.
Loading

0 comments on commit e368a99

Please sign in to comment.