diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-01-13 16:54:38 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-01-13 16:54:38 -0800 |
commit | 2914deb17f3857bb02eeec87a58a3ed6d4a8853a (patch) | |
tree | 5425d058e199bade4f43cf0dc526a52f4b556b71 /tests | |
parent | 7844db37f5b6dce1e7772f955ff606ef806ae032 (diff) | |
parent | ee4a2df911e834285aed9148eb4cab4546c8a063 (diff) |
Merge pull request #2004 from waywardmonkeys/updates
Updates
Diffstat (limited to 'tests')
-rw-r--r-- | tests/core/test_literal_negative_zero.in | 27 | ||||
-rw-r--r-- | tests/core/test_literal_negative_zero.out | 6 | ||||
-rw-r--r-- | tests/math/lgamma.in | 105 | ||||
-rw-r--r-- | tests/math/lgamma.out | 18 | ||||
-rw-r--r-- | tests/test_core.py | 25 |
5 files changed, 181 insertions, 0 deletions
diff --git a/tests/core/test_literal_negative_zero.in b/tests/core/test_literal_negative_zero.in new file mode 100644 index 00000000..1554fbf5 --- /dev/null +++ b/tests/core/test_literal_negative_zero.in @@ -0,0 +1,27 @@ +#include <stdio.h> +#include <math.h> + +static float XXXf = -0.0f; +static double XXXd = -0.0; + +struct x { + float f; + double d; +}; + +static struct x xx[] = { + -0x0p+0, + -0x0p+0, +}; + +int main(int argc, char ** argv) { + float YYYf = -0.0f; + float YYYd = -0.0; + + printf("%.2f\n", XXXf); + printf("%.2f\n", XXXd); + printf("%.2f\n", YYYf); + printf("%.2f\n", YYYd); + printf("%.2f\n", xx->f); + printf("%.2f\n", xx->d); +} diff --git a/tests/core/test_literal_negative_zero.out b/tests/core/test_literal_negative_zero.out new file mode 100644 index 00000000..d1b863b8 --- /dev/null +++ b/tests/core/test_literal_negative_zero.out @@ -0,0 +1,6 @@ +-0.00 +-0.00 +-0.00 +-0.00 +-0.00 +-0.00 diff --git a/tests/math/lgamma.in b/tests/math/lgamma.in new file mode 100644 index 00000000..e96f5610 --- /dev/null +++ b/tests/math/lgamma.in @@ -0,0 +1,105 @@ +#define _BSD_SOURCE 1 +#define _XOPEN_SOURCE 700 +#include <stdint.h> +#include <stdio.h> +#include <fenv.h> +#include <float.h> +#include <math.h> + +#define RN 0 +#define T(...) {__FILE__, __LINE__, __VA_ARGS__}, +#define POS const char *file; int line; +struct f_fi {POS int r; float x; float y; float dy; long long i; int e; }; + +#define DIVBYZERO 0 +#define INEXACT 0 +#define INVALID 0 +#define OVERFLOW 0 +#define UNDERFLOW 0 + +#define inf INFINITY +#define nan NAN + +static struct f_fi t[] = { +T(RN, -0x1.02239f3c6a8f1p+3, -0x1.0120f61b63d5ep+3, 0x1.89ccc4p-6, -1, INEXACT) +T(RN, 0x1.161868e18bc67p+2, 0x1.1ef3b263fd60bp+1, -0x1.6d0264p-3, 1, INEXACT) +T(RN, -0x1.0c34b3e01e6e7p+3, -0x1.46d73255263d9p+3, 0x1.e0ec76p-3, -1, INEXACT) +T(RN, -0x1.a206f0a19dcc4p+2, -0x1.9c91f19ac48c5p+2, 0x1.c2a38cp-2, -1, INEXACT) +T(RN, 0x1.288bbb0d6a1e6p+3, 0x1.65c60768fcc11p+3, 0x1.2f22c2p-2, 1, INEXACT) +T(RN, 0x1.52efd0cd80497p-1, 0x1.3cc760be720b3p-2, 0x1.0527e2p-2, 1, INEXACT) +T(RN, -0x1.a05cc754481d1p-2, 0x1.4ef387fea1014p+0, -0x1.c3b036p-2, -1, INEXACT) +T(RN, 0x1.1f9ef934745cbp-1, 0x1.d6f0efacc5699p-2, 0x1.c0b0a8p-2, 1, INEXACT) +T(RN, 0x1.8c5db097f7442p-1, 0x1.6c1a14cf91533p-3, 0x1.16f4cap-5, 1, INEXACT) +T(RN, -0x1.5b86ea8118a0ep-1, 0x1.695b1e0a0a59ep+0, 0x1.ada69ep-2, -1, INEXACT) +T(RN, 0x0p+0, inf, 0x0p+0, 1, DIVBYZERO) +/* T(RN, -0x0p+0, inf, 0x0p+0, -1, DIVBYZERO) This one fails in native as well */ +T(RN, 0x1p+0, 0x0p+0, 0x0p+0, 1, 0) +T(RN, -0x1p+0, inf, 0x0p+0, 1, DIVBYZERO) +T(RN, 0x1p+1, 0x0p+0, 0x0p+0, 1, 0) +T(RN, -0x1p+1, inf, 0x0p+0, 1, DIVBYZERO) +T(RN, inf, inf, 0x0p+0, 1, 0) +T(RN, -inf, inf, 0x0p+0, -1, 0) +T(RN, nan, nan, 0x0p+0, 1, 0) +}; + +static int eulpf(float x) +{ + union { float f; uint32_t i; } u = { x }; + int e = u.i>>23 & 0xff; + + if (!e) + e++; + return e - 0x7f - 23; +} + +static int checkulp(float d, int r) +{ + // TODO: we only care about >=1.5 ulp errors for now, should be 1.0 + if (r == RN) + return fabsf(d) < 1.5; + return 1; +} + +static float ulperrf(float got, float want, float dwant) +{ + if (isnan(got) && isnan(want)) + return 0; + if (got == want) { + if (signbit(got) == signbit(want)) + return dwant; + return INFINITY; + } + if (isinf(got)) { + got = copysignf(0x1p127, got); + want *= 0.5; + } + return scalbn(got - want, -eulpf(want)) + dwant; +} + +int main(void) +{ + int yi; + double y; + float d; + int e, i, err = 0; + struct f_fi *p; + + for (i = 0; i < sizeof t/sizeof *t; i++) { + p = t + i; + + if (p->r < 0) + continue; + y = lgammaf(p->x); + yi = signgam; + + printf("%g,%d\n", y, yi); + + d = ulperrf(y, p->y, p->dy); + if (!checkulp(d, p->r) || (!isnan(p->x) && p->x!=-inf && !(p->e&DIVBYZERO) && yi != p->i)) { + /* printf("%s:%d: %d lgammaf(%g) want %g,%lld got %g,%d ulperr %.3f = %g + %g\n", + p->file, p->line, p->r, p->x, p->y, p->i, y, yi, d, d-p->dy, p->dy); */ + err++; + } + } + return !!err; +} diff --git a/tests/math/lgamma.out b/tests/math/lgamma.out new file mode 100644 index 00000000..7412ffb6 --- /dev/null +++ b/tests/math/lgamma.out @@ -0,0 +1,18 @@ +-8.03528,-1 +2.24181,1 +-10.2138,-1 +-6.44641,-1 +11.1804,1 +0.309354,1 +1.3084,-1 +0.459903,1 +0.177784,1 +1.41155,-1 +inf,1 +0,1 +inf,1 +0,1 +inf,1 +inf,1 +inf,1 +nan,1 diff --git a/tests/test_core.py b/tests/test_core.py index 799e47f0..826437b1 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -477,6 +477,14 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) + def test_literal_negative_zero(self): + if self.emcc_args == None: return self.skip('needs emcc') + + test_path = path_from_root('tests', 'core', 'test_literal_negative_zero') + src, output = (test_path + s for s in ('.in', '.out')) + + self.do_run_from_file(src, output) + def test_llvm_intrinsics(self): if self.emcc_args == None: return self.skip('needs ta2') @@ -502,6 +510,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co def test_cube2md5(self): if self.emcc_args == None: return self.skip('needs emcc') + if not self.is_le32(): return self.skip('le32 needed for accurate math') self.emcc_args += ['--embed-file', 'cube2md5.txt'] shutil.copyfile(path_from_root('tests', 'cube2md5.txt'), os.path.join(self.get_dir(), 'cube2md5.txt')) self.do_run(open(path_from_root('tests', 'cube2md5.cpp')).read(), open(path_from_root('tests', 'cube2md5.ok')).read()) @@ -829,6 +838,15 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co expected = open(path_from_root('tests', 'hyperbolic', 'output.txt'), 'r').read() self.do_run(src, expected) + def test_math_lgamma(self): + if self.emcc_args is None: return self.skip('requires emcc') + if not self.is_le32(): return self.skip('le32 needed for accurate math') + + test_path = path_from_root('tests', 'math', 'lgamma') + src, output = (test_path + s for s in ('.in', '.out')) + + self.do_run_from_file(src, output) + def test_frexp(self): test_path = path_from_root('tests', 'core', 'test_frexp') src, output = (test_path + s for s in ('.in', '.out')) @@ -1281,6 +1299,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) + def test_white_list_exception(self): if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') @@ -3536,6 +3555,7 @@ ok def test_strtod(self): if self.emcc_args is None: return self.skip('needs emcc for libc') + if not self.is_le32(): return self.skip('le32 needed for accurate math') src = r''' #include <stdio.h> @@ -3565,6 +3585,8 @@ ok printf("%g\n", strtod("123e-50", &endptr)); printf("%g\n", strtod("123e-250", &endptr)); printf("%g\n", strtod("123e-450", &endptr)); + printf("%g\n", strtod("0x6", &endptr)); + printf("%g\n", strtod("-0x0p+0", &endptr)); char str[] = " 12.34e56end"; printf("%g\n", strtod(str, &endptr)); @@ -3597,6 +3619,8 @@ ok 1.23e-48 1.23e-248 0 + 6 + -0 1.234e+57 10 inf @@ -3681,6 +3705,7 @@ ok def test_sscanf(self): if self.emcc_args is None: return self.skip('needs emcc for libc') + if not self.is_le32(): return self.skip('le32 needed for accurate math') test_path = path_from_root('tests', 'core', 'test_sscanf') src, output = (test_path + s for s in ('.in', '.out')) |