inline SafeProduct<F> AfterLUPartialPiv( const Matrix<F>& A, const Matrix<Int>& p ) { #ifndef RELEASE CallStackEntry entry("determinant::AfterLUPartialPiv"); #endif if( A.Height() != A.Width() ) LogicError("Cannot compute determinant of nonsquare matrix"); if( A.Height() != p.Height() ) LogicError("Pivot vector is incorrect length"); typedef BASE(F) R; const Int n = A.Height(); Matrix<F> d; A.GetDiagonal( d ); const R scale(n); SafeProduct<F> det( n ); for( Int i=0; i<n; ++i ) { const F delta = d.Get(i,0); R alpha = Abs(delta); det.rho *= delta/alpha; det.kappa += Log(alpha)/scale; } const bool isOdd = PivotParity( p ); if( isOdd ) det.rho = -det.rho; return det; }
inline SafeProduct<F> SafeDeterminant( DistMatrix<F,MC,MR>& A ) { #ifndef RELEASE PushCallStack("SafeDeterminant"); #endif if( A.Height() != A.Width() ) throw std::logic_error ("Cannot compute determinant of nonsquare matrix"); typedef typename Base<F>::type R; const int n = A.Height(); SafeProduct<F> det( n ); const Grid& g = A.Grid(); try { DistMatrix<int,VC,STAR> p; LU( A, p ); const bool isOdd = PivotParity( p ); DistMatrix<F,MD,STAR> d(g); A.GetDiagonal( d ); F localRho = 1; R localKappa = 0; if( d.InDiagonal() ) { const int nLocalDiag = d.LocalHeight(); for( int iLocal=0; iLocal<nLocalDiag; ++iLocal ) { const F delta = d.GetLocalEntry(iLocal,0); R alpha = Abs(delta); localRho *= delta/alpha; localKappa += std::log(alpha)/n; } } mpi::AllReduce( &localRho, &det.rho, 1, mpi::PROD, g.VCComm() ); mpi::AllReduce( &localKappa, &det.kappa, 1, mpi::SUM, g.VCComm() ); if( isOdd ) det.rho = -det.rho; } catch( SingularMatrixException& e ) { det.rho = 0; det.kappa = 0; } #ifndef RELEASE PopCallStack(); #endif return det; }
inline SafeProduct<F> LUPartialPiv( DistMatrix<F>& A ) { #ifndef RELEASE CallStackEntry entry("determinant::LUPartialPiv"); #endif if( A.Height() != A.Width() ) throw std::logic_error ("Cannot compute determinant of nonsquare matrix"); typedef BASE(F) R; const int n = A.Height(); const R scale(n); SafeProduct<F> det( n ); const Grid& g = A.Grid(); try { DistMatrix<int,VC,STAR> p(g); elem::LU( A, p ); const bool isOdd = PivotParity( p ); DistMatrix<F,MD,STAR> d(g); A.GetDiagonal( d ); F localRho = 1; R localKappa = 0; if( d.Participating() ) { const int nLocalDiag = d.LocalHeight(); for( int iLocal=0; iLocal<nLocalDiag; ++iLocal ) { const F delta = d.GetLocal(iLocal,0); R alpha = Abs(delta); localRho *= delta/alpha; localKappa += Log(alpha)/scale; } } mpi::AllReduce( &localRho, &det.rho, 1, mpi::PROD, g.VCComm() ); mpi::AllReduce( &localKappa, &det.kappa, 1, mpi::SUM, g.VCComm() ); if( isOdd ) det.rho = -det.rho; } catch( SingularMatrixException& e ) { det.rho = 0; det.kappa = 0; } return det; }
inline SafeProduct<F> AfterLUPartialPiv( const DistMatrix<F>& A, const DistMatrix<Int,VC,STAR>& p ) { #ifndef RELEASE CallStackEntry entry("determinant::AfterLUPartialPiv"); #endif if( A.Height() != A.Width() ) LogicError("Cannot compute determinant of nonsquare matrix"); if( A.Grid() != p.Grid() ) LogicError("A and p must have the same grid"); if( A.Height() != p.Height() ) LogicError("Pivot vector is incorrect length"); typedef BASE(F) R; const Int n = A.Height(); const Grid& g = A.Grid(); DistMatrix<F,MD,STAR> d(g); A.GetDiagonal( d ); F localRho = 1; R localKappa = 0; if( d.Participating() ) { const R scale(n); const Int nLocalDiag = d.LocalHeight(); for( Int iLoc=0; iLoc<nLocalDiag; ++iLoc ) { const F delta = d.GetLocal(iLoc,0); R alpha = Abs(delta); localRho *= delta/alpha; localKappa += Log(alpha)/scale; } } SafeProduct<F> det( n ); det.rho = mpi::AllReduce( localRho, mpi::PROD, g.VCComm() ); det.kappa = mpi::AllReduce( localKappa, mpi::SUM, g.VCComm() ); const bool isOdd = PivotParity( p ); if( isOdd ) det.rho = -det.rho; return det; }
inline SafeProduct<F> SafeDeterminant( Matrix<F>& A ) { #ifndef RELEASE PushCallStack("SafeDeterminant"); #endif if( A.Height() != A.Width() ) throw std::logic_error ("Cannot compute determinant of nonsquare matrix"); typedef typename Base<F>::type R; const int n = A.Height(); SafeProduct<F> det( n ); try { Matrix<int> p; LU( A, p ); const bool isOdd = PivotParity( p ); Matrix<F> d; A.GetDiagonal( d ); for( int i=0; i<n; ++i ) { const F delta = d.Get(i,0); R alpha = Abs(delta); det.rho *= delta/alpha; det.kappa += std::log(alpha)/n; } if( isOdd ) det.rho = -det.rho; } catch( SingularMatrixException& e ) { det.rho = 0; det.kappa = 0; } #ifndef RELEASE PopCallStack(); #endif return det; }
inline SafeProduct<F> LUPartialPiv( Matrix<F>& A ) { #ifndef RELEASE CallStackEntry entry("determinant::LUPartialPiv"); #endif if( A.Height() != A.Width() ) throw std::logic_error ("Cannot compute determinant of nonsquare matrix"); typedef BASE(F) R; const int n = A.Height(); const R scale(n); SafeProduct<F> det( n ); try { Matrix<int> p; elem::LU( A, p ); const bool isOdd = PivotParity( p ); Matrix<F> d; A.GetDiagonal( d ); for( int i=0; i<n; ++i ) { const F delta = d.Get(i,0); R alpha = Abs(delta); det.rho *= delta/alpha; det.kappa += Log(alpha)/scale; } if( isOdd ) det.rho = -det.rho; } catch( SingularMatrixException& e ) { det.rho = 0; det.kappa = 0; } return det; }