@ -38,7 +38,7 @@ namespace kaldi {
/// Base class which provides matrix operations not involving resizing
/// Base class which provides matrix operations not involving resizing
/// or allocation. Classes Matrix and SubMatrix inherit from it and take care
/// or allocation. Classes Matrix and SubMatrix inherit from it and take care
/// of allocation and resizing.
/// of allocation and resizing.
template < typename Real >
template < typename Real >
class MatrixBase {
class MatrixBase {
public :
public :
// so this child can access protected members of other instances.
// so this child can access protected members of other instances.
@ -62,22 +62,20 @@ class MatrixBase {
}
}
/// Gives pointer to raw data (const).
/// Gives pointer to raw data (const).
inline const Real * Data ( ) const {
inline const Real * Data ( ) const { return data_ ; }
return data_ ;
}
/// Gives pointer to raw data (non-const).
/// Gives pointer to raw data (non-const).
inline Real * Data ( ) { return data_ ; }
inline Real * Data ( ) { return data_ ; }
/// Returns pointer to data for one row (non-const)
/// Returns pointer to data for one row (non-const)
inline Real * RowData ( MatrixIndexT i ) {
inline Real * RowData ( MatrixIndexT i ) {
KALDI_ASSERT ( static_cast < UnsignedMatrixIndexT > ( i ) <
KALDI_ASSERT ( static_cast < UnsignedMatrixIndexT > ( i ) <
static_cast < UnsignedMatrixIndexT > ( num_rows_ ) ) ;
static_cast < UnsignedMatrixIndexT > ( num_rows_ ) ) ;
return data_ + i * stride_ ;
return data_ + i * stride_ ;
}
}
/// Returns pointer to data for one row (const)
/// Returns pointer to data for one row (const)
inline const Real * RowData ( MatrixIndexT i ) const {
inline const Real * RowData ( MatrixIndexT i ) const {
KALDI_ASSERT ( static_cast < UnsignedMatrixIndexT > ( i ) <
KALDI_ASSERT ( static_cast < UnsignedMatrixIndexT > ( i ) <
static_cast < UnsignedMatrixIndexT > ( num_rows_ ) ) ;
static_cast < UnsignedMatrixIndexT > ( num_rows_ ) ) ;
return data_ + i * stride_ ;
return data_ + i * stride_ ;
@ -85,8 +83,9 @@ class MatrixBase {
/// Indexing operator, non-const
/// Indexing operator, non-const
/// (only checks sizes if compiled with -DKALDI_PARANOID)
/// (only checks sizes if compiled with -DKALDI_PARANOID)
inline Real & operator ( ) ( MatrixIndexT r , MatrixIndexT c ) {
inline Real & operator ( ) ( MatrixIndexT r , MatrixIndexT c ) {
KALDI_PARANOID_ASSERT ( static_cast < UnsignedMatrixIndexT > ( r ) <
KALDI_PARANOID_ASSERT (
static_cast < UnsignedMatrixIndexT > ( r ) <
static_cast < UnsignedMatrixIndexT > ( num_rows_ ) & &
static_cast < UnsignedMatrixIndexT > ( num_rows_ ) & &
static_cast < UnsignedMatrixIndexT > ( c ) <
static_cast < UnsignedMatrixIndexT > ( c ) <
static_cast < UnsignedMatrixIndexT > ( num_cols_ ) ) ;
static_cast < UnsignedMatrixIndexT > ( num_cols_ ) ) ;
@ -94,12 +93,13 @@ class MatrixBase {
}
}
/// Indexing operator, provided for ease of debugging (gdb doesn't work
/// Indexing operator, provided for ease of debugging (gdb doesn't work
/// with parenthesis operator).
/// with parenthesis operator).
Real & Index ( MatrixIndexT r , MatrixIndexT c ) { return ( * this ) ( r , c ) ; }
Real & Index ( MatrixIndexT r , MatrixIndexT c ) { return ( * this ) ( r , c ) ; }
/// Indexing operator, const
/// Indexing operator, const
/// (only checks sizes if compiled with -DKALDI_PARANOID)
/// (only checks sizes if compiled with -DKALDI_PARANOID)
inline const Real operator ( ) ( MatrixIndexT r , MatrixIndexT c ) const {
inline const Real operator ( ) ( MatrixIndexT r , MatrixIndexT c ) const {
KALDI_PARANOID_ASSERT ( static_cast < UnsignedMatrixIndexT > ( r ) <
KALDI_PARANOID_ASSERT (
static_cast < UnsignedMatrixIndexT > ( r ) <
static_cast < UnsignedMatrixIndexT > ( num_rows_ ) & &
static_cast < UnsignedMatrixIndexT > ( num_rows_ ) & &
static_cast < UnsignedMatrixIndexT > ( c ) <
static_cast < UnsignedMatrixIndexT > ( c ) <
static_cast < UnsignedMatrixIndexT > ( num_cols_ ) ) ;
static_cast < UnsignedMatrixIndexT > ( num_cols_ ) ) ;
@ -115,22 +115,22 @@ class MatrixBase {
/// Sets to zero, except ones along diagonal [for non-square matrices too]
/// Sets to zero, except ones along diagonal [for non-square matrices too]
/// Copy given matrix. (no resize is done).
/// Copy given matrix. (no resize is done).
template < typename OtherReal >
template < typename OtherReal >
void CopyFromMat ( const MatrixBase < OtherReal > & M ,
void CopyFromMat ( const MatrixBase < OtherReal > & M ,
MatrixTransposeType trans = kNoTrans ) ;
MatrixTransposeType trans = kNoTrans ) ;
/// Copy from compressed matrix.
/// Copy from compressed matrix.
// void CopyFromMat(const CompressedMatrix &M);
// void CopyFromMat(const CompressedMatrix &M);
/// Copy given tpmatrix. (no resize is done).
/// Copy given tpmatrix. (no resize is done).
// template<typename OtherReal>
// template<typename OtherReal>
// void CopyFromTp(const TpMatrix<OtherReal> &M,
// void CopyFromTp(const TpMatrix<OtherReal> &M,
// MatrixTransposeType trans = kNoTrans);
// MatrixTransposeType trans = kNoTrans);
/// Copy from CUDA matrix. Implemented in ../cudamatrix/cu-matrix.h
/// Copy from CUDA matrix. Implemented in ../cudamatrix/cu-matrix.h
// template<typename OtherReal>
// template<typename OtherReal>
// void CopyFromMat(const CuMatrixBase<OtherReal> &M,
// void CopyFromMat(const CuMatrixBase<OtherReal> &M,
// MatrixTransposeType trans = kNoTrans);
// MatrixTransposeType trans = kNoTrans);
/// This function has two modes of operation. If v.Dim() == NumRows() *
/// This function has two modes of operation. If v.Dim() == NumRows() *
/// NumCols(), then treats the vector as a row-by-row concatenation of a
/// NumCols(), then treats the vector as a row-by-row concatenation of a
@ -138,10 +138,11 @@ class MatrixBase {
/// if v.Dim() == NumCols(), it sets each row of *this to a copy of v.
/// if v.Dim() == NumCols(), it sets each row of *this to a copy of v.
void CopyRowsFromVec ( const VectorBase < Real > & v ) ;
void CopyRowsFromVec ( const VectorBase < Real > & v ) ;
/// This version of CopyRowsFromVec is implemented in ../cudamatrix/cu-vector.cc
/// This version of CopyRowsFromVec is implemented in
//void CopyRowsFromVec(const CuVectorBase<Real> &v);
/// ../cudamatrix/cu-vector.cc
// void CopyRowsFromVec(const CuVectorBase<Real> &v);
template < typename OtherReal >
template < typename OtherReal >
void CopyRowsFromVec ( const VectorBase < OtherReal > & v ) ;
void CopyRowsFromVec ( const VectorBase < OtherReal > & v ) ;
/// Copies vector into matrix, column-by-column.
/// Copies vector into matrix, column-by-column.
@ -177,8 +178,8 @@ class MatrixBase {
const MatrixIndexT num_rows ,
const MatrixIndexT num_rows ,
const MatrixIndexT col_offset ,
const MatrixIndexT col_offset ,
const MatrixIndexT num_cols ) const {
const MatrixIndexT num_cols ) const {
return SubMatrix < Real > ( * this , row_offset , num_rows ,
return SubMatrix < Real > (
col_offset , num_cols ) ;
* this , row_offset , num_rows , col_offset , num_cols ) ;
}
}
inline SubMatrix < Real > RowRange ( const MatrixIndexT row_offset ,
inline SubMatrix < Real > RowRange ( const MatrixIndexT row_offset ,
const MatrixIndexT num_rows ) const {
const MatrixIndexT num_rows ) const {
@ -189,7 +190,7 @@ class MatrixBase {
return SubMatrix < Real > ( * this , 0 , num_rows_ , col_offset , num_cols ) ;
return SubMatrix < Real > ( * this , 0 , num_rows_ , col_offset , num_cols ) ;
}
}
/*
/*
/// Returns sum of all elements in matrix.
/// Returns sum of all elements in matrix.
Real Sum ( ) const ;
Real Sum ( ) const ;
/// Returns trace of matrix.
/// Returns trace of matrix.
@ -223,7 +224,8 @@ class MatrixBase {
/// each row by a scalar taken from that dimension of the vector.
/// each row by a scalar taken from that dimension of the vector.
void MulRowsVec ( const VectorBase < Real > & scale ) ;
void MulRowsVec ( const VectorBase < Real > & scale ) ;
/// Divide each row into src.NumCols() equal groups, and then scale i'th row's
/// Divide each row into src.NumCols() equal groups, and then scale i'th
row ' s
/// j'th group of elements by src(i, j). Requires src.NumRows() ==
/// j'th group of elements by src(i, j). Requires src.NumRows() ==
/// this->NumRows() and this->NumCols() % src.NumCols() == 0.
/// this->NumRows() and this->NumCols() % src.NumCols() == 0.
void MulRowsGroupMat ( const MatrixBase < Real > & src ) ;
void MulRowsGroupMat ( const MatrixBase < Real > & src ) ;
@ -242,77 +244,79 @@ class MatrixBase {
/// Does inversion in double precision even if matrix was not double.
/// Does inversion in double precision even if matrix was not double.
void InvertDouble ( Real * LogDet = NULL , Real * det_sign = NULL ,
void InvertDouble ( Real * LogDet = NULL , Real * det_sign = NULL ,
bool inverse_needed = true ) ;
bool inverse_needed = true ) ;
*/
*/
/// Inverts all the elements of the matrix
/// Inverts all the elements of the matrix
void InvertElements ( ) ;
void InvertElements ( ) ;
/*
/*
/// Transpose the matrix. This one is only
/// Transpose the matrix. This one is only
/// applicable to square matrices (the one in the
/// applicable to square matrices (the one in the
/// Matrix child class works also for non-square.
/// Matrix child class works also for non-square.
void Transpose ( ) ;
void Transpose ( ) ;
*/
*/
/// Copies column r from column indices[r] of src.
/// Copies column r from column indices[r] of src.
/// As a special case, if indexes[i] == -1, sets column i to zero.
/// As a special case, if indexes[i] == -1, sets column i to zero.
/// all elements of "indices" must be in [-1, src.NumCols()-1],
/// all elements of "indices" must be in [-1, src.NumCols()-1],
/// and src.NumRows() must equal this.NumRows()
/// and src.NumRows() must equal this.NumRows()
void CopyCols ( const MatrixBase < Real > & src ,
void CopyCols ( const MatrixBase < Real > & src , const MatrixIndexT * indices ) ;
const MatrixIndexT * indices ) ;
/// Copies row r from row indices[r] of src (does nothing
/// Copies row r from row indices[r] of src (does nothing
/// As a special case, if indexes[i] == -1, sets row i to zero.
/// As a special case, if indexes[i] == -1, sets row i to zero.
/// all elements of "indices" must be in [-1, src.NumRows()-1],
/// all elements of "indices" must be in [-1, src.NumRows()-1],
/// and src.NumCols() must equal this.NumCols()
/// and src.NumCols() must equal this.NumCols()
void CopyRows ( const MatrixBase < Real > & src ,
void CopyRows ( const MatrixBase < Real > & src , const MatrixIndexT * indices ) ;
const MatrixIndexT * indices ) ;
/// Add column indices[r] of src to column r.
/// Add column indices[r] of src to column r.
/// As a special case, if indexes[i] == -1, skip column i
/// As a special case, if indexes[i] == -1, skip column i
/// indices.size() must equal this->NumCols(),
/// indices.size() must equal this->NumCols(),
/// all elements of "reorder" must be in [-1, src.NumCols()-1],
/// all elements of "reorder" must be in [-1, src.NumCols()-1],
/// and src.NumRows() must equal this.NumRows()
/// and src.NumRows() must equal this.NumRows()
// void AddCols(const MatrixBase<Real> &src,
// void AddCols(const MatrixBase<Real> &src,
// const MatrixIndexT *indices);
// const MatrixIndexT *indices);
/// Copies row r of this matrix from an array of floats at the location given
/// Copies row r of this matrix from an array of floats at the location
/// given
/// by src[r]. If any src[r] is NULL then this.Row(r) will be set to zero.
/// by src[r]. If any src[r] is NULL then this.Row(r) will be set to zero.
/// Note: we are using "pointer to const pointer to const object" for "src",
/// Note: we are using "pointer to const pointer to const object" for "src",
/// because we may create "src" by calling Data() of const CuArray
/// because we may create "src" by calling Data() of const CuArray
void CopyRows ( const Real * const * src ) ;
void CopyRows ( const Real * const * src ) ;
/// Copies row r of this matrix to the array of floats at the location given
/// Copies row r of this matrix to the array of floats at the location given
/// by dst[r]. If dst[r] is NULL, does not copy anywhere. Requires that none
/// by dst[r]. If dst[r] is NULL, does not copy anywhere. Requires that
/// none
/// of the memory regions pointed to by the pointers in "dst" overlap (e.g.
/// of the memory regions pointed to by the pointers in "dst" overlap (e.g.
/// none of the pointers should be the same).
/// none of the pointers should be the same).
void CopyToRows ( Real * const * dst ) const ;
void CopyToRows ( Real * const * dst ) const ;
/// Does for each row r, this.Row(r) += alpha * src.row(indexes[r]).
/// Does for each row r, this.Row(r) += alpha * src.row(indexes[r]).
/// If indexes[r] < 0, does not add anything. all elements of "indexes" must
/// If indexes[r] < 0, does not add anything. all elements of "indexes" must
/// be in [-1, src.NumRows()-1], and src.NumCols() must equal this.NumCols().
/// be in [-1, src.NumRows()-1], and src.NumCols() must equal
/// this.NumCols().
// void AddRows(Real alpha,
// void AddRows(Real alpha,
// const MatrixBase<Real> &src,
// const MatrixBase<Real> &src,
// const MatrixIndexT *indexes);
// const MatrixIndexT *indexes);
/// Does for each row r, this.Row(r) += alpha * src[r], treating src[r] as the
/// Does for each row r, this.Row(r) += alpha * src[r], treating src[r] as
/// the
/// beginning of a region of memory representing a vector of floats, of the
/// beginning of a region of memory representing a vector of floats, of the
/// same length as this.NumCols(). If src[r] is NULL, does not add anything.
/// same length as this.NumCols(). If src[r] is NULL, does not add anything.
// void AddRows(Real alpha, const Real *const *src);
// void AddRows(Real alpha, const Real *const *src);
/// For each row r of this matrix, adds it (times alpha) to the array of
/// For each row r of this matrix, adds it (times alpha) to the array of
/// floats at the location given by dst[r]. If dst[r] is NULL, does not do
/// floats at the location given by dst[r]. If dst[r] is NULL, does not do
/// anything for that row. Requires that none of the memory regions pointed
/// anything for that row. Requires that none of the memory regions pointed
/// to by the pointers in "dst" overlap (e.g. none of the pointers should be
/// to by the pointers in "dst" overlap (e.g. none of the pointers should be
/// the same).
/// the same).
// void AddToRows(Real alpha, Real *const *dst) const;
// void AddToRows(Real alpha, Real *const *dst) const;
/// For each row i of *this, adds this->Row(i) to
/// For each row i of *this, adds this->Row(i) to
/// dst->Row(indexes(i)) if indexes(i) >= 0, else do nothing.
/// dst->Row(indexes(i)) if indexes(i) >= 0, else do nothing.
/// Requires that all the indexes[i] that are >= 0
/// Requires that all the indexes[i] that are >= 0
/// be distinct, otherwise the behavior is undefined.
/// be distinct, otherwise the behavior is undefined.
// void AddToRows(Real alpha,
// void AddToRows(Real alpha,
// const MatrixIndexT *indexes,
// const MatrixIndexT *indexes,
// MatrixBase<Real> *dst) const;
// MatrixBase<Real> *dst) const;
/*
/*
inline void ApplyPow ( Real power ) {
inline void ApplyPow ( Real power ) {
this - > Pow ( * this , power ) ;
this - > Pow ( * this , power ) ;
}
}
@ -349,66 +353,82 @@ class MatrixBase {
inline void ApplyLog ( ) {
inline void ApplyLog ( ) {
this - > Log ( * this ) ;
this - > Log ( * this ) ;
}
}
*/
*/
/// Eigenvalue Decomposition of a square NxN matrix into the form (*this) = P D
/// Eigenvalue Decomposition of a square NxN matrix into the form (*this) =
/// P^{-1}. Be careful: the relationship of D to the eigenvalues we output is
/// P D
/// slightly complicated, due to the need for P to be real. In the symmetric
/// P^{-1}. Be careful: the relationship of D to the eigenvalues we output
/// is
/// slightly complicated, due to the need for P to be real. In the
/// symmetric
/// case D is diagonal and real, but in
/// case D is diagonal and real, but in
/// the non-symmetric case there may be complex-conjugate pairs of eigenvalues.
/// the non-symmetric case there may be complex-conjugate pairs of
/// In this case, for the equation (*this) = P D P^{-1} to hold, D must actually
/// eigenvalues.
/// be block diagonal, with 2x2 blocks corresponding to any such pairs. If a
/// In this case, for the equation (*this) = P D P^{-1} to hold, D must
/// actually
/// be block diagonal, with 2x2 blocks corresponding to any such pairs. If
/// a
/// pair is lambda +- i*mu, D will have a corresponding 2x2 block
/// pair is lambda +- i*mu, D will have a corresponding 2x2 block
/// [lambda, mu; -mu, lambda].
/// [lambda, mu; -mu, lambda].
/// Note that if the input matrix (*this) is non-invertible, P may not be invertible
/// Note that if the input matrix (*this) is non-invertible, P may not be
/// so in this case instead of the equation (*this) = P D P^{-1} holding, we have
/// invertible
/// so in this case instead of the equation (*this) = P D P^{-1} holding, we
/// have
/// instead (*this) P = P D.
/// instead (*this) P = P D.
///
///
/// The non-member function CreateEigenvalueMatrix creates D from eigs_real and eigs_imag.
/// The non-member function CreateEigenvalueMatrix creates D from eigs_real
//void Eig(MatrixBase<Real> *P,
/// and eigs_imag.
// void Eig(MatrixBase<Real> *P,
// VectorBase<Real> *eigs_real,
// VectorBase<Real> *eigs_real,
// VectorBase<Real> *eigs_imag) const;
// VectorBase<Real> *eigs_imag) const;
/// The Power method attempts to take the matrix to a power using a method that
/// The Power method attempts to take the matrix to a power using a method
/// works in general for fractional and negative powers. The input matrix must
/// that
/// works in general for fractional and negative powers. The input matrix
/// must
/// be invertible and have reasonable condition (or we don't guarantee the
/// be invertible and have reasonable condition (or we don't guarantee the
/// results. The method is based on the eigenvalue decomposition. It will
/// results. The method is based on the eigenvalue decomposition. It will
/// return false and leave the matrix unchanged, if at entry the matrix had
/// return false and leave the matrix unchanged, if at entry the matrix had
/// real negative eigenvalues (or if it had zero eigenvalues and the power was
/// real negative eigenvalues (or if it had zero eigenvalues and the power
/// was
/// negative).
/// negative).
// bool Power(Real pow);
// bool Power(Real pow);
/** Singular value decomposition
/** Singular value decomposition
Major limitations :
Major limitations :
For nonsquare matrices , we assume m > = n ( NumRows > = NumCols ) , and we return
For nonsquare matrices , we assume m > = n ( NumRows > = NumCols ) , and we
return
the " skinny " Svd , i . e . the matrix in the middle is diagonal , and the
the " skinny " Svd , i . e . the matrix in the middle is diagonal , and the
one on the left is rectangular .
one on the left is rectangular .
In Svd , * this = U * diag ( S ) * Vt .
In Svd , * this = U * diag ( S ) * Vt .
Null pointers for U and / or Vt at input mean we do not want that output . We
Null pointers for U and / or Vt at input mean we do not want that output .
We
expect that S . Dim ( ) = = m , U is either NULL or m by n ,
expect that S . Dim ( ) = = m , U is either NULL or m by n ,
and v is either NULL or n by n .
and v is either NULL or n by n .
The singular values are not sorted ( use SortSvd for that ) . */
The singular values are not sorted ( use SortSvd for that ) . */
// void DestructiveSvd(VectorBase<Real> *s, MatrixBase<Real> *U,
// void DestructiveSvd(VectorBase<Real> *s, MatrixBase<Real> *U,
// MatrixBase<Real> *Vt); // Destroys calling matrix.
// MatrixBase<Real> *Vt); // Destroys calling matrix.
/// Compute SVD (*this) = U diag(s) Vt. Note that the V in the call is already
/// Compute SVD (*this) = U diag(s) Vt. Note that the V in the call is
/// already
/// transposed; the normal formulation is U diag(s) V^T.
/// transposed; the normal formulation is U diag(s) V^T.
/// Null pointers for U or V mean we don't want that output (this saves
/// Null pointers for U or V mean we don't want that output (this saves
/// compute). The singular values are not sorted (use SortSvd for that).
/// compute). The singular values are not sorted (use SortSvd for that).
// void Svd(VectorBase<Real> *s, MatrixBase<Real> *U,
// void Svd(VectorBase<Real> *s, MatrixBase<Real> *U,
// MatrixBase<Real> *Vt) const;
// MatrixBase<Real> *Vt) const;
/// Compute SVD but only retain the singular values.
/// Compute SVD but only retain the singular values.
// void Svd(VectorBase<Real> *s) const { Svd(s, NULL, NULL); }
// void Svd(VectorBase<Real> *s) const { Svd(s, NULL, NULL); }
/// Returns smallest singular value.
/// Returns smallest singular value.
// Real MinSingularValue() const {
// Real MinSingularValue() const {
// Vector<Real> tmp(std::min(NumRows(), NumCols()));
// Vector<Real> tmp(std::min(NumRows(), NumCols()));
// Svd(&tmp);
// Svd(&tmp);
// return tmp.Min();
// return tmp.Min();
//}
//}
//void TestUninitialized() const; // This function is designed so that if any element
// void TestUninitialized() const; // This function is designed so that if
// any element
// if the matrix is uninitialized memory, valgrind will complain.
// if the matrix is uninitialized memory, valgrind will complain.
/// Returns condition number by computing Svd. Works even if cols > rows.
/// Returns condition number by computing Svd. Works even if cols > rows.
@ -422,16 +442,19 @@ class MatrixBase {
/// Returns true if matrix is Diagonal.
/// Returns true if matrix is Diagonal.
bool IsDiagonal ( Real cutoff = 1.0e-05 ) const ; // replace magic number
bool IsDiagonal ( Real cutoff = 1.0e-05 ) const ; // replace magic number
/// Returns true if the matrix is all zeros, except for ones on diagonal. (it
/// Returns true if the matrix is all zeros, except for ones on diagonal.
( it
/// does not have to be square). More specifically, this function returns
/// does not have to be square). More specifically, this function returns
/// false if for any i, j, (*this)(i, j) differs by more than cutoff from the
/// false if for any i, j, (*this)(i, j) differs by more than cutoff from
the
/// expression (i == j ? 1 : 0).
/// expression (i == j ? 1 : 0).
bool IsUnit ( Real cutoff = 1.0e-05 ) const ; // replace magic number
bool IsUnit ( Real cutoff = 1.0e-05 ) const ; // replace magic number
/// Returns true if matrix is all zeros.
/// Returns true if matrix is all zeros.
bool IsZero ( Real cutoff = 1.0e-05 ) const ; // replace magic number
bool IsZero ( Real cutoff = 1.0e-05 ) const ; // replace magic number
/// Frobenius norm, which is the sqrt of sum of square elements. Same as Schatten 2-norm,
/// Frobenius norm, which is the sqrt of sum of square elements. Same as
Schatten 2 - norm ,
/// or just "2-norm".
/// or just "2-norm".
Real FrobeniusNorm ( ) const ;
Real FrobeniusNorm ( ) const ;
@ -461,7 +484,8 @@ class MatrixBase {
/// Sets each element to the Heaviside step function (x > 0 ? 1 : 0) of the
/// Sets each element to the Heaviside step function (x > 0 ? 1 : 0) of the
/// corresponding element in "src". Note: in general you can make different
/// corresponding element in "src". Note: in general you can make different
/// choices for x = 0, but for now please leave it as it (i.e. returning zero)
/// choices for x = 0, but for now please leave it as it (i.e. returning
zero )
/// because it affects the RectifiedLinearComponent in the neural net code.
/// because it affects the RectifiedLinearComponent in the neural net code.
void Heaviside ( const MatrixBase < Real > & src ) ;
void Heaviside ( const MatrixBase < Real > & src ) ;
@ -477,7 +501,8 @@ class MatrixBase {
/// If the power is negative and the input to the power is zero,
/// If the power is negative and the input to the power is zero,
/// The output will be set zero. If include_sign is true, it will
/// The output will be set zero. If include_sign is true, it will
/// multiply the result by the sign of the input.
/// multiply the result by the sign of the input.
void PowAbs ( const MatrixBase < Real > & src , Real power , bool include_sign = false ) ;
void PowAbs ( const MatrixBase < Real > & src , Real power , bool
include_sign = false ) ;
void Floor ( const MatrixBase < Real > & src , Real floor_val ) ;
void Floor ( const MatrixBase < Real > & src , Real floor_val ) ;
@ -492,36 +517,52 @@ class MatrixBase {
/// Floor(src, lower_limit);
/// Floor(src, lower_limit);
/// Ceiling(src, upper_limit);
/// Ceiling(src, upper_limit);
/// Exp(src)
/// Exp(src)
void ExpLimited ( const MatrixBase < Real > & src , Real lower_limit , Real upper_limit ) ;
void ExpLimited ( const MatrixBase < Real > & src , Real lower_limit , Real
upper_limit ) ;
/// Set each element to y = log(1 + exp(x))
/// Set each element to y = log(1 + exp(x))
void SoftHinge ( const MatrixBase < Real > & src ) ;
void SoftHinge ( const MatrixBase < Real > & src ) ;
/// Apply the function y(i) = (sum_{j = i*G}^{(i+1)*G-1} x_j^(power))^(1 / p).
/// Apply the function y(i) = (sum_{j = i*G}^{(i+1)*G-1} x_j^(power))^(1 /
/// Requires src.NumRows() == this->NumRows() and src.NumCols() % this->NumCols() == 0.
p ) .
/// Requires src.NumRows() == this->NumRows() and src.NumCols() %
this - > NumCols ( ) = = 0.
void GroupPnorm ( const MatrixBase < Real > & src , Real power ) ;
void GroupPnorm ( const MatrixBase < Real > & src , Real power ) ;
/// Calculate derivatives for the GroupPnorm function above...
/// Calculate derivatives for the GroupPnorm function above...
/// if "input" is the input to the GroupPnorm function above (i.e. the "src" variable),
/// if "input" is the input to the GroupPnorm function above (i.e. the "src"
/// and "output" is the result of the computation (i.e. the "this" of that function
variable ) ,
/// call), and *this has the same dimension as "input", then it sets each element
/// and "output" is the result of the computation (i.e. the "this" of that
/// of *this to the derivative d(output-elem)/d(input-elem) for each element of "input", where
function
/// "output-elem" is whichever element of output depends on that input element.
/// call), and *this has the same dimension as "input", then it sets each
void GroupPnormDeriv ( const MatrixBase < Real > & input , const MatrixBase < Real > & output ,
element
/// of *this to the derivative d(output-elem)/d(input-elem) for each element
of " input " , where
/// "output-elem" is whichever element of output depends on that input
element .
void GroupPnormDeriv ( const MatrixBase < Real > & input , const MatrixBase < Real >
& output ,
Real power ) ;
Real power ) ;
/// Apply the function y(i) = (max_{j = i*G}^{(i+1)*G-1} x_j
/// Apply the function y(i) = (max_{j = i*G}^{(i+1)*G-1} x_j
/// Requires src.NumRows() == this->NumRows() and src.NumCols() % this->NumCols() == 0.
/// Requires src.NumRows() == this->NumRows() and src.NumCols() %
this - > NumCols ( ) = = 0.
void GroupMax ( const MatrixBase < Real > & src ) ;
void GroupMax ( const MatrixBase < Real > & src ) ;
/// Calculate derivatives for the GroupMax function above, where
/// Calculate derivatives for the GroupMax function above, where
/// "input" is the input to the GroupMax function above (i.e. the "src" variable),
/// "input" is the input to the GroupMax function above (i.e. the "src"
/// and "output" is the result of the computation (i.e. the "this" of that function
variable ) ,
/// and "output" is the result of the computation (i.e. the "this" of that
function
/// call), and *this must have the same dimension as "input". Each element
/// call), and *this must have the same dimension as "input". Each element
/// of *this will be set to 1 if the corresponding input equals the output of
/// of *this will be set to 1 if the corresponding input equals the output
/// the group, and 0 otherwise. The equals the function derivative where it is
of
/// defined (it's not defined where multiple inputs in the group are equal to the output).
/// the group, and 0 otherwise. The equals the function derivative where it
void GroupMaxDeriv ( const MatrixBase < Real > & input , const MatrixBase < Real > & output ) ;
is
/// defined (it's not defined where multiple inputs in the group are equal
to the output ) .
void GroupMaxDeriv ( const MatrixBase < Real > & input , const MatrixBase < Real >
& output ) ;
/// Set each element to the tanh of the corresponding element of "src".
/// Set each element to the tanh of the corresponding element of "src".
void Tanh ( const MatrixBase < Real > & src ) ;
void Tanh ( const MatrixBase < Real > & src ) ;
@ -535,55 +576,56 @@ class MatrixBase {
// element-by-element, set *this = diff * (1.0 - value^2).
// element-by-element, set *this = diff * (1.0 - value^2).
void DiffTanh ( const MatrixBase < Real > & value ,
void DiffTanh ( const MatrixBase < Real > & value ,
const MatrixBase < Real > & diff ) ;
const MatrixBase < Real > & diff ) ;
*/
*/
/** Uses Svd to compute the eigenvalue decomposition of a symmetric positive
/** Uses Svd to compute the eigenvalue decomposition of a symmetric positive
* semi - definite matrix : ( * this ) = rP * diag ( rS ) * rP ^ T , with rP an
* semi - definite matrix : ( * this ) = rP * diag ( rS ) * rP ^ T , with rP an
* orthogonal matrix so rP ^ { - 1 } = rP ^ T . Throws exception if input was not
* orthogonal matrix so rP ^ { - 1 } = rP ^ T . Throws exception if input was not
* positive semi - definite ( check_thresh controls how stringent the check is ;
* positive semi - definite ( check_thresh controls how stringent the check is ;
* set it to 2 to ensure it won ' t ever complain , but it will zero out negative
* set it to 2 to ensure it won ' t ever complain , but it will zero out
* negative
* dimensions in your matrix .
* dimensions in your matrix .
*
*
* Caution : if you want the eigenvalues , it may make more sense to convert to
* Caution : if you want the eigenvalues , it may make more sense to convert
* SpMatrix and use Eig ( ) function there , which uses eigenvalue decomposition
* to
* SpMatrix and use Eig ( ) function there , which uses eigenvalue
* decomposition
* directly rather than SVD .
* directly rather than SVD .
*/
*/
/// stream read.
/// stream read.
/// Use instead of stream<<*this, if you want to add to existing contents.
/// Use instead of stream<<*this, if you want to add to existing contents.
// Will throw exception on failure.
// Will throw exception on failure.
void Read ( std : : istream & in , bool binary ) ;
void Read ( std : : istream & in , bool binary ) ;
/// write to stream.
/// write to stream.
void Write ( std : : ostream & out , bool binary ) const ;
void Write ( std : : ostream & out , bool binary ) const ;
// Below is internal methods for Svd, user does not have to know about this.
// Below is internal methods for Svd, user does not have to know about this.
protected :
protected :
/// Initializer, callable only from child.
/// Initializer, callable only from child.
explicit MatrixBase ( Real * data , MatrixIndexT cols , MatrixIndexT rows , MatrixIndexT stride ) :
explicit MatrixBase ( Real * data ,
data_ ( data ) , num_cols_ ( cols ) , num_rows_ ( rows ) , stride_ ( stride ) {
MatrixIndexT cols ,
MatrixIndexT rows ,
MatrixIndexT stride )
: data_ ( data ) , num_cols_ ( cols ) , num_rows_ ( rows ) , stride_ ( stride ) {
KALDI_ASSERT_IS_FLOATING_TYPE ( Real ) ;
KALDI_ASSERT_IS_FLOATING_TYPE ( Real ) ;
}
}
/// Initializer, callable only from child.
/// Initializer, callable only from child.
/// Empty initializer, for un-initialized matrix.
/// Empty initializer, for un-initialized matrix.
explicit MatrixBase ( ) : data_ ( NULL ) {
explicit MatrixBase ( ) : data_ ( NULL ) { KALDI_ASSERT_IS_FLOATING_TYPE ( Real ) ; }
KALDI_ASSERT_IS_FLOATING_TYPE ( Real ) ;
}
// Make sure pointers to MatrixBase cannot be deleted.
// Make sure pointers to MatrixBase cannot be deleted.
~ MatrixBase ( ) { }
~ MatrixBase ( ) { }
/// A workaround that allows SubMatrix to get a pointer to non-const data
/// A workaround that allows SubMatrix to get a pointer to non-const data
/// for const Matrix. Unfortunately C++ does not allow us to declare a
/// for const Matrix. Unfortunately C++ does not allow us to declare a
/// "public const" inheritance or anything like that, so it would require
/// "public const" inheritance or anything like that, so it would require
/// a lot of work to make the SubMatrix class totally const-correct--
/// a lot of work to make the SubMatrix class totally const-correct--
/// we would have to override many of the Matrix functions.
/// we would have to override many of the Matrix functions.
inline Real * Data_workaround ( ) const {
inline Real * Data_workaround ( ) const { return data_ ; }
return data_ ;
}
/// data memory area
/// data memory area
Real * data_ ;
Real * data_ ;
/// these attributes store the real matrix size as it is stored in memory
/// these attributes store the real matrix size as it is stored in memory
/// including memalignment
/// including memalignment
@ -592,63 +634,66 @@ class MatrixBase {
/** True number of columns for the internal matrix. This number may differ
/** True number of columns for the internal matrix. This number may differ
* from num_cols_ as memory alignment might be used . */
* from num_cols_ as memory alignment might be used . */
MatrixIndexT stride_ ;
MatrixIndexT stride_ ;
private :
private :
KALDI_DISALLOW_COPY_AND_ASSIGN ( MatrixBase ) ;
KALDI_DISALLOW_COPY_AND_ASSIGN ( MatrixBase ) ;
} ;
} ;
/// A class for storing matrices.
/// A class for storing matrices.
template < typename Real >
template < typename Real >
class Matrix : public MatrixBase < Real > {
class Matrix : public MatrixBase < Real > {
public :
public :
/// Empty constructor.
/// Empty constructor.
Matrix ( ) ;
Matrix ( ) ;
/// Basic constructor.
/// Basic constructor.
Matrix ( const MatrixIndexT r , const MatrixIndexT c ,
Matrix ( const MatrixIndexT r ,
const MatrixIndexT c ,
MatrixResizeType resize_type = kSetZero ,
MatrixResizeType resize_type = kSetZero ,
MatrixStrideType stride_type = kDefaultStride ) :
MatrixStrideType stride_type = kDefaultStride )
MatrixBase < Real > ( ) { Resize ( r , c , resize_type , stride_type ) ; }
: MatrixBase < Real > ( ) {
Resize ( r , c , resize_type , stride_type ) ;
}
/// Swaps the contents of *this and *other. Shallow swap.
/// Swaps the contents of *this and *other. Shallow swap.
void Swap ( Matrix < Real > * other ) ;
void Swap ( Matrix < Real > * other ) ;
/// Constructor from any MatrixBase. Can also copy with transpose.
/// Constructor from any MatrixBase. Can also copy with transpose.
/// Allocates new memory.
/// Allocates new memory.
explicit Matrix ( const MatrixBase < Real > & M ,
explicit Matrix ( const MatrixBase < Real > & M ,
MatrixTransposeType trans = kNoTrans ) ;
MatrixTransposeType trans = kNoTrans ) ;
/// Same as above, but need to avoid default copy constructor.
/// Same as above, but need to avoid default copy constructor.
Matrix ( const Matrix < Real > & M ) ; // (cannot make explicit)
Matrix ( const Matrix < Real > & M ) ; // (cannot make explicit)
/// Copy constructor: as above, but from another type.
/// Copy constructor: as above, but from another type.
template < typename OtherReal >
template < typename OtherReal >
explicit Matrix ( const MatrixBase < OtherReal > & M ,
explicit Matrix ( const MatrixBase < OtherReal > & M ,
MatrixTransposeType trans = kNoTrans ) ;
MatrixTransposeType trans = kNoTrans ) ;
/// Copy constructor taking TpMatrix...
/// Copy constructor taking TpMatrix...
// template <typename OtherReal>
// template <typename OtherReal>
// explicit Matrix(const TpMatrix<OtherReal> & M,
// explicit Matrix(const TpMatrix<OtherReal> & M,
// MatrixTransposeType trans = kNoTrans) : MatrixBase<Real>() {
// MatrixTransposeType trans = kNoTrans) : MatrixBase<Real>() {
// if (trans == kNoTrans) {
// if (trans == kNoTrans) {
// Resize(M.NumRows(), M.NumCols(), kUndefined);
// Resize(M.NumRows(), M.NumCols(), kUndefined);
// this->CopyFromTp(M);
// this->CopyFromTp(M);
//} else {
//} else {
// Resize(M.NumCols(), M.NumRows(), kUndefined);
// Resize(M.NumCols(), M.NumRows(), kUndefined);
// this->CopyFromTp(M, kTrans);
// this->CopyFromTp(M, kTrans);
//}
//}
//}
//}
/// read from stream.
/// read from stream.
// Unlike one in base, allows resizing.
// Unlike one in base, allows resizing.
void Read ( std : : istream & in , bool binary ) ;
void Read ( std : : istream & in , bool binary ) ;
/// Remove a specified row.
/// Remove a specified row.
void RemoveRow ( MatrixIndexT i ) ;
void RemoveRow ( MatrixIndexT i ) ;
/// Transpose the matrix. Works for non-square
/// Transpose the matrix. Works for non-square
/// matrices as well as square ones.
/// matrices as well as square ones.
// void Transpose();
// void Transpose();
/// Distructor to free matrices.
/// Distructor to free matrices.
~ Matrix ( ) { Destroy ( ) ; }
~ Matrix ( ) { Destroy ( ) ; }
@ -671,7 +716,7 @@ class Matrix : public MatrixBase<Real> {
MatrixStrideType stride_type = kDefaultStride ) ;
MatrixStrideType stride_type = kDefaultStride ) ;
/// Assignment operator that takes MatrixBase.
/// Assignment operator that takes MatrixBase.
Matrix < Real > & operator = ( const MatrixBase < Real > & other ) {
Matrix < Real > & operator = ( const MatrixBase < Real > & other ) {
if ( MatrixBase < Real > : : NumRows ( ) ! = other . NumRows ( ) | |
if ( MatrixBase < Real > : : NumRows ( ) ! = other . NumRows ( ) | |
MatrixBase < Real > : : NumCols ( ) ! = other . NumCols ( ) )
MatrixBase < Real > : : NumCols ( ) ! = other . NumCols ( ) )
Resize ( other . NumRows ( ) , other . NumCols ( ) , kUndefined ) ;
Resize ( other . NumRows ( ) , other . NumCols ( ) , kUndefined ) ;
@ -680,7 +725,7 @@ class Matrix : public MatrixBase<Real> {
}
}
/// Assignment operator. Needed for inclusion in std::vector.
/// Assignment operator. Needed for inclusion in std::vector.
Matrix < Real > & operator = ( const Matrix < Real > & other ) {
Matrix < Real > & operator = ( const Matrix < Real > & other ) {
if ( MatrixBase < Real > : : NumRows ( ) ! = other . NumRows ( ) | |
if ( MatrixBase < Real > : : NumRows ( ) ! = other . NumRows ( ) | |
MatrixBase < Real > : : NumCols ( ) ! = other . NumCols ( ) )
MatrixBase < Real > : : NumCols ( ) ! = other . NumCols ( ) )
Resize ( other . NumRows ( ) , other . NumCols ( ) , kUndefined ) ;
Resize ( other . NumRows ( ) , other . NumCols ( ) , kUndefined ) ;
@ -694,13 +739,14 @@ class Matrix : public MatrixBase<Real> {
void Destroy ( ) ;
void Destroy ( ) ;
/// Init assumes the current class contents are invalid (i.e. junk or have
/// Init assumes the current class contents are invalid (i.e. junk or have
/// already been freed), and it sets the matrix to newly allocated memory with
/// already been freed), and it sets the matrix to newly allocated memory
/// the specified number of rows and columns. r == c == 0 is acceptable. The data
/// with
/// the specified number of rows and columns. r == c == 0 is acceptable.
/// The data
/// memory contents will be undefined.
/// memory contents will be undefined.
void Init ( const MatrixIndexT r ,
void Init ( const MatrixIndexT r ,
const MatrixIndexT c ,
const MatrixIndexT c ,
const MatrixStrideType stride_type ) ;
const MatrixStrideType stride_type ) ;
} ;
} ;
/// @} end "addtogroup matrix_group"
/// @} end "addtogroup matrix_group"
@ -710,7 +756,7 @@ class Matrix : public MatrixBase<Real> {
/// A structure containing the HTK header.
/// A structure containing the HTK header.
/// [TODO: change the style of the variables to Kaldi-compliant]
/// [TODO: change the style of the variables to Kaldi-compliant]
template < typename Real >
template < typename Real >
class SubMatrix : public MatrixBase < Real > {
class SubMatrix : public MatrixBase < Real > {
public :
public :
// Initialize a SubMatrix from part of a matrix; this is
// Initialize a SubMatrix from part of a matrix; this is
@ -718,7 +764,7 @@ class SubMatrix : public MatrixBase<Real> {
// This initializer is against the proper semantics of "const", since
// This initializer is against the proper semantics of "const", since
// SubMatrix can change its contents. It would be hard to implement
// SubMatrix can change its contents. It would be hard to implement
// a "const-safe" version of this class.
// a "const-safe" version of this class.
SubMatrix ( const MatrixBase < Real > & T ,
SubMatrix ( const MatrixBase < Real > & T ,
const MatrixIndexT ro , // row offset, 0 < ro < NumRows()
const MatrixIndexT ro , // row offset, 0 < ro < NumRows()
const MatrixIndexT r , // number of rows, r > 0
const MatrixIndexT r , // number of rows, r > 0
const MatrixIndexT co , // column offset, 0 < co < NumCols()
const MatrixIndexT co , // column offset, 0 < co < NumCols()
@ -735,13 +781,13 @@ class SubMatrix : public MatrixBase<Real> {
/// This type of constructor is needed for Range() to work [in Matrix base
/// This type of constructor is needed for Range() to work [in Matrix base
/// class]. Cannot make it explicit.
/// class]. Cannot make it explicit.
SubMatrix < Real > ( const SubMatrix & other ) :
SubMatrix < Real > ( const SubMatrix & other )
MatrixBase < Real > ( other . data_ , other . num_cols_ , other . num_rows_ ,
: MatrixBase < Real > (
other . stride_ ) { }
other . data_ , other . num_cols_ , other . num_rows_ , other . stride_ ) { }
private :
private :
/// Disallow assignment.
/// Disallow assignment.
SubMatrix < Real > & operator = ( const SubMatrix < Real > & other ) ;
SubMatrix < Real > & operator = ( const SubMatrix < Real > & other ) ;
} ;
} ;
/// @} End of "addtogroup matrix_funcs_io".
/// @} End of "addtogroup matrix_funcs_io".
@ -794,25 +840,33 @@ Real TraceMatMatMatMat(const MatrixBase<Real> &A, MatrixTransposeType transA,
/// the same as U->NumCols(), and we sort s from greatest to least absolute
/// the same as U->NumCols(), and we sort s from greatest to least absolute
/// value (if sort_on_absolute_value == true) or greatest to least value
/// value (if sort_on_absolute_value == true) or greatest to least value
/// otherwise, moving the columns of U, if it exists, and the rows of Vt, if it
/// otherwise, moving the columns of U, if it exists, and the rows of Vt, if it
/// exists, around in the same way. Note: the "absolute value" part won't matter
/// exists, around in the same way. Note: the "absolute value" part won't
matter
/// if this is an actual SVD, since singular values are non-negative.
/// if this is an actual SVD, since singular values are non-negative.
template < typename Real > void SortSvd ( VectorBase < Real > * s , MatrixBase < Real > * U ,
template < typename Real > void SortSvd ( VectorBase < Real > * s , MatrixBase < Real > * U ,
MatrixBase < Real > * Vt = NULL ,
MatrixBase < Real > * Vt = NULL ,
bool sort_on_absolute_value = true ) ;
bool sort_on_absolute_value = true ) ;
/// Creates the eigenvalue matrix D that is part of the decomposition used Matrix::Eig.
/// Creates the eigenvalue matrix D that is part of the decomposition used
Matrix : : Eig .
/// D will be block-diagonal with blocks of size 1 (for real eigenvalues) or 2x2
/// D will be block-diagonal with blocks of size 1 (for real eigenvalues) or 2x2
/// for complex pairs. If a complex pair is lambda +- i*mu, D will have a corresponding
/// for complex pairs. If a complex pair is lambda +- i*mu, D will have a
corresponding
/// 2x2 block [lambda, mu; -mu, lambda].
/// 2x2 block [lambda, mu; -mu, lambda].
/// This function will throw if any complex eigenvalues are not in complex conjugate
/// This function will throw if any complex eigenvalues are not in complex
conjugate
/// pairs (or the members of such pairs are not consecutively numbered).
/// pairs (or the members of such pairs are not consecutively numbered).
template < typename Real >
template < typename Real >
void CreateEigenvalueMatrix ( const VectorBase < Real > & real , const VectorBase < Real > & imag ,
void CreateEigenvalueMatrix ( const VectorBase < Real > & real , const VectorBase < Real >
& imag ,
MatrixBase < Real > * D ) ;
MatrixBase < Real > * D ) ;
/// The following function is used in Matrix::Power, and separately tested, so we
/// The following function is used in Matrix::Power, and separately tested, so
/// declare it here mainly for the testing code to see. It takes a complex value to
we
/// a power using a method that will work for noninteger powers (but will fail if the
/// declare it here mainly for the testing code to see. It takes a complex
value to
/// a power using a method that will work for noninteger powers (but will fail
if the
/// complex value is real and negative).
/// complex value is real and negative).
template < typename Real >
template < typename Real >
bool AttemptComplexPower ( Real * x_re , Real * x_im , Real power ) ;
bool AttemptComplexPower ( Real * x_re , Real * x_im , Real power ) ;
@ -823,17 +877,17 @@ bool AttemptComplexPower(Real *x_re, Real *x_im, Real power);
/// \addtogroup matrix_funcs_io
/// \addtogroup matrix_funcs_io
/// @{
/// @{
template < typename Real >
template < typename Real >
std : : ostream & operator < < ( std : : ostream & Out , const MatrixBase < Real > & M ) ;
std : : ostream & operator < < ( std : : ostream & Out , const MatrixBase < Real > & M ) ;
template < typename Real >
template < typename Real >
std : : istream & operator > > ( std : : istream & In , MatrixBase < Real > & M ) ;
std : : istream & operator > > ( std : : istream & In , MatrixBase < Real > & M ) ;
// The Matrix read allows resizing, so we override the MatrixBase one.
// The Matrix read allows resizing, so we override the MatrixBase one.
template < typename Real >
template < typename Real >
std : : istream & operator > > ( std : : istream & In , Matrix < Real > & M ) ;
std : : istream & operator > > ( std : : istream & In , Matrix < Real > & M ) ;
template < typename Real >
template < typename Real >
bool SameDim ( const MatrixBase < Real > & M , const MatrixBase < Real > & N ) {
bool SameDim ( const MatrixBase < Real > & M , const MatrixBase < Real > & N ) {
return ( M . NumRows ( ) = = N . NumRows ( ) & & M . NumCols ( ) = = N . NumCols ( ) ) ;
return ( M . NumRows ( ) = = N . NumRows ( ) & & M . NumCols ( ) = = N . NumCols ( ) ) ;
}
}
@ -844,7 +898,6 @@ bool SameDim(const MatrixBase<Real> &M, const MatrixBase<Real> &N) {
} // namespace kaldi
} // namespace kaldi
// we need to include the implementation and some
// we need to include the implementation and some
// template specializations.
// template specializations.
# include "matrix/kaldi-matrix-inl.h"
# include "matrix/kaldi-matrix-inl.h"