void LatticeImageAndKernel ( const Matrix<Field>& B, Matrix<Field>& M, Matrix<Field>& K, const LLLCtrl<Base<Field>>& ctrl ) { EL_DEBUG_CSE Matrix<Field> BCopy( B ); Matrix<Field> U, R; auto info = LLL( BCopy, U, R, ctrl ); const Int rank = info.rank; const Int n = B.Width(); M = BCopy(ALL,IR(0,rank)); K = U(ALL,IR(rank,n)); // Reduce the columns of U that corresponded to the kernel LLL( K, ctrl ); // Rather than explicitly inverting the Gram matrix of the kernel basis // as suggested by Cohen, we can simply solve a least squares problem // // NOTE: 'R' is reused for the least squares solution // TODO(poulson): Support other options than just "Babai rounding", e.g., // Nulling and Cancelling (with optimal ordering) LeastSquares( NORMAL, K, M, R ); Round( R ); Gemm( NORMAL, NORMAL, Field(-1), K, R, Field(1), M ); }
inline typename Base<F>::type LogDetDivergence ( UpperOrLower uplo, const DistMatrix<F>& A, const DistMatrix<F>& B ) { #ifndef RELEASE PushCallStack("LogDetDivergence"); #endif if( A.Grid() != B.Grid() ) throw std::logic_error("A and B must use the same grid"); if( A.Height() != A.Width() || B.Height() != B.Width() || A.Height() != B.Height() ) throw std::logic_error ("A and B must be square matrices of the same size"); typedef typename Base<F>::type R; const int n = A.Height(); const Grid& g = A.Grid(); DistMatrix<F> ACopy( A ); DistMatrix<F> BCopy( B ); Cholesky( uplo, ACopy ); Cholesky( uplo, BCopy ); if( uplo == LOWER ) { Trtrsm( LEFT, uplo, NORMAL, NON_UNIT, F(1), BCopy, ACopy ); } else { MakeTrapezoidal( LEFT, uplo, 0, ACopy ); Trsm( LEFT, uplo, NORMAL, NON_UNIT, F(1), BCopy, ACopy ); } MakeTrapezoidal( LEFT, uplo, 0, ACopy ); const R frobNorm = Norm( ACopy, FROBENIUS_NORM ); R logDet; R localLogDet(0); DistMatrix<F,MD,STAR> d(g); ACopy.GetDiagonal( d ); if( d.InDiagonal() ) { const int nLocalDiag = d.LocalHeight(); for( int iLocal=0; iLocal<nLocalDiag; ++iLocal ) { const R delta = RealPart(d.GetLocal(iLocal,0)); localLogDet += 2*Log(delta); } } mpi::AllReduce( &localLogDet, &logDet, 1, mpi::SUM, g.VCComm() ); const R logDetDiv = frobNorm*frobNorm - logDet - R(n); #ifndef RELEASE PopCallStack(); #endif return logDetDiv; }
inline typename Base<F>::type LogDetDivergence( UpperOrLower uplo, const Matrix<F>& A, const Matrix<F>& B ) { #ifndef RELEASE PushCallStack("LogDetDivergence"); #endif if( A.Height() != A.Width() || B.Height() != B.Width() || A.Height() != B.Height() ) throw std::logic_error ("A and B must be square matrices of the same size"); typedef typename Base<F>::type R; const int n = A.Height(); Matrix<F> ACopy( A ); Matrix<F> BCopy( B ); Cholesky( uplo, ACopy ); Cholesky( uplo, BCopy ); if( uplo == LOWER ) { Trtrsm( LEFT, uplo, NORMAL, NON_UNIT, F(1), BCopy, ACopy ); } else { MakeTrapezoidal( LEFT, uplo, 0, ACopy ); Trsm( LEFT, uplo, NORMAL, NON_UNIT, F(1), BCopy, ACopy ); } MakeTrapezoidal( LEFT, uplo, 0, ACopy ); const R frobNorm = Norm( ACopy, FROBENIUS_NORM ); Matrix<F> d; ACopy.GetDiagonal( d ); R logDet(0); for( int i=0; i<n; ++i ) logDet += 2*Log( RealPart(d.Get(i,0)) ); const R logDetDiv = frobNorm*frobNorm - logDet - R(n); #ifndef RELEASE PopCallStack(); #endif return logDetDiv; }
void LatticeKernel ( const Matrix<Field>& B, Matrix<Field>& K, const LLLCtrl<Base<Field>>& ctrl ) { EL_DEBUG_CSE // TODO(poulson): Take the shortcuts suggested in Algorithm 2.7.2 of // Henri Cohen's // "A course in computational algebraic number theory". Matrix<Field> BCopy( B ); Matrix<Field> U, R; auto info = LLL( BCopy, U, R, ctrl ); const Int rank = info.rank; const Int n = B.Width(); K = U(ALL,IR(rank,n)); // Reduce the columns of U that corresponded to the kernel LLL( K, ctrl ); }
// 填指定字节。 explicit Uuid(unsigned char (&abyData)[16]) noexcept { BCopy(x_unData, abyData); }