// matrix/kaldi-vector.h // Copyright 2009-2012 Ondrej Glembek; Microsoft Corporation; Lukas Burget; // Saarland University (Author: Arnab Ghoshal); // Ariya Rastrow; Petr Schwarz; Yanmin Qian; // Karel Vesely; Go Vivace Inc.; Arnab Ghoshal // Wei Shi; // 2015 Guoguo Chen // 2017 Daniel Galvez // 2019 Yiwen Shao // 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_KALDI_VECTOR_H_ #define KALDI_MATRIX_KALDI_VECTOR_H_ 1 #include "matrix/matrix-common.h" namespace kaldi { /// \addtogroup matrix_group /// @{ /// Provides a vector abstraction class. /// This class provides a way to work with vectors in kaldi. /// It encapsulates basic operations and memory optimizations. template <typename Real> class VectorBase { public: /// Set vector to all zeros. void SetZero(); /// Returns true if matrix is all zeros. bool IsZero(Real cutoff = 1.0e-06) const; // replace magic number /// Set all members of a vector to a specified value. void Set(Real f); /// Returns the dimension of the vector. inline MatrixIndexT Dim() const { return dim_; } /// Returns the size in memory of the vector, in bytes. inline MatrixIndexT SizeInBytes() const { return (dim_ * sizeof(Real)); } /// Returns a pointer to the start of the vector's data. inline Real *Data() { return data_; } /// Returns a pointer to the start of the vector's data (const). inline const Real *Data() const { return data_; } /// Indexing operator (const). inline Real operator()(MatrixIndexT i) const { KALDI_PARANOID_ASSERT(static_cast<UnsignedMatrixIndexT>(i) < static_cast<UnsignedMatrixIndexT>(dim_)); return *(data_ + i); } /// Indexing operator (non-const). inline Real &operator()(MatrixIndexT i) { KALDI_PARANOID_ASSERT(static_cast<UnsignedMatrixIndexT>(i) < static_cast<UnsignedMatrixIndexT>(dim_)); return *(data_ + i); } /** @brief Returns a sub-vector of a vector (a range of elements). * @param o [in] Origin, 0 < o < Dim() * @param l [in] Length 0 < l < Dim()-o * @return A SubVector object that aliases the data of the Vector object. * See @c SubVector class for details */ SubVector<Real> Range(const MatrixIndexT o, const MatrixIndexT l) { return SubVector<Real>(*this, o, l); } /** @brief Returns a const sub-vector of a vector (a range of elements). * @param o [in] Origin, 0 < o < Dim() * @param l [in] Length 0 < l < Dim()-o * @return A SubVector object that aliases the data of the Vector object. * See @c SubVector class for details */ const SubVector<Real> Range(const MatrixIndexT o, const MatrixIndexT l) const { return SubVector<Real>(*this, o, l); } /// Copy data from another vector (must match own size). void CopyFromVec(const VectorBase<Real> &v); /// Copy data from another vector of different type (double vs. float) template <typename OtherReal> void CopyFromVec(const VectorBase<OtherReal> &v); /// Performs a row stack of the matrix M void CopyRowsFromMat(const MatrixBase<Real> &M); template <typename OtherReal> void CopyRowsFromMat(const MatrixBase<OtherReal> &M); /// Performs a column stack of the matrix M void CopyColsFromMat(const MatrixBase<Real> &M); /// Extracts a row of the matrix M. Could also do this with /// this->Copy(M[row]). void CopyRowFromMat(const MatrixBase<Real> &M, MatrixIndexT row); /// Extracts a row of the matrix M with type conversion. template <typename OtherReal> void CopyRowFromMat(const MatrixBase<OtherReal> &M, MatrixIndexT row); /// Extracts a column of the matrix M. template <typename OtherReal> void CopyColFromMat(const MatrixBase<OtherReal> &M, MatrixIndexT col); /// Reads from C++ stream (option to add to existing contents). /// Throws exception on failure void Read(std::istream &in, bool binary); /// Writes to C++ stream (option to write in binary). void Write(std::ostream &Out, bool binary) const; friend class VectorBase<double>; friend class VectorBase<float>; protected: /// Destructor; does not deallocate memory, this is handled by child /// classes. /// This destructor is protected so this object can only be /// deleted via a child. ~VectorBase() {} /// Empty initializer, corresponds to vector of zero size. explicit VectorBase() : data_(NULL), dim_(0) { KALDI_ASSERT_IS_FLOATING_TYPE(Real); } /// data memory area Real *data_; /// dimension of vector MatrixIndexT dim_; KALDI_DISALLOW_COPY_AND_ASSIGN(VectorBase); }; // class VectorBase /** @brief A class representing a vector. * * This class provides a way to work with vectors in kaldi. * It encapsulates basic operations and memory optimizations. */ template <typename Real> class Vector : public VectorBase<Real> { public: /// Constructor that takes no arguments. Initializes to empty. Vector() : VectorBase<Real>() {} /// Constructor with specific size. Sets to all-zero by default /// if set_zero == false, memory contents are undefined. explicit Vector(const MatrixIndexT s, MatrixResizeType resize_type = kSetZero) : VectorBase<Real>() { Resize(s, resize_type); } /// Copy constructor from CUDA vector /// This is defined in ../cudamatrix/cu-vector.h // template<typename OtherReal> // explicit Vector(const CuVectorBase<OtherReal> &cu); /// Copy constructor. The need for this is controversial. Vector(const Vector<Real> &v) : VectorBase<Real>() { // (cannot be explicit) Resize(v.Dim(), kUndefined); this->CopyFromVec(v); } /// Copy-constructor from base-class, needed to copy from SubVector. explicit Vector(const VectorBase<Real> &v) : VectorBase<Real>() { Resize(v.Dim(), kUndefined); this->CopyFromVec(v); } /// Type conversion constructor. template <typename OtherReal> explicit Vector(const VectorBase<OtherReal> &v) : VectorBase<Real>() { Resize(v.Dim(), kUndefined); this->CopyFromVec(v); } // Took this out since it is unsafe : Arnab // /// Constructor from a pointer and a size; copies the data to a location // /// it owns. // Vector(const Real* Data, const MatrixIndexT s): VectorBase<Real>() { // Resize(s); // CopyFromPtr(Data, s); // } /// Swaps the contents of *this and *other. Shallow swap. void Swap(Vector<Real> *other); /// Destructor. Deallocates memory. ~Vector() { Destroy(); } /// Read function using C++ streams. Can also add to existing contents /// of matrix. void Read(std::istream &in, bool binary); /// Set vector 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 length, MatrixResizeType resize_type = kSetZero); /// Remove one element and shifts later elements down. void RemoveElement(MatrixIndexT i); /// Assignment operator. Vector<Real> &operator=(const Vector<Real> &other) { Resize(other.Dim(), kUndefined); this->CopyFromVec(other); return *this; } /// Assignment operator that takes VectorBase. Vector<Real> &operator=(const VectorBase<Real> &other) { Resize(other.Dim(), kUndefined); this->CopyFromVec(other); return *this; } private: /// Init assumes the current contents of the class are invalid (i.e. junk or /// has already been freed), and it sets the vector to newly allocated /// memory /// with the specified dimension. dim == 0 is acceptable. The memory /// contents /// pointed to by data_ will be undefined. void Init(const MatrixIndexT dim); /// Destroy function, called internally. void Destroy(); }; /// Represents a non-allocating general vector which can be defined /// as a sub-vector of higher-level vector [or as the row of a matrix]. template <typename Real> class SubVector : public VectorBase<Real> { public: /// Constructor from a Vector or SubVector. /// SubVectors are not const-safe and it's very hard to make them /// so for now we just give up. This function contains const_cast. SubVector(const VectorBase<Real> &t, const MatrixIndexT origin, const MatrixIndexT length) : VectorBase<Real>() { // following assert equiv to origin>=0 && length>=0 && // origin+length <= rt.dim_ KALDI_ASSERT(static_cast<UnsignedMatrixIndexT>(origin) + static_cast<UnsignedMatrixIndexT>(length) <= static_cast<UnsignedMatrixIndexT>(t.Dim())); VectorBase<Real>::data_ = const_cast<Real *>(t.Data() + origin); VectorBase<Real>::dim_ = length; } /// This constructor initializes the vector to point at the contents /// of this packed matrix (SpMatrix or TpMatrix). // SubVector(const PackedMatrix<Real> &M) { // VectorBase<Real>::data_ = const_cast<Real*> (M.Data()); // VectorBase<Real>::dim_ = (M.NumRows()*(M.NumRows()+1))/2; //} /// Copy constructor SubVector(const SubVector &other) : VectorBase<Real>() { // this copy constructor needed for Range() to work in base class. VectorBase<Real>::data_ = other.data_; VectorBase<Real>::dim_ = other.dim_; } /// Constructor from a pointer to memory and a length. Keeps a pointer /// to the data but does not take ownership (will never delete). /// Caution: this constructor enables you to evade const constraints. SubVector(const Real *data, MatrixIndexT length) : VectorBase<Real>() { VectorBase<Real>::data_ = const_cast<Real *>(data); VectorBase<Real>::dim_ = length; } /// This operation does not preserve const-ness, so be careful. SubVector(const MatrixBase<Real> &matrix, MatrixIndexT row) { VectorBase<Real>::data_ = const_cast<Real *>(matrix.RowData(row)); VectorBase<Real>::dim_ = matrix.NumCols(); } ~SubVector() {} ///< Destructor (does nothing; no pointers are owned here). private: /// Disallow assignment operator. SubVector &operator=(const SubVector &other) {} }; /// @} end of "addtogroup matrix_group" /// \addtogroup matrix_funcs_io /// @{ /// Output to a C++ stream. Non-binary by default (use Write for /// binary output). template <typename Real> std::ostream &operator<<(std::ostream &out, const VectorBase<Real> &v); /// Input from a C++ stream. Will automatically read text or /// binary data from the stream. template <typename Real> std::istream &operator>>(std::istream &in, VectorBase<Real> &v); /// Input from a C++ stream. Will automatically read text or /// binary data from the stream. template <typename Real> std::istream &operator>>(std::istream &in, Vector<Real> &v); /// @} end of \addtogroup matrix_funcs_io /// \addtogroup matrix_funcs_scalar /// @{ // template<typename Real> // bool ApproxEqual(const VectorBase<Real> &a, // const VectorBase<Real> &b, Real tol = 0.01) { // return a.ApproxEqual(b, tol); //} // template<typename Real> // inline void AssertEqual(VectorBase<Real> &a, VectorBase<Real> &b, // float tol = 0.01) { // KALDI_ASSERT(a.ApproxEqual(b, tol)); //} } // namespace kaldi // we need to include the implementation #include "matrix/kaldi-vector-inl.h" #endif // KALDI_MATRIX_KALDI_VECTOR_H_