From a74183ddb4ab8383bfe214b3745eb8a0a99ee47a Mon Sep 17 00:00:00 2001 From: Determinant Date: Thu, 25 Jun 2015 12:56:45 +0800 Subject: let HTK I/O implementation be a single package --- htk_io/src/KaldiLib/Matrix.tcc | 796 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 796 insertions(+) create mode 100644 htk_io/src/KaldiLib/Matrix.tcc (limited to 'htk_io/src/KaldiLib/Matrix.tcc') diff --git a/htk_io/src/KaldiLib/Matrix.tcc b/htk_io/src/KaldiLib/Matrix.tcc new file mode 100644 index 0000000..f6ffb8f --- /dev/null +++ b/htk_io/src/KaldiLib/Matrix.tcc @@ -0,0 +1,796 @@ + +/** @file Matrix.tcc + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + + +#ifndef TNet_Matrix_tcc +#define TNet_Matrix_tcc + +//#pragma GCC system_header + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Common.h" + +#ifndef _XOPEN_SOURCE + #define _XOPEN_SOURCE 600 +#endif + + +#ifdef HAVE_ATLAS +extern "C"{ + #include +} +#endif + + +#include "Common.h" +#include "Vector.h" +namespace TNet +{ + +//****************************************************************************** + template + Matrix<_ElemT> & + Matrix<_ElemT>:: + Init(const size_t rows, + const size_t cols, + bool clear) + { + if(mpData != NULL) Destroy(); + if(rows*cols == 0){ + assert(rows==0 && cols==0); + mMRows=rows; + mMCols=cols; +#ifdef STK_MEMALIGN_MANUAL + mpFreeData=NULL; +#endif + mpData=NULL; + return *this; + } + // initialize some helping vars + size_t skip; + size_t real_cols; + size_t size; + void* data; // aligned memory block + void* free_data; // memory block to be really freed + + // compute the size of skip and real cols + skip = ((16 / sizeof(_ElemT)) - cols % (16 / sizeof(_ElemT))) % (16 / sizeof(_ElemT)); + real_cols = cols + skip; + size = rows * real_cols * sizeof(_ElemT); + + // allocate the memory and set the right dimensions and parameters + + if (NULL != (data = stk_memalign(16, size, &free_data))) + { + mpData = static_cast<_ElemT *> (data); +#ifdef STK_MEMALIGN_MANUAL + mpFreeData = static_cast<_ElemT *> (free_data); +#endif + mMRows = rows; + mMCols = cols; + mStride = real_cols; + } + else + { + throw std::bad_alloc(); + } + if(clear) Zero(); + return *this; + } // + + //**************************************************************************** + //**************************************************************************** + template + template + Matrix<_ElemT> & + Matrix<_ElemT>:: + Copy(const Matrix<_ElemU> & rM, MatrixTrasposeType Trans) + { + if(Trans==NO_TRANS){ + assert(mMRows == rM.Rows() && mMCols == rM.Cols()); + for(size_t i = 0; i < mMRows; i++) + (*this)[i].Copy(rM[i]); + return *this; + } else { + assert(mMCols == rM.Rows() && mMRows == rM.Cols()); + for(size_t i = 0; i < mMRows; i++) + for(size_t j = 0; j < mMCols; j++) + (*this)(i,j) = rM(j,i); + return *this; + } + } + + + + //**************************************************************************** + //**************************************************************************** + template + Matrix<_ElemT> & + Matrix<_ElemT>:: + CopyVectorSplicedRows(const Vector<_ElemT> &rV, const size_t nRows, const size_t nCols) { + assert(rV.Dim() == nRows*nCols); + mMRows = nRows; + mMCols = nCols; + Init(nRows,nCols,true); + for(size_t r=0; r + Matrix<_ElemT> & + Matrix<_ElemT>:: + RemoveRow(size_t i) + { + assert(i < mMRows && "Access out of matrix"); + for(size_t j = i + 1; j < mMRows; j++) + (*this)[j - 1].Copy((*this)[j]); + mMRows--; + return *this; + } + + + //**************************************************************************** + //**************************************************************************** + // The destructor + template + void + Matrix<_ElemT>:: + Destroy() + { + // we need to free the data block if it was defined +#ifndef STK_MEMALIGN_MANUAL + if (NULL != mpData) free(mpData); +#else + if (NULL != mpData) free(mpFreeData); + mpFreeData = NULL; +#endif + + mpData = NULL; + mMRows = mMCols = 0; + } + + //**************************************************************************** + //**************************************************************************** +// template +// void +// Matrix<_ElemT>:: +// VectorizeRows(Vector<_ElemT> &rV) { +//#ifdef PARANIOD +// assert(rV.Dim() == mMRows*mMCols); +//#endif +// for(size_t r=0; r + bool + Matrix<_ElemT>:: + LoadHTK(const char* pFileName) + { + HtkHeader htk_hdr; + + FILE *fp = fopen(pFileName, "rb"); + if(!fp) + { + return false; + } + + read(fileno(fp), &htk_hdr, sizeof(htk_hdr)); + + swap4(htk_hdr.mNSamples); + swap4(htk_hdr.mSamplePeriod); + swap2(htk_hdr.mSampleSize); + swap2(htk_hdr.mSampleKind); + + Init(htk_hdr.mNSamples, htk_hdr.mSampleSize / sizeof(float)); + + size_t i; + size_t j; + if (typeid(_ElemT) == typeid(float)) + { + for (i=0; i< Rows(); ++i) { + read(fileno(fp), (*this).pRowData(i), Cols() * sizeof(float)); + + for(j = 0; j < Cols(); j++) { + swap4(((*this)(i,j))); + } + } + } + else + { + float *pmem = new (std::nothrow) float[Cols()]; + if (!pmem) + { + fclose(fp); + return false; + } + + for(i = 0; i < Rows(); i++) { + read(fileno(fp), pmem, Cols() * sizeof(float)); + + for (j = 0; j < Cols(); ++j) { + swap4(pmem[j]); + (*this)(i,j) = static_cast<_ElemT>(pmem[j]); + } + } + delete [] pmem; + } + + fclose(fp); + + return true; + } + + //**************************************************************************** + //**************************************************************************** + template + Matrix<_ElemT> & + Matrix<_ElemT>:: + DotMul(const ThisType& a) + { + size_t i; + size_t j; + + for (i = 0; i < mMRows; ++i) { + for (j = 0; j < mMCols; ++j) { + (*this)(i,j) *= a(i,j); + } + } + return *this; + } + + //**************************************************************************** + //**************************************************************************** + template + _ElemT & + Matrix<_ElemT>:: + Sum() const + { + double sum = 0.0; + + for (size_t i = 0; i < Rows(); ++i) { + for (size_t j = 0; j < Cols(); ++j) { + sum += (*this)(i,j); + } + } + + return sum; + } + + //**************************************************************************** + //**************************************************************************** + template + Matrix<_ElemT>& + Matrix<_ElemT>:: + Scale(_ElemT alpha) + { +#if 0 + for (size_t i = 0; i < Rows(); ++i) + for (size_t j = 0; j < Cols(); ++j) + (*this)(i,j) *= alpha; +#else + for (size_t i = 0; i < Rows(); ++i) { + _ElemT* p_data = pRowData(i); + for (size_t j = 0; j < Cols(); ++j) { + *p_data++ *= alpha; + } + } +#endif + return *this; + } + + //**************************************************************************** + //**************************************************************************** + template + Matrix<_ElemT>& + Matrix<_ElemT>:: + ScaleRows(const Vector<_ElemT>& scale) // scales each row by scale[i]. + { + assert(scale.Dim() == Rows()); + size_t M = Rows(), N = Cols(); + + for (size_t i = 0; i < M; i++) { + _ElemT this_scale = scale(i); + for (size_t j = 0; j < N; j++) { + (*this)(i,j) *= this_scale; + } + } + return *this; + } + + //**************************************************************************** + //**************************************************************************** + template + Matrix<_ElemT>& + Matrix<_ElemT>:: + ScaleCols(const Vector<_ElemT>& scale) // scales each column by scale[i]. + { + assert(scale.Dim() == Cols()); + for (size_t i = 0; i < Rows(); i++) { + for (size_t j = 0; j < Cols(); j++) { + _ElemT this_scale = scale(j); + (*this)(i,j) *= this_scale; + } + } + return *this; + } + + + //**************************************************************************** + //**************************************************************************** + template + Matrix<_ElemT>& + Matrix<_ElemT>:: + Add(const Matrix<_ElemT>& rMatrix) + { + assert(rMatrix.Cols() == Cols()); + assert(rMatrix.Rows() == Rows()); + +#if 0 + //this can be slow + for (size_t i = 0; i < Rows(); i++) { + for (size_t j = 0; j < Cols(); j++) { + (*this)(i,j) += rMatrix(i,j); + } + } +#else + //this will be faster (but less secure) + for(size_t i=0; i + Matrix<_ElemT>& + Matrix<_ElemT>:: + AddScaled(_ElemT alpha, const Matrix<_ElemT>& rMatrix) + { + assert(rMatrix.Cols() == Cols()); + assert(rMatrix.Rows() == Rows()); + +#if 0 + //this can be slow + for (size_t i = 0; i < Rows(); i++) { + for (size_t j = 0; j < Cols(); j++) { + (*this)(i,j) += rMatrix(i,j) * alpha; + } + } +#else + /* + //this will be faster (but less secure) + for(size_t i=0; i + Matrix<_ElemT>& + Matrix<_ElemT>:: + ApplyLog() + { + +#if 0 + //this can be slow + for (size_t i = 0; i < Rows(); i++) { + for (size_t j = 0; j < Cols(); j++) { + (*this)(i,j) = += _LOG((*this)(i,j)); + } + } +#else + //this will be faster (but less secure) + for(size_t i=0; i + Matrix<_ElemT> & + Matrix<_ElemT>:: + Zero() + { + for(size_t row=0;row + Matrix<_ElemT> & + Matrix<_ElemT>:: + Unit() + { + for(size_t row=0;row + void + Matrix<_ElemT>:: + PrintOut(char* file) + { + FILE* f = fopen(file, "w"); + unsigned i,j; + fprintf(f, "%dx%d\n", this->mMRows, this->mMCols); + + for(i=0; imMRows; i++) + { + _ElemT* row = (*this)[i]; + + for(j=0; jmStride; j++){ + fprintf(f, "%20.17f ",row[j]); + } + fprintf(f, "\n"); + } + + fclose(f); + } + + + //**************************************************************************** + //**************************************************************************** + template + void + Matrix<_ElemT>:: + ReadIn(char* file) + { + FILE* f = fopen(file, "r"); + int i = 0; + int j = 0; + fscanf(f, "%dx%d\n", &i,&j); + fprintf(stderr, "%dx%d\n", i,j); + + for(i=0; imMRows; i++) + { + _ElemT* row = (*this)[i]; + + for(j=0; jmStride; j++){ + fscanf(f, "%f ",&row[j]); + } + //fprintf(f, "\n"); + } + + fclose(f); + } + + + //**************************************************************************** + //**************************************************************************** + template + void Save (std::ostream &rOut, const Matrix<_ElemT> &rM) + { + for (size_t i = 0; i < rM.Rows(); i++) { + for (size_t j = 0; j < rM.Cols(); j++) { + rOut << rM(i,j) << ' '; + } + rOut << '\n'; + } + if(rOut.fail()) + throw std::runtime_error("Failed to write matrix to stream"); + } + + + //**************************************************************************** + //**************************************************************************** + template + std::ostream & + operator << (std::ostream & rOut, const Matrix<_ElemT> & rM) + { + rOut << "m " << rM.Rows() << ' ' << rM.Cols() << '\n'; + Save(rOut, rM); + return rOut; + } + + + + //**************************************************************************** + //**************************************************************************** + template + void Load (std::istream & rIn, Matrix<_ElemT> & rM) + { + if(MatrixVectorIostreamControl::Flags(rIn, ACCUMULATE_INPUT)) { + for (size_t i = 0; i < rM.Rows(); i++) { + std::streamoff pos = rIn.tellg(); + for (size_t j = 0; j < rM.Cols(); j++) { + _ElemT tmp; + rIn >> tmp; + rM(i,j) += tmp; + if(rIn.fail()){ + throw std::runtime_error("Failed to read matrix from stream. File position is "+to_string(pos)); + } + } + } + } else { + for (size_t i = 0; i < rM.Rows(); i++) { + std::streamoff pos = rIn.tellg(); + for (size_t j = 0; j < rM.Cols(); j++) { + rIn >> rM(i,j); + if(rIn.fail()){ + throw std::runtime_error("Failed to read matrix from stream. File position is "+to_string(pos)); + } + + } + } + } + } + + + //**************************************************************************** + //**************************************************************************** + template + std::istream & + operator >> (std::istream & rIn, Matrix<_ElemT> & rM) + { + while(isascii(rIn.peek()) && isspace(rIn.peek())) rIn.get(); // eat up space. + if(rIn.peek() == 'm'){ // "new" format: m \n 1.0 0.2 4.3 ... + rIn.get();// eat up the 'm'. + long long int nrows=-1; rIn>>nrows; + long long int ncols=-1; rIn>>ncols; + if(rIn.fail()||nrows<0||ncols<0){ throw std::runtime_error("Failed to read matrix from stream: no size\n"); } + + size_t nrows2 = size_t(nrows), ncols2 = size_t(ncols); + assert((long long int)nrows2 == nrows && (long long int)ncols2 == ncols); + + if(rM.Rows()!=nrows2 || rM.Cols()!=ncols2) rM.Init(nrows2,ncols2); + } + Load(rIn,rM); + return rIn; + } + + + + //**************************************************************************** + //**************************************************************************** + // Constructor + template + SubMatrix<_ElemT>:: + SubMatrix(const Matrix<_ElemT>& rT, // Matrix cannot be const because SubMatrix can change its contents. Would have to have a ConstSubMatrix or something... + const size_t ro, + const size_t r, + const size_t co, + const size_t c) + { + assert(ro >= 0 && ro <= rT.Rows()); + assert(co >= 0 && co <= rT.Cols()); + assert(r > 0 && r <= rT.Rows() - ro); + assert(c > 0 && c <= rT.Cols() - co); + // point to the begining of window + Matrix<_ElemT>::mMRows = r; + Matrix<_ElemT>::mMCols = c; + Matrix<_ElemT>::mStride = rT.Stride(); + Matrix<_ElemT>::mpData = rT.pData_workaround() + co + ro * rT.Stride(); + } + + + +#ifdef HAVE_ATLAS + + template<> + Matrix & + Matrix:: + BlasGer(const float alpha, const Vector& rA, const Vector& rB); + + + template<> + Matrix & + Matrix:: + BlasGer(const double alpha, const Vector& rA, const Vector& rB); + + + template<> + Matrix& + Matrix:: + BlasGemm(const float alpha, + const Matrix& rA, MatrixTrasposeType transA, + const Matrix& rB, MatrixTrasposeType transB, + const float beta); + + template<> + Matrix& + Matrix:: + BlasGemm(const double alpha, + const Matrix& rA, MatrixTrasposeType transA, + const Matrix& rB, MatrixTrasposeType transB, + const double beta); + + template<> + Matrix& + Matrix:: + Axpy(const float alpha, + const Matrix& rA, MatrixTrasposeType transA); + + template<> + Matrix& + Matrix:: + Axpy(const double alpha, + const Matrix& rA, MatrixTrasposeType transA); + + template <> // non-member so automatic namespace lookup can occur. + double TraceOfProduct(const Matrix &A, const Matrix &B); + + template <> // non-member so automatic namespace lookup can occur. + double TraceOfProductT(const Matrix &A, const Matrix &B); + + template <> // non-member so automatic namespace lookup can occur. + float TraceOfProduct(const Matrix &A, const Matrix &B); + + template <> // non-member so automatic namespace lookup can occur. + float TraceOfProductT(const Matrix &A, const Matrix &B); + + + +#else // HAVE_ATLAS + #error Routines in this section are not implemented yet without BLAS +#endif // HAVE_ATLAS + + template + bool + Matrix<_ElemT>:: + IsSymmetric(_ElemT cutoff) const { + size_t R=Rows(), C=Cols(); + if(R!=C) return false; + _ElemT bad_sum=0.0, good_sum=0.0; + for(size_t i=0;i cutoff*good_sum) return false; + return true; + } + + template + bool + Matrix<_ElemT>:: + IsDiagonal(_ElemT cutoff) const{ + size_t R=Rows(), C=Cols(); + _ElemT bad_sum=0.0, good_sum=0.0; + for(size_t i=0;i good_sum * cutoff)); + } + + template + bool + Matrix<_ElemT>:: + IsUnit(_ElemT cutoff) const { + size_t R=Rows(), C=Cols(); + if(R!=C) return false; + _ElemT bad_sum=0.0; + for(size_t i=0;i + bool + Matrix<_ElemT>:: + IsZero(_ElemT cutoff)const { + size_t R=Rows(), C=Cols(); + _ElemT bad_sum=0.0; + for(size_t i=0;i + _ElemT + Matrix<_ElemT>:: + FrobeniusNorm() const{ + size_t R=Rows(), C=Cols(); + _ElemT sum=0.0; + for(size_t i=0;i + _ElemT + Matrix<_ElemT>:: + LargestAbsElem() const{ + size_t R=Rows(), C=Cols(); + _ElemT largest=0.0; + for(size_t i=0;i + _ElemT + Matrix<_ElemT>:: + LogAbsDeterminant(_ElemT *DetSign){ + _ElemT LogDet; + Matrix<_ElemT> tmp(*this); + tmp.Invert(&LogDet, DetSign, false); // false== output not needed (saves some computation). + return LogDet; + } + +}// namespace TNet + +// #define TNet_Matrix_tcc +#endif -- cgit v1.2.3