#ifndef KALDI_CUDAMATRIX_CU_SP_MATRIX_H_ #define KALDI_CUDAMATRIX_CU_SP_MATRIX_H_ #include #include "cudamatrix/cu-common.h" #include "matrix/matrix-common.h" #include "matrix/sp-matrix.h" #include "cudamatrix/cu-array.h" #include "cudamatrix/cu-math.h" #include "cudamatrix/cu-packed-matrix.h" #include "cudamatrix/cu-matrix.h" namespace kaldi { /// TraceSpSp returns tr(A B) template Real TraceSpSp(const CuSpMatrix &A, const CuSpMatrix &B); template class CuSpMatrix : public CuPackedMatrix { friend class CuMatrixBase; friend class CuVectorBase; friend class CuTpMatrix; friend class CuSubMatrix; friend class CuRand; template friend R TraceSpSp(const CuSpMatrix &A, const CuSpMatrix &B); public: CuSpMatrix(): CuPackedMatrix() {} explicit CuSpMatrix(MatrixIndexT r, MatrixResizeType resize_type = kSetZero) : CuPackedMatrix(r, resize_type) {} explicit CuSpMatrix(const SpMatrix &orig) : CuPackedMatrix(orig) {} explicit CuSpMatrix(const CuSpMatrix &orig) : CuPackedMatrix(orig) {} explicit CuSpMatrix(const CuMatrixBase &orig, SpCopyType copy_type = kTakeLower) : CuPackedMatrix(orig.NumRows(), kUndefined) { CopyFromMat(orig, copy_type); } ~CuSpMatrix() {} inline void Resize(MatrixIndexT nRows, MatrixResizeType resize_type = kSetZero) { CuPackedMatrix::Resize(nRows, resize_type); } Real FrobeniusNorm() const { return sqrt(TraceSpSp(*this, *this)); } bool IsUnit(Real tol = 0.001) const; bool ApproxEqual(const CuSpMatrix &other, Real tol = 0.001) const; void CopyFromSp(const CuSpMatrix &other) { CuPackedMatrix::CopyFromPacked(other); } void CopyFromSp(const SpMatrix &other) { CuPackedMatrix::CopyFromPacked(other); } void CopyFromMat(const CuMatrixBase &orig, SpCopyType copy_type = kTakeLower); void CopyToSp(SpMatrix *dst) const { //added const by hxu CuPackedMatrix::CopyToPacked(dst); } inline CuValue operator() (MatrixIndexT r, MatrixIndexT c) { if (static_cast(c) > static_cast(r)) std::swap(c, r); KALDI_ASSERT(static_cast(r) < static_cast(this->num_rows_)); return CuValue(this->data_ + (r * (r+1)) / 2 + c); } inline Real operator() (MatrixIndexT r, MatrixIndexT c) const { if (static_cast(c) > static_cast(r)) std::swap(c, r); KALDI_ASSERT(static_cast(r) < static_cast(this->num_rows_)); return CuValue(this->data_ + (r * (r+1)) / 2 + c); // will be // casted to Real. } /// Approximate inversion of positive definite matrices, using repeated /// multiplication. Limits the error by ensuring that /// || I - A Ainv ||^2 <= max_error, using Frobenius norm (so guarantees // that (I - A Ainv).IsUnit(max_error) == true). void InvertPosDefApprox(BaseFloat max_error = 0.1); /// Note: the CuMatrix version of the Invert() function will only work for /// positive definite matrices; it is based on Cholesky. void Invert(); void AddVec2(const Real alpha, const CuVectorBase &v); void AddMat2(const Real alpha, const CuMatrixBase &M, MatrixTransposeType transM, const Real beta); void AddSp(const Real alpha, const CuSpMatrix &Ma) { this->AddPacked(alpha, Ma); } protected: inline const SpMatrix &Mat() const { return *(reinterpret_cast* >(this)); } inline SpMatrix &Mat() { return *(reinterpret_cast* >(this)); } }; template inline bool ApproxEqual(const CuSpMatrix &A, const CuSpMatrix &B, Real tol = 0.001) { return A.ApproxEqual(B, tol); } template inline void AssertEqual(const CuSpMatrix &A, const CuSpMatrix &B, Real tol = 0.001) { KALDI_ASSERT(ApproxEqual(A, B, tol)); } template SpMatrix::SpMatrix(const CuSpMatrix &cu) { Resize(cu.NumRows()); cu.CopyToSp(this); } } // namespace #endif