Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
mathutils.cc
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#include "mathutils.hh"
3#include "internal.hh"
4
5namespace Ase {
6
7} // Ase
8
9#include "testing.hh"
10
11namespace { // Anon
12using namespace Ase;
13
14TEST_INTEGRITY (mathutils_tests);
15static void
16mathutils_tests()
17{
18 float f;
19 double d;
20 // check proper Inf and NaN handling (depends on compiler flags)
21 f = d = .5 * INFINITY; TASSERT (d > 0 && f > 0 && std::isinf (f) && std::isinf (d));
22 f = d = -3 * INFINITY; TASSERT (d < 0 && f < 0 && std::isinf (f) && std::isinf (d));
23 f = f - f; TASSERT (!(f == f) && std::isnan (f)); // Infinity - Infinity yields NaN
24 d = 0.0 / 0.0; TASSERT (!(d == d) && std::isnan (d));
25 // check rounding
26 TASSERT (int (+0.40) == +0.0 && irintf (+0.40) == +0.0);
27 TASSERT (int (-0.40) == -0.0 && irintf (-0.40) == -0.0);
28 TASSERT (int (+0.51) == +0.0 && irintf (+0.51) == +1.0);
29 TASSERT (int (-0.51) == -0.0 && irintf (-0.51) == -1.0);
30 TASSERT (int (+1.90) == +1.0 && irintf (+1.90) == +2.0);
31 TASSERT (int (-1.90) == -1.0 && irintf (-1.90) == -2.0);
32 // check fast_exp2(int), 2^(-126..+127) must be calculated with 0 error
33 volatile float mf = 1.0, pf = 1.0;
34 for (ssize_t i = 0; i <= 127; i++)
35 {
36 // printerr ("2^±%-3d = %15.10g, %-.14g\n", i, fast_exp2 (i), fast_exp2 (-i));
37 TASSERT (fast_exp2 (i) == pf);
38 if (i != 127)
39 TASSERT (fast_exp2 (-i) == mf);
40 else
41 TASSERT (fast_exp2 (-i) <= mf); // single precision result for 2^-127 is 0 or subnormal
42 pf *= 2;
43 mf /= 2;
44 }
45 // check fast_exp2 error margin in [-1..+1]
46 const double exp2step = Test::slow() ? 0.0000001 : 0.0001;
47 for (d = -1; d <= +1; d += exp2step)
48 {
49 const double r = std::exp2 (d);
50 const double err = std::fabs (r - fast_exp2 (d));
51 TASSERT (err < 4e-7);
52 }
53 // check fast_log2(int), log2(2^(1..127)) must be calculated with 0 error
54 pf = 1.0;
55 for (ssize_t i = 0; i <= 127; i++)
56 {
57 if (fast_log2 (pf) != float (i))
58 printerr ("fast_log2(%.17g)=%.17g\n", pf, fast_log2 (pf));
59 TASSERT (fast_log2 (pf) == float (i));
60 pf *= 2;
61 }
62 TASSERT (-126 == fast_log2 (1.1754944e-38));
63 TASSERT ( -64 == fast_log2 (5.421011e-20));
64 TASSERT ( -16 == fast_log2 (1.525879e-5));
65 TASSERT ( -8 == fast_log2 (0.00390625));
66 TASSERT ( -4 == fast_log2 (0.0625));
67 TASSERT ( -2 == fast_log2 (0.25));
68 TASSERT ( -1 == fast_log2 (0.5));
69 TASSERT ( 0 == fast_log2 (1));
70 // check fast_log2 error margin in [1/16..16]
71 const double log2step = Test::slow() ? 0.0000001 : 0.0001;
72 for (double d = 1 / 16.; d <= 16; d += log2step)
73 {
74 const double r = std::log2 (d);
75 const double err = std::fabs (r - fast_log2 (d));
76 if (!(err < 3.8e-6))
77 printerr ("fast_log2(%.17g)=%.17g (diff=%.17g)\n", d, fast_log2 (d), r - fast_log2 (d));
78 TASSERT (err < 3.8e-6);
79 }
80}
81
82} // Anon
T exp2(T... args)
T fabs(T... args)
#define TEST_INTEGRITY(FUNC)
Register func as an integrity test.
Definition internal.hh:77
T isinf(T... args)
T isnan(T... args)
T log2(T... args)
bool slow()
Indicates whether slow tests should be run.
Definition testing.cc:171
The Anklang C++ API namespace.
Definition api.hh:9
float fast_exp2(float x)
Definition mathutils.hh:82
int irintf(float f)
Definition mathutils.hh:14
float fast_log2(float x)
Definition mathutils.hh:101
#define TASSERT(cond)
Unconditional test assertion, enters breakpoint if not fullfilled.
Definition testing.hh:24