kaldi-math-test.cc
Go to the documentation of this file.
1 // base/kaldi-math-test.cc
2 //
3 // Copyright 2009-2011 Microsoft Corporation; Yanmin Qian; Jan Silovsky
4 
5 // See ../../COPYING for clarification regarding multiple authors
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 
11 // http://www.apache.org/licenses/LICENSE-2.0
12 
13 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
15 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
16 // MERCHANTABLITY OR NON-INFRINGEMENT.
17 // See the Apache 2 License for the specific language governing permissions and
18 // limitations under the License.
19 #include "base/kaldi-math.h"
20 #include <limits>
21 #include "base/timer.h"
22 
23 namespace kaldi {
24 
25 template<class I> void UnitTestGcdLcmTpl() {
26  for (I a = 1; a < 15; a++) { // a is min gcd.
27  I b = (I)(Rand() % 10);
28  I c = (I)(Rand() % 10);
29  if (std::numeric_limits<I>::is_signed) {
30  if (Rand() % 2 == 0) b = -b;
31  if (Rand() % 2 == 0) c = -c;
32  }
33  if (b == 0 && c == 0) continue; // gcd not defined for such numbers.
34  I g = Gcd(b*a, c*a);
35  KALDI_ASSERT(g >= a);
36  KALDI_ASSERT((b*a) % g == 0);
37  KALDI_ASSERT((c*a) % g == 0);
38 
39  // test least common multiple
40  if (b <= 0 || c <= 0) continue; // lcm not defined unless both positive.
41  I h = Lcm(b*a, c*a);
42  KALDI_ASSERT(h != 0 && (h % (b*a)) == 0 &&
43  (h % (c*a)) == 0);
44  }
45 }
46 
57  KALDI_ASSERT(RoundUpToNearestPowerOfTwo(1073700000) == 1073741824);
58 }
59 
61  for (int32 i = 0; i < 100; i++) {
62  int32 a = RandInt(-100, 100);
63  int32 b = 0;
64  while (b == 0)
65  b = RandInt(-100, 100);
67  std::floor(static_cast<double>(a) / static_cast<double>(b)));
68  }
69 }
70 
72  UnitTestGcdLcmTpl<int>();
73  UnitTestGcdLcmTpl<size_t>();
74  UnitTestGcdLcmTpl<int16>();
75 }
76 
77 void UnitTestRand() {
78  // Testing random-number generation.
79  std::cout << "Testing random-number generation. "
80  << "If there is an error this may not terminate.\n";
81  std::cout << "If this does not terminate, look more closely. "
82  << "There might be a problem [but might not be]\n";
83  for (int i = 1; i < 10; i++) {
84  { // test RandUniform.
85  std::cout << "Test RandUniform\n";
86  KALDI_ASSERT(RandUniform() >= 0 && RandUniform() <= 1);
87  float sum = RandUniform()-0.5;
88  for (int j = 0; ; j++) {
89  sum += RandUniform()-0.5;
90  if (std::abs(sum) < 0.5*sqrt(static_cast<double>(j))) break;
91  }
92  }
93  { // test RandGauss.
94  float sum = RandGauss();
95  for (int j = 0; ; j++) {
96  sum += RandGauss();
97  if (std::abs(sum) < 0.5*sqrt(static_cast<double>(j))) break;
98  }
99  }
100  { // test RandGauss.
101  float sum = RandGauss();
102  for (int j = 0; ; j++) {
103  float a, b;
104  RandGauss2(&a, &b);
105  if (i % 2 == 0) sum += a;
106  else
107  sum += b;
108  if (std::abs(sum) < 0.5*sqrt(static_cast<double>(j))) break;
109  }
110  }
111  { // test poisson_Rand().
112  KALDI_ASSERT(RandPoisson(3.0) >= 0);
113  KALDI_ASSERT(RandPoisson(0.0) == 0);
114  std::cout << "Test RandPoisson\n";
115  float lambda = RandUniform() * 3.0; // between 0 and 3.
116  double sum = RandPoisson(lambda) - lambda; // expected value is zero.
117  for (int j = 0; ; j++) {
118  sum += RandPoisson(lambda) - lambda;
119  if (std::abs(sum) < 0.5*sqrt(static_cast<double>(j))) break;
120  }
121  }
122 
123  { // test WithProb().
124  for (int32 i = 0; i < 10; i++) {
125  KALDI_ASSERT((WithProb(0.0) == false) && (WithProb(1.0) == true));
126  }
127  {
128  int32 tot = 0, n = 10000;
129  BaseFloat p = 0.5;
130  for (int32 i = 0; i < n; i++)
131  tot += WithProb(p);
132  KALDI_ASSERT(tot > (n * p * 0.8) && tot < (n * p * 1.2));
133  }
134  {
135  int32 tot = 0, n = 10000;
136  BaseFloat p = 0.25;
137  for (int32 i = 0; i < n; i++)
138  tot += WithProb(p);
139  KALDI_ASSERT(tot > (n * p * 0.8) && tot < (n * p * 1.2));
140  }
141  }
142  { // test RandInt().
143  KALDI_ASSERT(RandInt(0, 3) >= 0 && RandInt(0, 3) <= 3);
144 
145  std::cout << "Test RandInt\n";
146  int minint = Rand() % 200;
147  int maxint = minint + 1 + Rand() % 20;
148 
149  float sum = RandInt(minint, maxint) + 0.5*(minint+maxint);
150  for (int j = 0; ; j++) {
151  sum += RandInt(minint, maxint) - 0.5*(minint+maxint);
152  if (std::abs(static_cast<float>(sum)) <
153  0.5*sqrt(static_cast<double>(j))*(maxint-minint)) break;
154  }
155  }
156  { // test RandPrune in basic way.
157  KALDI_ASSERT(RandPrune(1.1, 1.0) == 1.1);
158  KALDI_ASSERT(RandPrune(0.0, 0.0) == 0.0);
159  KALDI_ASSERT(RandPrune(-1.1, 1.0) == -1.1);
160  KALDI_ASSERT(RandPrune(0.0, 1.0) == 0.0);
161  KALDI_ASSERT(RandPrune(0.5, 1.0) >= 0.0);
162  KALDI_ASSERT(RandPrune(-0.5, 1.0) <= 0.0);
163  BaseFloat f = RandPrune(-0.5, 1.0);
164  KALDI_ASSERT(f == 0.0 || f == -1.0);
165  f = RandPrune(0.5, 1.0);
166  KALDI_ASSERT(f == 0.0 || f == 1.0);
167  }
168  }
169 }
170 
172  for (int i = 0; i < 100; i++) {
173  double f1 = Rand() % 10000, f2 = Rand() % 20;
174  double add1 = Exp(LogAdd(Log(f1), Log(f2)));
175  double add2 = Exp(LogAdd(Log(f2), Log(f1)));
176  double add = f1 + f2, thresh = add*0.00001;
177  KALDI_ASSERT(std::abs(add-add1) < thresh && std::abs(add-add2) < thresh);
178 
179 
180  try {
181  double f2_check = Exp(LogSub(Log(add), Log(f1))),
182  thresh = (f2*0.01)+0.001;
183  KALDI_ASSERT(std::abs(f2_check-f2) < thresh);
184  } catch(...) {
185  KALDI_ASSERT(f2 == 0); // It will probably crash for f2=0.
186  }
187  }
188 }
189 
190 void UnitTestDefines() { // Yes, we even unit-test the preprocessor statements.
191  KALDI_ASSERT(Exp(kLogZeroFloat) == 0.0);
193  BaseFloat den = 0.0;
194  KALDI_ASSERT(KALDI_ISNAN(0.0 / den));
195  KALDI_ASSERT(!KALDI_ISINF(0.0 / den));
196  KALDI_ASSERT(!KALDI_ISFINITE(0.0 / den));
197  KALDI_ASSERT(!KALDI_ISNAN(1.0 / den));
198  KALDI_ASSERT(KALDI_ISINF(1.0 / den));
199  KALDI_ASSERT(!KALDI_ISFINITE(1.0 / den));
201  KALDI_ASSERT(!KALDI_ISINF(0.0));
202  KALDI_ASSERT(!KALDI_ISNAN(0.0));
203 
204  std::cout << 1.0+DBL_EPSILON;
205  std::cout << 1.0 + 0.5*DBL_EPSILON;
206  KALDI_ASSERT(1.0 + DBL_EPSILON != 1.0 && 1.0 + (0.5*DBL_EPSILON) == 1.0
207  && "If this test fails, you can probably just comment it out-- "
208  "may mean your CPU exceeds expected floating point precision");
209  KALDI_ASSERT(1.0f + FLT_EPSILON != 1.0f && 1.0f + (0.5f*FLT_EPSILON) == 1.0f
210  && "If this test fails, you can probably just comment it out-- "
211  "may mean your CPU exceeds expected floating point precision");
212  KALDI_ASSERT(std::abs(sin(M_PI)) < 1.0e-05
213  && std::abs(cos(M_PI)+1.0) < 1.0e-05);
214  KALDI_ASSERT(std::abs(sin(M_2PI)) < 1.0e-05
215  && std::abs(cos(M_2PI)-1.0) < 1.0e-05);
216  KALDI_ASSERT(std::abs(sin(Exp(M_LOG_2PI))) < 1.0e-05);
217  KALDI_ASSERT(std::abs(cos(Exp(M_LOG_2PI)) - 1.0) < 1.0e-05);
218 }
219 
220 void UnitTestAssertFunc() { // Testing Assert** *functions
221  for (int i = 1; i < 100; i++) {
222  float f1 = Rand() % 10000 + 1, f2 = Rand() % 20 + 1;
223  float tmp1 = f1 * f2;
224  float tmp2 = (1/f1 + 1/f2);
225  float add = f1 + f2;
226  float addeql = tmp1 * tmp2;
227  float thresh = 0.00001;
228  AssertEqual(add, addeql, thresh); // test AssertEqual()
229  }
230 }
231 
232 template<class I> void UnitTestFactorizeTpl() {
233  for (int p= 0; p < 100; p++) {
234  I m = Rand() % 100000;
235  if (m >= 1) {
236  std::vector<I> factors;
237  Factorize(m, &factors);
238  I m2 = 1;
239  for (size_t i = 0; i < factors.size(); i++) {
240  m2 *= factors[i];
241  if (i+1 < factors.size())
242  KALDI_ASSERT(factors[i+1] >= factors[i]); // check sorted.
243  }
244  KALDI_ASSERT(m2 == m); // check correctness.
245  }
246  }
247 }
248 
250  UnitTestFactorizeTpl<int>();
251  UnitTestFactorizeTpl<size_t>();
252  UnitTestFactorizeTpl<int16>();
253 }
254 
256  KALDI_ASSERT(ApproxEqual(1.0, 1.00001));
257  KALDI_ASSERT(ApproxEqual(1.0, 1.00001, 0.001));
258  KALDI_ASSERT(!ApproxEqual(1.0, 1.1));
259  KALDI_ASSERT(!ApproxEqual(1.0, 1.01, 0.001));
260  KALDI_ASSERT(!ApproxEqual(1.0, 0.0));
261  KALDI_ASSERT(ApproxEqual(0.0, 0.0));
262  KALDI_ASSERT(!ApproxEqual(0.0, 0.00001));
263  KALDI_ASSERT(!ApproxEqual(std::numeric_limits<float>::infinity(),
264  -std::numeric_limits<float>::infinity()));
265  KALDI_ASSERT(ApproxEqual(std::numeric_limits<float>::infinity(),
266  std::numeric_limits<float>::infinity()));
267  KALDI_ASSERT(ApproxEqual(-std::numeric_limits<float>::infinity(),
268  -std::numeric_limits<float>::infinity()));
269  KALDI_ASSERT(!ApproxEqual(-std::numeric_limits<float>::infinity(),
270  0));
271  KALDI_ASSERT(!ApproxEqual(-std::numeric_limits<float>::infinity(),
272  1));
273 }
274 
275 template<class Real>
277  Real sum = 0.0; // compute the sum to avoid optimizing it away.
278  Real time = 0.01; // how long this should last.
279  int block_size = 10;
280  int num_ops = 0;
281  Timer tim;
282  while (tim.Elapsed() < time) {
283  for (int i = 0; i < block_size; i++) {
284  sum += Exp((Real)i);
285  }
286  num_ops += block_size;
287  }
288  KALDI_ASSERT(sum > 0.0); // make it harder for the compiler to optimize Exp
289  // away, as we have a conditional.
290  Real flops = 1.0e-06 * num_ops / tim.Elapsed();
291  KALDI_LOG << "Megaflops doing Exp("
292  << (sizeof(Real) == 4 ? "float" : "double") << ") is " << flops;
293 }
294 
295 
296 template<class Real>
298  Real sum = 0.0; // compute the sum to avoid optimizing it away.
299  Real time = 0.01; // how long this should last.
300  int block_size = 10;
301  int num_ops = 0;
302  Timer tim;
303  while (tim.Elapsed() < time) {
304  for (int i = 0; i < block_size; i++) {
305  sum += Log(static_cast<float>(i + 1));
306  }
307  num_ops += block_size;
308  }
309  KALDI_ASSERT(sum > 0.0); // make it harder for the compiler to optimize Log
310  // away, as we have a conditional.
311  Real flops = 1.0e-06 * num_ops / tim.Elapsed();
312  KALDI_LOG << "Megaflops doing Log("
313  << (sizeof(Real) == 4 ? "float" : "double") << ") is " << flops;
314 }
315 
316 } // end namespace kaldi.
317 
318 int main() {
319  using namespace kaldi;
321  UnitTestGcdLcm();
323  UnitTestDefines();
325  UnitTestRand();
329  UnitTestExpSpeed<float>();
330  UnitTestExpSpeed<double>();
331  UnitTestLogSpeed<float>();
332  UnitTestLogSpeed<double>();
333 }
334 
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
double Exp(double x)
Definition: kaldi-math.h:83
static int32 DivideRoundingDown(int32 a, int32 b)
Returns a / b, rounding towards negative infinity in all cases.
Definition: kaldi-math.h:287
#define M_LOG_2PI
Definition: kaldi-math.h:60
#define DBL_EPSILON
Definition: kaldi-math.h:37
void UnitTestDivideRoundingDown()
void UnitTestLogAddSub()
float RandUniform(struct RandomState *state=NULL)
Returns a random number strictly between 0 and 1.
Definition: kaldi-math.h:151
#define M_PI
Definition: kaldi-math.h:44
void UnitTestDefines()
#define KALDI_ISINF
Definition: kaldi-math.h:73
bool WithProb(BaseFloat prob, struct RandomState *state)
Definition: kaldi-math.cc:72
Float RandPrune(Float post, BaseFloat prune_thresh, struct RandomState *state=NULL)
Definition: kaldi-math.h:174
void UnitTestGcdLcmTpl()
I Gcd(I m, I n)
Definition: kaldi-math.h:297
#define KALDI_ISFINITE(x)
Definition: kaldi-math.h:74
void UnitTestExpSpeed()
float RandGauss(struct RandomState *state=NULL)
Definition: kaldi-math.h:155
kaldi::int32 int32
int32 RoundUpToNearestPowerOfTwo(int32 n)
Definition: kaldi-math.cc:32
void UnitTestRoundUpToNearestPowerOfTwo()
I Lcm(I m, I n)
Returns the least common multiple of two integers.
Definition: kaldi-math.h:318
int32 RandPoisson(float lambda, struct RandomState *state)
Definition: kaldi-math.cc:126
void UnitTestGcdLcm()
float BaseFloat
Definition: kaldi-types.h:29
double Log(double x)
Definition: kaldi-math.h:100
double LogSub(double x, double y)
Definition: kaldi-math.h:228
void UnitTestLogSpeed()
void RandGauss2(float *a, float *b, RandomState *state)
Definition: kaldi-math.cc:139
struct rnnlm::@11::@12 n
void UnitTestAssertFunc()
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
double LogAdd(double x, double y)
Definition: kaldi-math.h:184
#define FLT_EPSILON
Definition: kaldi-math.h:40
#define KALDI_ISNAN
Definition: kaldi-math.h:72
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
static void AssertEqual(float a, float b, float relative_tolerance=0.001)
assert abs(a - b) <= relative_tolerance * (abs(a)+abs(b))
Definition: kaldi-math.h:276
#define M_2PI
Definition: kaldi-math.h:52
const float kLogZeroFloat
Definition: kaldi-math.h:128
void UnitTestRand()
#define KALDI_LOG
Definition: kaldi-error.h:153
const double kLogZeroDouble
Definition: kaldi-math.h:129
double Elapsed() const
Returns time in seconds.
Definition: timer.h:74
void UnitTestFactorize()
void UnitTestFactorizeTpl()
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
Definition: kaldi-math.h:265
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95
void Factorize(I m, std::vector< I > *factors)
Definition: kaldi-math.h:325
int main()
void UnitTestApproxEqual()