summaryrefslogtreecommitdiff
path: root/kaldi_io/src/kaldi/matrix/packed-matrix.h
blob: 722d932b4b0199760c5ddb615747d4b0de85dfd7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// 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 <algorithm>

namespace kaldi {

/// \addtogroup matrix_funcs_io
// we need to declare the friend << operator here
template<typename Real>
std::ostream & operator <<(std::ostream & out, const PackedMatrix<Real>& M);


/// \addtogroup matrix_group
/// @{

/// @brief Packed matrix: base class for triangular and symmetric matrices.
template<typename Real> class PackedMatrix {
  friend class CuPackedMatrix<Real>;
 public:
  //friend class CuPackedMatrix<Real>;

  PackedMatrix() : data_(NULL), num_rows_(0) {}

  explicit PackedMatrix(MatrixIndexT r, MatrixResizeType resize_type = kSetZero):
      data_(NULL) {  Resize(r, resize_type);  }

  explicit PackedMatrix(const PackedMatrix<Real> &orig) : data_(NULL) {
    Resize(orig.num_rows_, kUndefined);
    CopyFromPacked(orig);
  }

  template<typename OtherReal>
  explicit PackedMatrix(const PackedMatrix<OtherReal> &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<Real> & operator =(const PackedMatrix<Real> &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<typename OtherReal>
  void CopyFromPacked(const PackedMatrix<OtherReal> &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<typename OtherReal>
  void CopyFromVec(const SubVector<OtherReal> &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<size_t>(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<UnsignedMatrixIndexT>(r) <
                 static_cast<UnsignedMatrixIndexT>(num_rows_) &&
                 static_cast<UnsignedMatrixIndexT>(c) <
                 static_cast<UnsignedMatrixIndexT>(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<UnsignedMatrixIndexT>(r) <
                 static_cast<UnsignedMatrixIndexT>(num_rows_) &&
                 static_cast<UnsignedMatrixIndexT>(c) <
                 static_cast<UnsignedMatrixIndexT>(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<Real> &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<Real> *other);
  void Swap(Matrix<Real> *other);


 protected:
  // Will only be called from this class or derived classes.
  void AddPacked(const Real alpha, const PackedMatrix<Real>& 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<typename Real>
std::ostream & operator << (std::ostream & os, const PackedMatrix<Real>& M) {
  M.Write(os, false);
  return os;
}

template<typename Real>
std::istream & operator >> (std::istream &is, PackedMatrix<Real> &M) {
  M.Read(is, false);
  return is;
}

/// @}

}  // namespace kaldi

#endif