// matrix/packed-matrix.h // Copyright 2009-2013 Ondrej Glembek; Lukas Burget; Microsoft Corporation; // Saarland University; Yanmin Qian; // Johns Hopkins University (Author: Daniel Povey) // See ../../COPYING for clarification regarding multiple authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, // MERCHANTABLITY OR NON-INFRINGEMENT. // See the Apache 2 License for the specific language governing permissions and // limitations under the License. #ifndef KALDI_MATRIX_PACKED_MATRIX_H_ #define KALDI_MATRIX_PACKED_MATRIX_H_ #include "matrix/matrix-common.h" #include namespace kaldi { /// \addtogroup matrix_funcs_io // we need to declare the friend << operator here template std::ostream & operator <<(std::ostream & out, const PackedMatrix& M); /// \addtogroup matrix_group /// @{ /// @brief Packed matrix: base class for triangular and symmetric matrices. template class PackedMatrix { friend class CuPackedMatrix; public: //friend class CuPackedMatrix; PackedMatrix() : data_(NULL), num_rows_(0) {} explicit PackedMatrix(MatrixIndexT r, MatrixResizeType resize_type = kSetZero): data_(NULL) { Resize(r, resize_type); } explicit PackedMatrix(const PackedMatrix &orig) : data_(NULL) { Resize(orig.num_rows_, kUndefined); CopyFromPacked(orig); } template explicit PackedMatrix(const PackedMatrix &orig) : data_(NULL) { Resize(orig.NumRows(), kUndefined); CopyFromPacked(orig); } void SetZero(); /// < Set to zero void SetUnit(); /// < Set to unit matrix. void SetRandn(); /// < Set to random values of a normal distribution Real Trace() const; // Needed for inclusion in std::vector PackedMatrix & operator =(const PackedMatrix &other) { Resize(other.NumRows()); CopyFromPacked(other); return *this; } ~PackedMatrix() { Destroy(); } /// Set packed matrix to a specified size (can be zero). /// The value of the new data depends on resize_type: /// -if kSetZero, the new data will be zero /// -if kUndefined, the new data will be undefined /// -if kCopyData, the new data will be the same as the old data in any /// shared positions, and zero elsewhere. /// This function takes time proportional to the number of data elements. void Resize(MatrixIndexT nRows, MatrixResizeType resize_type = kSetZero); void AddToDiag(const Real r); // Adds r to diaginal void ScaleDiag(const Real alpha); // Scales diagonal by alpha. void SetDiag(const Real alpha); // Sets diagonal to this value. template void CopyFromPacked(const PackedMatrix &orig); /// CopyFromVec just interprets the vector as having the same layout /// as the packed matrix. Must have the same dimension, i.e. /// orig.Dim() == (NumRows()*(NumRows()+1)) / 2; template void CopyFromVec(const SubVector &orig); Real* Data() { return data_; } const Real* Data() const { return data_; } inline MatrixIndexT NumRows() const { return num_rows_; } inline MatrixIndexT NumCols() const { return num_rows_; } size_t SizeInBytes() const { size_t nr = static_cast(num_rows_); return ((nr * (nr+1)) / 2) * sizeof(Real); } //MatrixIndexT Stride() const { return stride_; } // This code is duplicated in child classes to avoid extra levels of calls. Real operator() (MatrixIndexT r, MatrixIndexT c) const { KALDI_ASSERT(static_cast(r) < static_cast(num_rows_) && static_cast(c) < static_cast(num_rows_) && c <= r); return *(data_ + (r * (r + 1)) / 2 + c); } // This code is duplicated in child classes to avoid extra levels of calls. Real &operator() (MatrixIndexT r, MatrixIndexT c) { KALDI_ASSERT(static_cast(r) < static_cast(num_rows_) && static_cast(c) < static_cast(num_rows_) && c <= r); return *(data_ + (r * (r + 1)) / 2 + c); } Real Max() const { KALDI_ASSERT(num_rows_ > 0); return * (std::max_element(data_, data_ + ((num_rows_*(num_rows_+1))/2) )); } Real Min() const { KALDI_ASSERT(num_rows_ > 0); return * (std::min_element(data_, data_ + ((num_rows_*(num_rows_+1))/2) )); } void Scale(Real c); friend std::ostream & operator << <> (std::ostream & out, const PackedMatrix &m); // Use instead of stream<<*this, if you want to add to existing contents. // Will throw exception on failure. void Read(std::istream &in, bool binary, bool add = false); void Write(std::ostream &out, bool binary) const; void Destroy(); /// Swaps the contents of *this and *other. Shallow swap. void Swap(PackedMatrix *other); void Swap(Matrix *other); protected: // Will only be called from this class or derived classes. void AddPacked(const Real alpha, const PackedMatrix& M); Real *data_; MatrixIndexT num_rows_; //MatrixIndexT stride_; private: /// Init assumes the current contents of the class are is invalid (i.e. junk or /// has already been freed), and it sets the matrixd to newly allocated memory /// with the specified dimension. dim == 0 is acceptable. The memory contents /// pointed to by data_ will be undefined. void Init(MatrixIndexT dim); }; /// @} end "addtogroup matrix_group" /// \addtogroup matrix_funcs_io /// @{ template std::ostream & operator << (std::ostream & os, const PackedMatrix& M) { M.Write(os, false); return os; } template std::istream & operator >> (std::istream &is, PackedMatrix &M) { M.Read(is, false); return is; } /// @} } // namespace kaldi #endif