56 template<
typename Real>
77 <<
static_cast<int32>(method);
86 float min_value = mat.
Min(), max_value = mat.
Max();
90 if (max_value == min_value)
91 max_value = min_value + (1.0 + fabs(min_value));
93 max_value - max_value == 0 &&
94 "Cannot compress a matrix with Nan's or Inf's");
97 header->
range = max_value - min_value;
106 header->
range = 65535.0;
111 header->
range = 255.0;
120 KALDI_ERR <<
"Unknown compression method = " 121 <<
static_cast<int32>(method);
128 template<
typename Real>
132 delete []
static_cast<float*
>(
data_);
135 if (mat.
NumRows() == 0) {
return; }
153 reinterpret_cast<uint8*
>(header_data + global_header.
num_cols);
155 const Real *matrix_data = mat.
Data();
159 matrix_data + col, mat.
Stride(),
161 header_data, byte_data);
163 byte_data += global_header.
num_rows;
166 uint16 *data =
reinterpret_cast<uint16*
>(
static_cast<char*
>(
data_) +
169 for (
int32 r = 0; r < num_rows; r++) {
170 const Real *row_data = mat.
RowData(r);
171 for (
int32 c = 0; c < num_cols; c++)
177 uint8 *data =
reinterpret_cast<uint8*
>(
static_cast<char*
>(
data_) +
180 for (
int32 r = 0; r < num_rows; r++) {
181 const Real *row_data = mat.
RowData(r);
182 for (
int32 c = 0; c < num_cols; c++)
205 bool allow_padding):
data_(NULL) {
208 if (old_num_rows == 0) {
218 KALDI_ASSERT(row_offset + num_rows <= old_num_rows || allow_padding);
221 if (num_rows == 0 || num_cols == 0) {
return; }
223 bool padding_is_used = (row_offset < 0 ||
224 row_offset + num_rows > old_num_rows);
231 new_global_header = *old_global_header;
232 new_global_header.
num_cols = num_cols;
233 new_global_header.
num_rows = num_rows;
247 uint8 *old_byte_data =
248 reinterpret_cast<uint8*
>(old_per_col_header +
254 memcpy(new_per_col_header, old_per_col_header + col_offset,
257 uint8 *new_byte_data =
258 reinterpret_cast<uint8*
>(new_per_col_header + num_cols);
259 if (!padding_is_used) {
260 uint8 *old_start_of_subcol =
261 old_byte_data + row_offset + (col_offset * old_num_rows),
262 *new_start_of_col = new_byte_data;
263 for (
int32 i = 0;
i < num_cols;
i++) {
264 memcpy(new_start_of_col, old_start_of_subcol, num_rows);
265 new_start_of_col += num_rows;
266 old_start_of_subcol += old_num_rows;
269 uint8 *old_start_of_col =
270 old_byte_data + (col_offset * old_num_rows),
271 *new_start_of_col = new_byte_data;
272 for (
int32 i = 0;
i < num_cols;
i++) {
274 for (
int32 j = 0;
j < num_rows;
j++) {
275 int32 old_j =
j + row_offset;
276 if (old_j < 0) old_j = 0;
277 else if (old_j >= old_num_rows) old_j = old_num_rows - 1;
278 new_start_of_col[
j] = old_start_of_col[old_j];
280 new_start_of_col += num_rows;
281 old_start_of_col += old_num_rows;
285 const uint16 *old_data =
286 reinterpret_cast<const uint16*
>(old_global_header + 1);
287 uint16 *new_row_data =
290 for (
int32 row = 0; row < num_rows; row++) {
291 int32 old_row = row + row_offset;
293 if (old_row < 0) old_row = 0;
294 else if (old_row >= old_num_rows) old_row = old_num_rows - 1;
295 const uint16 *old_row_data =
296 old_data + col_offset + (old_num_cols * old_row);
297 memcpy(new_row_data, old_row_data,
sizeof(uint16) * num_cols);
298 new_row_data += num_cols;
302 const uint8 *old_data =
303 reinterpret_cast<const uint8*
>(old_global_header + 1);
304 uint8 *new_row_data =
307 for (
int32 row = 0; row < num_rows; row++) {
308 int32 old_row = row + row_offset;
310 if (old_row < 0) old_row = 0;
311 else if (old_row >= old_num_rows) old_row = old_num_rows - 1;
312 const uint8 *old_row_data =
313 old_data + col_offset + (old_num_cols * old_row);
314 memcpy(new_row_data, old_row_data,
sizeof(uint8) * num_cols);
315 new_row_data += num_cols;
329 this->
Swap(&temp_cmat);
334 template<
typename Real>
350 float f = (value - global_header.
min_value) /
352 if (f > 1.0) f = 1.0;
353 if (f < 0.0) f = 0.0;
354 return static_cast<int>(f * 65535 + 0.499);
362 float f = (value - global_header.
min_value) /
364 if (f > 1.0) f = 1.0;
365 if (f < 0.0) f = 0.0;
366 return static_cast<int>(f * 255 + 0.499);
376 + global_header.
range * 1.52590218966964e-05F * value;
379 template<
typename Real>
385 std::vector<Real> sdata(num_rows);
386 for (
size_t i = 0, size = sdata.size();
i < size;
i++)
387 sdata[
i] = data[
i*stride];
390 int quarter_nr = num_rows/4;
394 std::nth_element(sdata.begin(), sdata.begin() + quarter_nr, sdata.end());
397 std::nth_element(sdata.begin(), sdata.begin(), sdata.begin() + quarter_nr);
400 std::nth_element(sdata.begin() + quarter_nr + 1,
401 sdata.begin() + (3*quarter_nr), sdata.end());
405 std::nth_element(sdata.begin() + (3*quarter_nr) + 1, sdata.end() - 1,
412 std::min<uint16>(
FloatToUint16(global_header, sdata[0]), 65532);
428 std::sort(sdata.begin(), sdata.end());
458 float p0,
float p25,
float p75,
float p100,
463 float f = (value - p0) / (p25 - p0);
464 ans =
static_cast<int>(f * 64 + 0.5);
468 if (ans < 0) ans = 0;
469 if (ans > 64) ans = 64;
470 }
else if (value < p75) {
472 float f = (value - p25) / (p75 - p25);
473 ans = 64 +
static_cast<int>(f * 128 + 0.5);
474 if (ans < 64) ans = 64;
475 if (ans > 192) ans = 192;
480 float f = (value - p75) / (p100 - p75);
481 ans = 192 +
static_cast<int>(f * 63 + 0.5);
482 if (ans < 192) ans = 192;
483 if (ans > 255) ans = 255;
485 return static_cast<uint8
>(ans);
491 float p0,
float p25,
float p75,
float p100,
494 return p0 + (p25 - p0) * value * (1/64.0);
495 }
else if (value <= 192) {
496 return p25 + (p75 - p25) * (value - 64) * (1/128.0);
498 return p75 + (p100 - p75) * (value - 192) * (1/63.0);
503 template<
typename Real>
517 for (
int32 i = 0;
i < num_rows;
i++) {
518 Real this_data = data[
i * stride];
519 byte_data[
i] =
FloatToChar(p0, p25, p75, p100, this_data);
528 return reinterpret_cast<void*
>(
new float[(num_bytes/3) + 4]);
545 os.write(reinterpret_cast<const char*>(
data_) + 4, size - 4);
552 os.write(reinterpret_cast<const char*>(&h),
sizeof(h));
560 temp_mat.
Write(os, binary);
563 KALDI_ERR <<
"Error writing compressed matrix to stream.";
568 delete [] (
static_cast<float*
>(
data_));
572 int peekval =
Peek(is, binary);
573 if (peekval ==
'C') {
577 if (tok ==
"CM") { h.
format = 1; }
578 else if (tok ==
"CM2") { h.
format = 2; }
579 else if (tok ==
"CM3") { h.
format = 3; }
581 KALDI_ERR <<
"Unexpected token " << tok <<
", expecting CM, CM2 or CM3";
584 is.read(reinterpret_cast<char*>(&h) + 4,
sizeof(h) - 4);
592 is.read(reinterpret_cast<char*>(data_) +
sizeof(
GlobalHeader),
606 temp.
Read(is, binary);
613 template<
typename Real>
636 uint8 *byte_data =
reinterpret_cast<uint8*
>(per_col_header +
638 for (
int32 i = 0;
i < num_cols;
i++, per_col_header++) {
643 for (
int32 j = 0;
j < num_rows;
j++, byte_data++) {
644 float f =
CharToFloat(p0, p25, p75, p100, *byte_data);
649 const uint16 *data =
reinterpret_cast<const uint16*
>(h + 1);
651 increment = h->
range * (1.0 / 65535.0);
652 for (
int32 i = 0;
i < num_rows;
i++) {
654 for (
int32 j = 0;
j < num_cols;
j++)
655 row_data[
j] = min_value + data[
j] * increment;
660 float min_value = h->
min_value, increment = h->
range * (1.0 / 255.0);
662 const uint8 *data =
reinterpret_cast<const uint8*
>(h + 1);
663 for (
int32 i = 0;
i < num_rows;
i++) {
665 for (
int32 j = 0;
j < num_cols;
j++)
666 row_data[
j] = min_value + data[
j] * increment;
680 template<
typename Real>
691 uint8 *byte_data =
reinterpret_cast<uint8*
>(per_col_header +
694 for (
int32 i = 0;
i < h->num_cols;
695 i++, per_col_header++, byte_data += h->num_rows) {
700 float f =
CharToFloat(p0, p25, p75, p100, *byte_data);
704 int32 num_cols = h->num_cols;
705 float min_value = h->min_value,
706 increment = h->range * (1.0 / 65535.0);
707 const uint16 *row_data =
reinterpret_cast<uint16*
>(h + 1) + (num_cols * row);
708 Real *v_data = v->
Data();
709 for (
int32 c = 0; c < num_cols; c++)
710 v_data[c] = min_value + row_data[c] * increment;
713 int32 num_cols = h->num_cols;
714 float min_value = h->min_value,
715 increment = h->range * (1.0 / 255.0);
716 const uint8 *row_data =
reinterpret_cast<uint8*
>(h + 1) + (num_cols * row);
717 Real *v_data = v->
Data();
718 for (
int32 c = 0; c < num_cols; c++)
719 v_data[c] = min_value + row_data[c] * increment;
723 template<
typename Real>
735 uint8 *byte_data =
reinterpret_cast<uint8*
>(per_col_header +
737 byte_data += col*h->num_rows;
738 per_col_header += col;
743 for (
int32 i = 0;
i < h->num_rows;
i++, byte_data++) {
744 float f =
CharToFloat(p0, p25, p75, p100, *byte_data);
748 int32 num_rows = h->num_rows, num_cols = h->num_cols;
749 float min_value = h->min_value,
750 increment = h->range * (1.0 / 65535.0);
751 const uint16 *col_data =
reinterpret_cast<uint16*
>(h + 1) + col;
752 Real *v_data = v->
Data();
753 for (
int32 r = 0; r < num_rows; r++)
754 v_data[r] = min_value + increment * col_data[r * num_cols];
757 int32 num_rows = h->num_rows, num_cols = h->num_cols;
758 float min_value = h->min_value,
759 increment = h->range * (1.0 / 255.0);
760 const uint8 *col_data =
reinterpret_cast<uint8*
>(h + 1) + col;
761 Real *v_data = v->
Data();
762 for (
int32 r = 0; r < num_rows; r++)
763 v_data[r] = min_value + increment * col_data[r * num_cols];
777 template<
typename Real>
795 uint8 *byte_data =
reinterpret_cast<uint8*
>(per_col_header +
798 uint8 *start_of_subcol = byte_data+row_offset;
800 start_of_subcol += col_offset*num_rows;
802 per_col_header += col_offset;
806 i++, per_col_header++, start_of_subcol+=num_rows) {
807 byte_data = start_of_subcol;
812 for (
int32 j = 0;
j < tgt_rows;
j++, byte_data++) {
813 float f =
CharToFloat(p0, p25, p75, p100, *byte_data);
818 const uint16 *data =
reinterpret_cast<const uint16*
>(h+1) + col_offset +
819 (num_cols * row_offset);
820 float min_value = h->min_value,
821 increment = h->range * (1.0 / 65535.0);
823 for (
int32 row = 0; row < tgt_rows; row++) {
824 Real *dest_row = dest->
RowData(row);
825 for (
int32 col = 0; col < tgt_cols; col++)
826 dest_row[col] = min_value + increment * data[col];
831 const uint8 *data =
reinterpret_cast<const uint8*
>(h+1) + col_offset +
832 (num_cols * row_offset);
833 float min_value = h->min_value,
834 increment = h->range * (1.0 / 255.0);
835 for (
int32 row = 0; row < tgt_rows; row++) {
836 Real *dest_row = dest->
RowData(row);
837 for (
int32 col = 0; col < tgt_cols; col++)
838 dest_row[col] = min_value + increment * data[col];
854 delete []
static_cast<float*
>(
data_);
865 if (mat.
data_ != NULL) {
868 memcpy(static_cast<void*>(
data_),
869 static_cast<void*>(mat.
data_),
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Real Min() const
Returns minimum element of matrix.
void Write(std::ostream &out, bool binary) const
write to stream.
void CopyRowToVec(MatrixIndexT row, VectorBase< Real > *v) const
Copies row #row of the matrix into vector v.
void CopyColToVec(MatrixIndexT col, VectorBase< Real > *v) const
Copies column #col of the matrix into vector v.
void Swap(CompressedMatrix *other)
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Base class which provides matrix operations not involving resizing or allocation. ...
const Real * Data() const
Gives pointer to raw data (const).
Real Max() const
Returns maximum element of matrix.
Real * RowData(MatrixIndexT i)
Returns pointer to data for one row (non-const)
void ReadToken(std::istream &is, bool binary, std::string *str)
ReadToken gets the next token and puts it in str (exception on failure).
CompressedMatrix & operator=(const CompressedMatrix &mat)
void Write(std::ostream &os, bool binary) const
void CopyFromMat(const MatrixBase< OtherReal > &M, MatrixTransposeType trans=kNoTrans)
Copy given matrix. (no resize is done).
void Read(std::istream &is, bool binary)
int Peek(std::istream &is, bool binary)
Peek consumes whitespace (if binary == false) and then returns the peek() value of the stream...
static uint16 FloatToUint16(const GlobalHeader &global_header, float value)
void Read(std::istream &in, bool binary, bool add=false)
read from stream.
MatrixIndexT Stride() const
Stride (distance in memory between each row). Will be >= NumCols.
#define KALDI_PARANOID_ASSERT(cond)
void Scale(float alpha)
scales all elements of matrix by alpha.
Real * Data()
Returns a pointer to the start of the vector's data.
void WriteToken(std::ostream &os, bool binary, const char *token)
The WriteToken functions are for writing nonempty sequences of non-space characters.
MatrixIndexT Dim() const
Returns the dimension of the vector.
static float Uint16ToFloat(const GlobalHeader &global_header, uint16 value)
static void ComputeGlobalHeader(const MatrixBase< Real > &mat, CompressionMethod method, GlobalHeader *header)
static uint8 FloatToUint8(const GlobalHeader &global_header, float value)
MatrixIndexT NumRows() const
Returns number of rows (or zero for emtpy matrix).
#define KALDI_ASSERT(cond)
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
static void CompressColumn(const GlobalHeader &global_header, const Real *data, MatrixIndexT stride, int32 num_rows, PerColHeader *header, uint8 *byte_data)
static float CharToFloat(float p0, float p25, float p75, float p100, uint8 value)
static uint8 FloatToChar(float p0, float p25, float p75, float p100, float value)
static void * AllocateData(int32 num_bytes)
Provides a vector abstraction class.
static void ComputeColHeader(const GlobalHeader &global_header, const Real *data, MatrixIndexT stride, int32 num_rows, PerColHeader *header)
MatrixIndexT NumCols() const
Returns number of columns (or zero for emtpy matrix).
void CopyToMat(MatrixBase< Real > *mat, MatrixTransposeType trans=kNoTrans) const
Copies contents to matrix.
void CopyFromMat(const MatrixBase< Real > &mat, CompressionMethod method=kAutomaticMethod)
This will resize *this and copy the contents of mat to *this.
#define KALDI_COMPILE_TIME_ASSERT(b)
static MatrixIndexT DataSize(const GlobalHeader &header)