sparse-matrix.cc
Go to the documentation of this file.
1 // matrix/sparse-matrix.cc
2 
3 // Copyright 2015 Johns Hopkins University (author: Daniel Povey)
4 // 2015 Guoguo Chen
5 // 2017 Shiyin Kang
6 
7 // See ../../COPYING for clarification regarding multiple authors
8 //
9 // Licensed under the Apache License, Version 2.0 (the "License");
10 // you may not use this file except in compliance with the License.
11 // You may obtain a copy of the License at
12 //
13 // http://www.apache.org/licenses/LICENSE-2.0
14 //
15 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
17 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
18 // MERCHANTABLITY OR NON-INFRINGEMENT.
19 // See the Apache 2 License for the specific language governing permissions and
20 // limitations under the License.
21 
22 #include <algorithm>
23 #include <limits>
24 #include <string>
25 
26 #include "matrix/sparse-matrix.h"
27 #include "matrix/kaldi-matrix.h"
28 
29 namespace kaldi {
30 
31 template <typename Real>
32 std::pair<MatrixIndexT, Real>* SparseVector<Real>::Data() {
33  if (pairs_.empty())
34  return NULL;
35  else
36  return &(pairs_[0]);
37 }
38 
39 template <typename Real>
40 const std::pair<MatrixIndexT, Real>* SparseVector<Real>::Data() const {
41  if (pairs_.empty())
42  return NULL;
43  else
44  return &(pairs_[0]);
45 }
46 
47 template <typename Real>
49  Real sum = 0;
50  for (int32 i = 0; i < pairs_.size(); ++i) {
51  sum += pairs_[i].second;
52  }
53  return sum;
54 }
55 
56 template<typename Real>
57 void SparseVector<Real>::Scale(Real alpha) {
58  for (int32 i = 0; i < pairs_.size(); ++i)
59  pairs_[i].second *= alpha;
60 }
61 
62 template <typename Real>
63 template <typename OtherReal>
65  KALDI_ASSERT(vec->Dim() == this->dim_);
66  vec->SetZero();
67  OtherReal *other_data = vec->Data();
68  typename std::vector<std::pair<MatrixIndexT, Real> >::const_iterator
69  iter = pairs_.begin(), end = pairs_.end();
70  for (; iter != end; ++iter)
71  other_data[iter->first] = iter->second;
72 }
73 template
75 template
77 template
79 template
81 
82 template <typename Real>
83 template <typename OtherReal>
85  VectorBase<OtherReal> *vec) const {
86  KALDI_ASSERT(vec->Dim() == dim_);
87  OtherReal *other_data = vec->Data();
88  typename std::vector<std::pair<MatrixIndexT, Real> >::const_iterator
89  iter = pairs_.begin(), end = pairs_.end();
90  if (alpha == 1.0) { // treat alpha==1.0 case specially.
91  for (; iter != end; ++iter)
92  other_data[iter->first] += iter->second;
93  } else {
94  for (; iter != end; ++iter)
95  other_data[iter->first] += alpha * iter->second;
96  }
97 }
98 
99 template
100 void SparseVector<float>::AddToVec(float alpha, VectorBase<float> *vec) const;
101 template
102 void SparseVector<float>::AddToVec(float alpha, VectorBase<double> *vec) const;
103 template
104 void SparseVector<double>::AddToVec(double alpha, VectorBase<float> *vec) const;
105 template
106 void SparseVector<double>::AddToVec(double alpha,
107  VectorBase<double> *vec) const;
108 
109 template <typename Real>
110 template <typename OtherReal>
112  dim_ = other.Dim();
113  pairs_.clear();
114  if (dim_ == 0) return;
115  for (int32 i = 0; i < other.NumElements(); ++i) {
116  pairs_.push_back(std::make_pair(
117  other.GetElement(i).first,
118  static_cast<Real>(other.GetElement(i).second)));
119  }
120 }
121 template
123 template
125 template
127 template
129 
130 
131 template <typename Real>
133  const SparseVector<Real> &other) {
134  this->CopyFromSvec(other);
135  dim_ = other.dim_;
136  pairs_ = other.pairs_;
137  return *this;
138 }
139 
140 template <typename Real>
142  pairs_.swap(other->pairs_);
143  std::swap(dim_, other->dim_);
144 }
145 
146 template <typename Real>
147 void SparseVector<Real>::Write(std::ostream &os, bool binary) const {
148  if (binary) {
149  WriteToken(os, binary, "SV");
150  WriteBasicType(os, binary, dim_);
151  MatrixIndexT num_elems = pairs_.size();
152  WriteBasicType(os, binary, num_elems);
153  typename std::vector<std::pair<MatrixIndexT, Real> >::const_iterator
154  iter = pairs_.begin(), end = pairs_.end();
155  for (; iter != end; ++iter) {
156  WriteBasicType(os, binary, iter->first);
157  WriteBasicType(os, binary, iter->second);
158  }
159  } else {
160  // In text-mode, use a human-friendly, script-friendly format;
161  // format is "dim=5 [ 0 0.2 3 0.9 ] "
162  os << "dim=" << dim_ << " [ ";
163  typename std::vector<std::pair<MatrixIndexT, Real> >::const_iterator
164  iter = pairs_.begin(), end = pairs_.end();
165  for (; iter != end; ++iter)
166  os << iter->first << ' ' << iter->second << ' ';
167  os << "] ";
168  }
169 }
170 
171 
172 template <typename Real>
173 void SparseVector<Real>::Read(std::istream &is, bool binary) {
174  if (binary) {
175  ExpectToken(is, binary, "SV");
176  ReadBasicType(is, binary, &dim_);
177  KALDI_ASSERT(dim_ >= 0);
178  int32 num_elems;
179  ReadBasicType(is, binary, &num_elems);
180  KALDI_ASSERT(num_elems >= 0 && num_elems <= dim_);
181  pairs_.resize(num_elems);
182  typename std::vector<std::pair<MatrixIndexT, Real> >::iterator
183  iter = pairs_.begin(), end = pairs_.end();
184  for (; iter != end; ++iter) {
185  ReadBasicType(is, binary, &(iter->first));
186  ReadBasicType(is, binary, &(iter->second));
187  }
188  } else {
189  // In text-mode, format is "dim=5 [ 0 0.2 3 0.9 ]
190  std::string str;
191  is >> str;
192  if (str.substr(0, 4) != "dim=")
193  KALDI_ERR << "Reading sparse vector, expected 'dim=xxx', got " << str;
194  std::string dim_str = str.substr(4, std::string::npos);
195  std::istringstream dim_istr(dim_str);
196  int32 dim = -1;
197  dim_istr >> dim;
198  if (dim < 0 || dim_istr.fail()) {
199  KALDI_ERR << "Reading sparse vector, expected 'dim=[int]', got " << str;
200  }
201  dim_ = dim;
202  is >> std::ws;
203  is >> str;
204  if (str != "[")
205  KALDI_ERR << "Reading sparse vector, expected '[', got " << str;
206  pairs_.clear();
207  while (1) {
208  is >> std::ws;
209  if (is.peek() == ']') {
210  is.get();
211  break;
212  }
213  MatrixIndexT i;
214  BaseFloat p;
215  is >> i >> p;
216  if (is.fail())
217  KALDI_ERR << "Error reading sparse vector, expecting numbers.";
218  KALDI_ASSERT(i >= 0 && i < dim
219  && (pairs_.empty() || i > pairs_.back().first));
220  pairs_.push_back(std::pair<MatrixIndexT, BaseFloat>(i, p));
221  }
222  }
223 }
224 
225 
226 namespace sparse_vector_utils {
227 template <typename Real>
228 struct CompareFirst {
229  inline bool operator() (const std::pair<MatrixIndexT, Real> &p1,
230  const std::pair<MatrixIndexT, Real> &p2) const {
231  return p1.first < p2.first;
232  }
233 };
234 }
235 
236 template <typename Real>
238  MatrixIndexT dim, const std::vector<std::pair<MatrixIndexT, Real> > &pairs):
239  dim_(dim),
240  pairs_(pairs) {
241  std::sort(pairs_.begin(), pairs_.end(),
243  typename std::vector<std::pair<MatrixIndexT, Real> >::iterator
244  out = pairs_.begin(), in = out, end = pairs_.end();
245  // special case: while there is nothing to be changed, skip over
246  // initial input (avoids unnecessary copying).
247  while (in + 1 < end && in[0].first != in[1].first && in[0].second != 0.0) {
248  in++;
249  out++;
250  }
251  while (in < end) {
252  // We reach this point only at the first element of
253  // each stretch of identical .first elements.
254  *out = *in;
255  ++in;
256  while (in < end && in->first == out->first) {
257  out->second += in->second; // this is the merge operation.
258  ++in;
259  }
260  if (out->second != Real(0.0)) // Don't keep zero elements.
261  out++;
262  }
263  pairs_.erase(out, end);
264  if (!pairs_.empty()) {
265  // range check.
266  KALDI_ASSERT(pairs_.front().first >= 0 && pairs_.back().first < dim_);
267  }
268 }
269 
270 template <typename Real>
272  pairs_.clear();
273  KALDI_ASSERT(zero_prob >= 0 && zero_prob <= 1.0);
274  for (MatrixIndexT i = 0; i < dim_; i++)
275  if (WithProb(1.0 - zero_prob))
276  pairs_.push_back(std::pair<MatrixIndexT, Real>(i, RandGauss()));
277 }
278 
279 template <typename Real>
281  MatrixResizeType resize_type) {
282  if (resize_type != kCopyData || dim == 0)
283  pairs_.clear();
284  KALDI_ASSERT(dim >= 0);
285  if (dim < dim_ && resize_type == kCopyData)
286  while (!pairs_.empty() && pairs_.back().first >= dim)
287  pairs_.pop_back();
288  dim_ = dim;
289 }
290 
291 template <typename Real>
293  return rows_.size();
294 }
295 
296 template <typename Real>
298  if (rows_.empty())
299  return 0.0;
300  else
301  return rows_[0].Dim();
302 }
303 
304 template <typename Real>
306  int32 num_elements = 0;
307  for (int32 i = 0; i < rows_.size(); ++i) {
308  num_elements += rows_[i].NumElements();
309  }
310  return num_elements;
311 }
312 
313 template <typename Real>
315  if (rows_.empty())
316  return NULL;
317  else
318  return rows_.data();
319 }
320 
321 template <typename Real>
323  if (rows_.empty())
324  return NULL;
325  else
326  return rows_.data();
327 }
328 
329 template <typename Real>
331  Real sum = 0;
332  for (int32 i = 0; i < rows_.size(); ++i) {
333  sum += rows_[i].Sum();
334  }
335  return sum;
336 }
337 
338 template<typename Real>
340  Real squared_sum = 0;
341  for (int32 i = 0; i < rows_.size(); ++i) {
342  const std::pair<MatrixIndexT, Real> *row_data = rows_[i].Data();
343  for (int32 j = 0; j < rows_[i].NumElements(); ++j) {
344  squared_sum += row_data[j].second * row_data[j].second;
345  }
346  }
347  return std::sqrt(squared_sum);
348 }
349 
350 template <typename Real>
351 template <typename OtherReal>
353  MatrixTransposeType trans) const {
354  if (trans == kNoTrans) {
355  MatrixIndexT num_rows = rows_.size();
356  KALDI_ASSERT(other->NumRows() == num_rows);
357  for (MatrixIndexT i = 0; i < num_rows; i++) {
358  SubVector<OtherReal> vec(*other, i);
359  rows_[i].CopyElementsToVec(&vec);
360  }
361  } else {
362  OtherReal *other_col_data = other->Data();
363  MatrixIndexT other_stride = other->Stride(),
364  num_rows = NumRows(), num_cols = NumCols();
365  KALDI_ASSERT(num_rows == other->NumCols() && num_cols == other->NumRows());
366  other->SetZero();
367  for (MatrixIndexT row = 0; row < num_rows; row++, other_col_data++) {
368  const SparseVector<Real> &svec = rows_[row];
369  MatrixIndexT num_elems = svec.NumElements();
370  const std::pair<MatrixIndexT, Real> *sdata = svec.Data();
371  for (MatrixIndexT e = 0; e < num_elems; e++)
372  other_col_data[sdata[e].first * other_stride] = sdata[e].second;
373  }
374  }
375 }
376 
377 template
379  MatrixTransposeType trans) const;
380 template
382  MatrixTransposeType trans) const;
383 template
385  MatrixTransposeType trans) const;
386 template
388  MatrixTransposeType trans) const;
389 
390 template <typename Real>
392  KALDI_ASSERT(other->Dim() == NumElements());
393  Real *dst_data = other->Data();
394  int32 dst_index = 0;
395  for (int32 i = 0; i < rows_.size(); ++i) {
396  for (int32 j = 0; j < rows_[i].NumElements(); ++j) {
397  dst_data[dst_index] =
398  static_cast<Real>(rows_[i].GetElement(j).second);
399  dst_index++;
400  }
401  }
402 }
403 
404 template<typename Real>
405 template<typename OtherReal>
407  MatrixTransposeType trans) {
408  if (trans == kNoTrans) {
409  rows_.resize(other.NumRows());
410  if (rows_.size() == 0)
411  return;
412  for (int32 r = 0; r < rows_.size(); ++r) {
413  rows_[r].CopyFromSvec(other.Row(r));
414  }
415  } else {
416  std::vector<std::vector<std::pair<MatrixIndexT, Real> > > pairs(
417  other.NumCols());
418  for (MatrixIndexT i = 0; i < other.NumRows(); ++i) {
419  for (int id = 0; id < other.Row(i).NumElements(); ++id) {
420  MatrixIndexT j = other.Row(i).GetElement(id).first;
421  Real v = static_cast<Real>(other.Row(i).GetElement(id).second);
422  pairs[j].push_back( { i, v });
423  }
424  }
425  SparseMatrix<Real> temp(other.NumRows(), pairs);
426  Swap(&temp);
427  }
428 }
429 template
431  MatrixTransposeType trans);
432 template
434  MatrixTransposeType trans);
435 template
437  MatrixTransposeType trans);
438 template
440  MatrixTransposeType trans);
441 
442 template <typename Real>
443 void SparseMatrix<Real>::Write(std::ostream &os, bool binary) const {
444  if (binary) {
445  // Note: we can use the same marker for float and double SparseMatrix,
446  // because internally we use WriteBasicType and ReadBasicType to read the
447  // floats and doubles, and this will automatically take care of type
448  // conversion.
449  WriteToken(os, binary, "SM");
450  int32 num_rows = rows_.size();
451  WriteBasicType(os, binary, num_rows);
452  for (int32 row = 0; row < num_rows; row++)
453  rows_[row].Write(os, binary);
454  } else {
455  // The format is "rows=10 dim=20 [ 1 0.4 9 1.2 ] dim=20 [ 3 1.7 19 0.6 ] ..
456  // not 100% efficient, but easy to work with, and we can re-use the
457  // read/write code from SparseVector.
458  int32 num_rows = rows_.size();
459  os << "rows=" << num_rows << " ";
460  for (int32 row = 0; row < num_rows; row++)
461  rows_[row].Write(os, binary);
462  os << "\n"; // Might make it a little more readable.
463  }
464 }
465 
466 template <typename Real>
467 void SparseMatrix<Real>::Read(std::istream &is, bool binary) {
468  if (binary) {
469  ExpectToken(is, binary, "SM");
470  int32 num_rows;
471  ReadBasicType(is, binary, &num_rows);
472  KALDI_ASSERT(num_rows >= 0 && num_rows < 10000000);
473  rows_.resize(num_rows);
474  for (int32 row = 0; row < num_rows; row++)
475  rows_[row].Read(is, binary);
476  } else {
477  std::string str;
478  is >> str;
479  if (str.substr(0, 5) != "rows=")
480  KALDI_ERR << "Reading sparse matrix, expected 'rows=xxx', got " << str;
481  std::string rows_str = str.substr(5, std::string::npos);
482  std::istringstream rows_istr(rows_str);
483  int32 num_rows = -1;
484  rows_istr >> num_rows;
485  if (num_rows < 0 || rows_istr.fail()) {
486  KALDI_ERR << "Reading sparse vector, expected 'rows=[int]', got " << str;
487  }
488  rows_.resize(num_rows);
489  for (int32 row = 0; row < num_rows; row++)
490  rows_[row].Read(is, binary);
491  }
492 }
493 
494 
495 template <typename Real>
497  MatrixBase<Real> *other,
498  MatrixTransposeType trans) const {
499  if (trans == kNoTrans) {
500  MatrixIndexT num_rows = rows_.size();
501  KALDI_ASSERT(other->NumRows() == num_rows);
502  for (MatrixIndexT i = 0; i < num_rows; i++) {
503  SubVector<Real> vec(*other, i);
504  rows_[i].AddToVec(alpha, &vec);
505  }
506  } else {
507  Real *other_col_data = other->Data();
508  MatrixIndexT other_stride = other->Stride(),
509  num_rows = NumRows(), num_cols = NumCols();
510  KALDI_ASSERT(num_rows == other->NumCols() && num_cols == other->NumRows());
511  for (MatrixIndexT row = 0; row < num_rows; row++, other_col_data++) {
512  const SparseVector<Real> &svec = rows_[row];
513  MatrixIndexT num_elems = svec.NumElements();
514  const std::pair<MatrixIndexT, Real> *sdata = svec.Data();
515  for (MatrixIndexT e = 0; e < num_elems; e++)
516  other_col_data[sdata[e].first * other_stride] +=
517  alpha * sdata[e].second;
518  }
519  }
520 }
521 
522 template <typename Real>
523 Real VecSvec(const VectorBase<Real> &vec,
524  const SparseVector<Real> &svec) {
525  KALDI_ASSERT(vec.Dim() == svec.Dim());
526  MatrixIndexT n = svec.NumElements();
527  const std::pair<MatrixIndexT, Real> *sdata = svec.Data();
528  const Real *data = vec.Data();
529  Real ans = 0.0;
530  for (MatrixIndexT i = 0; i < n; i++)
531  ans += data[sdata[i].first] * sdata[i].second;
532  return ans;
533 }
534 
535 template
536 float VecSvec(const VectorBase<float> &vec,
537  const SparseVector<float> &svec);
538 template
539 double VecSvec(const VectorBase<double> &vec,
540  const SparseVector<double> &svec);
541 
542 template <typename Real>
544  KALDI_ASSERT(static_cast<size_t>(r) < rows_.size());
545  return rows_[r];
546 }
547 
548 template <typename Real>
550  KALDI_ASSERT(static_cast<size_t>(r) < rows_.size() &&
551  vec.Dim() == rows_[0].Dim());
552  rows_[r] = vec;
553 }
554 
555 
556 template<typename Real>
557 void SparseMatrix<Real>::SelectRows(const std::vector<int32> &row_indexes,
558  const SparseMatrix<Real> &smat_other) {
559  Resize(row_indexes.size(), smat_other.NumCols());
560  for (int i = 0; i < row_indexes.size(); ++i) {
561  SetRow(i, smat_other.Row(row_indexes[i]));
562  }
563 }
564 
565 template<typename Real>
566 SparseMatrix<Real>::SparseMatrix(const std::vector<int32> &indexes, int32 dim,
567  MatrixTransposeType trans) {
568  const std::vector<int32>& idx = indexes;
569  std::vector<std::vector<std::pair<MatrixIndexT, Real> > > pair(idx.size());
570  for (int i = 0; i < idx.size(); ++i) {
571  if (idx[i] >= 0) {
572  pair[i].push_back( { idx[i], Real(1) });
573  }
574  }
575  SparseMatrix<Real> smat_cpu(dim, pair);
576  if (trans == kNoTrans) {
577  this->Swap(&smat_cpu);
578  } else {
579  SparseMatrix<Real> tmp(smat_cpu, kTrans);
580  this->Swap(&tmp);
581  }
582 }
583 
584 template<typename Real>
585 SparseMatrix<Real>::SparseMatrix(const std::vector<int32> &indexes,
586  const VectorBase<Real> &weights, int32 dim,
587  MatrixTransposeType trans) {
588  const std::vector<int32>& idx = indexes;
589  const VectorBase<Real>& w = weights;
590  std::vector<std::vector<std::pair<MatrixIndexT, Real> > > pair(idx.size());
591  for (int i = 0; i < idx.size(); ++i) {
592  if (idx[i] >= 0) {
593  pair[i].push_back( { idx[i], w(i) });
594  }
595  }
596  SparseMatrix<Real> smat_cpu(dim, pair);
597  if (trans == kNoTrans) {
598  this->Swap(&smat_cpu);
599  } else {
600  SparseMatrix<Real> tmp(smat_cpu, kTrans);
601  this->Swap(&tmp);
602  }
603 }
604 
605 template <typename Real>
607  const SparseMatrix<Real> &other) {
608  rows_ = other.rows_;
609  return *this;
610 }
611 
612 template <typename Real>
614  rows_.swap(other->rows_);
615 }
616 
617 template<typename Real>
619  MatrixIndexT dim,
620  const std::vector<std::vector<std::pair<MatrixIndexT, Real> > > &pairs):
621  rows_(pairs.size()) {
622  MatrixIndexT num_rows = pairs.size();
623  for (MatrixIndexT row = 0; row < num_rows; row++) {
624  SparseVector<Real> svec(dim, pairs[row]);
625  rows_[row].Swap(&svec);
626  }
627 }
628 
629 template <typename Real>
631  MatrixIndexT num_rows = rows_.size();
632  for (MatrixIndexT row = 0; row < num_rows; row++)
633  rows_[row].SetRandn(zero_prob);
634 }
635 
636 template <typename Real>
638  MatrixIndexT num_cols,
639  MatrixResizeType resize_type) {
640  KALDI_ASSERT(num_rows >= 0 && num_cols >= 0);
641  if (resize_type == kSetZero || resize_type == kUndefined) {
642  rows_.clear();
643  Resize(num_rows, num_cols, kCopyData);
644  } else {
645  // Assume resize_type == kCopyData from here.
646  int32 old_num_rows = rows_.size(), old_num_cols = NumCols();
647  SparseVector<Real> initializer(num_cols);
648  rows_.resize(num_rows, initializer);
649  if (num_cols != old_num_cols)
650  for (int32 row = 0; row < old_num_rows; row++)
651  rows_[row].Resize(num_cols, kCopyData);
652  }
653 }
654 
655 template <typename Real>
657  std::vector<SparseMatrix<Real> > *inputs) {
658  rows_.clear();
659  size_t num_rows = 0;
660  typename std::vector<SparseMatrix<Real> >::iterator
661  input_iter = inputs->begin(),
662  input_end = inputs->end();
663  for (; input_iter != input_end; ++input_iter)
664  num_rows += input_iter->rows_.size();
665  rows_.resize(num_rows);
666  typename std::vector<SparseVector<Real> >::iterator
667  row_iter = rows_.begin(),
668  row_end = rows_.end();
669  for (input_iter = inputs->begin(); input_iter != input_end; ++input_iter) {
670  typename std::vector<SparseVector<Real> >::iterator
671  input_row_iter = input_iter->rows_.begin(),
672  input_row_end = input_iter->rows_.end();
673  for (; input_row_iter != input_row_end; ++input_row_iter, ++row_iter)
674  row_iter->Swap(&(*input_row_iter));
675  }
676  KALDI_ASSERT(row_iter == row_end);
677  int32 num_cols = NumCols();
678  for (row_iter = rows_.begin(); row_iter != row_end; ++row_iter) {
679  if (row_iter->Dim() != num_cols)
680  KALDI_ERR << "Appending rows with inconsistent dimensions, "
681  << row_iter->Dim() << " vs. " << num_cols;
682  }
683  inputs->clear();
684 }
685 
686 template<typename Real>
687 void SparseMatrix<Real>::Scale(Real alpha) {
688  MatrixIndexT num_rows = rows_.size();
689  for (MatrixIndexT row = 0; row < num_rows; row++)
690  rows_[row].Scale(alpha);
691 }
692 
693 template<typename Real>
695  MatrixIndexT num_rows = mat.NumRows();
696  rows_.resize(num_rows);
697  for (int32 row = 0; row < num_rows; row++) {
698  SparseVector<Real> this_row(mat.Row(row));
699  rows_[row].Swap(&this_row);
700  }
701 }
702 
703 template<typename Real>
705  const SparseMatrix<Real> &B,
706  MatrixTransposeType trans) {
707  Real sum = 0.0;
708  if (trans == kTrans) {
709  MatrixIndexT num_rows = A.NumRows();
710  KALDI_ASSERT(B.NumRows() == num_rows);
711  for (MatrixIndexT r = 0; r < num_rows; r++)
712  sum += VecSvec(A.Row(r), B.Row(r));
713  } else {
714  const Real *A_col_data = A.Data();
715  MatrixIndexT Astride = A.Stride(), Acols = A.NumCols(), Arows = A.NumRows();
716  KALDI_ASSERT(Arows == B.NumCols() && Acols == B.NumRows());
717  sum = 0.0;
718  for (MatrixIndexT i = 0; i < Acols; i++, A_col_data++) {
719  Real col_sum = 0.0;
720  const SparseVector<Real> &svec = B.Row(i);
721  MatrixIndexT num_elems = svec.NumElements();
722  const std::pair<MatrixIndexT, Real> *sdata = svec.Data();
723  for (MatrixIndexT e = 0; e < num_elems; e++)
724  col_sum += A_col_data[Astride * sdata[e].first] * sdata[e].second;
725  sum += col_sum;
726  }
727  }
728  return sum;
729 }
730 
731 template
732 float TraceMatSmat(const MatrixBase<float> &A,
733  const SparseMatrix<float> &B,
734  MatrixTransposeType trans);
735 template
736 double TraceMatSmat(const MatrixBase<double> &A,
737  const SparseMatrix<double> &B,
738  MatrixTransposeType trans);
739 
740 void GeneralMatrix::Clear() {
741  mat_.Resize(0, 0);
742  cmat_.Clear();
743  smat_.Resize(0, 0);
744 }
745 
746 GeneralMatrix& GeneralMatrix::operator= (const MatrixBase<BaseFloat> &mat) {
747  Clear();
748  mat_ = mat;
749  return *this;
750 }
751 
752 GeneralMatrix& GeneralMatrix::operator= (const CompressedMatrix &cmat) {
753  Clear();
754  cmat_ = cmat;
755  return *this;
756 }
757 
758 GeneralMatrix& GeneralMatrix::operator= (const SparseMatrix<BaseFloat> &smat) {
759  Clear();
760  smat_ = smat;
761  return *this;
762 }
763 
764 GeneralMatrix& GeneralMatrix::operator= (const GeneralMatrix &gmat) {
765  mat_ = gmat.mat_;
766  smat_ = gmat.smat_;
767  cmat_ = gmat.cmat_;
768  return *this;
769 }
770 
771 
772 GeneralMatrixType GeneralMatrix::Type() const {
773  if (smat_.NumRows() != 0)
774  return kSparseMatrix;
775  else if (cmat_.NumRows() != 0)
776  return kCompressedMatrix;
777  else
778  return kFullMatrix;
779 }
780 
781 MatrixIndexT GeneralMatrix::NumRows() const {
782  MatrixIndexT r = smat_.NumRows();
783  if (r != 0)
784  return r;
785  r = cmat_.NumRows();
786  if (r != 0)
787  return r;
788  return mat_.NumRows();
789 }
790 
791 MatrixIndexT GeneralMatrix::NumCols() const {
792  MatrixIndexT r = smat_.NumCols();
793  if (r != 0)
794  return r;
795  r = cmat_.NumCols();
796  if (r != 0)
797  return r;
798  return mat_.NumCols();
799 }
800 
801 
802 void GeneralMatrix::Compress() {
803  if (mat_.NumRows() != 0) {
804  cmat_.CopyFromMat(mat_);
805  mat_.Resize(0, 0);
806  }
807 }
808 
809 void GeneralMatrix::Uncompress() {
810  if (cmat_.NumRows() != 0) {
811  mat_.Resize(cmat_.NumRows(), cmat_.NumCols(), kUndefined);
812  cmat_.CopyToMat(&mat_);
813  cmat_.Clear();
814  }
815 }
816 
817 void GeneralMatrix::GetMatrix(Matrix<BaseFloat> *mat) const {
818  if (mat_.NumRows() !=0) {
819  *mat = mat_;
820  } else if (cmat_.NumRows() != 0) {
821  mat->Resize(cmat_.NumRows(), cmat_.NumCols(), kUndefined);
822  cmat_.CopyToMat(mat);
823  } else if (smat_.NumRows() != 0) {
824  mat->Resize(smat_.NumRows(), smat_.NumCols(), kUndefined);
825  smat_.CopyToMat(mat);
826  } else {
827  mat->Resize(0, 0);
828  }
829 }
830 
831 void GeneralMatrix::CopyToMat(MatrixBase<BaseFloat> *mat,
832  MatrixTransposeType trans) const {
833  if (mat_.NumRows() !=0) {
834  mat->CopyFromMat(mat_, trans);
835  } else if (cmat_.NumRows() != 0) {
836  cmat_.CopyToMat(mat, trans);
837  } else if (smat_.NumRows() != 0) {
838  smat_.CopyToMat(mat, trans);
839  } else {
840  KALDI_ASSERT(mat->NumRows() == 0);
841  }
842 }
843 
844 void GeneralMatrix::Scale(BaseFloat alpha) {
845  if (mat_.NumRows() != 0) {
846  mat_.Scale(alpha);
847  } else if (cmat_.NumRows() != 0) {
848  cmat_.Scale(alpha);
849  } else if (smat_.NumRows() != 0) {
850  smat_.Scale(alpha);
851  }
852 
853 }
854 const SparseMatrix<BaseFloat>& GeneralMatrix::GetSparseMatrix() const {
855  if (mat_.NumRows() != 0 || cmat_.NumRows() != 0)
856  KALDI_ERR << "GetSparseMatrix called on GeneralMatrix of wrong type.";
857  return smat_;
858 }
859 
860 void GeneralMatrix::SwapSparseMatrix(SparseMatrix<BaseFloat> *smat) {
861  if (mat_.NumRows() != 0 || cmat_.NumRows() != 0)
862  KALDI_ERR << "GetSparseMatrix called on GeneralMatrix of wrong type.";
863  smat->Swap(&smat_);
864 }
865 
866 void GeneralMatrix::SwapCompressedMatrix(CompressedMatrix *cmat) {
867  if (mat_.NumRows() != 0 || smat_.NumRows() != 0)
868  KALDI_ERR << "GetSparseMatrix called on GeneralMatrix of wrong type.";
869  cmat->Swap(&cmat_);
870 }
871 
872 const CompressedMatrix &GeneralMatrix::GetCompressedMatrix() const {
873  if (mat_.NumRows() != 0 || smat_.NumRows() != 0)
874  KALDI_ERR << "GetCompressedMatrix called on GeneralMatrix of wrong type.";
875  return cmat_;
876 }
877 
878 const Matrix<BaseFloat> &GeneralMatrix::GetFullMatrix() const {
879  if (smat_.NumRows() != 0 || cmat_.NumRows() != 0)
880  KALDI_ERR << "GetFullMatrix called on GeneralMatrix of wrong type.";
881  return mat_;
882 }
883 
884 
885 void GeneralMatrix::SwapFullMatrix(Matrix<BaseFloat> *mat) {
886  if (cmat_.NumRows() != 0 || smat_.NumRows() != 0)
887  KALDI_ERR << "SwapMatrix called on GeneralMatrix of wrong type.";
888  mat->Swap(&mat_);
889 }
890 
891 void GeneralMatrix::Write(std::ostream &os, bool binary) const {
892  if (smat_.NumRows() != 0) {
893  smat_.Write(os, binary);
894  } else if (cmat_.NumRows() != 0) {
895  cmat_.Write(os, binary);
896  } else {
897  mat_.Write(os, binary);
898  }
899 }
900 
901 void GeneralMatrix::Read(std::istream &is, bool binary) {
902  Clear();
903  if (binary) {
904  int peekval = is.peek();
905  if (peekval == 'C') {
906  // Token CM for compressed matrix
907  cmat_.Read(is, binary);
908  } else if (peekval == 'S') {
909  // Token SM for sparse matrix
910  smat_.Read(is, binary);
911  } else {
912  mat_.Read(is, binary);
913  }
914  } else {
915  // note: in text mode we will only ever read regular
916  // or sparse matrices, because the compressed-matrix format just
917  // gets written as a regular matrix in text mode.
918  is >> std::ws; // Eat up white space.
919  int peekval = is.peek();
920  if (peekval == 'r') { // sparse format starts rows=[int].
921  smat_.Read(is, binary);
922  } else {
923  mat_.Read(is, binary);
924  }
925  }
926 }
927 
928 
929 void AppendGeneralMatrixRows(const std::vector<const GeneralMatrix *> &src,
930  GeneralMatrix *mat) {
931  mat->Clear();
932  int32 size = src.size();
933  if (size == 0)
934  return;
935  bool all_sparse = true;
936  for (int32 i = 0; i < size; i++) {
937  if (src[i]->Type() != kSparseMatrix && src[i]->NumRows() != 0) {
938  all_sparse = false;
939  break;
940  }
941  }
942  if (all_sparse) {
943  std::vector<SparseMatrix<BaseFloat> > sparse_mats(size);
944  for (int32 i = 0; i < size; i++)
945  sparse_mats[i] = src[i]->GetSparseMatrix();
946  SparseMatrix<BaseFloat> appended_mat;
947  appended_mat.AppendSparseMatrixRows(&sparse_mats);
948  mat->SwapSparseMatrix(&appended_mat);
949  } else {
950  int32 tot_rows = 0, num_cols = -1;
951  for (int32 i = 0; i < size; i++) {
952  const GeneralMatrix &src_mat = *(src[i]);
953  int32 src_rows = src_mat.NumRows(), src_cols = src_mat.NumCols();
954  if (src_rows != 0) {
955  tot_rows += src_rows;
956  if (num_cols == -1) num_cols = src_cols;
957  else if (num_cols != src_cols)
958  KALDI_ERR << "Appending rows of matrices with inconsistent num-cols: "
959  << num_cols << " vs. " << src_cols;
960  }
961  }
962  Matrix<BaseFloat> appended_mat(tot_rows, num_cols, kUndefined);
963  int32 row_offset = 0;
964  for (int32 i = 0; i < size; i++) {
965  const GeneralMatrix &src_mat = *(src[i]);
966  int32 src_rows = src_mat.NumRows();
967  if (src_rows != 0) {
968  SubMatrix<BaseFloat> dest_submat(appended_mat, row_offset, src_rows,
969  0, num_cols);
970  src_mat.CopyToMat(&dest_submat);
971  row_offset += src_rows;
972  }
973  }
974  KALDI_ASSERT(row_offset == tot_rows);
975  mat->SwapFullMatrix(&appended_mat);
976  }
977 }
978 
980  const std::vector<bool> &keep_rows,
981  Matrix<BaseFloat> *out) {
982  KALDI_ASSERT(keep_rows.size() == static_cast<size_t>(in.NumRows()));
983  int32 num_kept_rows = 0;
984  std::vector<bool>::const_iterator iter = keep_rows.begin(),
985  end = keep_rows.end();
986  for (; iter != end; ++iter)
987  if (*iter)
988  num_kept_rows++;
989  if (num_kept_rows == 0)
990  KALDI_ERR << "No kept rows";
991  if (num_kept_rows == static_cast<int32>(keep_rows.size())) {
992  out->Resize(in.NumRows(), in.NumCols(), kUndefined);
993  in.CopyToMat(out);
994  return;
995  }
996  const BaseFloat heuristic = 0.33;
997  // should be > 0 and < 1.0. represents the performance hit we get from
998  // iterating row-wise versus column-wise in compressed-matrix uncompression.
999 
1000  if (num_kept_rows > heuristic * in.NumRows()) {
1001  // if quite a few of the the rows are kept, it may be more efficient
1002  // to uncompress the entire compressed matrix, since per-column operation
1003  // is more efficient.
1004  Matrix<BaseFloat> full_mat(in);
1005  FilterMatrixRows(full_mat, keep_rows, out);
1006  } else {
1007  out->Resize(num_kept_rows, in.NumCols(), kUndefined);
1008 
1009  iter = keep_rows.begin();
1010  int32 out_row = 0;
1011  for (int32 in_row = 0; iter != end; ++iter, ++in_row) {
1012  if (*iter) {
1013  SubVector<BaseFloat> dest(*out, out_row);
1014  in.CopyRowToVec(in_row, &dest);
1015  out_row++;
1016  }
1017  }
1018  KALDI_ASSERT(out_row == num_kept_rows);
1019  }
1020 }
1021 
1022 template <typename Real>
1024  const std::vector<bool> &keep_rows,
1025  Matrix<Real> *out) {
1026  KALDI_ASSERT(keep_rows.size() == static_cast<size_t>(in.NumRows()));
1027  int32 num_kept_rows = 0;
1028  std::vector<bool>::const_iterator iter = keep_rows.begin(),
1029  end = keep_rows.end();
1030  for (; iter != end; ++iter)
1031  if (*iter)
1032  num_kept_rows++;
1033  if (num_kept_rows == 0)
1034  KALDI_ERR << "No kept rows";
1035  if (num_kept_rows == static_cast<int32>(keep_rows.size())) {
1036  *out = in;
1037  return;
1038  }
1039  out->Resize(num_kept_rows, in.NumCols(), kUndefined);
1040  iter = keep_rows.begin();
1041  int32 out_row = 0;
1042  for (int32 in_row = 0; iter != end; ++iter, ++in_row) {
1043  if (*iter) {
1044  SubVector<Real> src(in, in_row);
1045  SubVector<Real> dest(*out, out_row);
1046  dest.CopyFromVec(src);
1047  out_row++;
1048  }
1049  }
1050  KALDI_ASSERT(out_row == num_kept_rows);
1051 }
1052 
1053 template
1054 void FilterMatrixRows(const Matrix<float> &in,
1055  const std::vector<bool> &keep_rows,
1056  Matrix<float> *out);
1057 template
1058 void FilterMatrixRows(const Matrix<double> &in,
1059  const std::vector<bool> &keep_rows,
1060  Matrix<double> *out);
1061 
1062 template <typename Real>
1064  const std::vector<bool> &keep_rows,
1065  SparseMatrix<Real> *out) {
1066  KALDI_ASSERT(keep_rows.size() == static_cast<size_t>(in.NumRows()));
1067  int32 num_kept_rows = 0;
1068  std::vector<bool>::const_iterator iter = keep_rows.begin(),
1069  end = keep_rows.end();
1070  for (; iter != end; ++iter)
1071  if (*iter)
1072  num_kept_rows++;
1073  if (num_kept_rows == 0)
1074  KALDI_ERR << "No kept rows";
1075  if (num_kept_rows == static_cast<int32>(keep_rows.size())) {
1076  *out = in;
1077  return;
1078  }
1079  out->Resize(num_kept_rows, in.NumCols(), kUndefined);
1080  iter = keep_rows.begin();
1081  int32 out_row = 0;
1082  for (int32 in_row = 0; iter != end; ++iter, ++in_row) {
1083  if (*iter) {
1084  out->SetRow(out_row, in.Row(in_row));
1085  out_row++;
1086  }
1087  }
1088  KALDI_ASSERT(out_row == num_kept_rows);
1089 }
1090 
1091 template
1093  const std::vector<bool> &keep_rows,
1094  SparseMatrix<float> *out);
1095 template
1097  const std::vector<bool> &keep_rows,
1098  SparseMatrix<double> *out);
1099 
1100 
1102  const std::vector<bool> &keep_rows,
1103  GeneralMatrix *out) {
1104  out->Clear();
1105  KALDI_ASSERT(keep_rows.size() == static_cast<size_t>(in.NumRows()));
1106  int32 num_kept_rows = 0;
1107  std::vector<bool>::const_iterator iter = keep_rows.begin(),
1108  end = keep_rows.end();
1109  for (; iter != end; ++iter)
1110  if (*iter)
1111  num_kept_rows++;
1112  if (num_kept_rows == 0)
1113  KALDI_ERR << "No kept rows";
1114  if (num_kept_rows == static_cast<int32>(keep_rows.size())) {
1115  *out = in;
1116  return;
1117  }
1118  switch (in.Type()) {
1119  case kCompressedMatrix: {
1120  const CompressedMatrix &cmat = in.GetCompressedMatrix();
1121  Matrix<BaseFloat> full_mat;
1122  FilterCompressedMatrixRows(cmat, keep_rows, &full_mat);
1123  out->SwapFullMatrix(&full_mat);
1124  return;
1125  }
1126  case kSparseMatrix: {
1127  const SparseMatrix<BaseFloat> &smat = in.GetSparseMatrix();
1128  SparseMatrix<BaseFloat> smat_out;
1129  FilterSparseMatrixRows(smat, keep_rows, &smat_out);
1130  out->SwapSparseMatrix(&smat_out);
1131  return;
1132  }
1133  case kFullMatrix: {
1134  const Matrix<BaseFloat> &full_mat = in.GetFullMatrix();
1135  Matrix<BaseFloat> full_mat_out;
1136  FilterMatrixRows(full_mat, keep_rows, &full_mat_out);
1137  out->SwapFullMatrix(&full_mat_out);
1138  return;
1139  }
1140  default:
1141  KALDI_ERR << "Invalid general-matrix type.";
1142  }
1143 }
1144 
1145 void GeneralMatrix::AddToMat(BaseFloat alpha, MatrixBase<BaseFloat> *mat,
1146  MatrixTransposeType trans) const {
1147  switch (this->Type()) {
1148  case kFullMatrix: {
1149  mat->AddMat(alpha, mat_, trans);
1150  break;
1151  }
1152  case kSparseMatrix: {
1153  smat_.AddToMat(alpha, mat, trans);
1154  break;
1155  }
1156  case kCompressedMatrix: {
1157  Matrix<BaseFloat> temp_mat(cmat_);
1158  mat->AddMat(alpha, temp_mat, trans);
1159  break;
1160  }
1161  default:
1162  KALDI_ERR << "Invalid general-matrix type.";
1163  }
1164 }
1165 
1166 template <class Real>
1167 Real SparseVector<Real>::Max(int32 *index_out) const {
1168  KALDI_ASSERT(dim_ > 0 && pairs_.size() <= static_cast<size_t>(dim_));
1169  Real ans = -std::numeric_limits<Real>::infinity();
1170  int32 index = 0;
1171  typename std::vector<std::pair<MatrixIndexT, Real> >::const_iterator
1172  iter = pairs_.begin(), end = pairs_.end();
1173  for (; iter != end; ++iter) {
1174  if (iter->second > ans) {
1175  ans = iter->second;
1176  index = iter->first;
1177  }
1178  }
1179  if (ans >= 0 || pairs_.size() == dim_) {
1180  // ans >= 0 will be the normal case.
1181  // if pairs_.size() == dim_ then we need to return
1182  // even a negative answer as there are no spaces (hence no unlisted zeros).
1183  *index_out = index;
1184  return ans;
1185  }
1186  // all the stored elements are < 0, but there are unlisted
1187  // elements -> pick the first unlisted element.
1188  // Note that this class requires that the indexes are sorted
1189  // and unique.
1190  index = 0; // "index" will always be the next index, that
1191  // we haven't seen listed yet.
1192  iter = pairs_.begin();
1193  for (; iter != end; ++iter) {
1194  if (iter->first > index) { // index "index" is not listed.
1195  *index_out = index;
1196  return 0.0;
1197  } else {
1198  // index is the next potential gap in the indexes.
1199  index = iter->first + 1;
1200  }
1201  }
1202  // we can reach here if either pairs_.empty(), or
1203  // pairs_ is nonempty but contains a sequence (0, 1, 2,...).
1204  if (!pairs_.empty())
1205  index = pairs_.back().first + 1;
1206  // else leave index at zero
1207  KALDI_ASSERT(index < dim_);
1208  *index_out = index;
1209  return 0.0;
1210 }
1211 
1212 template <typename Real>
1214  MatrixIndexT dim = vec.Dim();
1215  dim_ = dim;
1216  if (dim == 0)
1217  return;
1218  const Real *ptr = vec.Data();
1219  for (MatrixIndexT i = 0; i < dim; i++) {
1220  Real val = ptr[i];
1221  if (val != 0.0)
1222  pairs_.push_back(std::pair<MatrixIndexT,Real>(i,val));
1223  }
1224 }
1225 
1226 void GeneralMatrix::Swap(GeneralMatrix *other) {
1227  mat_.Swap(&(other->mat_));
1228  cmat_.Swap(&(other->cmat_));
1229  smat_.Swap(&(other->smat_));
1230 }
1231 
1232 
1234  const GeneralMatrix &in,
1235  int32 row_offset,
1236  int32 num_rows,
1237  GeneralMatrix *out) {
1238  // make sure 'out' is empty to start with.
1239  Matrix<BaseFloat> empty_mat;
1240  *out = empty_mat;
1241  if (num_rows == 0) return;
1242  switch (in.Type()) {
1243  case kFullMatrix: {
1244  const Matrix<BaseFloat> &mat_in = in.GetFullMatrix();
1245  int32 num_rows_in = mat_in.NumRows(), num_cols = mat_in.NumCols();
1246  KALDI_ASSERT(num_rows_in > 0); // we can't extract >0 rows from an empty
1247  // matrix.
1248  Matrix<BaseFloat> mat_out(num_rows, num_cols, kUndefined);
1249  for (int32 row = 0; row < num_rows; row++) {
1250  int32 row_in = row + row_offset;
1251  if (row_in < 0) row_in = 0;
1252  else if (row_in >= num_rows_in) row_in = num_rows_in - 1;
1253  SubVector<BaseFloat> vec_in(mat_in, row_in),
1254  vec_out(mat_out, row);
1255  vec_out.CopyFromVec(vec_in);
1256  }
1257  out->SwapFullMatrix(&mat_out);
1258  break;
1259  }
1260  case kSparseMatrix: {
1261  const SparseMatrix<BaseFloat> &smat_in = in.GetSparseMatrix();
1262  int32 num_rows_in = smat_in.NumRows(),
1263  num_cols = smat_in.NumCols();
1264  KALDI_ASSERT(num_rows_in > 0); // we can't extract >0 rows from an empty
1265  // matrix.
1266  SparseMatrix<BaseFloat> smat_out(num_rows, num_cols);
1267  for (int32 row = 0; row < num_rows; row++) {
1268  int32 row_in = row + row_offset;
1269  if (row_in < 0) row_in = 0;
1270  else if (row_in >= num_rows_in) row_in = num_rows_in - 1;
1271  smat_out.SetRow(row, smat_in.Row(row_in));
1272  }
1273  out->SwapSparseMatrix(&smat_out);
1274  break;
1275  }
1276  case kCompressedMatrix: {
1277  const CompressedMatrix &cmat_in = in.GetCompressedMatrix();
1278  bool allow_padding = true;
1279  CompressedMatrix cmat_out(cmat_in, row_offset, num_rows,
1280  0, cmat_in.NumCols(), allow_padding);
1281  out->SwapCompressedMatrix(&cmat_out);
1282  break;
1283  }
1284  default:
1285  KALDI_ERR << "Bad matrix type.";
1286  }
1287 }
1288 
1289 
1290 
1291 template class SparseVector<float>;
1292 template class SparseVector<double>;
1293 template class SparseMatrix<float>;
1294 template class SparseMatrix<double>;
1295 
1296 } // namespace kaldi
void CopyElementsToVec(VectorBase< OtherReal > *vec) const
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
This class provides a way for switching between double and float types.
Definition: matrix-common.h:84
void Scale(Real alpha)
Scale all elements of sparse vector.
This class is a wrapper that enables you to store a matrix in one of three forms: either as a Matrix<...
void SelectRows(const std::vector< int32 > &row_indexes, const SparseMatrix< Real > &smat_other)
Select a subset of the rows of a SparseMatrix.
MatrixResizeType
Definition: matrix-common.h:37
void CopyRowToVec(MatrixIndexT row, VectorBase< Real > *v) const
Copies row #row of the matrix into vector v.
CompressedMatrix cmat_
SparseVector< Real > & operator=(const SparseVector< Real > &other)
void SetRandn(BaseFloat zero_prob)
Sets elements to zero with probability zero_prob, else normally distributed.
void Swap(CompressedMatrix *other)
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Definition: kaldi-matrix.h:67
Base class which provides matrix operations not involving resizing or allocation. ...
Definition: kaldi-matrix.h:49
void Read(std::istream &os, bool binary)
const Real * Data() const
Gives pointer to raw data (const).
Definition: kaldi-matrix.h:79
void ReadBasicType(std::istream &is, bool binary, T *t)
ReadBasicType is the name of the read function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:55
bool operator()(const std::pair< MatrixIndexT, Real > &p1, const std::pair< MatrixIndexT, Real > &p2) const
const std::pair< MatrixIndexT, Real > & GetElement(MatrixIndexT i) const
get an indexed element (0 <= i < NumElements()).
Definition: sparse-matrix.h:77
bool WithProb(BaseFloat prob, struct RandomState *state)
Definition: kaldi-math.cc:72
void SetRow(int32 r, const SparseVector< Real > &vec)
Sets row r to "vec"; makes sure it has the correct dimension.
const CompressedMatrix & GetCompressedMatrix() const
Returns the contents as a compressed matrix.
void AddToVec(Real alpha, VectorBase< OtherReal > *vec) const
std::vector< std::pair< MatrixIndexT, Real > > pairs_
void AddMat(const Real alpha, const MatrixBase< Real > &M, MatrixTransposeType transA=kNoTrans)
*this += alpha * M [or M^T]
void swap(basic_filebuf< CharT, Traits > &x, basic_filebuf< CharT, Traits > &y)
float RandGauss(struct RandomState *state=NULL)
Definition: kaldi-math.h:155
kaldi::int32 int32
void Write(std::ostream &os, bool binary) const
const Matrix< BaseFloat > & GetFullMatrix() const
Returns the contents as a Matrix<BaseFloat>.
void Swap(Matrix< Real > *other)
Swaps the contents of *this and *other. Shallow swap.
void CopyFromMat(const MatrixBase< OtherReal > &M, MatrixTransposeType trans=kNoTrans)
Copy given matrix. (no resize is done).
void SwapSparseMatrix(SparseMatrix< BaseFloat > *smat)
Swaps the with the given SparseMatrix.
std::vector< SparseVector< Real > > rows_
template double VecSvec(const VectorBase< double > &vec, const SparseVector< double > &svec)
void CopyFromSvec(const SparseVector< OtherReal > &other)
void FilterGeneralMatrixRows(const GeneralMatrix &in, const std::vector< bool > &keep_rows, GeneralMatrix *out)
Outputs a GeneralMatrix containing only the rows r of "in" such that keep_rows[r] == true...
Real VecSvec(const VectorBase< Real > &vec, const SparseVector< Real > &svec)
void CopyToMat(MatrixBase< OtherReal > *other, MatrixTransposeType t=kNoTrans) const
Copy to matrix. It must already have the correct size.
template void FilterMatrixRows(const Matrix< double > &in, const std::vector< bool > &keep_rows, Matrix< double > *out)
void AddToMat(BaseFloat alpha, MatrixBase< Real > *other, MatrixTransposeType t=kNoTrans) const
Does *other = *other + alpha * *this.
void CopyFromVec(const VectorBase< Real > &v)
Copy data from another vector (must match own size).
MatrixIndexT NumCols() const
MatrixIndexT NumCols() const
SparseVector< Real > * Data()
MatrixIndexT Stride() const
Stride (distance in memory between each row). Will be >= NumCols.
Definition: kaldi-matrix.h:70
float BaseFloat
Definition: kaldi-types.h:29
int32 MatrixIndexT
Definition: matrix-common.h:98
void Read(std::istream &os, bool binary)
const SubVector< Real > Row(MatrixIndexT i) const
Return specific row of matrix [const].
Definition: kaldi-matrix.h:188
void CopyElementsToVec(VectorBase< Real > *other) const
Copies the values of all the elements in SparseMatrix into a VectorBase object.
GeneralMatrixType Type() const
Returns the type of the matrix: kSparseMatrix, kCompressedMatrix or kFullMatrix.
void CopyFromSmat(const SparseMatrix< OtherReal > &other, MatrixTransposeType trans=kNoTrans)
Copies data from another sparse matrix.
template void FilterSparseMatrixRows(const SparseMatrix< double > &in, const std::vector< bool > &keep_rows, SparseMatrix< double > *out)
void ExpectToken(std::istream &is, bool binary, const char *token)
ExpectToken tries to read in the given token, and throws an exception on failure. ...
Definition: io-funcs.cc:191
void SwapCompressedMatrix(CompressedMatrix *cmat)
Swaps the with the given CompressedMatrix.
MatrixIndexT Dim() const
Definition: sparse-matrix.h:43
struct rnnlm::@11::@12 n
void FilterCompressedMatrixRows(const CompressedMatrix &in, const std::vector< bool > &keep_rows, Matrix< BaseFloat > *out)
Outputs a Matrix<Real> containing only the rows r of "in" such that keep_rows[r] == true...
void ExtractRowRangeWithPadding(const GeneralMatrix &in, int32 row_offset, int32 num_rows, GeneralMatrix *out)
This function extracts a row-range of a GeneralMatrix and writes as a GeneralMatrix containing the sa...
#define KALDI_ERR
Definition: kaldi-error.h:147
MatrixIndexT NumElements() const
Returns the number of nonzero elements.
Definition: sparse-matrix.h:74
GeneralMatrixType
Real * Data()
Returns a pointer to the start of the vector&#39;s data.
Definition: kaldi-vector.h:70
void WriteToken(std::ostream &os, bool binary, const char *token)
The WriteToken functions are for writing nonempty sequences of non-space characters.
Definition: io-funcs.cc:134
MatrixIndexT Dim() const
Returns the dimension of the vector.
Definition: kaldi-vector.h:64
void SetZero()
Sets matrix to zero.
void CopyToMat(MatrixBase< BaseFloat > *mat, MatrixTransposeType trans=kNoTrans) const
Copies contents, regardless of type, to "mat", which must be correctly sized.
void AppendGeneralMatrixRows(const std::vector< const GeneralMatrix *> &src, GeneralMatrix *mat)
Appends all the matrix rows of a list of GeneralMatrixes, to get a single GeneralMatrix.
void Write(std::ostream &os, bool binary) const
MatrixIndexT NumRows() const
Returns number of rows (or zero for emtpy matrix).
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
Definition: kaldi-matrix.h:64
MatrixIndexT NumRows() const
MatrixIndexT NumRows() const
void SwapFullMatrix(Matrix< BaseFloat > *mat)
Swaps the with the given Matrix.
MatrixTransposeType
Definition: matrix-common.h:32
void WriteBasicType(std::ostream &os, bool binary, T t)
WriteBasicType is the name of the write function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:34
void Resize(const MatrixIndexT r, const MatrixIndexT c, MatrixResizeType resize_type=kSetZero, MatrixStrideType stride_type=kDefaultStride)
Sets matrix to a specified size (zero is OK as long as both r and c are zero).
void AppendSparseMatrixRows(std::vector< SparseMatrix< Real > > *inputs)
Sets *this to all the rows of *inputs appended together; this function is destructive of the inputs...
Real FrobeniusNorm() const
Matrix< BaseFloat > mat_
void Resize(MatrixIndexT dim, MatrixResizeType resize_type=kSetZero)
Resizes to this dimension.
SparseMatrix< BaseFloat > smat_
void Swap(SparseMatrix< Real > *other)
const SparseMatrix< BaseFloat > & GetSparseMatrix() const
Returns the contents as a SparseMatrix.
Provides a vector abstraction class.
Definition: kaldi-vector.h:41
void SetZero()
Set vector to all zeros.
MatrixIndexT NumCols() const
Returns number of columns (or zero for emtpy matrix).
SparseMatrix< Real > & operator=(const SparseMatrix< Real > &other)
void CopyToMat(MatrixBase< Real > *mat, MatrixTransposeType trans=kNoTrans) const
Copies contents to matrix.
void Swap(SparseVector< Real > *other)
std::pair< MatrixIndexT, Real > * Data()
Sub-matrix representation.
Definition: kaldi-matrix.h:988
void Resize(MatrixIndexT rows, MatrixIndexT cols, MatrixResizeType resize_type=kSetZero)
Resizes the matrix; analogous to Matrix::Resize().
Represents a non-allocating general vector which can be defined as a sub-vector of higher-level vecto...
Definition: kaldi-vector.h:501
template double TraceMatSmat(const MatrixBase< double > &A, const SparseMatrix< double > &B, MatrixTransposeType trans)
MatrixIndexT NumElements() const
const SparseVector< Real > & Row(MatrixIndexT r) const