summaryrefslogtreecommitdiff
path: root/kaldi_io/src/kaldi/base
diff options
context:
space:
mode:
Diffstat (limited to 'kaldi_io/src/kaldi/base')
-rw-r--r--kaldi_io/src/kaldi/base/io-funcs-inl.h219
-rw-r--r--kaldi_io/src/kaldi/base/io-funcs.h231
-rw-r--r--kaldi_io/src/kaldi/base/kaldi-common.h41
-rw-r--r--kaldi_io/src/kaldi/base/kaldi-error.h153
-rw-r--r--kaldi_io/src/kaldi/base/kaldi-math.h346
-rw-r--r--kaldi_io/src/kaldi/base/kaldi-types.h64
-rw-r--r--kaldi_io/src/kaldi/base/kaldi-utils.h157
-rw-r--r--kaldi_io/src/kaldi/base/timer.h83
8 files changed, 1294 insertions, 0 deletions
diff --git a/kaldi_io/src/kaldi/base/io-funcs-inl.h b/kaldi_io/src/kaldi/base/io-funcs-inl.h
new file mode 100644
index 0000000..e55458e
--- /dev/null
+++ b/kaldi_io/src/kaldi/base/io-funcs-inl.h
@@ -0,0 +1,219 @@
+// base/io-funcs-inl.h
+
+// Copyright 2009-2011 Microsoft Corporation; Saarland University;
+// Jan Silovsky; 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_BASE_IO_FUNCS_INL_H_
+#define KALDI_BASE_IO_FUNCS_INL_H_ 1
+
+// Do not include this file directly. It is included by base/io-funcs.h
+
+#include <limits>
+#include <vector>
+
+namespace kaldi {
+
+// Template that covers integers.
+template<class T> void WriteBasicType(std::ostream &os,
+ bool binary, T t) {
+ // Compile time assertion that this is not called with a wrong type.
+ KALDI_ASSERT_IS_INTEGER_TYPE(T);
+ if (binary) {
+ char len_c = (std::numeric_limits<T>::is_signed ? 1 : -1)
+ * static_cast<char>(sizeof(t));
+ os.put(len_c);
+ os.write(reinterpret_cast<const char *>(&t), sizeof(t));
+ } else {
+ if (sizeof(t) == 1)
+ os << static_cast<int16>(t) << " ";
+ else
+ os << t << " ";
+ }
+ if (os.fail()) {
+ throw std::runtime_error("Write failure in WriteBasicType.");
+ }
+}
+
+// Template that covers integers.
+template<class T> inline void ReadBasicType(std::istream &is,
+ bool binary, T *t) {
+ KALDI_PARANOID_ASSERT(t != NULL);
+ // Compile time assertion that this is not called with a wrong type.
+ KALDI_ASSERT_IS_INTEGER_TYPE(T);
+ if (binary) {
+ int len_c_in = is.get();
+ if (len_c_in == -1)
+ KALDI_ERR << "ReadBasicType: encountered end of stream.";
+ char len_c = static_cast<char>(len_c_in), len_c_expected
+ = (std::numeric_limits<T>::is_signed ? 1 : -1)
+ * static_cast<char>(sizeof(*t));
+
+ if (len_c != len_c_expected) {
+ KALDI_ERR << "ReadBasicType: did not get expected integer type, "
+ << static_cast<int>(len_c)
+ << " vs. " << static_cast<int>(len_c_expected)
+ << ". You can change this code to successfully"
+ << " read it later, if needed.";
+ // insert code here to read "wrong" type. Might have a switch statement.
+ }
+ is.read(reinterpret_cast<char *>(t), sizeof(*t));
+ } else {
+ if (sizeof(*t) == 1) {
+ int16 i;
+ is >> i;
+ *t = i;
+ } else {
+ is >> *t;
+ }
+ }
+ if (is.fail()) {
+ KALDI_ERR << "Read failure in ReadBasicType, file position is "
+ << is.tellg() << ", next char is " << is.peek();
+ }
+}
+
+
+template<class T> inline void WriteIntegerVector(std::ostream &os, bool binary,
+ const std::vector<T> &v) {
+ // Compile time assertion that this is not called with a wrong type.
+ KALDI_ASSERT_IS_INTEGER_TYPE(T);
+ if (binary) {
+ char sz = sizeof(T); // this is currently just a check.
+ os.write(&sz, 1);
+ int32 vecsz = static_cast<int32>(v.size());
+ KALDI_ASSERT((size_t)vecsz == v.size());
+ os.write(reinterpret_cast<const char *>(&vecsz), sizeof(vecsz));
+ if (vecsz != 0) {
+ os.write(reinterpret_cast<const char *>(&(v[0])), sizeof(T)*vecsz);
+ }
+ } else {
+ // focus here is on prettiness of text form rather than
+ // efficiency of reading-in.
+ // reading-in is dominated by low-level operations anyway:
+ // for efficiency use binary.
+ os << "[ ";
+ typename std::vector<T>::const_iterator iter = v.begin(), end = v.end();
+ for (; iter != end; ++iter) {
+ if (sizeof(T) == 1)
+ os << static_cast<int16>(*iter) << " ";
+ else
+ os << *iter << " ";
+ }
+ os << "]\n";
+ }
+ if (os.fail()) {
+ throw std::runtime_error("Write failure in WriteIntegerType.");
+ }
+}
+
+
+template<class T> inline void ReadIntegerVector(std::istream &is,
+ bool binary,
+ std::vector<T> *v) {
+ KALDI_ASSERT_IS_INTEGER_TYPE(T);
+ KALDI_ASSERT(v != NULL);
+ if (binary) {
+ int sz = is.peek();
+ if (sz == sizeof(T)) {
+ is.get();
+ } else { // this is currently just a check.
+ KALDI_ERR << "ReadIntegerVector: expected to see type of size "
+ << sizeof(T) << ", saw instead " << sz << ", at file position "
+ << is.tellg();
+ }
+ int32 vecsz;
+ is.read(reinterpret_cast<char *>(&vecsz), sizeof(vecsz));
+ if (is.fail() || vecsz < 0) goto bad;
+ v->resize(vecsz);
+ if (vecsz > 0) {
+ is.read(reinterpret_cast<char *>(&((*v)[0])), sizeof(T)*vecsz);
+ }
+ } else {
+ std::vector<T> tmp_v; // use temporary so v doesn't use extra memory
+ // due to resizing.
+ is >> std::ws;
+ if (is.peek() != static_cast<int>('[')) {
+ KALDI_ERR << "ReadIntegerVector: expected to see [, saw "
+ << is.peek() << ", at file position " << is.tellg();
+ }
+ is.get(); // consume the '['.
+ is >> std::ws; // consume whitespace.
+ while (is.peek() != static_cast<int>(']')) {
+ if (sizeof(T) == 1) { // read/write chars as numbers.
+ int16 next_t;
+ is >> next_t >> std::ws;
+ if (is.fail()) goto bad;
+ else
+ tmp_v.push_back((T)next_t);
+ } else {
+ T next_t;
+ is >> next_t >> std::ws;
+ if (is.fail()) goto bad;
+ else
+ tmp_v.push_back(next_t);
+ }
+ }
+ is.get(); // get the final ']'.
+ *v = tmp_v; // could use std::swap to use less temporary memory, but this
+ // uses less permanent memory.
+ }
+ if (!is.fail()) return;
+ bad:
+ KALDI_ERR << "ReadIntegerVector: read failure at file position "
+ << is.tellg();
+}
+
+// Initialize an opened stream for writing by writing an optional binary
+// header and modifying the floating-point precision.
+inline void InitKaldiOutputStream(std::ostream &os, bool binary) {
+ // This does not throw exceptions (does not check for errors).
+ if (binary) {
+ os.put('\0');
+ os.put('B');
+ }
+ // Note, in non-binary mode we may at some point want to mess with
+ // the precision a bit.
+ // 7 is a bit more than the precision of float..
+ if (os.precision() < 7)
+ os.precision(7);
+}
+
+/// Initialize an opened stream for reading by detecting the binary header and
+// setting the "binary" value appropriately.
+inline bool InitKaldiInputStream(std::istream &is, bool *binary) {
+ // Sets the 'binary' variable.
+ // Throws exception in the very unusual situation that stream
+ // starts with '\0' but not then 'B'.
+
+ if (is.peek() == '\0') { // seems to be binary
+ is.get();
+ if (is.peek() != 'B') {
+ return false;
+ }
+ is.get();
+ *binary = true;
+ return true;
+ } else {
+ *binary = false;
+ return true;
+ }
+}
+
+} // end namespace kaldi.
+
+#endif // KALDI_BASE_IO_FUNCS_INL_H_
diff --git a/kaldi_io/src/kaldi/base/io-funcs.h b/kaldi_io/src/kaldi/base/io-funcs.h
new file mode 100644
index 0000000..2bc9da8
--- /dev/null
+++ b/kaldi_io/src/kaldi/base/io-funcs.h
@@ -0,0 +1,231 @@
+// base/io-funcs.h
+
+// Copyright 2009-2011 Microsoft Corporation; Saarland University;
+// Jan Silovsky; Yanmin Qian
+
+// 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_BASE_IO_FUNCS_H_
+#define KALDI_BASE_IO_FUNCS_H_
+
+// This header only contains some relatively low-level I/O functions.
+// The full Kaldi I/O declarations are in ../util/kaldi-io.h
+// and ../util/kaldi-table.h
+// They were put in util/ in order to avoid making the Matrix library
+// dependent on them.
+
+#include <cctype>
+#include <vector>
+#include <string>
+#include "base/kaldi-common.h"
+
+namespace kaldi {
+
+
+
+/*
+ This comment describes the Kaldi approach to I/O. All objects can be written
+ and read in two modes: binary and text. In addition we want to make the I/O
+ work if we redefine the typedef "BaseFloat" between floats and doubles.
+ We also want to have control over whitespace in text mode without affecting
+ the meaning of the file, for pretty-printing purposes.
+
+ Errors are handled by throwing an exception (std::runtime_error).
+
+ For integer and floating-point types (and boolean values):
+
+ WriteBasicType(std::ostream &, bool binary, const T&);
+ ReadBasicType(std::istream &, bool binary, T*);
+
+ and we expect these functions to be defined in such a way that they work when
+ the type T changes between float and double, so you can read float into double
+ and vice versa]. Note that for efficiency and space-saving reasons, the Vector
+ and Matrix classes do not use these functions [but they preserve the type
+ interchangeability in their own way]
+
+ For a class (or struct) C:
+ class C {
+ ..
+ Write(std::ostream &, bool binary, [possibly extra optional args for specific classes]) const;
+ Read(std::istream &, bool binary, [possibly extra optional args for specific classes]);
+ ..
+ }
+ NOTE: The only actual optional args we used are the "add" arguments in
+ Vector/Matrix classes, which specify whether we should sum the data already
+ in the class with the data being read.
+
+ For types which are typedef's involving stl classes, I/O is as follows:
+ typedef std::vector<std::pair<A, B> > MyTypedefName;
+
+ The user should define something like:
+
+ WriteMyTypedefName(std::ostream &, bool binary, const MyTypedefName &t);
+ ReadMyTypedefName(std::ostream &, bool binary, MyTypedefName *t);
+
+ The user would have to write these functions.
+
+ For a type std::vector<T>:
+
+ void WriteIntegerVector(std::ostream &os, bool binary, const std::vector<T> &v);
+ void ReadIntegerVector(std::istream &is, bool binary, std::vector<T> *v);
+
+ For other types, e.g. vectors of pairs, the user should create a routine of the
+ type WriteMyTypedefName. This is to avoid introducing confusing templated functions;
+ we could easily create templated functions to handle most of these cases but they
+ would have to share the same name.
+
+ It also often happens that the user needs to write/read special tokens as part
+ of a file. These might be class headers, or separators/identifiers in the class.
+ We provide special functions for manipulating these. These special tokens must
+ be nonempty and must not contain any whitespace.
+
+ void WriteToken(std::ostream &os, bool binary, const char*);
+ void WriteToken(std::ostream &os, bool binary, const std::string & token);
+ int Peek(std::istream &is, bool binary);
+ void ReadToken(std::istream &is, bool binary, std::string *str);
+ void PeekToken(std::istream &is, bool binary, std::string *str);
+
+
+ WriteToken writes the token and one space (whether in binary or text mode).
+
+ Peek returns the first character of the next token, by consuming whitespace
+ (in text mode) and then returning the peek() character. It returns -1 at EOF;
+ it doesn't throw. It's useful if a class can have various forms based on
+ typedefs and virtual classes, and wants to know which version to read.
+
+ ReadToken allow the caller to obtain the next token. PeekToken works just
+ like ReadToken, but seeks back to the beginning of the token. A subsequent
+ call to ReadToken will read the same token again. This is useful when
+ different object types are written to the same file; using PeekToken one can
+ decide which of the objects to read.
+
+ There is currently no special functionality for writing/reading strings (where the strings
+ contain data rather than "special tokens" that are whitespace-free and nonempty). This is
+ because Kaldi is structured in such a way that strings don't appear, except as OpenFst symbol
+ table entries (and these have their own format).
+
+
+ NOTE: you should not call ReadIntegerType and WriteIntegerType with types,
+ such as int and size_t, that are machine-independent -- at least not
+ if you want your file formats to port between machines. Use int32 and
+ int64 where necessary. There is no way to detect this using compile-time
+ assertions because C++ only keeps track of the internal representation of
+ the type.
+*/
+
+/// \addtogroup io_funcs_basic
+/// @{
+
+
+/// WriteBasicType is the name of the write function for bool, integer types,
+/// and floating-point types. They all throw on error.
+template<class T> void WriteBasicType(std::ostream &os, bool binary, T t);
+
+/// ReadBasicType is the name of the read function for bool, integer types,
+/// and floating-point types. They all throw on error.
+template<class T> void ReadBasicType(std::istream &is, bool binary, T *t);
+
+
+// Declare specialization for bool.
+template<>
+void WriteBasicType<bool>(std::ostream &os, bool binary, bool b);
+
+template <>
+void ReadBasicType<bool>(std::istream &is, bool binary, bool *b);
+
+// Declare specializations for float and double.
+template<>
+void WriteBasicType<float>(std::ostream &os, bool binary, float f);
+
+template<>
+void WriteBasicType<double>(std::ostream &os, bool binary, double f);
+
+template<>
+void ReadBasicType<float>(std::istream &is, bool binary, float *f);
+
+template<>
+void ReadBasicType<double>(std::istream &is, bool binary, double *f);
+
+// Define ReadBasicType that accepts an "add" parameter to add to
+// the destination. Caution: if used in Read functions, be careful
+// to initialize the parameters concerned to zero in the default
+// constructor.
+template<class T>
+inline void ReadBasicType(std::istream &is, bool binary, T *t, bool add) {
+ if (!add) {
+ ReadBasicType(is, binary, t);
+ } else {
+ T tmp = T(0);
+ ReadBasicType(is, binary, &tmp);
+ *t += tmp;
+ }
+}
+
+/// Function for writing STL vectors of integer types.
+template<class T> inline void WriteIntegerVector(std::ostream &os, bool binary,
+ const std::vector<T> &v);
+
+/// Function for reading STL vector of integer types.
+template<class T> inline void ReadIntegerVector(std::istream &is, bool binary,
+ std::vector<T> *v);
+
+/// The WriteToken functions are for writing nonempty sequences of non-space
+/// characters. They are not for general strings.
+void WriteToken(std::ostream &os, bool binary, const char *token);
+void WriteToken(std::ostream &os, bool binary, const std::string & token);
+
+/// Peek consumes whitespace (if binary == false) and then returns the peek()
+/// value of the stream.
+int Peek(std::istream &is, bool binary);
+
+/// ReadToken gets the next token and puts it in str (exception on failure).
+void ReadToken(std::istream &is, bool binary, std::string *token);
+
+/// PeekToken will return the first character of the next token, or -1 if end of
+/// file. It's the same as Peek(), except if the first character is '<' it will
+/// skip over it and will return the next character. It will unget the '<' so
+/// the stream is where it was before you did PeekToken().
+int PeekToken(std::istream &is, bool binary);
+
+/// ExpectToken tries to read in the given token, and throws an exception
+/// on failure.
+void ExpectToken(std::istream &is, bool binary, const char *token);
+void ExpectToken(std::istream &is, bool binary, const std::string & token);
+
+/// ExpectPretty attempts to read the text in "token", but only in non-binary
+/// mode. Throws exception on failure. It expects an exact match except that
+/// arbitrary whitespace matches arbitrary whitespace.
+void ExpectPretty(std::istream &is, bool binary, const char *token);
+void ExpectPretty(std::istream &is, bool binary, const std::string & token);
+
+/// @} end "addtogroup io_funcs_basic"
+
+
+/// InitKaldiOutputStream initializes an opened stream for writing by writing an
+/// optional binary header and modifying the floating-point precision; it will
+/// typically not be called by users directly.
+inline void InitKaldiOutputStream(std::ostream &os, bool binary);
+
+/// InitKaldiInputStream initializes an opened stream for reading by detecting
+/// the binary header and setting the "binary" value appropriately;
+/// It will typically not be called by users directly.
+inline bool InitKaldiInputStream(std::istream &is, bool *binary);
+
+} // end namespace kaldi.
+
+#include "base/io-funcs-inl.h"
+
+#endif // KALDI_BASE_IO_FUNCS_H_
diff --git a/kaldi_io/src/kaldi/base/kaldi-common.h b/kaldi_io/src/kaldi/base/kaldi-common.h
new file mode 100644
index 0000000..33f6f31
--- /dev/null
+++ b/kaldi_io/src/kaldi/base/kaldi-common.h
@@ -0,0 +1,41 @@
+// base/kaldi-common.h
+
+// Copyright 2009-2011 Microsoft Corporation
+
+// 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_BASE_KALDI_COMMON_H_
+#define KALDI_BASE_KALDI_COMMON_H_ 1
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring> // C string stuff like strcpy
+#include <string>
+#include <sstream>
+#include <stdexcept>
+#include <cassert>
+#include <vector>
+#include <iostream>
+#include <fstream>
+
+#include "base/kaldi-utils.h"
+#include "base/kaldi-error.h"
+#include "base/kaldi-types.h"
+#include "base/io-funcs.h"
+#include "base/kaldi-math.h"
+
+#endif // KALDI_BASE_KALDI_COMMON_H_
+
diff --git a/kaldi_io/src/kaldi/base/kaldi-error.h b/kaldi_io/src/kaldi/base/kaldi-error.h
new file mode 100644
index 0000000..8334e42
--- /dev/null
+++ b/kaldi_io/src/kaldi/base/kaldi-error.h
@@ -0,0 +1,153 @@
+// base/kaldi-error.h
+
+// Copyright 2009-2011 Microsoft Corporation; Ondrej Glembek; Lukas Burget;
+// Saarland University
+
+// 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_BASE_KALDI_ERROR_H_
+#define KALDI_BASE_KALDI_ERROR_H_ 1
+
+#include <stdexcept>
+#include <string>
+#include <cstring>
+#include <sstream>
+#include <cstdio>
+
+#ifdef _MSC_VER
+#define NOEXCEPT(Predicate)
+#elif __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
+#define NOEXCEPT(Predicate) noexcept((Predicate))
+#else
+#define NOEXCEPT(Predicate)
+#endif
+
+#include "base/kaldi-types.h"
+#include "base/kaldi-utils.h"
+
+/* Important that this file does not depend on any other kaldi headers. */
+
+
+namespace kaldi {
+
+/// \addtogroup error_group
+/// @{
+
+/// This is set by util/parse-options.{h, cc} if you set --verbose = ? option
+extern int32 g_kaldi_verbose_level;
+
+/// This is set by util/parse-options.{h, cc} (from argv[0]) and used (if set)
+/// in error reporting code to display the name of the program (this is because
+/// in our scripts, we often mix together the stderr of many programs). it is
+/// the base-name of the program (no directory), followed by ':' We don't use
+/// std::string, due to the static initialization order fiasco.
+extern const char *g_program_name;
+
+inline int32 GetVerboseLevel() { return g_kaldi_verbose_level; }
+
+/// This should be rarely used; command-line programs set the verbose level
+/// automatically from ParseOptions.
+inline void SetVerboseLevel(int32 i) { g_kaldi_verbose_level = i; }
+
+// Class KaldiLogMessage is invoked from the KALDI_WARN, KALDI_VLOG and
+// KALDI_LOG macros. It prints the message to stderr. Note: we avoid
+// using cerr, due to problems with thread safety. fprintf is guaranteed
+// thread-safe.
+
+// class KaldiWarnMessage is invoked from the KALDI_WARN macro.
+class KaldiWarnMessage {
+ public:
+ inline std::ostream &stream() { return ss; }
+ KaldiWarnMessage(const char *func, const char *file, int32 line);
+ ~KaldiWarnMessage() { fprintf(stderr, "%s\n", ss.str().c_str()); }
+ private:
+ std::ostringstream ss;
+};
+
+// class KaldiLogMessage is invoked from the KALDI_LOG macro.
+class KaldiLogMessage {
+ public:
+ inline std::ostream &stream() { return ss; }
+ KaldiLogMessage(const char *func, const char *file, int32 line);
+ ~KaldiLogMessage() { fprintf(stderr, "%s\n", ss.str().c_str()); }
+ private:
+ std::ostringstream ss;
+};
+
+// Class KaldiVlogMessage is invoked from the KALDI_VLOG macro.
+class KaldiVlogMessage {
+ public:
+ KaldiVlogMessage(const char *func, const char *file, int32 line,
+ int32 verbose_level);
+ inline std::ostream &stream() { return ss; }
+ ~KaldiVlogMessage() { fprintf(stderr, "%s\n", ss.str().c_str()); }
+ private:
+ std::ostringstream ss;
+};
+
+
+// class KaldiErrorMessage is invoked from the KALDI_ERROR macro.
+// The destructor throws an exception.
+class KaldiErrorMessage {
+ public:
+ KaldiErrorMessage(const char *func, const char *file, int32 line);
+ inline std::ostream &stream() { return ss; }
+ ~KaldiErrorMessage() NOEXCEPT(false); // defined in kaldi-error.cc
+ private:
+ std::ostringstream ss;
+};
+
+
+
+#ifdef _MSC_VER
+#define __func__ __FUNCTION__
+#endif
+
+#ifndef NDEBUG
+#define KALDI_ASSERT(cond) \
+ if (!(cond)) kaldi::KaldiAssertFailure_(__func__, __FILE__, __LINE__, #cond);
+#else
+#define KALDI_ASSERT(cond)
+#endif
+// also see KALDI_COMPILE_TIME_ASSERT, defined in base/kaldi-utils.h,
+// and KALDI_ASSERT_IS_INTEGER_TYPE and KALDI_ASSERT_IS_FLOATING_TYPE,
+// also defined there.
+#ifdef KALDI_PARANOID // some more expensive asserts only checked if this defined
+#define KALDI_PARANOID_ASSERT(cond) \
+ if (!(cond)) kaldi::KaldiAssertFailure_(__func__, __FILE__, __LINE__, #cond);
+#else
+#define KALDI_PARANOID_ASSERT(cond)
+#endif
+
+#define KALDI_ERR kaldi::KaldiErrorMessage(__func__, __FILE__, __LINE__).stream()
+#define KALDI_WARN kaldi::KaldiWarnMessage(__func__, __FILE__, __LINE__).stream()
+#define KALDI_LOG kaldi::KaldiLogMessage(__func__, __FILE__, __LINE__).stream()
+
+#define KALDI_VLOG(v) if (v <= kaldi::g_kaldi_verbose_level) \
+ kaldi::KaldiVlogMessage(__func__, __FILE__, __LINE__, v).stream()
+
+inline bool IsKaldiError(const std::string &str) {
+ return(!strncmp(str.c_str(), "ERROR ", 6));
+}
+
+void KaldiAssertFailure_(const char *func, const char *file,
+ int32 line, const char *cond_str);
+
+/// @} end "addtogroup error_group"
+
+} // namespace kaldi
+
+#endif // KALDI_BASE_KALDI_ERROR_H_
diff --git a/kaldi_io/src/kaldi/base/kaldi-math.h b/kaldi_io/src/kaldi/base/kaldi-math.h
new file mode 100644
index 0000000..4f60d00
--- /dev/null
+++ b/kaldi_io/src/kaldi/base/kaldi-math.h
@@ -0,0 +1,346 @@
+// base/kaldi-math.h
+
+// Copyright 2009-2011 Ondrej Glembek; Microsoft Corporation; Yanmin Qian;
+// Jan Silovsky; Saarland University
+//
+// 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_BASE_KALDI_MATH_H_
+#define KALDI_BASE_KALDI_MATH_H_ 1
+
+#ifdef _MSC_VER
+#include <float.h>
+#endif
+
+#include <cmath>
+#include <limits>
+#include <vector>
+
+#include "base/kaldi-types.h"
+#include "base/kaldi-common.h"
+
+
+#ifndef DBL_EPSILON
+#define DBL_EPSILON 2.2204460492503131e-16
+#endif
+#ifndef FLT_EPSILON
+#define FLT_EPSILON 1.19209290e-7f
+#endif
+
+#ifndef M_PI
+# define M_PI 3.1415926535897932384626433832795
+#endif
+
+#ifndef M_SQRT2
+# define M_SQRT2 1.4142135623730950488016887
+#endif
+
+
+#ifndef M_2PI
+# define M_2PI 6.283185307179586476925286766559005
+#endif
+
+#ifndef M_SQRT1_2
+# define M_SQRT1_2 0.7071067811865475244008443621048490
+#endif
+
+#ifndef M_LOG_2PI
+#define M_LOG_2PI 1.8378770664093454835606594728112
+#endif
+
+#ifndef M_LN2
+#define M_LN2 0.693147180559945309417232121458
+#endif
+
+#ifdef _MSC_VER
+# define KALDI_ISNAN _isnan
+# define KALDI_ISINF(x) (!_isnan(x) && _isnan(x-x))
+# define KALDI_ISFINITE _finite
+#else
+# define KALDI_ISNAN std::isnan
+# define KALDI_ISINF std::isinf
+# define KALDI_ISFINITE(x) std::isfinite(x)
+#endif
+#if !defined(KALDI_SQR)
+# define KALDI_SQR(x) ((x) * (x))
+#endif
+
+namespace kaldi {
+
+// -infinity
+const float kLogZeroFloat = -std::numeric_limits<float>::infinity();
+const double kLogZeroDouble = -std::numeric_limits<double>::infinity();
+const BaseFloat kLogZeroBaseFloat = -std::numeric_limits<BaseFloat>::infinity();
+
+// Returns a random integer between 0 and RAND_MAX, inclusive
+int Rand(struct RandomState* state=NULL);
+
+// State for thread-safe random number generator
+struct RandomState {
+ RandomState();
+ unsigned seed;
+};
+
+// Returns a random integer between min and max inclusive.
+int32 RandInt(int32 min, int32 max, struct RandomState* state=NULL);
+
+bool WithProb(BaseFloat prob, struct RandomState* state=NULL); // Returns true with probability "prob",
+// with 0 <= prob <= 1 [we check this].
+// Internally calls Rand(). This function is carefully implemented so
+// that it should work even if prob is very small.
+
+/// Returns a random number strictly between 0 and 1.
+inline float RandUniform(struct RandomState* state = NULL) {
+ return static_cast<float>((Rand(state) + 1.0) / (RAND_MAX+2.0));
+}
+
+inline float RandGauss(struct RandomState* state = NULL) {
+ return static_cast<float>(sqrtf (-2 * logf(RandUniform(state)))
+ * cosf(2*M_PI*RandUniform(state)));
+}
+
+// Returns poisson-distributed random number. Uses Knuth's algorithm.
+// Take care: this takes time proportinal
+// to lambda. Faster algorithms exist but are more complex.
+int32 RandPoisson(float lambda, struct RandomState* state=NULL);
+
+// Returns a pair of gaussian random numbers. Uses Box-Muller transform
+void RandGauss2(float *a, float *b, RandomState *state = NULL);
+void RandGauss2(double *a, double *b, RandomState *state = NULL);
+
+// Also see Vector<float,double>::RandCategorical().
+
+// This is a randomized pruning mechanism that preserves expectations,
+// that we typically use to prune posteriors.
+template<class Float>
+inline Float RandPrune(Float post, BaseFloat prune_thresh, struct RandomState* state=NULL) {
+ KALDI_ASSERT(prune_thresh >= 0.0);
+ if (post == 0.0 || std::abs(post) >= prune_thresh)
+ return post;
+ return (post >= 0 ? 1.0 : -1.0) *
+ (RandUniform(state) <= fabs(post)/prune_thresh ? prune_thresh : 0.0);
+}
+
+static const double kMinLogDiffDouble = std::log(DBL_EPSILON); // negative!
+static const float kMinLogDiffFloat = std::log(FLT_EPSILON); // negative!
+
+inline double LogAdd(double x, double y) {
+ double diff;
+ if (x < y) {
+ diff = x - y;
+ x = y;
+ } else {
+ diff = y - x;
+ }
+ // diff is negative. x is now the larger one.
+
+ if (diff >= kMinLogDiffDouble) {
+ double res;
+#ifdef _MSC_VER
+ res = x + log(1.0 + exp(diff));
+#else
+ res = x + log1p(exp(diff));
+#endif
+ return res;
+ } else {
+ return x; // return the larger one.
+ }
+}
+
+
+inline float LogAdd(float x, float y) {
+ float diff;
+ if (x < y) {
+ diff = x - y;
+ x = y;
+ } else {
+ diff = y - x;
+ }
+ // diff is negative. x is now the larger one.
+
+ if (diff >= kMinLogDiffFloat) {
+ float res;
+#ifdef _MSC_VER
+ res = x + logf(1.0 + expf(diff));
+#else
+ res = x + log1pf(expf(diff));
+#endif
+ return res;
+ } else {
+ return x; // return the larger one.
+ }
+}
+
+
+// returns exp(x) - exp(y).
+inline double LogSub(double x, double y) {
+ if (y >= x) { // Throws exception if y>=x.
+ if (y == x)
+ return kLogZeroDouble;
+ else
+ KALDI_ERR << "Cannot subtract a larger from a smaller number.";
+ }
+
+ double diff = y - x; // Will be negative.
+ double res = x + log(1.0 - exp(diff));
+
+ // res might be NAN if diff ~0.0, and 1.0-exp(diff) == 0 to machine precision
+ if (KALDI_ISNAN(res))
+ return kLogZeroDouble;
+ return res;
+}
+
+
+// returns exp(x) - exp(y).
+inline float LogSub(float x, float y) {
+ if (y >= x) { // Throws exception if y>=x.
+ if (y == x)
+ return kLogZeroDouble;
+ else
+ KALDI_ERR << "Cannot subtract a larger from a smaller number.";
+ }
+
+ float diff = y - x; // Will be negative.
+ float res = x + logf(1.0 - expf(diff));
+
+ // res might be NAN if diff ~0.0, and 1.0-exp(diff) == 0 to machine precision
+ if (KALDI_ISNAN(res))
+ return kLogZeroFloat;
+ return res;
+}
+
+/// return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
+static inline bool ApproxEqual(float a, float b,
+ float relative_tolerance = 0.001) {
+ // a==b handles infinities.
+ if (a==b) return true;
+ float diff = std::abs(a-b);
+ if (diff == std::numeric_limits<float>::infinity()
+ || diff != diff) return false; // diff is +inf or nan.
+ return (diff <= relative_tolerance*(std::abs(a)+std::abs(b)));
+}
+
+/// assert abs(a - b) <= relative_tolerance * (abs(a)+abs(b))
+static inline void AssertEqual(float a, float b,
+ float relative_tolerance = 0.001) {
+ // a==b handles infinities.
+ KALDI_ASSERT(ApproxEqual(a, b, relative_tolerance));
+}
+
+
+// RoundUpToNearestPowerOfTwo does the obvious thing. It crashes if n <= 0.
+int32 RoundUpToNearestPowerOfTwo(int32 n);
+
+template<class I> I Gcd(I m, I n) {
+ if (m == 0 || n == 0) {
+ if (m == 0 && n == 0) { // gcd not defined, as all integers are divisors.
+ KALDI_ERR << "Undefined GCD since m = 0, n = 0.";
+ }
+ return (m == 0 ? (n > 0 ? n : -n) : ( m > 0 ? m : -m));
+ // return absolute value of whichever is nonzero
+ }
+ // could use compile-time assertion
+ // but involves messing with complex template stuff.
+ KALDI_ASSERT(std::numeric_limits<I>::is_integer);