// 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;
// 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);
/// Set vector to random normally-distributed noise.
void SetRandn();
/// This function returns a random index into this vector,
/// chosen with probability proportional to the corresponding
/// element. Requires that this->Min() >= 0 and this->Sum() > 0.
MatrixIndexT RandCategorical() const;
/// 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 a SpMatrix or TpMatrix (must match own size).
template<typename OtherReal>
void CopyFromPacked(const PackedMatrix<OtherReal> &M);
/// Copy data from another vector of different type (double vs. float)
template<typename OtherReal>
void CopyFromVec(const VectorBase<OtherReal> &v);
/// Copy from CuVector. This is defined in ../cudamatrix/cu-vector.h
template<typename OtherReal>
void CopyFromVec(const CuVectorBase<OtherReal> &v);
/// Apply natural log to all elements. Throw if any element of
/// the vector is negative (but doesn't complain about zero; the
/// log will be -infinity
void ApplyLog();
/// Apply natural log to another vector and put result in *this.
void ApplyLogAndCopy(const VectorBase<Real> &v);
/// Apply exponential to each value in vector.
void ApplyExp();
/// Take absolute value of each of the elements
void ApplyAbs();
/// Applies floor to all elements. Returns number of elements floored.
MatrixIndexT ApplyFloor(Real floor_val);
/// Applies ceiling to all elements. Returns number of elements changed.
MatrixIndexT ApplyCeiling(Real ceil_val);
/// Applies floor to all elements. Returns number of elements floored.
MatrixIndexT ApplyFloor(const VectorBase<Real> &floor_vec);
/// Apply soft-max to vector and return normalizer (log sum of exponentials).
/// This is the same as: \f$ x(i) = exp(x(i)) / \sum_i exp(x(i)) \f$
Real ApplySoftMax();
/// Sets each element of *this to the tanh of the corresponding element of "src".
void Tanh(const VectorBase<Real> &src);
/// Sets each element of *this to the sigmoid function of the corresponding
/// element of "src".
void Sigmoid(const VectorBase<Real> &src);
/// Take all elements of vector to a power.
void ApplyPow(Real power);
/// Take the absolute value of all elements of a vector to a power.
/// Include the sign of the input element if include_sign == true.
/// If power is negative and the input value is zero, the output is set zero.
void ApplyPowAbs(Real power, bool include_sign=false);
/// Compute the p-th norm of the vector.
Real Norm(Real p) const;
/// Returns true if ((*this)-other).Norm(2.0) <= tol * (*this).Norm(2.0).
bool ApproxEqual(const VectorBase<Real> &other, float tol = 0.01) const;
/// Invert all elements.
void InvertElements();
/// Add vector : *this = *this + alpha * rv (with casting between floats and
/// doubles)
template<typename OtherReal>
void AddVec(const Real alpha, const VectorBase<OtherReal> &v);
/// Add vector : *this = *this + alpha * rv^2 [element-wise squaring].
void AddVec2(const Real alpha, const VectorBase<Real> &v);
/// Add vector : *this = *this + alpha * rv^2 [element-wise squaring],
/// with casting between floats and doubles.
template<typename OtherReal>
void AddVec2(const Real alpha, const VectorBase<OtherReal> &v);
/// Add matrix times vector : this <-- beta*this + alpha*M*v.
/// Calls BLAS GEMV.
void AddMatVec(const Real alpha, const MatrixBase<Real> &M,
const MatrixTransposeType trans, const VectorBase<Real> &v,
const Real beta); // **beta previously defaulted to 0.0**
/// This is as AddMatVec, except optimized for where v contains a lot
/// of zeros.
void AddMatSvec(const Real alpha, const MatrixBase<Real> &M,
const MatrixTransposeType trans, const VectorBase<Real> &v,
const Real beta); // **beta previously defaulted to 0.0**
/// Add symmetric positive definite matrix times vector:
/// this <-- beta*this + alpha*M*v. Calls BLAS SPMV.
void AddSpVec(const Real alpha, const SpMatrix<Real> &M,
const VectorBase<Real> &v, const Real beta); // **beta previously defaulted to 0.0**
/// Add triangular matrix times vector: this <-- beta*this + alpha*M*v.
/// Works even if rv == *this.
void AddTpVec(const Real alpha, const TpMatrix<Real> &M,
const MatrixTransposeType trans, const VectorBase<Real> &v,
const Real beta); // **beta previously defaulted to 0.0**
/// Set each element to y = (x == orig ? changed : x).
void ReplaceValue(Real orig, Real changed);
/// Multipy element-by-element by another vector.
void MulElements(const VectorBase<Real> &v);
/// Multipy element-by-element by another vector of different type.
template<typename OtherReal>
void MulElements(const VectorBase<OtherReal> &v);
/// Divide element-by-element by a vector.
void DivElements(const VectorBase<Real> &v);
/// Divide element-by-element by a vector of different type.
template<typename OtherReal>
void DivElements(const VectorBase<OtherReal> &v);
/// Add a constant to each element of a vector.
void Add(Real c);
/// Add element-by-element product of vectlrs:
// this <-- alpha * v .* r + beta*this .
void AddVecVec(Real alpha, const VectorBase<Real> &v,
const VectorBase<Real> &r, Real beta);
/// Add element-by-element quotient of two vectors.
/// this <---- alpha*v/r + beta*this
void AddVecDivVec(Real alpha, const VectorBase<Real> &v,
const VectorBase<Real> &r, Real beta);
/// Multiplies all elements by this constant.
void Scale(Real alpha);
/// Multiplies this vector by lower-triangular marix: *this <-- *this *M
void MulTp(const TpMatrix<Real> &M,