Skip to content

Commit

Permalink
windows fixes -- resolving issues with incrrectly behaving expf/exp(f…
Browse files Browse the repository at this point in the history
…loat) under MSVC2013, plus some other improvements
  • Loading branch information
jtrmal committed Jul 22, 2015
1 parent db63ae2 commit e1f7623
Show file tree
Hide file tree
Showing 81 changed files with 365 additions and 251 deletions.
2 changes: 1 addition & 1 deletion src/base/kaldi-error.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include <sstream>
#include <cstdio>

#if _MSC_VER >= 0x1400 || !defined(MSC_VER) && __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
#if _MSC_VER >= 1900 || (!defined(_MSC_VER) && __cplusplus > 199711L) || defined(__GXX_EXPERIMENTAL_CXX0X__)
#define NOEXCEPT(Predicate) noexcept((Predicate))
#else
#define NOEXCEPT(Predicate)
Expand Down
21 changes: 12 additions & 9 deletions src/base/kaldi-math-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@
// limitations under the License.
#include "base/kaldi-math.h"
#include "base/timer.h"
#include <limits>

namespace kaldi {

template<class I> void UnitTestGcdLcmTpl() {
for (I a = 1; a < 15; a++) { // a is min gcd.
I b = (I)(Rand() % 10);
I c = (I)(Rand() % 10);
if (Rand()%2 == 0 && std::numeric_limits<I>::is_signed) b = -b;
if (Rand()%2 == 0 && std::numeric_limits<I>::is_signed) c = -c;
if (std::numeric_limits<I>::is_signed) {
if (Rand() % 2 == 0) b = -b;
if (Rand() % 2 == 0) c = -c;
}
if (b == 0 && c == 0) continue; // gcd not defined for such numbers.
I g = Gcd(b*a, c*a);
KALDI_ASSERT(g >= a);
Expand Down Expand Up @@ -157,14 +160,14 @@ void UnitTestLogAddSub() {
using namespace kaldi;
for (int i = 0; i < 100; i++) {
double f1 = Rand() % 10000, f2 = Rand() % 20;
double add1 = exp(LogAdd(log(f1), log(f2)));
double add2 = exp(LogAdd(log(f2), log(f1)));
double add1 = Exp(LogAdd(Log(f1), Log(f2)));
double add2 = Exp(LogAdd(Log(f2), Log(f1)));
double add = f1 + f2, thresh = add*0.00001;
KALDI_ASSERT(std::abs(add-add1) < thresh && std::abs(add-add2) < thresh);


try {
double f2_check = exp(LogSub(log(add), log(f1))), thresh = (f2*0.01)+0.001;
double f2_check = Exp(LogSub(Log(add), Log(f1))), thresh = (f2*0.01)+0.001;
KALDI_ASSERT(std::abs(f2_check-f2) < thresh);
} catch(...) {
KALDI_ASSERT(f2 == 0); // It will probably crash for f2=0.
Expand All @@ -173,8 +176,8 @@ void UnitTestLogAddSub() {
}

void UnitTestDefines() { // Yes, we even unit-test the preprocessor statements.
KALDI_ASSERT(exp(kLogZeroFloat) == 0.0);
KALDI_ASSERT(exp(kLogZeroDouble) == 0.0);
KALDI_ASSERT(Exp(kLogZeroFloat) == 0.0);
KALDI_ASSERT(Exp(kLogZeroDouble) == 0.0);
BaseFloat den = 0.0;
KALDI_ASSERT(KALDI_ISNAN(0.0 / den));
KALDI_ASSERT(!KALDI_ISINF(0.0 / den));
Expand All @@ -194,8 +197,8 @@ void UnitTestDefines() { // Yes, we even unit-test the preprocessor statements.
&& "If this test fails, you can probably just comment it out-- may mean your CPU exceeds expected floating point precision");
KALDI_ASSERT(std::abs(sin(M_PI)) < 1.0e-05 && std::abs(cos(M_PI)+1.0) < 1.0e-05);
KALDI_ASSERT(std::abs(sin(M_2PI)) < 1.0e-05 && std::abs(cos(M_2PI)-1.0) < 1.0e-05);
KALDI_ASSERT(std::abs(sin(exp(M_LOG_2PI))) < 1.0e-05);
KALDI_ASSERT(std::abs(cos(exp(M_LOG_2PI)) - 1.0) < 1.0e-05);
KALDI_ASSERT(std::abs(sin(Exp(M_LOG_2PI))) < 1.0e-05);
KALDI_ASSERT(std::abs(cos(Exp(M_LOG_2PI)) - 1.0) < 1.0e-05);
}

void UnitTestAssertFunc() { // Testing Assert** *functions
Expand Down
102 changes: 50 additions & 52 deletions src/base/kaldi-math.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,51 @@

namespace kaldi {

#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
inline double Exp(double x) { return exp(x); }
#ifndef KALDI_NO_EXPF
inline float Exp(float x) { return expf(x); }
#else
inline float Exp(float x) { return exp(static_cast<double>(x)); }
#endif // KALDI_NO_EXPF
#else
inline double Exp(double x) { return exp(x); }
#if !defined(__INTEL_COMPILER) && _MSC_VER == 1800 && defined(_M_X64)
// Microsoft CL v18.0 buggy 64-bit implementation of
// expf() incorrectly returns -inf for exp(-inf).
inline float Exp(float x) { return exp(static_cast<double>(x)); }
#else
inline float Exp(float x) { return expf(x); }
#endif // !defined(__INTEL_COMPILER) && _MSC_VER == 1800 && defined(_M_X64)
#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)

inline double Log(double x) { return log(x); }
inline float Log(float x) { return logf(x); }

#if !defined(_MSC_VER) || (_MSC_VER >= 1700)
inline double Log1p(double x) { return log1p(x); }
inline float Log1p(float x) { return log1pf(x); }
#else
inline double Log1p(double x) {
const double cutoff = 1.0e-08;
if (x < cutoff)
return x - 2 * x * x;
else
return Log(1.0 + x);
}

inline float Log1p(float x) {
const float cutoff = 1.0e-07;
if (x < cutoff)
return x - 2 * x * x;
else
return Log(1.0 + x);
}
#endif

static const double kMinLogDiffDouble = Log(DBL_EPSILON); // negative!
static const float kMinLogDiffFloat = Log(FLT_EPSILON); // negative!

// -infinity
const float kLogZeroFloat = -std::numeric_limits<float>::infinity();
const double kLogZeroDouble = -std::numeric_limits<double>::infinity();
Expand Down Expand Up @@ -103,7 +148,7 @@ inline float RandUniform(struct RandomState* state = NULL) {
}

inline float RandGauss(struct RandomState* state = NULL) {
return static_cast<float>(sqrtf (-2 * logf(RandUniform(state)))
return static_cast<float>(sqrtf (-2 * Log(RandUniform(state)))
* cosf(2*M_PI*RandUniform(state)));
}

Expand All @@ -129,8 +174,6 @@ inline Float RandPrune(Float post, BaseFloat prune_thresh, struct RandomState* s
(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;
Expand All @@ -144,13 +187,7 @@ inline double LogAdd(double x, double y) {

if (diff >= kMinLogDiffDouble) {
double res;
#if _MSC_VER >= 1800 || __cplusplus >= 201103L
res = x + std::log1p(std::exp(diff));
#elif defined _MSC_VER
res = x + log(1.0 + exp(diff));
#else
res = x + log1p(exp(diff));
#endif
res = x + Log1p(Exp(diff));
return res;
} else {
return x; // return the larger one.
Expand All @@ -170,13 +207,7 @@ inline float LogAdd(float x, float y) {

if (diff >= kMinLogDiffFloat) {
float res;
#if _MSC_VER >= 1800 || __cplusplus >= 201103L
res = x + std::log1p(std::exp(diff));
#elif defined _MSC_VER
res = x + logf(1.0 + expf(diff));
#else
res = x + log1pf(expf(diff));
#endif
res = x + Log1p(Exp(diff));
return res;
} else {
return x; // return the larger one.
Expand All @@ -194,7 +225,7 @@ inline double LogSub(double x, double y) {
}

double diff = y - x; // Will be negative.
double res = x + log(1.0 - exp(diff));
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))
Expand All @@ -213,7 +244,7 @@ inline float LogSub(float x, float y) {
}

float diff = y - x; // Will be negative.
float res = x + logf(1.0 - expf(diff));
float res = x + Log(1.0f - Exp(diff));

// res might be NAN if diff ~0.0, and 1.0-exp(diff) == 0 to machine precision
if (KALDI_ISNAN(res))
Expand Down Expand Up @@ -301,42 +332,9 @@ template<class I> void Factorize(I m, std::vector<I> *factors) {
}

inline double Hypot(double x, double y) { return hypot(x, y); }

inline float Hypot(float x, float y) { return hypotf(x, y); }

#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
inline double Log1p(double x) { return log1p(x); }

inline float Log1p(float x) { return log1pf(x); }
#else
inline double Log1p(double x) {
const double cutoff = 1.0e-08;
if (x < cutoff)
return x - 2 * x * x;
else
return log(1.0 + x);
}

inline float Log1p(float x) {
const float cutoff = 1.0e-07;
if (x < cutoff)
return x - 2 * x * x;
else
return log(1.0 + x);
}
#endif

inline double Exp(double x) { return exp(x); }

#ifndef KALDI_NO_EXPF
inline float Exp(float x) { return expf(x); }
#else
inline float Exp(float x) { return exp(x); }
#endif

inline double Log(double x) { return log(x); }

inline float Log(float x) { return logf(x); }


} // namespace kaldi
Expand Down
2 changes: 1 addition & 1 deletion src/bin/analyze-counts.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ int main(int argc, char *argv[]) {
// sort the counts
std::vector<std::pair<int32,int32> > sorted_counts;
for (int32 i = 0; i < counts.size(); i++) {
sorted_counts.push_back(std::make_pair(counts[i], i));
sorted_counts.push_back(std::make_pair(static_cast<int32>(counts[i]), i));
}
std::sort(sorted_counts.begin(), sorted_counts.end());

Expand Down
2 changes: 1 addition & 1 deletion src/bin/compute-mce-scale.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) {
// means it's more comparable with MMI/MPE.
BaseFloat den_score = den_score_reader.Value(key);
BaseFloat score_difference = mce_alpha * (num_score - den_score) + mce_beta;
BaseFloat sigmoid_difference = 1.0 / (1.0 + exp(score_difference));
BaseFloat sigmoid_difference = 1.0 / (1.0 + Exp(score_difference));
// It might be more natural to make the scale
//
BaseFloat scale = 4.0 * sigmoid_difference * (1 - sigmoid_difference);
Expand Down
4 changes: 2 additions & 2 deletions src/bin/get-silence-probs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ int main(int argc, char *argv[]) {
KALDI_ASSERT(quantize >= 0.0 && quantize <= 1.0);


double sil_log_bias = log(sil_prior / (1.0 - sil_prior));
double sil_log_bias = Log(sil_prior / (1.0 - sil_prior));

std::string silence_likes_rspecifier = po.GetArg(1),
nonsilence_likes_rspecifier = po.GetArg(2),
Expand Down Expand Up @@ -104,7 +104,7 @@ int main(int argc, char *argv[]) {
if (sil_loglike > 10) {
sil_probs(f) = 1.0; // because the exp below might fail.
} else {
BaseFloat e_sil_loglike = exp(sil_loglike);
BaseFloat e_sil_loglike = Exp(sil_loglike);
BaseFloat sil_prob = e_sil_loglike / (1.0 + e_sil_loglike);
if ( !(sil_prob >= 0.0 && sil_prob <= 1.0)) {
KALDI_WARN << "Bad silence prob (NaNs found?), setting to 0.5";
Expand Down
2 changes: 1 addition & 1 deletion src/bin/logprob-to-post.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ int main(int argc, char *argv[]) {
for (int32 i = 0; i < logprobs.NumRows(); i++) {
SubVector<BaseFloat> row(logprobs, i);
for (int32 j = 0; j < row.Dim(); j++) {
BaseFloat p = exp(row(j));
BaseFloat p = Exp(row(j));
if (p >= min_post) {
post[i].push_back(std::make_pair(j, p));
} else if (random_prune && (p / min_post) >= RandUniform()) {
Expand Down
2 changes: 1 addition & 1 deletion src/bin/thresh-post.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ int main(int argc, char *argv[]) {
if (weight < threshold) weight *= scale;
total_weight_out += weight;
if (weight != 0.0)
new_post[i].push_back(std::make_pair(tid, weight));
new_post[i].push_back(std::make_pair(tid, static_cast<BaseFloat>(weight)));
}
}
posterior_writer.Write(posterior_reader.Key(), new_post);
Expand Down
2 changes: 1 addition & 1 deletion src/cudamatrix/cu-matrix-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1621,7 +1621,7 @@ static void UnitTestCuDiffXent() {
//cpu
for(MatrixIndexT r=0; r<Hi.NumRows(); r++) {
int32 col_tgt = Htgt[r];
Hlogpost(r) = log(Hi(r, col_tgt));
Hlogpost(r) = Log(Hi(r, col_tgt));
Hi(r, col_tgt) -= 1.0;
}

Expand Down
4 changes: 2 additions & 2 deletions src/cudamatrix/cu-matrix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,7 @@ void CuMatrix<Real>::CompObjfAndDeriv(const std::vector<MatrixElement<Real> >& s
//KALDI_ASSERT(label >= 0 && label < nnet_.OutputDim());
Real this_prob = output(m, label);
KALDI_ASSERT(this_prob >= 0.99e-20); // we floored to 1.0e-20 in SoftmaxLayer.
*tot_objf += weight * log(this_prob);
*tot_objf += weight * Log(this_prob);
*tot_weight += weight;
(*this)(m, label) += weight / this_prob;
}
Expand Down Expand Up @@ -1399,7 +1399,7 @@ void CuMatrixBase<Real>::DiffXent(const CuArray<int32> &tgt,
for(int32 r = 0; r < num_rows; r++) {
int32 col_tgt = tgt.Data()[r];
Real &value = Mat()(r, col_tgt);
log_post_tgt->Vec()(r) = log(value);
log_post_tgt->Vec()(r) = Log(value);
value -= 1.0;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/cudamatrix/cu-vector-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ template<typename Real> void CuVectorUnitTestApplyExp() {
vector.ApplyExp();
for(int32 j = 0; j < dim; j++) {
//std::cout<<"diff is "<<exp(vector2(j))-vector(j)<<std::endl;;
KALDI_ASSERT(std::abs(exp(vector2(j))-vector(j)) < 0.000001 );
KALDI_ASSERT(std::abs(Exp(vector2(j))-vector(j)) < 0.000001 );
}

}
Expand All @@ -482,7 +482,7 @@ template<typename Real> void CuVectorUnitTestApplyLog() {
vector.ApplyLog();
for(int32 j = 0; j < dim; j++) {
//std::cout<<"diff is "<<exp(vector2(j))-vector(j)<<std::endl;;
KALDI_ASSERT(std::abs(log(vector2(j))-vector(j)) < 0.000001 );
KALDI_ASSERT(std::abs(Log(vector2(j))-vector(j)) < 0.000001 );
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/feat/feature-fbank.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace kaldi {
Fbank::Fbank(const FbankOptions &opts)
: opts_(opts), feature_window_function_(opts.frame_opts), srfft_(NULL) {
if (opts.energy_floor > 0.0)
log_energy_floor_ = log(opts.energy_floor);
log_energy_floor_ = Log(opts.energy_floor);

int32 padded_window_size = opts.frame_opts.PaddedWindowSize();
if ((padded_window_size & (padded_window_size-1)) == 0) // Is a power of two...
Expand Down Expand Up @@ -136,7 +136,7 @@ void Fbank::ComputeInternal(const VectorBase<BaseFloat> &wave,

// Compute energy after window function (not the raw one)
if (opts_.use_energy && !opts_.raw_energy)
log_energy = log(std::max(VecVec(window, window),
log_energy = Log(std::max(VecVec(window, window),
std::numeric_limits<BaseFloat>::min()));

if (srfft_ != NULL) // Compute FFT using split-radix algorithm.
Expand Down
4 changes: 2 additions & 2 deletions src/feat/feature-functions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ void ExtractWindow(const VectorBase<BaseFloat> &wave,
if (log_energy_pre_window != NULL) {
BaseFloat energy = std::max(VecVec(window_part, window_part),
std::numeric_limits<BaseFloat>::min());
*log_energy_pre_window = log(energy);
*log_energy_pre_window = Log(energy);
}

if (opts.preemph_coeff != 0.0)
Expand Down Expand Up @@ -385,7 +385,7 @@ BaseFloat ComputeLpc(const VectorBase<BaseFloat> &autocorr_in,
tmp.Data());
if (ans <= 0.0)
KALDI_WARN << "Zero energy in LPC computation";
return -log((double)1.0/ans); // forms the C0 value
return -Log((double)1.0/ans); // forms the C0 value
}

void SpliceFrames(const MatrixBase<BaseFloat> &input_features,
Expand Down
4 changes: 2 additions & 2 deletions src/feat/feature-mfcc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Mfcc::Mfcc(const MfccOptions &opts)
ComputeLifterCoeffs(opts.cepstral_lifter, &lifter_coeffs_);
}
if (opts.energy_floor > 0.0)
log_energy_floor_ = log(opts.energy_floor);
log_energy_floor_ = Log(opts.energy_floor);

int32 padded_window_size = opts.frame_opts.PaddedWindowSize();
if ((padded_window_size & (padded_window_size-1)) == 0) // Is a power of two...
Expand Down Expand Up @@ -138,7 +138,7 @@ void Mfcc::ComputeInternal(const VectorBase<BaseFloat> &wave,
(opts_.use_energy && opts_.raw_energy ? &log_energy : NULL));

if (opts_.use_energy && !opts_.raw_energy)
log_energy = log(std::max(VecVec(window, window),
log_energy = Log(std::max(VecVec(window, window),
std::numeric_limits<BaseFloat>::min()));

if (srfft_ != NULL) // Compute FFT using the split-radix algorithm.
Expand Down
Loading

0 comments on commit e1f7623

Please sign in to comment.