Index: head/lib/msun/tests/cexp_test.c =================================================================== --- head/lib/msun/tests/cexp_test.c (revision 314649) +++ head/lib/msun/tests/cexp_test.c (revision 314650) @@ -1,322 +1,322 @@ /*- * Copyright (c) 2008-2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for corner cases in cexp*(). */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "test-utils.h" #pragma STDC FENV_ACCESS ON #pragma STDC CX_LIMITED_RANGE OFF /* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several * reasons, but mainly because on some architectures it's impossible * to raise FE_OVERFLOW without raising FE_INEXACT. In some cases, * whether cexp() raises an invalid exception is unspecified. * * These are macros instead of functions so that assert provides more * meaningful error messages. * * XXX The volatile here is to avoid gcc's bogus constant folding and work * around the lack of support for the FENV_ACCESS pragma. */ #define test(func, z, result, exceptmask, excepts, checksign) do { \ volatile long double complex _d = z; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(cfpequal_cs((func)(_d), (result), (checksign))); \ assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* Test within a given tolerance. */ #define test_tol(func, z, result, tol) do { \ volatile long double complex _d = z; \ assert(cfpequal_tol((func)(_d), (result), (tol), \ FPE_ABS_ZERO | CS_BOTH)); \ } while (0) /* Test all the functions that compute cexp(x). */ #define testall(x, result, exceptmask, excepts, checksign) do { \ test(cexp, x, result, exceptmask, excepts, checksign); \ test(cexpf, x, result, exceptmask, excepts, checksign); \ } while (0) /* * Test all the functions that compute cexp(x), within a given tolerance. * The tolerance is specified in ulps. */ #define testall_tol(x, result, tol) do { \ test_tol(cexp, x, result, tol * DBL_ULP()); \ test_tol(cexpf, x, result, tol * FLT_ULP()); \ } while (0) /* Various finite non-zero numbers to test. */ static const float finites[] = { -42.0e20, -1.0, -1.0e-10, -0.0, 0.0, 1.0e-10, 1.0, 42.0e20 }; /* Tests for 0 */ -void +static void test_zero(void) { /* cexp(0) = 1, no exceptions raised */ testall(0.0, 1.0, ALL_STD_EXCEPT, 0, 1); testall(-0.0, 1.0, ALL_STD_EXCEPT, 0, 1); testall(CMPLXL(0.0, -0.0), CMPLXL(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); testall(CMPLXL(-0.0, -0.0), CMPLXL(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); } /* * Tests for NaN. The signs of the results are indeterminate unless the * imaginary part is 0. */ -void -test_nan() +static void +test_nan(void) { - int i; + unsigned i; /* cexp(x + NaNi) = NaN + NaNi and optionally raises invalid */ /* cexp(NaN + yi) = NaN + NaNi and optionally raises invalid (|y|>0) */ for (i = 0; i < nitems(finites); i++) { printf("# Run %d..\n", i); testall(CMPLXL(finites[i], NAN), CMPLXL(NAN, NAN), ALL_STD_EXCEPT & ~FE_INVALID, 0, 0); if (finites[i] == 0.0) continue; /* XXX FE_INEXACT shouldn't be raised here */ testall(CMPLXL(NAN, finites[i]), CMPLXL(NAN, NAN), ALL_STD_EXCEPT & ~(FE_INVALID | FE_INEXACT), 0, 0); } /* cexp(NaN +- 0i) = NaN +- 0i */ testall(CMPLXL(NAN, 0.0), CMPLXL(NAN, 0.0), ALL_STD_EXCEPT, 0, 1); testall(CMPLXL(NAN, -0.0), CMPLXL(NAN, -0.0), ALL_STD_EXCEPT, 0, 1); /* cexp(inf + NaN i) = inf + nan i */ testall(CMPLXL(INFINITY, NAN), CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); /* cexp(-inf + NaN i) = 0 */ testall(CMPLXL(-INFINITY, NAN), CMPLXL(0.0, 0.0), ALL_STD_EXCEPT, 0, 0); /* cexp(NaN + NaN i) = NaN + NaN i */ testall(CMPLXL(NAN, NAN), CMPLXL(NAN, NAN), ALL_STD_EXCEPT, 0, 0); } -void +static void test_inf(void) { - int i; + unsigned i; /* cexp(x + inf i) = NaN + NaNi and raises invalid */ for (i = 0; i < nitems(finites); i++) { printf("# Run %d..\n", i); testall(CMPLXL(finites[i], INFINITY), CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 1); } /* cexp(-inf + yi) = 0 * (cos(y) + sin(y)i) */ /* XXX shouldn't raise an inexact exception */ testall(CMPLXL(-INFINITY, M_PI_4), CMPLXL(0.0, 0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(-INFINITY, 3 * M_PI_4), CMPLXL(-0.0, 0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(-INFINITY, 5 * M_PI_4), CMPLXL(-0.0, -0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(-INFINITY, 7 * M_PI_4), CMPLXL(0.0, -0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(-INFINITY, 0.0), CMPLXL(0.0, 0.0), ALL_STD_EXCEPT, 0, 1); testall(CMPLXL(-INFINITY, -0.0), CMPLXL(0.0, -0.0), ALL_STD_EXCEPT, 0, 1); /* cexp(inf + yi) = inf * (cos(y) + sin(y)i) (except y=0) */ /* XXX shouldn't raise an inexact exception */ testall(CMPLXL(INFINITY, M_PI_4), CMPLXL(INFINITY, INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(INFINITY, 3 * M_PI_4), CMPLXL(-INFINITY, INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(INFINITY, 5 * M_PI_4), CMPLXL(-INFINITY, -INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); testall(CMPLXL(INFINITY, 7 * M_PI_4), CMPLXL(INFINITY, -INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); /* cexp(inf + 0i) = inf + 0i */ testall(CMPLXL(INFINITY, 0.0), CMPLXL(INFINITY, 0.0), ALL_STD_EXCEPT, 0, 1); testall(CMPLXL(INFINITY, -0.0), CMPLXL(INFINITY, -0.0), ALL_STD_EXCEPT, 0, 1); } -void +static void test_reals(void) { - int i; + unsigned i; for (i = 0; i < nitems(finites); i++) { /* XXX could check exceptions more meticulously */ printf("# Run %d..\n", i); test(cexp, CMPLXL(finites[i], 0.0), CMPLXL(exp(finites[i]), 0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); test(cexp, CMPLXL(finites[i], -0.0), CMPLXL(exp(finites[i]), -0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); test(cexpf, CMPLXL(finites[i], 0.0), CMPLXL(expf(finites[i]), 0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); test(cexpf, CMPLXL(finites[i], -0.0), CMPLXL(expf(finites[i]), -0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); } } -void +static void test_imaginaries(void) { - int i; + unsigned i; for (i = 0; i < nitems(finites); i++) { printf("# Run %d..\n", i); test(cexp, CMPLXL(0.0, finites[i]), CMPLXL(cos(finites[i]), sin(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); test(cexp, CMPLXL(-0.0, finites[i]), CMPLXL(cos(finites[i]), sin(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); test(cexpf, CMPLXL(0.0, finites[i]), CMPLXL(cosf(finites[i]), sinf(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); test(cexpf, CMPLXL(-0.0, finites[i]), CMPLXL(cosf(finites[i]), sinf(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); } } -void +static void test_small(void) { static const double tests[] = { /* csqrt(a + bI) = x + yI */ /* a b x y */ 1.0, M_PI_4, M_SQRT2 * 0.5 * M_E, M_SQRT2 * 0.5 * M_E, -1.0, M_PI_4, M_SQRT2 * 0.5 / M_E, M_SQRT2 * 0.5 / M_E, 2.0, M_PI_2, 0.0, M_E * M_E, M_LN2, M_PI, -2.0, 0.0, }; double a, b; double x, y; - int i; + unsigned i; for (i = 0; i < nitems(tests); i += 4) { printf("# Run %d..\n", i); a = tests[i]; b = tests[i + 1]; x = tests[i + 2]; y = tests[i + 3]; test_tol(cexp, CMPLXL(a, b), CMPLXL(x, y), 3 * DBL_ULP()); /* float doesn't have enough precision to pass these tests */ if (x == 0 || y == 0) continue; test_tol(cexpf, CMPLXL(a, b), CMPLXL(x, y), 1 * FLT_ULP()); } } /* Test inputs with a real part r that would overflow exp(r). */ -void +static void test_large(void) { test_tol(cexp, CMPLXL(709.79, 0x1p-1074), CMPLXL(INFINITY, 8.94674309915433533273e-16), DBL_ULP()); test_tol(cexp, CMPLXL(1000, 0x1p-1074), CMPLXL(INFINITY, 9.73344457300016401328e+110), DBL_ULP()); test_tol(cexp, CMPLXL(1400, 0x1p-1074), CMPLXL(INFINITY, 5.08228858149196559681e+284), DBL_ULP()); test_tol(cexp, CMPLXL(900, 0x1.23456789abcdep-1020), CMPLXL(INFINITY, 7.42156649354218408074e+83), DBL_ULP()); test_tol(cexp, CMPLXL(1300, 0x1.23456789abcdep-1020), CMPLXL(INFINITY, 3.87514844965996756704e+257), DBL_ULP()); test_tol(cexpf, CMPLXL(88.73, 0x1p-149), CMPLXL(INFINITY, 4.80265603e-07), 2 * FLT_ULP()); test_tol(cexpf, CMPLXL(90, 0x1p-149), CMPLXL(INFINITY, 1.7101492622e-06f), 2 * FLT_ULP()); test_tol(cexpf, CMPLXL(192, 0x1p-149), CMPLXL(INFINITY, 3.396809344e+38f), 2 * FLT_ULP()); test_tol(cexpf, CMPLXL(120, 0x1.234568p-120), CMPLXL(INFINITY, 1.1163382522e+16f), 2 * FLT_ULP()); test_tol(cexpf, CMPLXL(170, 0x1.234568p-120), CMPLXL(INFINITY, 5.7878851079e+37f), 2 * FLT_ULP()); } int -main(int argc, char *argv[]) +main(void) { printf("1..7\n"); test_zero(); printf("ok 1 - cexp zero\n"); test_nan(); printf("ok 2 - cexp nan\n"); test_inf(); printf("ok 3 - cexp inf\n"); #if defined(__i386__) printf("not ok 4 - cexp reals # TODO: PR # 191676 fails assertion on i386\n"); #else test_reals(); printf("ok 4 - cexp reals\n"); #endif test_imaginaries(); printf("ok 5 - cexp imaginaries\n"); test_small(); printf("ok 6 - cexp small\n"); test_large(); printf("ok 7 - cexp large\n"); return (0); } Index: head/lib/msun/tests/conj_test.c =================================================================== --- head/lib/msun/tests/conj_test.c (revision 314649) +++ head/lib/msun/tests/conj_test.c (revision 314650) @@ -1,139 +1,139 @@ /*- * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for conj{,f,l}() */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "test-utils.h" #pragma STDC CX_LIMITED_RANGE OFF /* Make sure gcc doesn't use builtin versions of these or honor __pure2. */ static float complex (*libconjf)(float complex) = conjf; static double complex (*libconj)(double complex) = conj; static long double complex (*libconjl)(long double complex) = conjl; static float (*libcrealf)(float complex) = crealf; static double (*libcreal)(double complex) = creal; static long double (*libcreall)(long double complex) = creall; static float (*libcimagf)(float complex) = cimagf; static double (*libcimag)(double complex) = cimag; static long double (*libcimagl)(long double complex) = cimagl; static const double tests[] = { /* a + bI */ 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, -1.0, 0.0, 1.0, -0.0, 0.0, -1.0, 2.0, 4.0, 0.0, INFINITY, 0.0, -INFINITY, INFINITY, 0.0, NAN, 1.0, 1.0, NAN, NAN, NAN, -INFINITY, INFINITY, }; int -main(int argc, char *argv[]) +main(void) { static const int ntests = sizeof(tests) / sizeof(tests[0]) / 2; complex float in; complex long double expected; int i; printf("1..%d\n", ntests * 3); for (i = 0; i < ntests; i++) { __real__ expected = __real__ in = tests[2 * i]; __imag__ in = tests[2 * i + 1]; __imag__ expected = -cimag(in); assert(fpequal(libcrealf(in), __real__ in)); assert(fpequal(libcreal(in), __real__ in)); assert(fpequal(libcreall(in), __real__ in)); assert(fpequal(libcimagf(in), __imag__ in)); assert(fpequal(libcimag(in), __imag__ in)); - assert(fpequal(libcimagl(in), __imag__ in)); + assert(fpequal(libcimagl(in), __imag__ in)); feclearexcept(FE_ALL_EXCEPT); if (!cfpequal(libconjf(in), expected)) { printf("not ok %d\t# conjf(%#.2g + %#.2gI): " "wrong value\n", 3 * i + 1, creal(in), cimag(in)); } else if (fetestexcept(FE_ALL_EXCEPT)) { printf("not ok %d\t# conjf(%#.2g + %#.2gI): " "threw an exception\n", 3 * i + 1, creal(in), cimag(in)); } else { printf("ok %d\t\t# conjf(%#.2g + %#.2gI)\n", 3 * i + 1, creal(in), cimag(in)); } feclearexcept(FE_ALL_EXCEPT); if (!cfpequal(libconj(in), expected)) { printf("not ok %d\t# conj(%#.2g + %#.2gI): " "wrong value\n", 3 * i + 2, creal(in), cimag(in)); } else if (fetestexcept(FE_ALL_EXCEPT)) { printf("not ok %d\t# conj(%#.2g + %#.2gI): " "threw an exception\n", 3 * i + 2, creal(in), cimag(in)); } else { printf("ok %d\t\t# conj(%#.2g + %#.2gI)\n", 3 * i + 2, creal(in), cimag(in)); } feclearexcept(FE_ALL_EXCEPT); if (!cfpequal(libconjl(in), expected)) { printf("not ok %d\t# conjl(%#.2g + %#.2gI): " "wrong value\n", 3 * i + 3, creal(in), cimag(in)); } else if (fetestexcept(FE_ALL_EXCEPT)) { printf("not ok %d\t# conjl(%#.2g + %#.2gI): " "threw an exception\n", 3 * i + 3, creal(in), cimag(in)); } else { printf("ok %d\t\t# conjl(%#.2g + %#.2gI)\n", 3 * i + 3, creal(in), cimag(in)); } } return (0); } Index: head/lib/msun/tests/csqrt_test.c =================================================================== --- head/lib/msun/tests/csqrt_test.c (revision 314649) +++ head/lib/msun/tests/csqrt_test.c (revision 314650) @@ -1,295 +1,295 @@ /*- * Copyright (c) 2007 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for csqrt{,f}() */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include "test-utils.h" /* * This is a test hook that can point to csqrtl(), _csqrt(), or to _csqrtf(). * The latter two convert to float or double, respectively, and test csqrtf() * and csqrt() with the same arguments. */ -long double complex (*t_csqrt)(long double complex); +static long double complex (*t_csqrt)(long double complex); static long double complex _csqrtf(long double complex d) { return (csqrtf((float complex)d)); } static long double complex _csqrt(long double complex d) { return (csqrt((double complex)d)); } #pragma STDC CX_LIMITED_RANGE OFF /* * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. * Fail an assertion if they differ. */ static void assert_equal(long double complex d1, long double complex d2) { assert(cfpequal(d1, d2)); } /* * Test csqrt for some finite arguments where the answer is exact. * (We do not test if it produces correctly rounded answers when the * result is inexact, nor do we check whether it throws spurious * exceptions.) */ static void -test_finite() +test_finite(void) { static const double tests[] = { /* csqrt(a + bI) = x + yI */ /* a b x y */ 0, 8, 2, 2, 0, -8, 2, -2, 4, 0, 2, 0, -4, 0, 0, 2, 3, 4, 2, 1, 3, -4, 2, -1, -3, 4, 1, 2, -3, -4, 1, -2, 5, 12, 3, 2, 7, 24, 4, 3, 9, 40, 5, 4, 11, 60, 6, 5, 13, 84, 7, 6, 33, 56, 7, 4, 39, 80, 8, 5, 65, 72, 9, 4, 987, 9916, 74, 67, 5289, 6640, 83, 40, 460766389075.0, 16762287900.0, 678910, 12345 }; /* * We also test some multiples of the above arguments. This * array defines which multiples we use. Note that these have * to be small enough to not cause overflow for float precision * with all of the constants in the above table. */ static const double mults[] = { 1, 2, 3, 13, 16, 0x1.p30, 0x1.p-30, }; double a, b; double x, y; - int i, j; + unsigned i, j; for (i = 0; i < nitems(tests); i += 4) { for (j = 0; j < nitems(mults); j++) { a = tests[i] * mults[j] * mults[j]; b = tests[i + 1] * mults[j] * mults[j]; x = tests[i + 2] * mults[j]; y = tests[i + 3] * mults[j]; assert(t_csqrt(CMPLXL(a, b)) == CMPLXL(x, y)); } } } /* * Test the handling of +/- 0. */ static void -test_zeros() +test_zeros(void) { assert_equal(t_csqrt(CMPLXL(0.0, 0.0)), CMPLXL(0.0, 0.0)); assert_equal(t_csqrt(CMPLXL(-0.0, 0.0)), CMPLXL(0.0, 0.0)); assert_equal(t_csqrt(CMPLXL(0.0, -0.0)), CMPLXL(0.0, -0.0)); assert_equal(t_csqrt(CMPLXL(-0.0, -0.0)), CMPLXL(0.0, -0.0)); } /* * Test the handling of infinities when the other argument is not NaN. */ static void -test_infinities() +test_infinities(void) { static const double vals[] = { 0.0, -0.0, 42.0, -42.0, INFINITY, -INFINITY, }; - int i; + unsigned i; for (i = 0; i < nitems(vals); i++) { if (isfinite(vals[i])) { assert_equal(t_csqrt(CMPLXL(-INFINITY, vals[i])), CMPLXL(0.0, copysignl(INFINITY, vals[i]))); assert_equal(t_csqrt(CMPLXL(INFINITY, vals[i])), CMPLXL(INFINITY, copysignl(0.0, vals[i]))); } assert_equal(t_csqrt(CMPLXL(vals[i], INFINITY)), CMPLXL(INFINITY, INFINITY)); assert_equal(t_csqrt(CMPLXL(vals[i], -INFINITY)), CMPLXL(INFINITY, -INFINITY)); } } /* * Test the handling of NaNs. */ static void -test_nans() +test_nans(void) { assert(creall(t_csqrt(CMPLXL(INFINITY, NAN))) == INFINITY); assert(isnan(cimagl(t_csqrt(CMPLXL(INFINITY, NAN))))); assert(isnan(creall(t_csqrt(CMPLXL(-INFINITY, NAN))))); assert(isinf(cimagl(t_csqrt(CMPLXL(-INFINITY, NAN))))); assert_equal(t_csqrt(CMPLXL(NAN, INFINITY)), CMPLXL(INFINITY, INFINITY)); assert_equal(t_csqrt(CMPLXL(NAN, -INFINITY)), CMPLXL(INFINITY, -INFINITY)); assert_equal(t_csqrt(CMPLXL(0.0, NAN)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(-0.0, NAN)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(42.0, NAN)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(-42.0, NAN)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(NAN, 0.0)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(NAN, -0.0)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(NAN, 42.0)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(NAN, -42.0)), CMPLXL(NAN, NAN)); assert_equal(t_csqrt(CMPLXL(NAN, NAN)), CMPLXL(NAN, NAN)); } /* * Test whether csqrt(a + bi) works for inputs that are large enough to * cause overflow in hypot(a, b) + a. In this case we are using * csqrt(115 + 252*I) == 14 + 9*I * scaled up to near MAX_EXP. */ static void test_overflow(int maxexp) { long double a, b; long double complex result; a = ldexpl(115 * 0x1p-8, maxexp); b = ldexpl(252 * 0x1p-8, maxexp); result = t_csqrt(CMPLXL(a, b)); assert(creall(result) == ldexpl(14 * 0x1p-4, maxexp / 2)); assert(cimagl(result) == ldexpl(9 * 0x1p-4, maxexp / 2)); } int -main(int argc, char *argv[]) +main(void) { printf("1..15\n"); /* Test csqrt() */ t_csqrt = _csqrt; test_finite(); printf("ok 1 - csqrt\n"); test_zeros(); printf("ok 2 - csqrt\n"); test_infinities(); printf("ok 3 - csqrt\n"); test_nans(); printf("ok 4 - csqrt\n"); test_overflow(DBL_MAX_EXP); printf("ok 5 - csqrt\n"); /* Now test csqrtf() */ t_csqrt = _csqrtf; test_finite(); printf("ok 6 - csqrt\n"); test_zeros(); printf("ok 7 - csqrt\n"); test_infinities(); printf("ok 8 - csqrt\n"); test_nans(); printf("ok 9 - csqrt\n"); test_overflow(FLT_MAX_EXP); printf("ok 10 - csqrt\n"); /* Now test csqrtl() */ t_csqrt = csqrtl; test_finite(); printf("ok 11 - csqrt\n"); test_zeros(); printf("ok 12 - csqrt\n"); test_infinities(); printf("ok 13 - csqrt\n"); test_nans(); printf("ok 14 - csqrt\n"); test_overflow(LDBL_MAX_EXP); printf("ok 15 - csqrt\n"); return (0); } Index: head/lib/msun/tests/ctrig_test.c =================================================================== --- head/lib/msun/tests/ctrig_test.c (revision 314649) +++ head/lib/msun/tests/ctrig_test.c (revision 314650) @@ -1,490 +1,491 @@ /*- * Copyright (c) 2008-2011 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for csin[h](), ccos[h](), and ctan[h](). */ #include __FBSDID("$FreeBSD$"); +#include #include #include #include #include #include #include #include "test-utils.h" #pragma STDC FENV_ACCESS ON #pragma STDC CX_LIMITED_RANGE OFF /* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several * reasons, but mainly because on some architectures it's impossible * to raise FE_OVERFLOW without raising FE_INEXACT. * * These are macros instead of functions so that assert provides more * meaningful error messages. * * XXX The volatile here is to avoid gcc's bogus constant folding and work * around the lack of support for the FENV_ACCESS pragma. */ #define test_p(func, z, result, exceptmask, excepts, checksign) do { \ volatile long double complex _d = z; \ debug(" testing %s(%Lg + %Lg I) == %Lg + %Lg I\n", #func, \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \ ATF_CHECK(feclearexcept(FE_ALL_EXCEPT) == 0); \ ATF_CHECK(cfpequal_cs((func)(_d), (result), (checksign))); \ ATF_CHECK(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* * Test within a given tolerance. The tolerance indicates relative error * in ulps. If result is 0, however, it measures absolute error in units * of _EPSILON. */ #define test_p_tol(func, z, result, tol) do { \ volatile long double complex _d = z; \ debug(" testing %s(%Lg + %Lg I) ~= %Lg + %Lg I\n", #func, \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \ ATF_CHECK(cfpequal_tol((func)(_d), (result), (tol), FPE_ABS_ZERO)); \ } while (0) /* These wrappers apply the identities f(conj(z)) = conj(f(z)). */ #define test(func, z, result, exceptmask, excepts, checksign) do { \ test_p(func, z, result, exceptmask, excepts, checksign); \ test_p(func, conjl(z), conjl(result), exceptmask, excepts, checksign); \ } while (0) #define test_tol(func, z, result, tol) do { \ test_p_tol(func, z, result, tol); \ test_p_tol(func, conjl(z), conjl(result), tol); \ } while (0) #define test_odd_tol(func, z, result, tol) do { \ test_tol(func, z, result, tol); \ test_tol(func, -(z), -(result), tol); \ } while (0) #define test_even_tol(func, z, result, tol) do { \ test_tol(func, z, result, tol); \ test_tol(func, -(z), result, tol); \ } while (0) /* Test the given function in all precisions. */ #define testall(func, x, result, exceptmask, excepts, checksign) do { \ test(func, x, result, exceptmask, excepts, checksign); \ test(func##f, x, result, exceptmask, excepts, checksign); \ } while (0) #define testall_odd(func, x, result, exceptmask, excepts, checksign) do { \ testall(func, x, result, exceptmask, excepts, checksign); \ testall(func, -x, -result, exceptmask, excepts, checksign); \ } while (0) #define testall_even(func, x, result, exceptmask, excepts, checksign) do { \ testall(func, x, result, exceptmask, excepts, checksign); \ testall(func, -x, result, exceptmask, excepts, checksign); \ } while (0) /* * Test the given function in all precisions, within a given tolerance. * The tolerance is specified in ulps. */ #define testall_tol(func, x, result, tol) do { \ test_tol(func, x, result, tol * DBL_ULP()); \ test_tol(func##f, x, result, tol * FLT_ULP()); \ } while (0) #define testall_odd_tol(func, x, result, tol) do { \ test_odd_tol(func, x, result, tol * DBL_ULP()); \ test_odd_tol(func##f, x, result, tol * FLT_ULP()); \ } while (0) #define testall_even_tol(func, x, result, tol) do { \ test_even_tol(func, x, result, tol * DBL_ULP()); \ test_even_tol(func##f, x, result, tol * FLT_ULP()); \ } while (0) ATF_TC(test_zero_input); ATF_TC_HEAD(test_zero_input, tc) { atf_tc_set_md_var(tc, "descr", "test 0 input"); } ATF_TC_BODY(test_zero_input, tc) { long double complex zero = CMPLXL(0.0, 0.0); /* csinh(0) = ctanh(0) = 0; ccosh(0) = 1 (no exceptions raised) */ testall_odd(csinh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(csin, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_even(ccosh, zero, 1.0, ALL_STD_EXCEPT, 0, CS_BOTH); testall_even(ccos, zero, CMPLXL(1.0, -0.0), ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(ctanh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(ctan, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); } ATF_TC(test_nan_inputs); ATF_TC_HEAD(test_nan_inputs, tc) { atf_tc_set_md_var(tc, "descr", "test NaN inputs"); } ATF_TC_BODY(test_nan_inputs, tc) { long double complex nan_nan = CMPLXL(NAN, NAN); long double complex z; /* * IN CSINH CCOSH CTANH * NaN,NaN NaN,NaN NaN,NaN NaN,NaN * finite,NaN NaN,NaN [inval] NaN,NaN [inval] NaN,NaN [inval] * NaN,finite NaN,NaN [inval] NaN,NaN [inval] NaN,NaN [inval] * NaN,Inf NaN,NaN [inval] NaN,NaN [inval] NaN,NaN [inval] * Inf,NaN +-Inf,NaN Inf,NaN 1,+-0 * 0,NaN +-0,NaN NaN,+-0 NaN,NaN [inval] * NaN,0 NaN,0 NaN,+-0 NaN,0 */ z = nan_nan; testall_odd(csinh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall_even(ccosh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall_odd(ctanh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall_odd(csin, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall_even(ccos, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall_odd(ctan, z, nan_nan, ALL_STD_EXCEPT, 0, 0); z = CMPLXL(42, NAN); testall_odd(csinh, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccosh, z, nan_nan, OPT_INVALID, 0, 0); /* XXX We allow a spurious inexact exception here. */ testall_odd(ctanh, z, nan_nan, OPT_INVALID & ~FE_INEXACT, 0, 0); testall_odd(csin, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccos, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctan, z, nan_nan, OPT_INVALID, 0, 0); z = CMPLXL(NAN, 42); testall_odd(csinh, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccosh, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctanh, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(csin, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccos, z, nan_nan, OPT_INVALID, 0, 0); /* XXX We allow a spurious inexact exception here. */ testall_odd(ctan, z, nan_nan, OPT_INVALID & ~FE_INEXACT, 0, 0); z = CMPLXL(NAN, INFINITY); testall_odd(csinh, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccosh, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctanh, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(csin, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, 0, 0); testall_even(ccos, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_IMAG); testall_odd(ctan, z, CMPLXL(0, 1), ALL_STD_EXCEPT, 0, CS_IMAG); z = CMPLXL(INFINITY, NAN); testall_odd(csinh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); testall_even(ccosh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_REAL); testall_odd(ctanh, z, CMPLXL(1, 0), ALL_STD_EXCEPT, 0, CS_REAL); testall_odd(csin, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccos, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctan, z, nan_nan, OPT_INVALID, 0, 0); z = CMPLXL(0, NAN); testall_odd(csinh, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, 0, 0); testall_even(ccosh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); testall_odd(ctanh, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(csin, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); testall_even(ccos, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); testall_odd(ctan, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); z = CMPLXL(NAN, 0); testall_odd(csinh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); testall_even(ccosh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); testall_odd(ctanh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); testall_odd(csin, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); testall_even(ccos, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); testall_odd(ctan, z, nan_nan, OPT_INVALID, 0, 0); } ATF_TC(test_inf_inputs); ATF_TC_HEAD(test_inf_inputs, tc) { atf_tc_set_md_var(tc, "descr", "test infinity inputs"); } ATF_TC_BODY(test_inf_inputs, tc) { static const long double finites[] = { 0, M_PI / 4, 3 * M_PI / 4, 5 * M_PI / 4, }; long double complex z, c, s; - int i; + unsigned i; /* * IN CSINH CCOSH CTANH * Inf,Inf +-Inf,NaN inval +-Inf,NaN inval 1,+-0 * Inf,finite Inf cis(finite) Inf cis(finite) 1,0 sin(2 finite) * 0,Inf +-0,NaN inval NaN,+-0 inval NaN,NaN inval * finite,Inf NaN,NaN inval NaN,NaN inval NaN,NaN inval */ z = CMPLXL(INFINITY, INFINITY); testall_odd(csinh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); testall_even(ccosh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); testall_odd(ctanh, z, CMPLXL(1, 0), ALL_STD_EXCEPT, 0, CS_REAL); testall_odd(csin, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, FE_INVALID, 0); testall_even(ccos, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); testall_odd(ctan, z, CMPLXL(0, 1), ALL_STD_EXCEPT, 0, CS_REAL); /* XXX We allow spurious inexact exceptions here (hard to avoid). */ - for (i = 0; i < sizeof(finites) / sizeof(finites[0]); i++) { + for (i = 0; i < nitems(finites); i++) { z = CMPLXL(INFINITY, finites[i]); c = INFINITY * cosl(finites[i]); s = finites[i] == 0 ? finites[i] : INFINITY * sinl(finites[i]); testall_odd(csinh, z, CMPLXL(c, s), OPT_INEXACT, 0, CS_BOTH); testall_even(ccosh, z, CMPLXL(c, s), OPT_INEXACT, 0, CS_BOTH); testall_odd(ctanh, z, CMPLXL(1, 0 * sin(finites[i] * 2)), OPT_INEXACT, 0, CS_BOTH); z = CMPLXL(finites[i], INFINITY); testall_odd(csin, z, CMPLXL(s, c), OPT_INEXACT, 0, CS_BOTH); testall_even(ccos, z, CMPLXL(c, -s), OPT_INEXACT, 0, CS_BOTH); testall_odd(ctan, z, CMPLXL(0 * sin(finites[i] * 2), 1), OPT_INEXACT, 0, CS_BOTH); } z = CMPLXL(0, INFINITY); testall_odd(csinh, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); testall_even(ccosh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); testall_odd(ctanh, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); z = CMPLXL(INFINITY, 0); testall_odd(csin, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); testall_even(ccos, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); testall_odd(ctan, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); z = CMPLXL(42, INFINITY); testall_odd(csinh, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); testall_even(ccosh, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); /* XXX We allow a spurious inexact exception here. */ testall_odd(ctanh, z, CMPLXL(NAN, NAN), OPT_INEXACT, FE_INVALID, 0); z = CMPLXL(INFINITY, 42); testall_odd(csin, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); testall_even(ccos, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); /* XXX We allow a spurious inexact exception here. */ testall_odd(ctan, z, CMPLXL(NAN, NAN), OPT_INEXACT, FE_INVALID, 0); } ATF_TC(test_axes); ATF_TC_HEAD(test_axes, tc) { atf_tc_set_md_var(tc, "descr", "test along the real/imaginary axes"); } ATF_TC_BODY(test_axes, tc) { static const long double nums[] = { M_PI / 4, M_PI / 2, 3 * M_PI / 4, 5 * M_PI / 4, 3 * M_PI / 2, 7 * M_PI / 4, }; long double complex z; - int i; + unsigned i; - for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) { + for (i = 0; i < nitems(nums); i++) { /* Real axis */ z = CMPLXL(nums[i], 0.0); test_odd_tol(csinh, z, CMPLXL(sinh(nums[i]), 0), DBL_ULP()); test_even_tol(ccosh, z, CMPLXL(cosh(nums[i]), 0), DBL_ULP()); test_odd_tol(ctanh, z, CMPLXL(tanh(nums[i]), 0), DBL_ULP()); test_odd_tol(csin, z, CMPLXL(sin(nums[i]), copysign(0, cos(nums[i]))), DBL_ULP()); test_even_tol(ccos, z, CMPLXL(cos(nums[i]), -copysign(0, sin(nums[i]))), DBL_ULP()); test_odd_tol(ctan, z, CMPLXL(tan(nums[i]), 0), DBL_ULP()); test_odd_tol(csinhf, z, CMPLXL(sinhf(nums[i]), 0), FLT_ULP()); test_even_tol(ccoshf, z, CMPLXL(coshf(nums[i]), 0), FLT_ULP()); printf("%a %a\n", creal(z), cimag(z)); printf("%a %a\n", creal(ctanhf(z)), cimag(ctanhf(z))); printf("%a\n", nextafterf(tanhf(nums[i]), INFINITY)); test_odd_tol(ctanhf, z, CMPLXL(tanhf(nums[i]), 0), 1.3 * FLT_ULP()); test_odd_tol(csinf, z, CMPLXL(sinf(nums[i]), copysign(0, cosf(nums[i]))), FLT_ULP()); test_even_tol(ccosf, z, CMPLXL(cosf(nums[i]), -copysign(0, sinf(nums[i]))), 2 * FLT_ULP()); test_odd_tol(ctanf, z, CMPLXL(tanf(nums[i]), 0), FLT_ULP()); /* Imaginary axis */ z = CMPLXL(0.0, nums[i]); test_odd_tol(csinh, z, CMPLXL(copysign(0, cos(nums[i])), sin(nums[i])), DBL_ULP()); test_even_tol(ccosh, z, CMPLXL(cos(nums[i]), copysign(0, sin(nums[i]))), DBL_ULP()); test_odd_tol(ctanh, z, CMPLXL(0, tan(nums[i])), DBL_ULP()); test_odd_tol(csin, z, CMPLXL(0, sinh(nums[i])), DBL_ULP()); test_even_tol(ccos, z, CMPLXL(cosh(nums[i]), -0.0), DBL_ULP()); test_odd_tol(ctan, z, CMPLXL(0, tanh(nums[i])), DBL_ULP()); test_odd_tol(csinhf, z, CMPLXL(copysign(0, cosf(nums[i])), sinf(nums[i])), FLT_ULP()); test_even_tol(ccoshf, z, CMPLXL(cosf(nums[i]), copysign(0, sinf(nums[i]))), FLT_ULP()); test_odd_tol(ctanhf, z, CMPLXL(0, tanf(nums[i])), FLT_ULP()); test_odd_tol(csinf, z, CMPLXL(0, sinhf(nums[i])), FLT_ULP()); test_even_tol(ccosf, z, CMPLXL(coshf(nums[i]), -0.0), FLT_ULP()); test_odd_tol(ctanf, z, CMPLXL(0, tanhf(nums[i])), 1.3 * FLT_ULP()); } } ATF_TC(test_small_inputs); ATF_TC_HEAD(test_small_inputs, tc) { atf_tc_set_md_var(tc, "descr", "test underflow inputs"); } ATF_TC_BODY(test_small_inputs, tc) { /* * z = 0.5 + i Pi/4 * sinh(z) = (sinh(0.5) + i cosh(0.5)) * sqrt(2)/2 * cosh(z) = (cosh(0.5) + i sinh(0.5)) * sqrt(2)/2 * tanh(z) = (2cosh(0.5)sinh(0.5) + i) / (2 cosh(0.5)**2 - 1) * z = -0.5 + i Pi/2 * sinh(z) = cosh(0.5) * cosh(z) = -i sinh(0.5) * tanh(z) = -coth(0.5) * z = 1.0 + i 3Pi/4 * sinh(z) = (-sinh(1) + i cosh(1)) * sqrt(2)/2 * cosh(z) = (-cosh(1) + i sinh(1)) * sqrt(2)/2 * tanh(z) = (2cosh(1)sinh(1) - i) / (2cosh(1)**2 - 1) */ static const struct { long double a, b; long double sinh_a, sinh_b; long double cosh_a, cosh_b; long double tanh_a, tanh_b; } tests[] = { { 0.5L, 0.78539816339744830961566084581987572L, 0.36847002415910435172083660522240710L, 0.79735196663945774996093142586179334L, 0.79735196663945774996093142586179334L, 0.36847002415910435172083660522240710L, 0.76159415595576488811945828260479359L, 0.64805427366388539957497735322615032L }, { -0.5L, 1.57079632679489661923132169163975144L, 0.0L, 1.12762596520638078522622516140267201L, 0.0L, -0.52109530549374736162242562641149156L, -2.16395341373865284877000401021802312L, 0.0L }, { 1.0L, 2.35619449019234492884698253745962716L, -0.83099273328405698212637979852748608L, 1.09112278079550143030545602018565236L, -1.09112278079550143030545602018565236L, 0.83099273328405698212637979852748609L, 0.96402758007581688394641372410092315L, -0.26580222883407969212086273981988897L } }; long double complex z; - int i; + unsigned i; - for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + for (i = 0; i < nitems(tests); i++) { z = CMPLXL(tests[i].a, tests[i].b); testall_odd_tol(csinh, z, CMPLXL(tests[i].sinh_a, tests[i].sinh_b), 1.1); testall_even_tol(ccosh, z, CMPLXL(tests[i].cosh_a, tests[i].cosh_b), 1.1); testall_odd_tol(ctanh, z, CMPLXL(tests[i].tanh_a, tests[i].tanh_b), 1.4); } } ATF_TC(test_large_inputs); ATF_TC_HEAD(test_large_inputs, tc) { atf_tc_set_md_var(tc, "descr", "Test inputs that might cause overflow in a sloppy implementation"); } ATF_TC_BODY(test_large_inputs, tc) { long double complex z; #ifdef __i386__ atf_tc_expect_fail("test fails on i386 - bug 205446"); #endif /* tanh() uses a threshold around x=22, so check both sides. */ z = CMPLXL(21, 0.78539816339744830961566084581987572L); testall_odd_tol(ctanh, z, CMPLXL(1.0, 1.14990445285871196133287617611468468e-18L), 1.2); z++; testall_odd_tol(ctanh, z, CMPLXL(1.0, 1.55622644822675930314266334585597964e-19L), 1); z = CMPLXL(355, 0.78539816339744830961566084581987572L); test_odd_tol(ctanh, z, CMPLXL(1.0, 8.95257245135025991216632140458264468e-309L), DBL_ULP()); z = CMPLXL(30, 0x1p1023L); test_odd_tol(ctanh, z, CMPLXL(1.0, -1.62994325413993477997492170229268382e-26L), DBL_ULP()); z = CMPLXL(1, 0x1p1023L); test_odd_tol(ctanh, z, CMPLXL(0.878606311888306869546254022621986509L, -0.225462792499754505792678258169527424L), DBL_ULP()); z = CMPLXL(710.6, 0.78539816339744830961566084581987572L); test_odd_tol(csinh, z, CMPLXL(1.43917579766621073533185387499658944e308L, 1.43917579766621073533185387499658944e308L), DBL_ULP()); test_even_tol(ccosh, z, CMPLXL(1.43917579766621073533185387499658944e308L, 1.43917579766621073533185387499658944e308L), DBL_ULP()); z = CMPLXL(1500, 0.78539816339744830961566084581987572L); testall_odd(csinh, z, CMPLXL(INFINITY, INFINITY), OPT_INEXACT, FE_OVERFLOW, CS_BOTH); testall_even(ccosh, z, CMPLXL(INFINITY, INFINITY), OPT_INEXACT, FE_OVERFLOW, CS_BOTH); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, test_zero_input); ATF_TP_ADD_TC(tp, test_nan_inputs); ATF_TP_ADD_TC(tp, test_inf_inputs); ATF_TP_ADD_TC(tp, test_axes); ATF_TP_ADD_TC(tp, test_small_inputs); ATF_TP_ADD_TC(tp, test_large_inputs); return (atf_no_error()); } Index: head/lib/msun/tests/exponential_test.c =================================================================== --- head/lib/msun/tests/exponential_test.c (revision 314649) +++ head/lib/msun/tests/exponential_test.c (revision 314650) @@ -1,169 +1,169 @@ /*- * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for corner cases in exp*(). */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #ifdef __i386__ #include #endif #include "test-utils.h" #pragma STDC FENV_ACCESS ON /* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several * reasoons, but mainly because on some architectures it's impossible * to raise FE_OVERFLOW without raising FE_INEXACT. * * These are macros instead of functions so that assert provides more * meaningful error messages. * * XXX The volatile here is to avoid gcc's bogus constant folding and work * around the lack of support for the FENV_ACCESS pragma. */ #define test(func, x, result, exceptmask, excepts) do { \ volatile long double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_d), (result))); \ assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* Test all the functions that compute b^x. */ #define _testall0(x, result, exceptmask, excepts) do { \ test(exp, x, result, exceptmask, excepts); \ test(expf, x, result, exceptmask, excepts); \ test(exp2, x, result, exceptmask, excepts); \ test(exp2f, x, result, exceptmask, excepts); \ } while (0) /* Skip over exp2l on platforms that don't support it. */ #if LDBL_PREC == 53 #define testall0 _testall0 #else #define testall0(x, result, exceptmask, excepts) do { \ _testall0(x, result, exceptmask, excepts); \ test(exp2l, x, result, exceptmask, excepts); \ } while (0) #endif /* Test all the functions that compute b^x - 1. */ #define testall1(x, result, exceptmask, excepts) do { \ test(expm1, x, result, exceptmask, excepts); \ test(expm1f, x, result, exceptmask, excepts); \ } while (0) -void +static void run_generic_tests(void) { /* exp(0) == 1, no exceptions raised */ testall0(0.0, 1.0, ALL_STD_EXCEPT, 0); testall1(0.0, 0.0, ALL_STD_EXCEPT, 0); testall0(-0.0, 1.0, ALL_STD_EXCEPT, 0); testall1(-0.0, -0.0, ALL_STD_EXCEPT, 0); /* exp(NaN) == NaN, no exceptions raised */ testall0(NAN, NAN, ALL_STD_EXCEPT, 0); testall1(NAN, NAN, ALL_STD_EXCEPT, 0); /* exp(Inf) == Inf, no exceptions raised */ testall0(INFINITY, INFINITY, ALL_STD_EXCEPT, 0); testall1(INFINITY, INFINITY, ALL_STD_EXCEPT, 0); /* exp(-Inf) == 0, no exceptions raised */ testall0(-INFINITY, 0.0, ALL_STD_EXCEPT, 0); testall1(-INFINITY, -1.0, ALL_STD_EXCEPT, 0); #if !defined(__i386__) /* exp(big) == Inf, overflow exception */ testall0(50000.0, INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_OVERFLOW); testall1(50000.0, INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_OVERFLOW); /* exp(small) == 0, underflow and inexact exceptions */ testall0(-50000.0, 0.0, ALL_STD_EXCEPT, FE_UNDERFLOW | FE_INEXACT); #endif testall1(-50000.0, -1.0, ALL_STD_EXCEPT, FE_INEXACT); } -void +static void run_exp2_tests(void) { - int i; + unsigned i; /* * We should insist that exp2() return exactly the correct * result and not raise an inexact exception for integer * arguments. */ feclearexcept(FE_ALL_EXCEPT); for (i = FLT_MIN_EXP - FLT_MANT_DIG; i < FLT_MAX_EXP; i++) { assert(exp2f(i) == ldexpf(1.0, i)); assert(fetestexcept(ALL_STD_EXCEPT) == 0); } for (i = DBL_MIN_EXP - DBL_MANT_DIG; i < DBL_MAX_EXP; i++) { assert(exp2(i) == ldexp(1.0, i)); assert(fetestexcept(ALL_STD_EXCEPT) == 0); } for (i = LDBL_MIN_EXP - LDBL_MANT_DIG; i < LDBL_MAX_EXP; i++) { assert(exp2l(i) == ldexpl(1.0, i)); assert(fetestexcept(ALL_STD_EXCEPT) == 0); } } int -main(int argc, char *argv[]) +main(void) { printf("1..3\n"); run_generic_tests(); printf("ok 1 - exponential\n"); #ifdef __i386__ fpsetprec(FP_PE); run_generic_tests(); #endif printf("ok 2 - exponential\n"); run_exp2_tests(); printf("ok 3 - exponential\n"); return (0); } Index: head/lib/msun/tests/fenv_test.c =================================================================== --- head/lib/msun/tests/fenv_test.c (revision 314649) +++ head/lib/msun/tests/fenv_test.c (revision 314650) @@ -1,576 +1,563 @@ /*- * Copyright (c) 2004 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Test the correctness and C99-compliance of various fenv.h features. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include /* * Implementations are permitted to define additional exception flags * not specified in the standard, so it is not necessarily true that * FE_ALL_EXCEPT == ALL_STD_EXCEPT. */ #define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ FE_OVERFLOW | FE_UNDERFLOW) #define NEXCEPTS (sizeof(std_excepts) / sizeof(std_excepts[0])) static const int std_excepts[] = { FE_INVALID, FE_DIVBYZERO, FE_OVERFLOW, FE_UNDERFLOW, FE_INEXACT, }; /* init_exceptsets() initializes this to the power set of std_excepts[] */ static int std_except_sets[1 << NEXCEPTS]; -static void init_exceptsets(void); - -static void test_dfl_env(void); -static void test_fegsetenv(void); -static void test_fegsetexceptflag(void); -static void test_masking(void); -static void test_fegsetround(void); -static void test_feholdupdate(void); -static void test_feraiseexcept(void); -static void test_fetestclearexcept(void); - -static int getround(void); -static void raiseexcept(int excepts); -static void trap_handler(int sig); - #pragma STDC FENV_ACCESS ON -int -main(int argc, char *argv[]) -{ - - printf("1..8\n"); - init_exceptsets(); - test_dfl_env(); - printf("ok 1 - fenv\n"); - test_fetestclearexcept(); - printf("ok 2 - fenv\n"); - test_fegsetexceptflag(); - printf("ok 3 - fenv\n"); - test_feraiseexcept(); - printf("ok 4 - fenv\n"); - test_fegsetround(); - printf("ok 5 - fenv\n"); - test_fegsetenv(); - printf("ok 6 - fenv\n"); - test_masking(); - printf("ok 7 - fenv\n"); - test_feholdupdate(); - printf("ok 8 - fenv\n"); - - return (0); -} - /* * Initialize std_except_sets[] to the power set of std_excepts[] */ -void +static void init_exceptsets(void) { - int i, j, sr; + unsigned i, j, sr; for (i = 0; i < 1 << NEXCEPTS; i++) { for (sr = i, j = 0; sr != 0; sr >>= 1, j++) std_except_sets[i] |= std_excepts[j] & ((~sr & 1) - 1); } } /* + * Raise a floating-point exception without relying on the standard + * library routines, which we are trying to test. + * + * XXX We can't raise an {over,under}flow without also raising an + * inexact exception. + */ +static void +raiseexcept(int excepts) +{ + volatile double d; + + /* + * With a compiler that supports the FENV_ACCESS pragma + * properly, simple expressions like '0.0 / 0.0' should + * be sufficient to generate traps. Unfortunately, we + * need to bring a volatile variable into the equation + * to prevent incorrect optimizations. + */ + if (excepts & FE_INVALID) { + d = 0.0; + d = 0.0 / d; + } + if (excepts & FE_DIVBYZERO) { + d = 0.0; + d = 1.0 / d; + } + if (excepts & FE_OVERFLOW) { + d = DBL_MAX; + d *= 2.0; + } + if (excepts & FE_UNDERFLOW) { + d = DBL_MIN; + d /= DBL_MAX; + } + if (excepts & FE_INEXACT) { + d = DBL_MIN; + d += 1.0; + } + + /* + * On the x86 (and some other architectures?) the FPU and + * integer units are decoupled. We need to execute an FWAIT + * or a floating-point instruction to get synchronous exceptions. + */ + d = 1.0; + d += 1.0; +} + +/* + * Determine the current rounding mode without relying on the fenv + * routines. This function may raise an inexact exception. + */ +static int +getround(void) +{ + volatile double d; + + /* + * This test works just as well with 0.0 - 0.0, except on ia64 + * where 0.0 - 0.0 gives the wrong sign when rounding downwards. + */ + d = 1.0; + d -= 1.0; + if (copysign(1.0, d) < 0.0) + return (FE_DOWNWARD); + + d = 1.0; + if (d + (DBL_EPSILON * 3.0 / 4.0) == 1.0) + return (FE_TOWARDZERO); + if (d + (DBL_EPSILON * 1.0 / 4.0) > 1.0) + return (FE_UPWARD); + + return (FE_TONEAREST); +} + +static void +trap_handler(int sig) +{ + + assert(sig == SIGFPE); + _exit(0); +} + +/* * This tests checks the default FP environment, so it must be first. * The memcmp() test below may be too much to ask for, since there * could be multiple machine-specific default environments. */ static void test_dfl_env(void) { #ifndef NO_STRICT_DFL_ENV fenv_t env; fegetenv(&env); #ifdef __amd64__ /* * Compare the fields that the AMD [1] and Intel [2] specs say will be * set once fnstenv returns. * * Not all amd64 capable processors implement the fnstenv instruction * by zero'ing out the env.__x87.__other field (example: AMD Opteron * 6308). The AMD64/x64 specs aren't explicit on what the * env.__x87.__other field will contain after fnstenv is executed, so * the values in env.__x87.__other could be filled with arbitrary * data depending on how the CPU implements fnstenv. * * 1. http://support.amd.com/TechDocs/26569_APM_v5.pdf * 2. http://www.intel.com/Assets/en_US/PDF/manual/253666.pdf */ assert(memcmp(&env.__mxcsr, &FE_DFL_ENV->__mxcsr, sizeof(env.__mxcsr)) == 0); assert(memcmp(&env.__x87.__control, &FE_DFL_ENV->__x87.__control, sizeof(env.__x87.__control)) == 0); assert(memcmp(&env.__x87.__status, &FE_DFL_ENV->__x87.__status, sizeof(env.__x87.__status)) == 0); assert(memcmp(&env.__x87.__tag, &FE_DFL_ENV->__x87.__tag, sizeof(env.__x87.__tag)) == 0); #else assert(memcmp(&env, FE_DFL_ENV, sizeof(env)) == 0); #endif #endif assert(fetestexcept(FE_ALL_EXCEPT) == 0); } /* * Test fetestexcept() and feclearexcept(). */ static void test_fetestclearexcept(void) { int excepts, i; for (i = 0; i < 1 << NEXCEPTS; i++) assert(fetestexcept(std_except_sets[i]) == 0); for (i = 0; i < 1 << NEXCEPTS; i++) { excepts = std_except_sets[i]; /* FE_ALL_EXCEPT might be special-cased, as on i386. */ raiseexcept(excepts); assert(fetestexcept(excepts) == excepts); assert(feclearexcept(FE_ALL_EXCEPT) == 0); assert(fetestexcept(FE_ALL_EXCEPT) == 0); raiseexcept(excepts); assert(fetestexcept(excepts) == excepts); if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0) { excepts |= FE_INEXACT; assert((fetestexcept(ALL_STD_EXCEPT) | FE_INEXACT) == excepts); } else { assert(fetestexcept(ALL_STD_EXCEPT) == excepts); } assert(feclearexcept(excepts) == 0); assert(fetestexcept(ALL_STD_EXCEPT) == 0); } } /* * Test fegetexceptflag() and fesetexceptflag(). * * Prerequisites: fetestexcept(), feclearexcept() */ static void test_fegsetexceptflag(void) { fexcept_t flag; int excepts, i; assert(fetestexcept(FE_ALL_EXCEPT) == 0); for (i = 0; i < 1 << NEXCEPTS; i++) { excepts = std_except_sets[i]; assert(fegetexceptflag(&flag, excepts) == 0); raiseexcept(ALL_STD_EXCEPT); assert(fesetexceptflag(&flag, excepts) == 0); assert(fetestexcept(ALL_STD_EXCEPT) == (ALL_STD_EXCEPT ^ excepts)); assert(fegetexceptflag(&flag, FE_ALL_EXCEPT) == 0); assert(feclearexcept(FE_ALL_EXCEPT) == 0); assert(fesetexceptflag(&flag, excepts) == 0); assert(fetestexcept(ALL_STD_EXCEPT) == 0); assert(fesetexceptflag(&flag, ALL_STD_EXCEPT ^ excepts) == 0); assert(fetestexcept(ALL_STD_EXCEPT) == (ALL_STD_EXCEPT ^ excepts)); assert(feclearexcept(FE_ALL_EXCEPT) == 0); } } /* * Test feraiseexcept(). * * Prerequisites: fetestexcept(), feclearexcept() */ static void test_feraiseexcept(void) { int excepts, i; for (i = 0; i < 1 << NEXCEPTS; i++) { excepts = std_except_sets[i]; assert(fetestexcept(FE_ALL_EXCEPT) == 0); assert(feraiseexcept(excepts) == 0); if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0) { excepts |= FE_INEXACT; assert((fetestexcept(ALL_STD_EXCEPT) | FE_INEXACT) == excepts); } else { assert(fetestexcept(ALL_STD_EXCEPT) == excepts); } assert(feclearexcept(FE_ALL_EXCEPT) == 0); } assert(feraiseexcept(FE_INVALID | FE_DIVBYZERO) == 0); assert(fetestexcept(ALL_STD_EXCEPT) == (FE_INVALID | FE_DIVBYZERO)); assert(feraiseexcept(FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) == 0); assert(fetestexcept(ALL_STD_EXCEPT) == ALL_STD_EXCEPT); assert(feclearexcept(FE_ALL_EXCEPT) == 0); } /* * Test fegetround() and fesetround(). */ static void test_fegsetround(void) { assert(fegetround() == FE_TONEAREST); assert(getround() == FE_TONEAREST); assert(FLT_ROUNDS == 1); assert(fesetround(FE_DOWNWARD) == 0); assert(fegetround() == FE_DOWNWARD); assert(getround() == FE_DOWNWARD); assert(FLT_ROUNDS == 3); assert(fesetround(FE_UPWARD) == 0); assert(getround() == FE_UPWARD); assert(fegetround() == FE_UPWARD); assert(FLT_ROUNDS == 2); assert(fesetround(FE_TOWARDZERO) == 0); assert(getround() == FE_TOWARDZERO); assert(fegetround() == FE_TOWARDZERO); assert(FLT_ROUNDS == 0); assert(fesetround(FE_TONEAREST) == 0); assert(getround() == FE_TONEAREST); assert(FLT_ROUNDS == 1); assert(feclearexcept(FE_ALL_EXCEPT) == 0); } /* * Test fegetenv() and fesetenv(). * * Prerequisites: fetestexcept(), feclearexcept(), fegetround(), fesetround() */ static void test_fegsetenv(void) { fenv_t env1, env2; int excepts, i; for (i = 0; i < 1 << NEXCEPTS; i++) { excepts = std_except_sets[i]; assert(fetestexcept(FE_ALL_EXCEPT) == 0); assert(fegetround() == FE_TONEAREST); assert(fegetenv(&env1) == 0); /* * fe[gs]etenv() should be able to save and restore * exception flags without the spurious inexact * exceptions that afflict raiseexcept(). */ raiseexcept(excepts); if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0 && (excepts & FE_INEXACT) == 0) assert(feclearexcept(FE_INEXACT) == 0); fesetround(FE_DOWNWARD); assert(fegetenv(&env2) == 0); assert(fesetenv(&env1) == 0); assert(fetestexcept(FE_ALL_EXCEPT) == 0); assert(fegetround() == FE_TONEAREST); assert(fesetenv(&env2) == 0); assert(fetestexcept(FE_ALL_EXCEPT) == excepts); assert(fegetround() == FE_DOWNWARD); assert(fesetenv(&env1) == 0); assert(fetestexcept(FE_ALL_EXCEPT) == 0); assert(fegetround() == FE_TONEAREST); } } /* * Test fegetexcept(), fedisableexcept(), and feenableexcept(). * * Prerequisites: fetestexcept(), feraiseexcept() */ static void test_masking(void) { struct sigaction act; - int except, i, pass, raise, status; + int except, pass, raise, status; + unsigned i; assert((fegetexcept() & ALL_STD_EXCEPT) == 0); assert((feenableexcept(FE_INVALID|FE_OVERFLOW) & ALL_STD_EXCEPT) == 0); assert((feenableexcept(FE_UNDERFLOW) & ALL_STD_EXCEPT) == (FE_INVALID | FE_OVERFLOW)); assert((fedisableexcept(FE_OVERFLOW) & ALL_STD_EXCEPT) == (FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)); assert((fegetexcept() & ALL_STD_EXCEPT) == (FE_INVALID | FE_UNDERFLOW)); assert((fedisableexcept(FE_ALL_EXCEPT) & ALL_STD_EXCEPT) == (FE_INVALID | FE_UNDERFLOW)); assert((fegetexcept() & ALL_STD_EXCEPT) == 0); sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = trap_handler; for (pass = 0; pass < 2; pass++) { for (i = 0; i < NEXCEPTS; i++) { except = std_excepts[i]; /* over/underflow may also raise inexact */ if (except == FE_INEXACT) raise = FE_DIVBYZERO | FE_INVALID; else raise = ALL_STD_EXCEPT ^ except; /* * We need to fork a child process because * there isn't a portable way to recover from * a floating-point exception. */ switch(fork()) { case 0: /* child */ assert((fegetexcept() & ALL_STD_EXCEPT) == 0); assert((feenableexcept(except) & ALL_STD_EXCEPT) == 0); assert(fegetexcept() == except); raiseexcept(raise); assert(feraiseexcept(raise) == 0); assert(fetestexcept(ALL_STD_EXCEPT) == raise); assert(sigaction(SIGFPE, &act, NULL) == 0); switch (pass) { case 0: raiseexcept(except); case 1: feraiseexcept(except); default: assert(0); } assert(0); default: /* parent */ assert(wait(&status) > 0); /* * Avoid assert() here so that it's possible * to examine a failed child's core dump. */ if (!WIFEXITED(status)) errx(1, "child aborted\n"); assert(WEXITSTATUS(status) == 0); break; case -1: /* error */ assert(0); } } } assert(fetestexcept(FE_ALL_EXCEPT) == 0); } /* * Test feholdexcept() and feupdateenv(). * * Prerequisites: fetestexcept(), fegetround(), fesetround(), * fedisableexcept(), feenableexcept() */ static void test_feholdupdate(void) { fenv_t env; struct sigaction act; - int except, i, pass, status, raise; + int except, pass, status, raise; + unsigned i; sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = trap_handler; for (pass = 0; pass < 2; pass++) { for (i = 0; i < NEXCEPTS; i++) { except = std_excepts[i]; /* over/underflow may also raise inexact */ if (except == FE_INEXACT) raise = FE_DIVBYZERO | FE_INVALID; else raise = ALL_STD_EXCEPT ^ except; /* * We need to fork a child process because * there isn't a portable way to recover from * a floating-point exception. */ switch(fork()) { case 0: /* child */ /* * We don't want to cause a fatal exception in * the child until the second pass, so we can * check other properties of feupdateenv(). - */ + */ if (pass == 1) assert((feenableexcept(except) & ALL_STD_EXCEPT) == 0); raiseexcept(raise); assert(fesetround(FE_DOWNWARD) == 0); assert(feholdexcept(&env) == 0); assert(fetestexcept(FE_ALL_EXCEPT) == 0); raiseexcept(except); assert(fesetround(FE_UPWARD) == 0); if (pass == 1) assert(sigaction(SIGFPE, &act, NULL) == 0); assert(feupdateenv(&env) == 0); assert(fegetround() == FE_DOWNWARD); assert(fetestexcept(ALL_STD_EXCEPT) == (except | raise)); assert(pass == 0); _exit(0); default: /* parent */ assert(wait(&status) > 0); /* * Avoid assert() here so that it's possible * to examine a failed child's core dump. */ if (!WIFEXITED(status)) errx(1, "child aborted\n"); assert(WEXITSTATUS(status) == 0); break; case -1: /* error */ assert(0); } } } assert(fetestexcept(FE_ALL_EXCEPT) == 0); } -/* - * Raise a floating-point exception without relying on the standard - * library routines, which we are trying to test. - * - * XXX We can't raise an {over,under}flow without also raising an - * inexact exception. - */ -static void -raiseexcept(int excepts) +int +main(void) { - volatile double d; - /* - * With a compiler that supports the FENV_ACCESS pragma - * properly, simple expressions like '0.0 / 0.0' should - * be sufficient to generate traps. Unfortunately, we - * need to bring a volatile variable into the equation - * to prevent incorrect optimizations. - */ - if (excepts & FE_INVALID) { - d = 0.0; - d = 0.0 / d; - } - if (excepts & FE_DIVBYZERO) { - d = 0.0; - d = 1.0 / d; - } - if (excepts & FE_OVERFLOW) { - d = DBL_MAX; - d *= 2.0; - } - if (excepts & FE_UNDERFLOW) { - d = DBL_MIN; - d /= DBL_MAX; - } - if (excepts & FE_INEXACT) { - d = DBL_MIN; - d += 1.0; - } + printf("1..8\n"); + init_exceptsets(); + test_dfl_env(); + printf("ok 1 - fenv\n"); + test_fetestclearexcept(); + printf("ok 2 - fenv\n"); + test_fegsetexceptflag(); + printf("ok 3 - fenv\n"); + test_feraiseexcept(); + printf("ok 4 - fenv\n"); + test_fegsetround(); + printf("ok 5 - fenv\n"); + test_fegsetenv(); + printf("ok 6 - fenv\n"); + test_masking(); + printf("ok 7 - fenv\n"); + test_feholdupdate(); + printf("ok 8 - fenv\n"); - /* - * On the x86 (and some other architectures?) the FPU and - * integer units are decoupled. We need to execute an FWAIT - * or a floating-point instruction to get synchronous exceptions. - */ - d = 1.0; - d += 1.0; -} - -/* - * Determine the current rounding mode without relying on the fenv - * routines. This function may raise an inexact exception. - */ -static int -getround(void) -{ - volatile double d; - - /* - * This test works just as well with 0.0 - 0.0, except on ia64 - * where 0.0 - 0.0 gives the wrong sign when rounding downwards. - */ - d = 1.0; - d -= 1.0; - if (copysign(1.0, d) < 0.0) - return (FE_DOWNWARD); - - d = 1.0; - if (d + (DBL_EPSILON * 3.0 / 4.0) == 1.0) - return (FE_TOWARDZERO); - if (d + (DBL_EPSILON * 1.0 / 4.0) > 1.0) - return (FE_UPWARD); - - return (FE_TONEAREST); -} - -static void -trap_handler(int sig) -{ - - assert(sig == SIGFPE); - _exit(0); + return (0); } Index: head/lib/msun/tests/fma_test.c =================================================================== --- head/lib/msun/tests/fma_test.c (revision 314649) +++ head/lib/msun/tests/fma_test.c (revision 314650) @@ -1,543 +1,543 @@ /*- * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for fma{,f,l}(). */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "test-utils.h" #pragma STDC FENV_ACCESS ON /* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several * reasons, but mainly because on some architectures it's impossible * to raise FE_OVERFLOW without raising FE_INEXACT. * * These are macros instead of functions so that assert provides more * meaningful error messages. */ #define test(func, x, y, z, result, exceptmask, excepts) do { \ volatile long double _vx = (x), _vy = (y), _vz = (z); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_vx, _vy, _vz), (result))); \ assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) #define testall(x, y, z, result, exceptmask, excepts) do { \ test(fma, (double)(x), (double)(y), (double)(z), \ (double)(result), (exceptmask), (excepts)); \ test(fmaf, (float)(x), (float)(y), (float)(z), \ (float)(result), (exceptmask), (excepts)); \ test(fmal, (x), (y), (z), (result), (exceptmask), (excepts)); \ } while (0) /* Test in all rounding modes. */ #define testrnd(func, x, y, z, rn, ru, rd, rz, exceptmask, excepts) do { \ fesetround(FE_TONEAREST); \ test((func), (x), (y), (z), (rn), (exceptmask), (excepts)); \ fesetround(FE_UPWARD); \ test((func), (x), (y), (z), (ru), (exceptmask), (excepts)); \ fesetround(FE_DOWNWARD); \ test((func), (x), (y), (z), (rd), (exceptmask), (excepts)); \ fesetround(FE_TOWARDZERO); \ test((func), (x), (y), (z), (rz), (exceptmask), (excepts)); \ } while (0) /* * This is needed because clang constant-folds fma in ways that are incorrect * in rounding modes other than FE_TONEAREST. */ -volatile double one = 1.0; +static volatile double one = 1.0; static void test_zeroes(void) { const int rd = (fegetround() == FE_DOWNWARD); testall(0.0, 0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0); testall(1.0, 0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0); testall(0.0, 1.0, 0.0, 0.0, ALL_STD_EXCEPT, 0); testall(0.0, 0.0, 1.0, 1.0, ALL_STD_EXCEPT, 0); testall(-0.0, 0.0, 0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); testall(0.0, -0.0, 0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); testall(-0.0, -0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0); testall(0.0, 0.0, -0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); testall(-0.0, -0.0, -0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); testall(-0.0, 0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0); testall(0.0, -0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0); testall(-one, one, one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); testall(one, -one, one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); testall(-one, -one, -one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); switch (fegetround()) { case FE_TONEAREST: case FE_TOWARDZERO: test(fmaf, -FLT_MIN, FLT_MIN, 0.0, -0.0, ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW); test(fma, -DBL_MIN, DBL_MIN, 0.0, -0.0, ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW); test(fmal, -LDBL_MIN, LDBL_MIN, 0.0, -0.0, ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW); } } static void test_infinities(void) { testall(INFINITY, 1.0, -1.0, INFINITY, ALL_STD_EXCEPT, 0); testall(-1.0, INFINITY, 0.0, -INFINITY, ALL_STD_EXCEPT, 0); testall(0.0, 0.0, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); testall(1.0, 1.0, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); testall(1.0, 1.0, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0); testall(INFINITY, -INFINITY, 1.0, -INFINITY, ALL_STD_EXCEPT, 0); testall(INFINITY, INFINITY, 1.0, INFINITY, ALL_STD_EXCEPT, 0); testall(-INFINITY, -INFINITY, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); testall(0.0, INFINITY, 1.0, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(INFINITY, 0.0, -0.0, NAN, ALL_STD_EXCEPT, FE_INVALID); /* The invalid exception is optional in this case. */ testall(INFINITY, 0.0, NAN, NAN, ALL_STD_EXCEPT & ~FE_INVALID, 0); testall(INFINITY, INFINITY, -INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(-INFINITY, INFINITY, INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(INFINITY, -1.0, INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); test(fmaf, FLT_MAX, FLT_MAX, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0); test(fma, DBL_MAX, DBL_MAX, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0); test(fmal, LDBL_MAX, LDBL_MAX, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0); test(fmaf, FLT_MAX, -FLT_MAX, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); test(fma, DBL_MAX, -DBL_MAX, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); test(fmal, LDBL_MAX, -LDBL_MAX, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); } static void test_nans(void) { testall(NAN, 0.0, 0.0, NAN, ALL_STD_EXCEPT, 0); testall(1.0, NAN, 1.0, NAN, ALL_STD_EXCEPT, 0); testall(1.0, -1.0, NAN, NAN, ALL_STD_EXCEPT, 0); testall(0.0, 0.0, NAN, NAN, ALL_STD_EXCEPT, 0); testall(NAN, NAN, NAN, NAN, ALL_STD_EXCEPT, 0); /* x*y should not raise an inexact/overflow/underflow if z is NaN. */ testall(M_PI, M_PI, NAN, NAN, ALL_STD_EXCEPT, 0); test(fmaf, FLT_MIN, FLT_MIN, NAN, NAN, ALL_STD_EXCEPT, 0); test(fma, DBL_MIN, DBL_MIN, NAN, NAN, ALL_STD_EXCEPT, 0); test(fmal, LDBL_MIN, LDBL_MIN, NAN, NAN, ALL_STD_EXCEPT, 0); test(fmaf, FLT_MAX, FLT_MAX, NAN, NAN, ALL_STD_EXCEPT, 0); test(fma, DBL_MAX, DBL_MAX, NAN, NAN, ALL_STD_EXCEPT, 0); test(fmal, LDBL_MAX, LDBL_MAX, NAN, NAN, ALL_STD_EXCEPT, 0); } /* * Tests for cases where z is very small compared to x*y. */ static void test_small_z(void) { /* x*y positive, z positive */ if (fegetround() == FE_UPWARD) { test(fmaf, one, one, 0x1.0p-100, 1.0 + FLT_EPSILON, ALL_STD_EXCEPT, FE_INEXACT); test(fma, one, one, 0x1.0p-200, 1.0 + DBL_EPSILON, ALL_STD_EXCEPT, FE_INEXACT); test(fmal, one, one, 0x1.0p-200, 1.0 + LDBL_EPSILON, ALL_STD_EXCEPT, FE_INEXACT); } else { testall(0x1.0p100, one, 0x1.0p-100, 0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } /* x*y negative, z negative */ if (fegetround() == FE_DOWNWARD) { test(fmaf, -one, one, -0x1.0p-100, -(1.0 + FLT_EPSILON), ALL_STD_EXCEPT, FE_INEXACT); test(fma, -one, one, -0x1.0p-200, -(1.0 + DBL_EPSILON), ALL_STD_EXCEPT, FE_INEXACT); test(fmal, -one, one, -0x1.0p-200, -(1.0 + LDBL_EPSILON), ALL_STD_EXCEPT, FE_INEXACT); } else { testall(0x1.0p100, -one, -0x1.0p-100, -0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } /* x*y positive, z negative */ if (fegetround() == FE_DOWNWARD || fegetround() == FE_TOWARDZERO) { test(fmaf, one, one, -0x1.0p-100, 1.0 - FLT_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); test(fma, one, one, -0x1.0p-200, 1.0 - DBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); test(fmal, one, one, -0x1.0p-200, 1.0 - LDBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); } else { testall(0x1.0p100, one, -0x1.0p-100, 0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } /* x*y negative, z positive */ if (fegetround() == FE_UPWARD || fegetround() == FE_TOWARDZERO) { test(fmaf, -one, one, 0x1.0p-100, -1.0 + FLT_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); test(fma, -one, one, 0x1.0p-200, -1.0 + DBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); test(fmal, -one, one, 0x1.0p-200, -1.0 + LDBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); } else { testall(-0x1.0p100, one, 0x1.0p-100, -0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } } /* * Tests for cases where z is very large compared to x*y. */ static void test_big_z(void) { /* z positive, x*y positive */ if (fegetround() == FE_UPWARD) { test(fmaf, 0x1.0p-50, 0x1.0p-50, 1.0, 1.0 + FLT_EPSILON, ALL_STD_EXCEPT, FE_INEXACT); test(fma, 0x1.0p-100, 0x1.0p-100, 1.0, 1.0 + DBL_EPSILON, ALL_STD_EXCEPT, FE_INEXACT); test(fmal, 0x1.0p-100, 0x1.0p-100, 1.0, 1.0 + LDBL_EPSILON, ALL_STD_EXCEPT, FE_INEXACT); } else { testall(-0x1.0p-50, -0x1.0p-50, 0x1.0p100, 0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } /* z negative, x*y negative */ if (fegetround() == FE_DOWNWARD) { test(fmaf, -0x1.0p-50, 0x1.0p-50, -1.0, -(1.0 + FLT_EPSILON), ALL_STD_EXCEPT, FE_INEXACT); test(fma, -0x1.0p-100, 0x1.0p-100, -1.0, -(1.0 + DBL_EPSILON), ALL_STD_EXCEPT, FE_INEXACT); test(fmal, -0x1.0p-100, 0x1.0p-100, -1.0, -(1.0 + LDBL_EPSILON), ALL_STD_EXCEPT, FE_INEXACT); } else { testall(0x1.0p-50, -0x1.0p-50, -0x1.0p100, -0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } /* z negative, x*y positive */ if (fegetround() == FE_UPWARD || fegetround() == FE_TOWARDZERO) { test(fmaf, -0x1.0p-50, -0x1.0p-50, -1.0, -1.0 + FLT_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); test(fma, -0x1.0p-100, -0x1.0p-100, -1.0, -1.0 + DBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); test(fmal, -0x1.0p-100, -0x1.0p-100, -1.0, -1.0 + LDBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); } else { testall(0x1.0p-50, 0x1.0p-50, -0x1.0p100, -0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } /* z positive, x*y negative */ if (fegetround() == FE_DOWNWARD || fegetround() == FE_TOWARDZERO) { test(fmaf, 0x1.0p-50, -0x1.0p-50, 1.0, 1.0 - FLT_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); test(fma, 0x1.0p-100, -0x1.0p-100, 1.0, 1.0 - DBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); test(fmal, 0x1.0p-100, -0x1.0p-100, 1.0, 1.0 - LDBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); } else { testall(-0x1.0p-50, 0x1.0p-50, 0x1.0p100, 0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } } static void test_accuracy(void) { /* ilogb(x*y) - ilogb(z) = 20 */ testrnd(fmaf, -0x1.c139d8p-51, -0x1.600e7ap32, 0x1.26558cp-38, 0x1.34e48ap-18, 0x1.34e48cp-18, 0x1.34e48ap-18, 0x1.34e48ap-18, ALL_STD_EXCEPT, FE_INEXACT); testrnd(fma, -0x1.c139d7b84f1a3p-51, -0x1.600e7a2a16484p32, 0x1.26558cac31580p-38, 0x1.34e48a78aae97p-18, 0x1.34e48a78aae97p-18, 0x1.34e48a78aae96p-18, 0x1.34e48a78aae96p-18, ALL_STD_EXCEPT, FE_INEXACT); #if LDBL_MANT_DIG == 113 testrnd(fmal, -0x1.c139d7b84f1a3079263afcc5bae3p-51L, -0x1.600e7a2a164840edbe2e7d301a72p32L, 0x1.26558cac315807eb07e448042101p-38L, 0x1.34e48a78aae96c76ed36077dd387p-18L, 0x1.34e48a78aae96c76ed36077dd388p-18L, 0x1.34e48a78aae96c76ed36077dd387p-18L, 0x1.34e48a78aae96c76ed36077dd387p-18L, ALL_STD_EXCEPT, FE_INEXACT); #elif LDBL_MANT_DIG == 64 testrnd(fmal, -0x1.c139d7b84f1a307ap-51L, -0x1.600e7a2a164840eep32L, 0x1.26558cac315807ecp-38L, 0x1.34e48a78aae96c78p-18L, 0x1.34e48a78aae96c78p-18L, 0x1.34e48a78aae96c76p-18L, 0x1.34e48a78aae96c76p-18L, ALL_STD_EXCEPT, FE_INEXACT); #elif LDBL_MANT_DIG == 53 testrnd(fmal, -0x1.c139d7b84f1a3p-51L, -0x1.600e7a2a16484p32L, 0x1.26558cac31580p-38L, 0x1.34e48a78aae97p-18L, 0x1.34e48a78aae97p-18L, 0x1.34e48a78aae96p-18L, 0x1.34e48a78aae96p-18L, ALL_STD_EXCEPT, FE_INEXACT); #endif /* ilogb(x*y) - ilogb(z) = -40 */ testrnd(fmaf, 0x1.98210ap53, 0x1.9556acp-24, 0x1.d87da4p70, 0x1.d87da4p70, 0x1.d87da6p70, 0x1.d87da4p70, 0x1.d87da4p70, ALL_STD_EXCEPT, FE_INEXACT); testrnd(fma, 0x1.98210ac83fe2bp53, 0x1.9556ac1475f0fp-24, 0x1.d87da3aafc60ep70, 0x1.d87da3aafda40p70, 0x1.d87da3aafda40p70, 0x1.d87da3aafda3fp70, 0x1.d87da3aafda3fp70, ALL_STD_EXCEPT, FE_INEXACT); #if LDBL_MANT_DIG == 113 testrnd(fmal, 0x1.98210ac83fe2a8f65b6278b74cebp53L, 0x1.9556ac1475f0f28968b61d0de65ap-24L, 0x1.d87da3aafc60d830aa4c6d73b749p70L, 0x1.d87da3aafda3f36a69eb86488224p70L, 0x1.d87da3aafda3f36a69eb86488225p70L, 0x1.d87da3aafda3f36a69eb86488224p70L, 0x1.d87da3aafda3f36a69eb86488224p70L, ALL_STD_EXCEPT, FE_INEXACT); #elif LDBL_MANT_DIG == 64 testrnd(fmal, 0x1.98210ac83fe2a8f6p53L, 0x1.9556ac1475f0f28ap-24L, 0x1.d87da3aafc60d83p70L, 0x1.d87da3aafda3f36ap70L, 0x1.d87da3aafda3f36ap70L, 0x1.d87da3aafda3f368p70L, 0x1.d87da3aafda3f368p70L, ALL_STD_EXCEPT, FE_INEXACT); #elif LDBL_MANT_DIG == 53 testrnd(fmal, 0x1.98210ac83fe2bp53L, 0x1.9556ac1475f0fp-24L, 0x1.d87da3aafc60ep70L, 0x1.d87da3aafda40p70L, 0x1.d87da3aafda40p70L, 0x1.d87da3aafda3fp70L, 0x1.d87da3aafda3fp70L, ALL_STD_EXCEPT, FE_INEXACT); #endif /* ilogb(x*y) - ilogb(z) = 0 */ testrnd(fmaf, 0x1.31ad02p+100, 0x1.2fbf7ap-42, -0x1.c3e106p+58, -0x1.64c27cp+56, -0x1.64c27ap+56, -0x1.64c27cp+56, -0x1.64c27ap+56, ALL_STD_EXCEPT, FE_INEXACT); testrnd(fma, 0x1.31ad012ede8aap+100, 0x1.2fbf79c839067p-42, -0x1.c3e106929056ep+58, -0x1.64c282b970a5fp+56, -0x1.64c282b970a5ep+56, -0x1.64c282b970a5fp+56, -0x1.64c282b970a5ep+56, ALL_STD_EXCEPT, FE_INEXACT); #if LDBL_MANT_DIG == 113 testrnd(fmal, 0x1.31ad012ede8aa282fa1c19376d16p+100L, 0x1.2fbf79c839066f0f5c68f6d2e814p-42L, -0x1.c3e106929056ec19de72bfe64215p+58L, -0x1.64c282b970a612598fc025ca8cddp+56L, -0x1.64c282b970a612598fc025ca8cddp+56L, -0x1.64c282b970a612598fc025ca8cdep+56L, -0x1.64c282b970a612598fc025ca8cddp+56L, ALL_STD_EXCEPT, FE_INEXACT); #elif LDBL_MANT_DIG == 64 testrnd(fmal, 0x1.31ad012ede8aa4eap+100L, 0x1.2fbf79c839066aeap-42L, -0x1.c3e106929056e61p+58L, -0x1.64c282b970a60298p+56L, -0x1.64c282b970a60298p+56L, -0x1.64c282b970a6029ap+56L, -0x1.64c282b970a60298p+56L, ALL_STD_EXCEPT, FE_INEXACT); #elif LDBL_MANT_DIG == 53 testrnd(fmal, 0x1.31ad012ede8aap+100L, 0x1.2fbf79c839067p-42L, -0x1.c3e106929056ep+58L, -0x1.64c282b970a5fp+56L, -0x1.64c282b970a5ep+56L, -0x1.64c282b970a5fp+56L, -0x1.64c282b970a5ep+56L, ALL_STD_EXCEPT, FE_INEXACT); #endif /* x*y (rounded) ~= -z */ /* XXX spurious inexact exceptions */ testrnd(fmaf, 0x1.bbffeep-30, -0x1.1d164cp-74, 0x1.ee7296p-104, -0x1.c46ea8p-128, -0x1.c46ea8p-128, -0x1.c46ea8p-128, -0x1.c46ea8p-128, ALL_STD_EXCEPT & ~FE_INEXACT, 0); testrnd(fma, 0x1.bbffeea6fc7d6p-30, 0x1.1d164c6cbf078p-74, -0x1.ee72993aff948p-104, -0x1.71f72ac7d9d8p-159, -0x1.71f72ac7d9d8p-159, -0x1.71f72ac7d9d8p-159, -0x1.71f72ac7d9d8p-159, ALL_STD_EXCEPT & ~FE_INEXACT, 0); #if LDBL_MANT_DIG == 113 testrnd(fmal, 0x1.bbffeea6fc7d65927d147f437675p-30L, 0x1.1d164c6cbf078b7a22607d1cd6a2p-74L, -0x1.ee72993aff94973876031bec0944p-104L, 0x1.64e086175b3a2adc36e607058814p-217L, 0x1.64e086175b3a2adc36e607058814p-217L, 0x1.64e086175b3a2adc36e607058814p-217L, 0x1.64e086175b3a2adc36e607058814p-217L, ALL_STD_EXCEPT & ~FE_INEXACT, 0); #elif LDBL_MANT_DIG == 64 testrnd(fmal, 0x1.bbffeea6fc7d6592p-30L, 0x1.1d164c6cbf078b7ap-74L, -0x1.ee72993aff949736p-104L, 0x1.af190e7a1ee6ad94p-168L, 0x1.af190e7a1ee6ad94p-168L, 0x1.af190e7a1ee6ad94p-168L, 0x1.af190e7a1ee6ad94p-168L, ALL_STD_EXCEPT & ~FE_INEXACT, 0); #elif LDBL_MANT_DIG == 53 testrnd(fmal, 0x1.bbffeea6fc7d6p-30L, 0x1.1d164c6cbf078p-74L, -0x1.ee72993aff948p-104L, -0x1.71f72ac7d9d8p-159L, -0x1.71f72ac7d9d8p-159L, -0x1.71f72ac7d9d8p-159L, -0x1.71f72ac7d9d8p-159L, ALL_STD_EXCEPT & ~FE_INEXACT, 0); #endif } static void test_double_rounding(void) { /* * a = 0x1.8000000000001p0 * b = 0x1.8000000000001p0 * c = -0x0.0000000000000000000000000080...1p+1 * a * b = 0x1.2000000000001800000000000080p+1 * * The correct behavior is to round DOWN to 0x1.2000000000001p+1 in * round-to-nearest mode. An implementation that computes a*b+c in * double+double precision, however, will get 0x1.20000000000018p+1, * and then round UP. */ fesetround(FE_TONEAREST); test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0, -0x1.0000000000001p-104, 0x1.2000000000001p+1, ALL_STD_EXCEPT, FE_INEXACT); fesetround(FE_DOWNWARD); test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0, -0x1.0000000000001p-104, 0x1.2000000000001p+1, ALL_STD_EXCEPT, FE_INEXACT); fesetround(FE_UPWARD); test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0, -0x1.0000000000001p-104, 0x1.2000000000002p+1, ALL_STD_EXCEPT, FE_INEXACT); fesetround(FE_TONEAREST); test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200002p+1, ALL_STD_EXCEPT, FE_INEXACT); fesetround(FE_DOWNWARD); test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200002p+1, ALL_STD_EXCEPT, FE_INEXACT); fesetround(FE_UPWARD); test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200004p+1, ALL_STD_EXCEPT, FE_INEXACT); fesetround(FE_TONEAREST); #if LDBL_MANT_DIG == 64 test(fmal, 0x1.4p+0L, 0x1.0000000000000004p+0L, 0x1p-128L, 0x1.4000000000000006p+0L, ALL_STD_EXCEPT, FE_INEXACT); #elif LDBL_MANT_DIG == 113 test(fmal, 0x1.8000000000000000000000000001p+0L, 0x1.8000000000000000000000000001p+0L, -0x1.0000000000000000000000000001p-224L, 0x1.2000000000000000000000000001p+1L, ALL_STD_EXCEPT, FE_INEXACT); #endif } int -main(int argc, char *argv[]) +main(void) { int rmodes[] = { FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO }; - int i, j; + unsigned i, j; #if defined(__i386__) printf("1..0 # SKIP all testcases fail on i386\n"); exit(0); #endif j = 1; printf("1..19\n"); for (i = 0; i < nitems(rmodes); i++, j++) { printf("rmode = %d\n", rmodes[i]); fesetround(rmodes[i]); test_zeroes(); printf("ok %d - fma zeroes\n", j); } for (i = 0; i < nitems(rmodes); i++, j++) { #if defined(__amd64__) printf("ok %d # SKIP testcase fails assertion on " "amd64\n", j); continue; #endif printf("rmode = %d\n", rmodes[i]); fesetround(rmodes[i]); test_infinities(); printf("ok %d - fma infinities\n", j); } fesetround(FE_TONEAREST); test_nans(); printf("ok %d - fma NaNs\n", j); j++; for (i = 0; i < nitems(rmodes); i++, j++) { printf("rmode = %d\n", rmodes[i]); fesetround(rmodes[i]); test_small_z(); printf("ok %d - fma small z\n", j); } for (i = 0; i < nitems(rmodes); i++, j++) { printf("rmode = %d\n", rmodes[i]); fesetround(rmodes[i]); test_big_z(); printf("ok %d - fma big z\n", j); } fesetround(FE_TONEAREST); test_accuracy(); printf("ok %d - fma accuracy\n", j); j++; test_double_rounding(); printf("ok %d - fma double rounding\n", j); j++; /* * TODO: * - Tests for subnormals * - Cancellation tests (e.g., z = (double)x*y, but x*y is inexact) */ return (0); } Index: head/lib/msun/tests/fmaxmin_test.c =================================================================== --- head/lib/msun/tests/fmaxmin_test.c (revision 314649) +++ head/lib/msun/tests/fmaxmin_test.c (revision 314650) @@ -1,154 +1,154 @@ /*- * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for fmax{,f,l}() and fmin{,f,l}. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include "test-utils.h" #pragma STDC FENV_ACCESS ON /* * Test whether func(x, y) has the expected result, and make sure no * exceptions are raised. */ #define TEST(func, type, x, y, expected) do { \ type __x = (x); /* convert before we clear exceptions */ \ type __y = (y); \ feclearexcept(ALL_STD_EXCEPT); \ long double __result = func((__x), (__y)); \ if (fetestexcept(ALL_STD_EXCEPT)) { \ fprintf(stderr, #func "(%.20Lg, %.20Lg) raised 0x%x\n", \ (x), (y), fetestexcept(FE_ALL_EXCEPT)); \ ok = 0; \ } \ if (!fpequal(__result, (expected))) { \ fprintf(stderr, #func "(%.20Lg, %.20Lg) = %.20Lg, " \ "expected %.20Lg\n", (x), (y), __result, (expected)); \ ok = 0; \ } \ } while (0) -int +static int testall_r(long double big, long double small) { int ok; long double expected_max = isnan(big) ? small : big; long double expected_min = isnan(small) ? big : small; ok = 1; TEST(fmaxf, float, big, small, expected_max); TEST(fmaxf, float, small, big, expected_max); TEST(fmax, double, big, small, expected_max); TEST(fmax, double, small, big, expected_max); TEST(fmaxl, long double, big, small, expected_max); TEST(fmaxl, long double, small, big, expected_max); TEST(fminf, float, big, small, expected_min); TEST(fminf, float, small, big, expected_min); TEST(fmin, double, big, small, expected_min); TEST(fmin, double, small, big, expected_min); TEST(fminl, long double, big, small, expected_min); TEST(fminl, long double, small, big, expected_min); return (ok); } -const char *comment = NULL; +static const char *comment = NULL; /* * Test all the functions: fmaxf, fmax, fmaxl, fminf, fmin, and fminl, * in all rounding modes and with the arguments in different orders. * The input 'big' must be >= 'small'. */ -void +static void testall(int testnum, long double big, long double small) { static const int rmodes[] = { FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO }; int i; for (i = 0; i < 4; i++) { fesetround(rmodes[i]); if (!testall_r(big, small)) { fprintf(stderr, "FAILURE in rounding mode %d\n", rmodes[i]); break; } } printf("%sok %d - big = %.20Lg, small = %.20Lg%s\n", (i == 4) ? "" : "not ", testnum, big, small, comment == NULL ? "" : comment); } /* Clang 3.8.0+ fails the invariants for testcase 6, 7, 10, and 11. */ #if defined(__clang__) && \ ((__clang_major__ > 3)) || \ ((__clang_major__ == 3 && __clang_minor__ >= 8)) #define affected_by_bug_208703 #endif int -main(int argc, char *argv[]) +main(void) { printf("1..12\n"); testall(1, 1.0, 0.0); testall(2, 42.0, nextafterf(42.0, -INFINITY)); testall(3, nextafterf(42.0, INFINITY), 42.0); testall(4, -5.0, -5.0); testall(5, -3.0, -4.0); #ifdef affected_by_bug_208703 comment = "# TODO: testcase 6-7 fails invariant with clang 3.8+ (bug 208703)"; #endif testall(6, 1.0, NAN); testall(7, INFINITY, NAN); comment = NULL; testall(8, INFINITY, 1.0); testall(9, -3.0, -INFINITY); testall(10, 3.0, -INFINITY); #ifdef affected_by_bug_208703 comment = "# TODO: testcase 11-12 fails invariant with clang 3.8+ (bug 208703)"; #endif testall(11, NAN, NAN); /* This test isn't strictly required to work by C99. */ testall(12, 0.0, -0.0); comment = NULL; return (0); } Index: head/lib/msun/tests/invctrig_test.c =================================================================== --- head/lib/msun/tests/invctrig_test.c (revision 314649) +++ head/lib/msun/tests/invctrig_test.c (revision 314650) @@ -1,367 +1,368 @@ /*- * Copyright (c) 2008-2013 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for casin[h](), cacos[h](), and catan[h](). */ #include __FBSDID("$FreeBSD$"); +#include #include #include #include #include #include #include #include "test-utils.h" #pragma STDC FENV_ACCESS ON #pragma STDC CX_LIMITED_RANGE OFF /* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several * reasons, but mainly because on some architectures it's impossible * to raise FE_OVERFLOW without raising FE_INEXACT. * * These are macros instead of functions so that assert provides more * meaningful error messages. * * XXX The volatile here is to avoid gcc's bogus constant folding and work * around the lack of support for the FENV_ACCESS pragma. */ #define test_p(func, z, result, exceptmask, excepts, checksign) do { \ volatile long double complex _d = z; \ debug(" testing %s(%Lg + %Lg I) == %Lg + %Lg I\n", #func, \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(cfpequal_cs((func)(_d), (result), (checksign))); \ assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* * Test within a given tolerance. The tolerance indicates relative error * in ulps. */ #define test_p_tol(func, z, result, tol) do { \ volatile long double complex _d = z; \ debug(" testing %s(%Lg + %Lg I) ~= %Lg + %Lg I\n", #func, \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \ assert(cfpequal_tol((func)(_d), (result), (tol), CS_BOTH)); \ } while (0) /* These wrappers apply the identities f(conj(z)) = conj(f(z)). */ #define test(func, z, result, exceptmask, excepts, checksign) do { \ test_p(func, z, result, exceptmask, excepts, checksign); \ test_p(func, conjl(z), conjl(result), exceptmask, excepts, checksign); \ } while (0) #define test_tol(func, z, result, tol) do { \ test_p_tol(func, z, result, tol); \ test_p_tol(func, conjl(z), conjl(result), tol); \ } while (0) /* Test the given function in all precisions. */ #define testall(func, x, result, exceptmask, excepts, checksign) do { \ test(func, x, result, exceptmask, excepts, checksign); \ test(func##f, x, result, exceptmask, excepts, checksign); \ } while (0) #define testall_odd(func, x, result, exceptmask, excepts, checksign) do { \ testall(func, x, result, exceptmask, excepts, checksign); \ testall(func, -(x), -result, exceptmask, excepts, checksign); \ } while (0) #define testall_even(func, x, result, exceptmask, excepts, checksign) do { \ testall(func, x, result, exceptmask, excepts, checksign); \ testall(func, -(x), result, exceptmask, excepts, checksign); \ } while (0) /* * Test the given function in all precisions, within a given tolerance. * The tolerance is specified in ulps. */ #define testall_tol(func, x, result, tol) do { \ test_tol(func, x, result, (tol) * DBL_ULP()); \ test_tol(func##f, x, result, (tol) * FLT_ULP()); \ } while (0) #define testall_odd_tol(func, x, result, tol) do { \ testall_tol(func, x, result, tol); \ testall_tol(func, -(x), -result, tol); \ } while (0) #define testall_even_tol(func, x, result, tol) do { \ testall_tol(func, x, result, tol); \ testall_tol(func, -(x), result, tol); \ } while (0) static const long double pi = 3.14159265358979323846264338327950280L, c3pi = 9.42477796076937971538793014983850839L; /* Tests for 0 */ -void +static void test_zero(void) { long double complex zero = CMPLXL(0.0, 0.0); testall_tol(cacosh, zero, CMPLXL(0.0, pi / 2), 1); testall_tol(cacosh, -zero, CMPLXL(0.0, -pi / 2), 1); testall_tol(cacos, zero, CMPLXL(pi / 2, -0.0), 1); testall_tol(cacos, -zero, CMPLXL(pi / 2, 0.0), 1); testall_odd(casinh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(casin, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(catanh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(catan, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); } /* * Tests for NaN inputs. */ -void -test_nan() +static void +test_nan(void) { long double complex nan_nan = CMPLXL(NAN, NAN); long double complex z; /* * IN CACOSH CACOS CASINH CATANH * NaN,NaN NaN,NaN NaN,NaN NaN,NaN NaN,NaN * finite,NaN NaN,NaN* NaN,NaN* NaN,NaN* NaN,NaN* * NaN,finite NaN,NaN* NaN,NaN* NaN,NaN* NaN,NaN* - * NaN,Inf Inf,NaN NaN,-Inf ?Inf,NaN ?0,pi/2 + * NaN,Inf Inf,NaN NaN,-Inf ?Inf,NaN ?0,pi/2 * +-Inf,NaN Inf,NaN NaN,?Inf +-Inf,NaN +-0,NaN * +-0,NaN NaN,NaN* pi/2,NaN NaN,NaN* +-0,NaN * NaN,0 NaN,NaN* NaN,NaN* NaN,0 NaN,NaN* * * * = raise invalid */ z = nan_nan; testall(cacosh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall(cacos, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall(casinh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall(casin, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall(catanh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall(catan, z, nan_nan, ALL_STD_EXCEPT, 0, 0); z = CMPLXL(0.5, NAN); testall(cacosh, z, nan_nan, OPT_INVALID, 0, 0); testall(cacos, z, nan_nan, OPT_INVALID, 0, 0); testall(casinh, z, nan_nan, OPT_INVALID, 0, 0); testall(casin, z, nan_nan, OPT_INVALID, 0, 0); testall(catanh, z, nan_nan, OPT_INVALID, 0, 0); testall(catan, z, nan_nan, OPT_INVALID, 0, 0); z = CMPLXL(NAN, 0.5); testall(cacosh, z, nan_nan, OPT_INVALID, 0, 0); testall(cacos, z, nan_nan, OPT_INVALID, 0, 0); testall(casinh, z, nan_nan, OPT_INVALID, 0, 0); testall(casin, z, nan_nan, OPT_INVALID, 0, 0); testall(catanh, z, nan_nan, OPT_INVALID, 0, 0); testall(catan, z, nan_nan, OPT_INVALID, 0, 0); z = CMPLXL(NAN, INFINITY); testall(cacosh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_REAL); testall(cacosh, -z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_REAL); testall(cacos, z, CMPLXL(NAN, -INFINITY), ALL_STD_EXCEPT, 0, CS_IMAG); testall(casinh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); testall(casin, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, 0, CS_IMAG); testall_tol(catanh, z, CMPLXL(0.0, pi / 2), 1); testall(catan, z, CMPLXL(NAN, 0.0), ALL_STD_EXCEPT, 0, CS_IMAG); z = CMPLXL(INFINITY, NAN); testall_even(cacosh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_REAL); testall_even(cacos, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, 0, 0); testall_odd(casinh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_REAL); testall_odd(casin, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, 0, 0); testall_odd(catanh, z, CMPLXL(0.0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); testall_odd_tol(catan, z, CMPLXL(pi / 2, 0.0), 1); z = CMPLXL(0.0, NAN); /* XXX We allow a spurious inexact exception here. */ testall_even(cacosh, z, nan_nan, OPT_INVALID & ~FE_INEXACT, 0, 0); testall_even_tol(cacos, z, CMPLXL(pi / 2, NAN), 1); testall_odd(casinh, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(casin, z, CMPLXL(0.0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); testall_odd(catanh, z, CMPLXL(0.0, NAN), OPT_INVALID, 0, CS_REAL); testall_odd(catan, z, nan_nan, OPT_INVALID, 0, 0); z = CMPLXL(NAN, 0.0); testall(cacosh, z, nan_nan, OPT_INVALID, 0, 0); testall(cacos, z, nan_nan, OPT_INVALID, 0, 0); testall(casinh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); testall(casin, z, nan_nan, OPT_INVALID, 0, 0); testall(catanh, z, nan_nan, OPT_INVALID, 0, CS_IMAG); testall(catan, z, CMPLXL(NAN, 0.0), ALL_STD_EXCEPT, 0, 0); } -void +static void test_inf(void) { long double complex z; /* * IN CACOSH CACOS CASINH CATANH * Inf,Inf Inf,pi/4 pi/4,-Inf Inf,pi/4 0,pi/2 * -Inf,Inf Inf,3pi/4 3pi/4,-Inf --- --- * Inf,finite Inf,0 0,-Inf Inf,0 0,pi/2 * -Inf,finite Inf,pi pi,-Inf --- --- * finite,Inf Inf,pi/2 pi/2,-Inf Inf,pi/2 0,pi/2 */ z = CMPLXL(INFINITY, INFINITY); testall_tol(cacosh, z, CMPLXL(INFINITY, pi / 4), 1); testall_tol(cacosh, -z, CMPLXL(INFINITY, -c3pi / 4), 1); testall_tol(cacos, z, CMPLXL(pi / 4, -INFINITY), 1); testall_tol(cacos, -z, CMPLXL(c3pi / 4, INFINITY), 1); testall_odd_tol(casinh, z, CMPLXL(INFINITY, pi / 4), 1); testall_odd_tol(casin, z, CMPLXL(pi / 4, INFINITY), 1); testall_odd_tol(catanh, z, CMPLXL(0, pi / 2), 1); testall_odd_tol(catan, z, CMPLXL(pi / 2, 0), 1); z = CMPLXL(INFINITY, 0.5); /* XXX We allow a spurious inexact exception here. */ testall(cacosh, z, CMPLXL(INFINITY, 0), OPT_INEXACT, 0, CS_BOTH); testall_tol(cacosh, -z, CMPLXL(INFINITY, -pi), 1); testall(cacos, z, CMPLXL(0, -INFINITY), OPT_INEXACT, 0, CS_BOTH); testall_tol(cacos, -z, CMPLXL(pi, INFINITY), 1); testall_odd(casinh, z, CMPLXL(INFINITY, 0), OPT_INEXACT, 0, CS_BOTH); testall_odd_tol(casin, z, CMPLXL(pi / 2, INFINITY), 1); testall_odd_tol(catanh, z, CMPLXL(0, pi / 2), 1); testall_odd_tol(catan, z, CMPLXL(pi / 2, 0), 1); z = CMPLXL(0.5, INFINITY); testall_tol(cacosh, z, CMPLXL(INFINITY, pi / 2), 1); testall_tol(cacosh, -z, CMPLXL(INFINITY, -pi / 2), 1); testall_tol(cacos, z, CMPLXL(pi / 2, -INFINITY), 1); testall_tol(cacos, -z, CMPLXL(pi / 2, INFINITY), 1); testall_odd_tol(casinh, z, CMPLXL(INFINITY, pi / 2), 1); /* XXX We allow a spurious inexact exception here. */ testall_odd(casin, z, CMPLXL(0.0, INFINITY), OPT_INEXACT, 0, CS_BOTH); testall_odd_tol(catanh, z, CMPLXL(0, pi / 2), 1); testall_odd_tol(catan, z, CMPLXL(pi / 2, 0), 1); } /* Tests along the real and imaginary axes. */ -void +static void test_axes(void) { static const long double nums[] = { -2, -1, -0.5, 0.5, 1, 2 }; long double complex z; - int i; + unsigned i; - for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) { + for (i = 0; i < nitems(nums); i++) { /* Real axis */ z = CMPLXL(nums[i], 0.0); if (fabsl(nums[i]) <= 1) { testall_tol(cacosh, z, CMPLXL(0.0, acos(nums[i])), 1); testall_tol(cacos, z, CMPLXL(acosl(nums[i]), -0.0), 1); testall_tol(casin, z, CMPLXL(asinl(nums[i]), 0.0), 1); testall_tol(catanh, z, CMPLXL(atanh(nums[i]), 0.0), 1); } else { testall_tol(cacosh, z, CMPLXL(acosh(fabsl(nums[i])), (nums[i] < 0) ? pi : 0), 1); testall_tol(cacos, z, CMPLXL((nums[i] < 0) ? pi : 0, -acosh(fabsl(nums[i]))), 1); testall_tol(casin, z, CMPLXL(copysign(pi / 2, nums[i]), acosh(fabsl(nums[i]))), 1); testall_tol(catanh, z, CMPLXL(atanh(1 / nums[i]), pi / 2), 1); } testall_tol(casinh, z, CMPLXL(asinh(nums[i]), 0.0), 1); testall_tol(catan, z, CMPLXL(atan(nums[i]), 0), 1); /* TODO: Test the imaginary axis. */ } } -void +static void test_small(void) { /* * z = 0.75 + i 0.25 * acos(z) = Pi/4 - i ln(2)/2 * asin(z) = Pi/4 + i ln(2)/2 * atan(z) = atan(4)/2 + i ln(17/9)/4 */ complex long double z; complex long double acos_z; complex long double asin_z; complex long double atan_z; z = CMPLXL(0.75L, 0.25L); acos_z = CMPLXL(pi / 4, -0.34657359027997265470861606072908828L); asin_z = CMPLXL(pi / 4, 0.34657359027997265470861606072908828L); atan_z = CMPLXL(0.66290883183401623252961960521423782L, 0.15899719167999917436476103600701878L); testall_tol(cacos, z, acos_z, 2); testall_odd_tol(casin, z, asin_z, 2); testall_odd_tol(catan, z, atan_z, 2); } /* Test inputs that might cause overflow in a sloppy implementation. */ -void +static void test_large(void) { /* TODO: Write these tests */ } int -main(int argc, char *argv[]) +main(void) { printf("1..6\n"); test_zero(); printf("ok 1 - invctrig zero\n"); test_nan(); printf("ok 2 - invctrig nan\n"); test_inf(); printf("ok 3 - invctrig inf\n"); test_axes(); printf("ok 4 - invctrig axes\n"); test_small(); printf("ok 5 - invctrig small\n"); test_large(); printf("ok 6 - invctrig large\n"); return (0); } Index: head/lib/msun/tests/invtrig_test.c =================================================================== --- head/lib/msun/tests/invtrig_test.c (revision 314649) +++ head/lib/msun/tests/invtrig_test.c (revision 314650) @@ -1,479 +1,478 @@ /*- * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for corner cases in the inverse trigonometric functions. Some * accuracy tests are included as well, but these are very basic * sanity checks, not intended to be comprehensive. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "test-utils.h" #pragma STDC FENV_ACCESS ON /* * Test that a function returns the correct value and sets the * exception flags correctly. A tolerance specifying the maximum * relative error allowed may be specified. For the 'testall' * functions, the tolerance is specified in ulps. * * These are macros instead of functions so that assert provides more * meaningful error messages. */ #define test_tol(func, x, result, tol, excepts) do { \ volatile long double _in = (x), _out = (result); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal_tol(func(_in), _out, (tol), CS_BOTH)); \ assert(((void)func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ } while (0) #define test(func, x, result, excepts) \ test_tol(func, (x), (result), 0, (excepts)) #define _testall_tol(prefix, x, result, tol, excepts) do { \ test_tol(prefix, (double)(x), (double)(result), \ (tol) * ldexp(1.0, 1 - DBL_MANT_DIG), (excepts)); \ test_tol(prefix##f, (float)(x), (float)(result), \ (tol) * ldexpf(1.0, 1 - FLT_MANT_DIG), (excepts)); \ } while (0) #if LDBL_PREC == 53 #define testall_tol _testall_tol #else #define testall_tol(prefix, x, result, tol, excepts) do { \ _testall_tol(prefix, x, result, tol, excepts); \ test_tol(prefix##l, (x), (result), \ (tol) * ldexpl(1.0, 1 - LDBL_MANT_DIG), (excepts)); \ } while (0) #endif #define testall(prefix, x, result, excepts) \ testall_tol(prefix, (x), (result), 0, (excepts)) #define test2_tol(func, y, x, result, tol, excepts) do { \ volatile long double _iny = (y), _inx = (x), _out = (result); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal_tol(func(_iny, _inx), _out, (tol), CS_BOTH)); \ assert(((void)func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ } while (0) #define test2(func, y, x, result, excepts) \ test2_tol(func, (y), (x), (result), 0, (excepts)) #define _testall2_tol(prefix, y, x, result, tol, excepts) do { \ test2_tol(prefix, (double)(y), (double)(x), (double)(result), \ (tol) * ldexp(1.0, 1 - DBL_MANT_DIG), (excepts)); \ test2_tol(prefix##f, (float)(y), (float)(x), (float)(result), \ (tol) * ldexpf(1.0, 1 - FLT_MANT_DIG), (excepts)); \ } while (0) #if LDBL_PREC == 53 #define testall2_tol _testall2_tol #else #define testall2_tol(prefix, y, x, result, tol, excepts) do { \ _testall2_tol(prefix, y, x, result, tol, excepts); \ test2_tol(prefix##l, (y), (x), (result), \ (tol) * ldexpl(1.0, 1 - LDBL_MANT_DIG), (excepts)); \ } while (0) #endif #define testall2(prefix, y, x, result, excepts) \ testall2_tol(prefix, (y), (x), (result), 0, (excepts)) -long double +static long double pi = 3.14159265358979323846264338327950280e+00L, pio3 = 1.04719755119659774615421446109316766e+00L, c3pi = 9.42477796076937971538793014983850839e+00L, -c5pi = 1.57079632679489661923132169163975140e+01L, c7pi = 2.19911485751285526692385036829565196e+01L, c5pio3 = 5.23598775598298873077107230546583851e+00L, sqrt2m1 = 4.14213562373095048801688724209698081e-01L; /* * Test special case inputs in asin(), acos() and atan(): signed * zeroes, infinities, and NaNs. */ static void test_special(void) { testall(asin, 0.0, 0.0, 0); testall(acos, 0.0, pi / 2, FE_INEXACT); testall(atan, 0.0, 0.0, 0); testall(asin, -0.0, -0.0, 0); testall(acos, -0.0, pi / 2, FE_INEXACT); testall(atan, -0.0, -0.0, 0); testall(asin, INFINITY, NAN, FE_INVALID); testall(acos, INFINITY, NAN, FE_INVALID); testall(atan, INFINITY, pi / 2, FE_INEXACT); testall(asin, -INFINITY, NAN, FE_INVALID); testall(acos, -INFINITY, NAN, FE_INVALID); testall(atan, -INFINITY, -pi / 2, FE_INEXACT); testall(asin, NAN, NAN, 0); testall(acos, NAN, NAN, 0); testall(atan, NAN, NAN, 0); } /* * Test special case inputs in atan2(), where the exact value of y/x is * zero or non-finite. */ static void test_special_atan2(void) { long double z; int e; testall2(atan2, 0.0, -0.0, pi, FE_INEXACT); testall2(atan2, -0.0, -0.0, -pi, FE_INEXACT); testall2(atan2, 0.0, 0.0, 0.0, 0); testall2(atan2, -0.0, 0.0, -0.0, 0); testall2(atan2, INFINITY, -INFINITY, c3pi / 4, FE_INEXACT); testall2(atan2, -INFINITY, -INFINITY, -c3pi / 4, FE_INEXACT); testall2(atan2, INFINITY, INFINITY, pi / 4, FE_INEXACT); testall2(atan2, -INFINITY, INFINITY, -pi / 4, FE_INEXACT); /* Tests with one input in the range (0, Inf]. */ z = 1.23456789L; for (e = FLT_MIN_EXP - FLT_MANT_DIG; e <= FLT_MAX_EXP; e++) { test2(atan2f, 0.0, ldexpf(z, e), 0.0, 0); test2(atan2f, -0.0, ldexpf(z, e), -0.0, 0); test2(atan2f, 0.0, ldexpf(-z, e), (float)pi, FE_INEXACT); test2(atan2f, -0.0, ldexpf(-z, e), (float)-pi, FE_INEXACT); test2(atan2f, ldexpf(z, e), 0.0, (float)pi / 2, FE_INEXACT); test2(atan2f, ldexpf(z, e), -0.0, (float)pi / 2, FE_INEXACT); test2(atan2f, ldexpf(-z, e), 0.0, (float)-pi / 2, FE_INEXACT); test2(atan2f, ldexpf(-z, e), -0.0, (float)-pi / 2, FE_INEXACT); } for (e = DBL_MIN_EXP - DBL_MANT_DIG; e <= DBL_MAX_EXP; e++) { test2(atan2, 0.0, ldexp(z, e), 0.0, 0); test2(atan2, -0.0, ldexp(z, e), -0.0, 0); test2(atan2, 0.0, ldexp(-z, e), (double)pi, FE_INEXACT); test2(atan2, -0.0, ldexp(-z, e), (double)-pi, FE_INEXACT); test2(atan2, ldexp(z, e), 0.0, (double)pi / 2, FE_INEXACT); test2(atan2, ldexp(z, e), -0.0, (double)pi / 2, FE_INEXACT); test2(atan2, ldexp(-z, e), 0.0, (double)-pi / 2, FE_INEXACT); test2(atan2, ldexp(-z, e), -0.0, (double)-pi / 2, FE_INEXACT); } for (e = LDBL_MIN_EXP - LDBL_MANT_DIG; e <= LDBL_MAX_EXP; e++) { test2(atan2l, 0.0, ldexpl(z, e), 0.0, 0); test2(atan2l, -0.0, ldexpl(z, e), -0.0, 0); test2(atan2l, 0.0, ldexpl(-z, e), pi, FE_INEXACT); test2(atan2l, -0.0, ldexpl(-z, e), -pi, FE_INEXACT); test2(atan2l, ldexpl(z, e), 0.0, pi / 2, FE_INEXACT); test2(atan2l, ldexpl(z, e), -0.0, pi / 2, FE_INEXACT); test2(atan2l, ldexpl(-z, e), 0.0, -pi / 2, FE_INEXACT); test2(atan2l, ldexpl(-z, e), -0.0, -pi / 2, FE_INEXACT); } /* Tests with one input in the range (0, Inf). */ for (e = FLT_MIN_EXP - FLT_MANT_DIG; e <= FLT_MAX_EXP - 1; e++) { test2(atan2f, ldexpf(z, e), INFINITY, 0.0, 0); test2(atan2f, ldexpf(-z,e), INFINITY, -0.0, 0); test2(atan2f, ldexpf(z, e), -INFINITY, (float)pi, FE_INEXACT); test2(atan2f, ldexpf(-z,e), -INFINITY, (float)-pi, FE_INEXACT); test2(atan2f, INFINITY, ldexpf(z,e), (float)pi/2, FE_INEXACT); test2(atan2f, INFINITY, ldexpf(-z,e), (float)pi/2, FE_INEXACT); test2(atan2f, -INFINITY, ldexpf(z,e), (float)-pi/2,FE_INEXACT); test2(atan2f, -INFINITY, ldexpf(-z,e),(float)-pi/2,FE_INEXACT); } for (e = DBL_MIN_EXP - DBL_MANT_DIG; e <= DBL_MAX_EXP - 1; e++) { test2(atan2, ldexp(z, e), INFINITY, 0.0, 0); test2(atan2, ldexp(-z,e), INFINITY, -0.0, 0); test2(atan2, ldexp(z, e), -INFINITY, (double)pi, FE_INEXACT); test2(atan2, ldexp(-z,e), -INFINITY, (double)-pi, FE_INEXACT); test2(atan2, INFINITY, ldexp(z,e), (double)pi/2, FE_INEXACT); test2(atan2, INFINITY, ldexp(-z,e), (double)pi/2, FE_INEXACT); test2(atan2, -INFINITY, ldexp(z,e), (double)-pi/2,FE_INEXACT); test2(atan2, -INFINITY, ldexp(-z,e),(double)-pi/2,FE_INEXACT); } for (e = LDBL_MIN_EXP - LDBL_MANT_DIG; e <= LDBL_MAX_EXP - 1; e++) { test2(atan2l, ldexpl(z, e), INFINITY, 0.0, 0); test2(atan2l, ldexpl(-z,e), INFINITY, -0.0, 0); test2(atan2l, ldexpl(z, e), -INFINITY, pi, FE_INEXACT); test2(atan2l, ldexpl(-z,e), -INFINITY, -pi, FE_INEXACT); test2(atan2l, INFINITY, ldexpl(z, e), pi / 2, FE_INEXACT); test2(atan2l, INFINITY, ldexpl(-z, e), pi / 2, FE_INEXACT); test2(atan2l, -INFINITY, ldexpl(z, e), -pi / 2, FE_INEXACT); test2(atan2l, -INFINITY, ldexpl(-z, e), -pi / 2, FE_INEXACT); } } /* * Test various inputs to asin(), acos() and atan() and verify that the * results are accurate to within 1 ulp. */ static void test_accuracy(void) { /* We expect correctly rounded results for these basic cases. */ testall(asin, 1.0, pi / 2, FE_INEXACT); testall(acos, 1.0, 0, 0); testall(atan, 1.0, pi / 4, FE_INEXACT); testall(asin, -1.0, -pi / 2, FE_INEXACT); testall(acos, -1.0, pi, FE_INEXACT); testall(atan, -1.0, -pi / 4, FE_INEXACT); /* * Here we expect answers to be within 1 ulp, although inexactness * in the input, combined with double rounding, could cause larger * errors. */ testall_tol(asin, sqrtl(2) / 2, pi / 4, 1, FE_INEXACT); testall_tol(acos, sqrtl(2) / 2, pi / 4, 1, FE_INEXACT); testall_tol(asin, -sqrtl(2) / 2, -pi / 4, 1, FE_INEXACT); testall_tol(acos, -sqrtl(2) / 2, c3pi / 4, 1, FE_INEXACT); testall_tol(asin, sqrtl(3) / 2, pio3, 1, FE_INEXACT); testall_tol(acos, sqrtl(3) / 2, pio3 / 2, 1, FE_INEXACT); testall_tol(atan, sqrtl(3), pio3, 1, FE_INEXACT); testall_tol(asin, -sqrtl(3) / 2, -pio3, 1, FE_INEXACT); testall_tol(acos, -sqrtl(3) / 2, c5pio3 / 2, 1, FE_INEXACT); testall_tol(atan, -sqrtl(3), -pio3, 1, FE_INEXACT); testall_tol(atan, sqrt2m1, pi / 8, 1, FE_INEXACT); testall_tol(atan, -sqrt2m1, -pi / 8, 1, FE_INEXACT); } /* * Test inputs to atan2() where x is a power of 2. These are easy cases * because y/x is exact. */ static void test_p2x_atan2(void) { testall2(atan2, 1.0, 1.0, pi / 4, FE_INEXACT); testall2(atan2, 1.0, -1.0, c3pi / 4, FE_INEXACT); testall2(atan2, -1.0, 1.0, -pi / 4, FE_INEXACT); testall2(atan2, -1.0, -1.0, -c3pi / 4, FE_INEXACT); testall2_tol(atan2, sqrt2m1 * 2, 2.0, pi / 8, 1, FE_INEXACT); testall2_tol(atan2, sqrt2m1 * 2, -2.0, c7pi / 8, 1, FE_INEXACT); testall2_tol(atan2, -sqrt2m1 * 2, 2.0, -pi / 8, 1, FE_INEXACT); testall2_tol(atan2, -sqrt2m1 * 2, -2.0, -c7pi / 8, 1, FE_INEXACT); testall2_tol(atan2, sqrtl(3) * 0.5, 0.5, pio3, 1, FE_INEXACT); testall2_tol(atan2, sqrtl(3) * 0.5, -0.5, pio3 * 2, 1, FE_INEXACT); testall2_tol(atan2, -sqrtl(3) * 0.5, 0.5, -pio3, 1, FE_INEXACT); testall2_tol(atan2, -sqrtl(3) * 0.5, -0.5, -pio3 * 2, 1, FE_INEXACT); } /* * Test inputs very close to 0. */ static void test_tiny(void) { float tiny = 0x1.23456p-120f; testall(asin, tiny, tiny, FE_INEXACT); testall(acos, tiny, pi / 2, FE_INEXACT); testall(atan, tiny, tiny, FE_INEXACT); testall(asin, -tiny, -tiny, FE_INEXACT); testall(acos, -tiny, pi / 2, FE_INEXACT); testall(atan, -tiny, -tiny, FE_INEXACT); /* Test inputs to atan2() that would cause y/x to underflow. */ test2(atan2f, 0x1.0p-100, 0x1.0p100, 0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2, 0x1.0p-1000, 0x1.0p1000, 0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2l, ldexpl(1.0, 100 - LDBL_MAX_EXP), ldexpl(1.0, LDBL_MAX_EXP - 100), 0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2f, -0x1.0p-100, 0x1.0p100, -0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2, -0x1.0p-1000, 0x1.0p1000, -0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2l, -ldexpl(1.0, 100 - LDBL_MAX_EXP), ldexpl(1.0, LDBL_MAX_EXP - 100), -0.0, FE_INEXACT | FE_UNDERFLOW); test2(atan2f, 0x1.0p-100, -0x1.0p100, (float)pi, FE_INEXACT); test2(atan2, 0x1.0p-1000, -0x1.0p1000, (double)pi, FE_INEXACT); test2(atan2l, ldexpl(1.0, 100 - LDBL_MAX_EXP), -ldexpl(1.0, LDBL_MAX_EXP - 100), pi, FE_INEXACT); test2(atan2f, -0x1.0p-100, -0x1.0p100, (float)-pi, FE_INEXACT); test2(atan2, -0x1.0p-1000, -0x1.0p1000, (double)-pi, FE_INEXACT); test2(atan2l, -ldexpl(1.0, 100 - LDBL_MAX_EXP), -ldexpl(1.0, LDBL_MAX_EXP - 100), -pi, FE_INEXACT); } /* * Test very large inputs to atan(). */ static void test_atan_huge(void) { float huge = 0x1.23456p120; testall(atan, huge, pi / 2, FE_INEXACT); testall(atan, -huge, -pi / 2, FE_INEXACT); /* Test inputs to atan2() that would cause y/x to overflow. */ test2(atan2f, 0x1.0p100, 0x1.0p-100, (float)pi / 2, FE_INEXACT); test2(atan2, 0x1.0p1000, 0x1.0p-1000, (double)pi / 2, FE_INEXACT); test2(atan2l, ldexpl(1.0, LDBL_MAX_EXP - 100), ldexpl(1.0, 100 - LDBL_MAX_EXP), pi / 2, FE_INEXACT); test2(atan2f, -0x1.0p100, 0x1.0p-100, (float)-pi / 2, FE_INEXACT); test2(atan2, -0x1.0p1000, 0x1.0p-1000, (double)-pi / 2, FE_INEXACT); test2(atan2l, -ldexpl(1.0, LDBL_MAX_EXP - 100), ldexpl(1.0, 100 - LDBL_MAX_EXP), -pi / 2, FE_INEXACT); test2(atan2f, 0x1.0p100, -0x1.0p-100, (float)pi / 2, FE_INEXACT); test2(atan2, 0x1.0p1000, -0x1.0p-1000, (double)pi / 2, FE_INEXACT); test2(atan2l, ldexpl(1.0, LDBL_MAX_EXP - 100), -ldexpl(1.0, 100 - LDBL_MAX_EXP), pi / 2, FE_INEXACT); test2(atan2f, -0x1.0p100, -0x1.0p-100, (float)-pi / 2, FE_INEXACT); test2(atan2, -0x1.0p1000, -0x1.0p-1000, (double)-pi / 2, FE_INEXACT); test2(atan2l, -ldexpl(1.0, LDBL_MAX_EXP - 100), -ldexpl(1.0, 100 - LDBL_MAX_EXP), -pi / 2, FE_INEXACT); } /* * Test that sin(asin(x)) == x, and similarly for acos() and atan(). * You need to have a working sinl(), cosl(), and tanl() for these * tests to pass. */ static long double sinasinf(float x) { return (sinl(asinf(x))); } static long double sinasin(double x) { return (sinl(asin(x))); } static long double sinasinl(long double x) { return (sinl(asinl(x))); } static long double cosacosf(float x) { return (cosl(acosf(x))); } static long double cosacos(double x) { return (cosl(acos(x))); } static long double cosacosl(long double x) { return (cosl(acosl(x))); } static long double tanatanf(float x) { return (tanl(atanf(x))); } static long double tanatan(double x) { return (tanl(atan(x))); } static long double tanatanl(long double x) { return (tanl(atanl(x))); } static void test_inverse(void) { float i; for (i = -1; i <= 1; i += 0x1.0p-12f) { testall_tol(sinasin, i, i, 2, i == 0 ? 0 : FE_INEXACT); /* The relative error for cosacos is very large near x=0. */ if (fabsf(i) > 0x1.0p-4f) testall_tol(cosacos, i, i, 16, i == 1 ? 0 : FE_INEXACT); testall_tol(tanatan, i, i, 2, i == 0 ? 0 : FE_INEXACT); } } int -main(int argc, char *argv[]) +main(void) { #if defined(__i386__) printf("1..0 # SKIP fails all assertions on i386\n"); return (0); #endif printf("1..7\n"); test_special(); printf("ok 1 - special\n"); test_special_atan2(); printf("ok 2 - atan2 special\n"); test_accuracy(); printf("ok 3 - accuracy\n"); test_p2x_atan2(); printf("ok 4 - atan2 p2x\n"); test_tiny(); printf("ok 5 - tiny inputs\n"); test_atan_huge(); printf("ok 6 - atan huge inputs\n"); test_inverse(); printf("ok 7 - inverse\n"); return (0); } Index: head/lib/msun/tests/logarithm_test.c =================================================================== --- head/lib/msun/tests/logarithm_test.c (revision 314649) +++ head/lib/msun/tests/logarithm_test.c (revision 314650) @@ -1,286 +1,287 @@ /*- * Copyright (c) 2008-2010 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for corner cases in log*(). */ #include __FBSDID("$FreeBSD$"); +#include #include #include #include #include #include #ifdef __i386__ #include #endif #include "test-utils.h" #pragma STDC FENV_ACCESS ON /* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several * reasoons, but mainly because on some architectures it's impossible * to raise FE_OVERFLOW without raising FE_INEXACT. * * These are macros instead of functions so that assert provides more * meaningful error messages. * * XXX The volatile here is to avoid gcc's bogus constant folding and work * around the lack of support for the FENV_ACCESS pragma. */ #define test(func, x, result, exceptmask, excepts) do { \ volatile long double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_d), (result))); \ assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) #define test(func, x, result, exceptmask, excepts) do { \ volatile long double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_d), (result))); \ assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) #define test_tol(func, z, result, tol) do { \ volatile long double _d = z; \ debug(" testing %6s(%15La) ~= % .36Le\n", #func, _d, result); \ assert(fpequal_tol((func)(_d), (result), (tol), CS_BOTH)); \ } while (0) /* Test all the functions that compute log(x). */ #define testall0(x, result, exceptmask, excepts) do { \ test(log, x, result, exceptmask, excepts); \ test(logf, x, result, exceptmask, excepts); \ test(logl, x, result, exceptmask, excepts); \ test(log2, x, result, exceptmask, excepts); \ test(log2f, x, result, exceptmask, excepts); \ test(log2l, x, result, exceptmask, excepts); \ test(log10, x, result, exceptmask, excepts); \ test(log10f, x, result, exceptmask, excepts); \ test(log10l, x, result, exceptmask, excepts); \ } while (0) /* Test all the functions that compute log(1+x). */ #define testall1(x, result, exceptmask, excepts) do { \ test(log1p, x, result, exceptmask, excepts); \ test(log1pf, x, result, exceptmask, excepts); \ test(log1pl, x, result, exceptmask, excepts); \ } while (0) -void +static void run_generic_tests(void) { /* log(1) == 0, no exceptions raised */ testall0(1.0, 0.0, ALL_STD_EXCEPT, 0); testall1(0.0, 0.0, ALL_STD_EXCEPT, 0); testall1(-0.0, -0.0, ALL_STD_EXCEPT, 0); /* log(NaN) == NaN, no exceptions raised */ testall0(NAN, NAN, ALL_STD_EXCEPT, 0); testall1(NAN, NAN, ALL_STD_EXCEPT, 0); /* log(Inf) == Inf, no exceptions raised */ testall0(INFINITY, INFINITY, ALL_STD_EXCEPT, 0); testall1(INFINITY, INFINITY, ALL_STD_EXCEPT, 0); /* log(x) == NaN for x < 0, invalid exception raised */ testall0(-INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall1(-INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall0(-1.0, NAN, ALL_STD_EXCEPT, FE_INVALID); testall1(-1.5, NAN, ALL_STD_EXCEPT, FE_INVALID); /* log(0) == -Inf, divide-by-zero exception */ testall0(0.0, -INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_DIVBYZERO); testall0(-0.0, -INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_DIVBYZERO); testall1(-1.0, -INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_DIVBYZERO); } -void +static void run_log2_tests(void) { - int i; + unsigned i; /* * We should insist that log2() return exactly the correct * result and not raise an inexact exception for powers of 2. */ feclearexcept(FE_ALL_EXCEPT); for (i = FLT_MIN_EXP - FLT_MANT_DIG; i < FLT_MAX_EXP; i++) { assert(log2f(ldexpf(1.0, i)) == i); assert(fetestexcept(ALL_STD_EXCEPT) == 0); } for (i = DBL_MIN_EXP - DBL_MANT_DIG; i < DBL_MAX_EXP; i++) { assert(log2(ldexp(1.0, i)) == i); assert(fetestexcept(ALL_STD_EXCEPT) == 0); } for (i = LDBL_MIN_EXP - LDBL_MANT_DIG; i < LDBL_MAX_EXP; i++) { assert(log2l(ldexpl(1.0, i)) == i); #if 0 /* XXX This test does not pass yet. */ assert(fetestexcept(ALL_STD_EXCEPT) == 0); #endif } } -void +static void run_roundingmode_tests(void) { /* * Corner cases in other rounding modes. */ fesetround(FE_DOWNWARD); /* These are still positive per IEEE 754R */ #if 0 testall0(1.0, 0.0, ALL_STD_EXCEPT, 0); #else /* logl, log2l, and log10l don't pass yet. */ test(log, 1.0, 0.0, ALL_STD_EXCEPT, 0); test(logf, 1.0, 0.0, ALL_STD_EXCEPT, 0); test(log2, 1.0, 0.0, ALL_STD_EXCEPT, 0); test(log2f, 1.0, 0.0, ALL_STD_EXCEPT, 0); test(log10, 1.0, 0.0, ALL_STD_EXCEPT, 0); test(log10f, 1.0, 0.0, ALL_STD_EXCEPT, 0); #endif testall1(0.0, 0.0, ALL_STD_EXCEPT, 0); fesetround(FE_TOWARDZERO); testall0(1.0, 0.0, ALL_STD_EXCEPT, 0); testall1(0.0, 0.0, ALL_STD_EXCEPT, 0); fesetround(FE_UPWARD); testall0(1.0, 0.0, ALL_STD_EXCEPT, 0); testall1(0.0, 0.0, ALL_STD_EXCEPT, 0); /* log1p(-0.0) == -0.0 even when rounding upwards */ testall1(-0.0, -0.0, ALL_STD_EXCEPT, 0); fesetround(FE_TONEAREST); } -void +static void run_accuracy_tests(void) { static const struct { float x; long double log2x; long double logex; long double log10x; } tests[] = { { 0x1p-120 + 0x1p-140, -1.19999998624139449158861798943319717e2L, -8.31776607135195754708796206665656732e1L, -3.61235990655024477716980559136055915e1L, }, { 1.0 - 0x1p-20, -1.37586186296463416424364914705656460e-6L, -9.53674771153890007250243736279163253e-7L, -4.14175690642480911859354110516159131e-7L, }, { 1.0 + 0x1p-20, 1.37586055084113820105668028340371476e-6L, 9.53673861659188233908415514963336144e-7L, 4.14175295653950611453333571759200697e-7L }, { 19.75, 4.30378074817710292442728634194115348e0L, 2.98315349134713087533848129856505779e0L, 1.29556709996247903756734359702926363e0L }, { 19.75 * 0x1p100, 1.043037807481771029244272863419411534e2L, 7.229787154734166181706169344438271459e1L, 3.139856666636059855894123306947856631e1L }, }; - int i; + unsigned i; - for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + for (i = 0; i < nitems(tests); i++) { test_tol(log2, tests[i].x, tests[i].log2x, DBL_ULP()); test_tol(log2f, tests[i].x, tests[i].log2x, FLT_ULP()); test_tol(log2l, tests[i].x, tests[i].log2x, LDBL_ULP()); test_tol(log, tests[i].x, tests[i].logex, DBL_ULP()); test_tol(logf, tests[i].x, tests[i].logex, FLT_ULP()); test_tol(logl, tests[i].x, tests[i].logex, LDBL_ULP()); test_tol(log10, tests[i].x, tests[i].log10x, DBL_ULP()); test_tol(log10f, tests[i].x, tests[i].log10x, FLT_ULP()); test_tol(log10l, tests[i].x, tests[i].log10x, LDBL_ULP()); if (tests[i].x >= 0.5) { test_tol(log1p, tests[i].x - 1, tests[i].logex, DBL_ULP()); test_tol(log1pf, tests[i].x - 1, tests[i].logex, FLT_ULP()); test_tol(log1pl, tests[i].x - 1, tests[i].logex, LDBL_ULP()); } } } -void +static void run_log1p_accuracy_tests(void) { test_tol(log1pf, 0x0.333333p0F, 1.82321546859847114303367992804596800640e-1L, FLT_ULP()); test_tol(log1p, 0x0.3333333333333p0, 1.82321556793954589204283870982629267635e-1L, DBL_ULP()); test_tol(log1pl, 0x0.33333333333333332p0L, 1.82321556793954626202683007050468762914e-1L, LDBL_ULP()); test_tol(log1pf, -0x0.333333p0F, -2.23143536413048672940940199918017467652e-1L, FLT_ULP()); test_tol(log1p, -0x0.3333333333333p0, -2.23143551314209700255143859052009022937e-1L, DBL_ULP()); test_tol(log1pl, -0x0.33333333333333332p0L, -2.23143551314209755752742563153765697950e-1L, LDBL_ULP()); } int -main(int argc, char *argv[]) +main(void) { printf("1..5\n"); run_generic_tests(); printf("ok 1 - logarithm\n"); run_log2_tests(); printf("ok 2 - logarithm\n"); run_roundingmode_tests(); printf("ok 3 - logarithm\n"); run_accuracy_tests(); printf("ok 4 - logarithm\n"); run_log1p_accuracy_tests(); printf("ok 5 - logarithm\n"); return (0); } Index: head/lib/msun/tests/lrint_test.c =================================================================== --- head/lib/msun/tests/lrint_test.c (revision 314649) +++ head/lib/msun/tests/lrint_test.c (revision 314650) @@ -1,149 +1,149 @@ /*- * Copyright (c) 2005-2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Test for lrint(), lrintf(), llrint(), and llrintf(). */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #ifdef __i386__ #include #endif /* * XXX The volatile here is to avoid gcc's bogus constant folding and work * around the lack of support for the FENV_ACCESS pragma. */ #define test(func, x, result, excepts) do { \ volatile double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert((func)(_d) == (result) || fetestexcept(FE_INVALID)); \ assert(fetestexcept(FE_ALL_EXCEPT) == (excepts)); \ } while (0) #define testall(x, result, excepts) do { \ test(lrint, x, result, excepts); \ test(lrintf, x, result, excepts); \ test(lrintl, x, result, excepts); \ test(llrint, x, result, excepts); \ test(llrintf, x, result, excepts); \ test(llrintl, x, result, excepts); \ } while (0) #define IGNORE 0 #pragma STDC FENV_ACCESS ON -void +static void run_tests(void) { assert(fesetround(FE_DOWNWARD) == 0); testall(0.75, 0, FE_INEXACT); testall(-0.5, -1, FE_INEXACT); assert(fesetround(FE_TONEAREST) == 0); testall(0.0, 0, 0); testall(0.25, 0, FE_INEXACT); testall(0.5, 0, FE_INEXACT); testall(-2.5, -2, FE_INEXACT); testall(1.0, 1, 0); testall(0x12345000p0, 0x12345000, 0); testall(0x1234.fp0, 0x1235, FE_INEXACT); testall(INFINITY, IGNORE, FE_INVALID); testall(NAN, IGNORE, FE_INVALID); #if (LONG_MAX == 0x7fffffffl) assert(fesetround(FE_UPWARD) == 0); test(lrint, 0x7fffffff.8p0, IGNORE, FE_INVALID); test(lrint, -0x80000000.4p0, -0x80000000l, FE_INEXACT); assert(fesetround(FE_DOWNWARD) == 0); test(lrint, -0x80000000.8p0, IGNORE, FE_INVALID); test(lrint, 0x80000000.0p0, IGNORE, FE_INVALID); test(lrint, 0x7fffffff.4p0, 0x7fffffffl, FE_INEXACT); test(lrintf, 0x80000000.0p0f, IGNORE, FE_INVALID); test(lrintf, 0x7fffff80.0p0f, 0x7fffff80l, 0); assert(fesetround(FE_TOWARDZERO) == 0); test(lrint, 0x7fffffff.8p0, 0x7fffffffl, FE_INEXACT); test(lrint, -0x80000000.8p0, -0x80000000l, FE_INEXACT); test(lrint, 0x80000000.0p0, IGNORE, FE_INVALID); test(lrintf, 0x80000000.0p0f, IGNORE, FE_INVALID); test(lrintf, 0x7fffff80.0p0f, 0x7fffff80l, 0); #elif (LONG_MAX == 0x7fffffffffffffffll) assert(fesetround(FE_TONEAREST) == 0); test(lrint, 0x8000000000000000.0p0, IGNORE, FE_INVALID); test(lrintf, 0x8000000000000000.0p0f, IGNORE, FE_INVALID); test(lrint, 0x7ffffffffffffc00.0p0, 0x7ffffffffffffc00l, 0); test(lrintf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000l, 0); test(lrint, -0x8000000000000800.0p0, IGNORE, FE_INVALID); test(lrintf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID); test(lrint, -0x8000000000000000.0p0, -0x8000000000000000l, 0); test(lrintf, -0x8000000000000000.0p0f, -0x8000000000000000l, 0); #else #error "Unsupported long size" #endif #if (LLONG_MAX == 0x7fffffffffffffffLL) assert(fesetround(FE_TONEAREST) == 0); test(llrint, 0x8000000000000000.0p0, IGNORE, FE_INVALID); test(llrintf, 0x8000000000000000.0p0f, IGNORE, FE_INVALID); test(llrint, 0x7ffffffffffffc00.0p0, 0x7ffffffffffffc00ll, 0); test(llrintf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000ll, 0); test(llrint, -0x8000000000000800.0p0, IGNORE, FE_INVALID); test(llrintf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID); test(llrint, -0x8000000000000000.0p0, -0x8000000000000000ll, 0); test(llrintf, -0x8000000000000000.0p0f, -0x8000000000000000ll, 0); #else #error "Unsupported long long size" #endif } int -main(int argc, char *argv[]) +main(void) { printf("1..1\n"); run_tests(); #ifdef __i386__ fpsetprec(FP_PE); run_tests(); #endif printf("ok 1 - lrint\n"); return (0); } Index: head/lib/msun/tests/nan_test.c =================================================================== --- head/lib/msun/tests/nan_test.c (revision 314649) +++ head/lib/msun/tests/nan_test.c (revision 314650) @@ -1,122 +1,122 @@ /*- * Copyright (C) 2007 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Test for nan(), nanf(), and nanl(). We also test that strtod("nan(...)") * and sscanf("nan(...)", ...) work identically. */ #include __FBSDID("$FreeBSD$"); +#include #include #include #include #include #include #include #include #include -void +static void testnan(const char *nan_format) { char nan_str[128]; char *end; long double ald[4]; double ad[4]; float af[4]; - int i; + unsigned i; snprintf(nan_str, sizeof(nan_str), "nan(%s)", nan_format); - for (i = 0; i < 4; i++) { + for (i = 0; i < nitems(ad); i++) { /* * x86 has an 80-bit long double stored in 96 bits, * so we need to initialize the memory for the memcmp() * checks below to work. */ bzero(&af[i], sizeof(float)); bzero(&ad[i], sizeof(double)); bzero(&ald[i], sizeof(long double)); - } af[0] = nanf(nan_format); assert(isnan(af[0])); af[1] = strtof(nan_str, &end); assert(end == nan_str + strlen(nan_str)); assert(sscanf(nan_str, "%e", &af[2]) == 1); assert(memcmp(&af[0], &af[1], sizeof(float)) == 0); assert(memcmp(&af[1], &af[2], sizeof(float)) == 0); if (*nan_format == '\0') { /* nanf("") == strtof("nan") */ af[3] = strtof("nan", NULL); assert(memcmp(&af[2], &af[3], sizeof(float)) == 0); } ad[0] = nan(nan_format); assert(isnan(ad[0])); ad[1] = strtod(nan_str, &end); assert(end == nan_str + strlen(nan_str)); assert(sscanf(nan_str, "%le", &ad[2]) == 1); assert(memcmp(&ad[0], &ad[1], sizeof(double)) == 0); assert(memcmp(&ad[1], &ad[2], sizeof(double)) == 0); if (*nan_format == '\0') { /* nan("") == strtod("nan") */ ad[3] = strtod("nan", NULL); assert(memcmp(&ad[2], &ad[3], sizeof(double)) == 0); } ald[0] = nanl(nan_format); assert(isnan(ald[0])); ald[1] = strtold(nan_str, &end); assert(end == nan_str + strlen(nan_str)); assert(sscanf(nan_str, "%Le", &ald[2]) == 1); assert(memcmp(&ald[0], &ald[1], sizeof(long double)) == 0); assert(memcmp(&ald[1], &ald[2], sizeof(long double)) == 0); if (*nan_format == '\0') { /* nanl("") == strtold("nan") */ ald[3] = strtold("nan", NULL); assert(memcmp(&ald[2], &ald[3], sizeof(long double)) == 0); } } int -main(int argc, char *argv[]) +main(void) { printf("1..1\n"); /* Die if a signalling NaN is returned */ feenableexcept(FE_INVALID); testnan("0x1234"); testnan(""); printf("ok 1 - nan\n"); return (0); } Index: head/lib/msun/tests/nearbyint_test.c =================================================================== --- head/lib/msun/tests/nearbyint_test.c (revision 314649) +++ head/lib/msun/tests/nearbyint_test.c (revision 314650) @@ -1,176 +1,175 @@ /*- * Copyright (c) 2010 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for nearbyint{,f,l}() * * TODO: * - adapt tests for rint(3) * - tests for harder values (more mantissa bits than float) */ #include __FBSDID("$FreeBSD$"); +#include #include #include #include #include #include "test-utils.h" static int testnum; static const int rmodes[] = { FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO, }; /* Make sure we're testing the library, not some broken compiler built-ins. */ -double (*libnearbyint)(double) = nearbyint; -float (*libnearbyintf)(float) = nearbyintf; -long double (*libnearbyintl)(long double) = nearbyintl; +static double (*libnearbyint)(double) = nearbyint; +static float (*libnearbyintf)(float) = nearbyintf; +static long double (*libnearbyintl)(long double) = nearbyintl; #define nearbyintf libnearbyintf #define nearbyint libnearbyint #define nearbyintl libnearbyintl static const struct { float in; float out[3]; /* one answer per rounding mode except towardzero */ } tests[] = { /* input output (expected) */ { 0.0, { 0.0, 0.0, 0.0 }}, { 0.5, { 0.0, 0.0, 1.0 }}, { M_PI, { 3.0, 3.0, 4.0 }}, { 65536.5, { 65536, 65536, 65537 }}, { INFINITY, { INFINITY, INFINITY, INFINITY }}, { NAN, { NAN, NAN, NAN }}, }; -static const int ntests = sizeof(tests) / sizeof(tests[0]); - /* Get the appropriate result for the current rounding mode. */ static float get_output(int testindex, int rmodeindex, int negative) { double out; if (negative) { /* swap downwards and upwards if input is negative */ if (rmodeindex == 1) rmodeindex = 2; else if (rmodeindex == 2) rmodeindex = 1; } if (rmodeindex == 3) /* FE_TOWARDZERO uses the value for downwards */ rmodeindex = 1; out = tests[testindex].out[rmodeindex]; return (negative ? -out : out); } static void test_nearby(int testindex) { float in, out; - int i; + unsigned i; for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { fesetround(rmodes[i]); feclearexcept(ALL_STD_EXCEPT); in = tests[testindex].in; out = get_output(testindex, i, 0); assert(fpequal(out, libnearbyintf(in))); assert(fpequal(out, nearbyint(in))); assert(fpequal(out, nearbyintl(in))); assert(fetestexcept(ALL_STD_EXCEPT) == 0); in = -tests[testindex].in; out = get_output(testindex, i, 1); assert(fpequal(out, nearbyintf(in))); assert(fpequal(out, nearbyint(in))); assert(fpequal(out, nearbyintl(in))); assert(fetestexcept(ALL_STD_EXCEPT) == 0); } printf("ok %d\t\t# nearbyint(+%g)\n", testnum++, in); } static void test_modf(int testindex) { float in, out; float ipartf, ipart_expected; double ipart; long double ipartl; - int i; + unsigned i; for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { fesetround(rmodes[i]); feclearexcept(ALL_STD_EXCEPT); in = tests[testindex].in; ipart_expected = tests[testindex].out[1]; out = copysignf( isinf(ipart_expected) ? 0.0 : in - ipart_expected, in); ipartl = ipart = ipartf = 42.0; assert(fpequal(out, modff(in, &ipartf))); assert(fpequal(ipart_expected, ipartf)); assert(fpequal(out, modf(in, &ipart))); assert(fpequal(ipart_expected, ipart)); assert(fpequal(out, modfl(in, &ipartl))); assert(fpequal(ipart_expected, ipartl)); assert(fetestexcept(ALL_STD_EXCEPT) == 0); in = -in; ipart_expected = -ipart_expected; out = -out; ipartl = ipart = ipartf = 42.0; assert(fpequal(out, modff(in, &ipartf))); assert(fpequal(ipart_expected, ipartf)); assert(fpequal(out, modf(in, &ipart))); assert(fpequal(ipart_expected, ipart)); assert(fpequal(out, modfl(in, &ipartl))); assert(fpequal(ipart_expected, ipartl)); assert(fetestexcept(ALL_STD_EXCEPT) == 0); } printf("ok %d\t\t# modf(+%g)\n", testnum++, in); } int -main(int argc, char *argv[]) +main(void) { - int i; + unsigned i; - printf("1..%d\n", ntests * 2); + printf("1..%zu\n", (size_t)(nitems(tests) * 2)); testnum = 1; - for (i = 0; i < ntests; i++) { + for (i = 0; i < nitems(tests); i++) { test_nearby(i); test_modf(i); } return (0); } Index: head/lib/msun/tests/next_test.c =================================================================== --- head/lib/msun/tests/next_test.c (revision 314649) +++ head/lib/msun/tests/next_test.c (revision 314650) @@ -1,265 +1,265 @@ /*- * Copyright (c) 2005 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Test the correctness of nextafter{,f,l} and nexttoward{,f,l}. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #ifdef __i386__ #include #endif #include "test-utils.h" #define test(exp, ans, ex) do { \ double __ans = (ans); \ feclearexcept(ALL_STD_EXCEPT); \ _testl(#exp, __LINE__, (exp), __ans, (ex)); \ } while (0) #define testf(exp, ans, ex) do { \ float __ans = (ans); \ feclearexcept(ALL_STD_EXCEPT); \ _testl(#exp, __LINE__, (exp), __ans, (ex)); \ } while (0) #define testl(exp, ans, ex) do { \ long double __ans = (ans); \ feclearexcept(ALL_STD_EXCEPT); \ _testl(#exp, __LINE__, (exp), __ans, (ex)); \ } while (0) #define testboth(arg1, arg2, ans, ex, prec) do { \ test##prec(nextafter##prec((arg1), (arg2)), (ans), (ex)); \ test##prec(nexttoward##prec((arg1), (arg2)), (ans), (ex)); \ } while (0) #define testall(arg1, arg2, ans, ex) do { \ testboth((arg1), (arg2), (ans), (ex), ); \ testboth((arg1), (arg2), (ans), (ex), f); \ testboth((arg1), (arg2), (ans), (ex), l); \ } while (0) static void _testl(const char *, int, long double, long double, int); static double idd(double); static float idf(float); int -main(int argc, char *argv[]) +main(void) { static const int ex_under = FE_UNDERFLOW | FE_INEXACT; /* shorthand */ static const int ex_over = FE_OVERFLOW | FE_INEXACT; long double ldbl_small, ldbl_eps, ldbl_max; printf("1..5\n"); #ifdef __i386__ fpsetprec(FP_PE); #endif /* * We can't use a compile-time constant here because gcc on * FreeBSD/i386 assumes long doubles are truncated to the * double format. */ ldbl_small = ldexpl(1.0, LDBL_MIN_EXP - LDBL_MANT_DIG); ldbl_eps = LDBL_EPSILON; ldbl_max = ldexpl(1.0 - ldbl_eps / 2, LDBL_MAX_EXP); /* * Special cases involving zeroes. */ #define ztest(prec) \ test##prec(copysign##prec(1.0, nextafter##prec(0.0, -0.0)), -1.0, 0); \ test##prec(copysign##prec(1.0, nextafter##prec(-0.0, 0.0)), 1.0, 0); \ test##prec(copysign##prec(1.0, nexttoward##prec(0.0, -0.0)), -1.0, 0);\ test##prec(copysign##prec(1.0, nexttoward##prec(-0.0, 0.0)), 1.0, 0) ztest(); ztest(f); ztest(l); #undef ztest #define stest(next, eps, prec) \ test##prec(next(-0.0, 42.0), eps, ex_under); \ test##prec(next(0.0, -42.0), -eps, ex_under); \ test##prec(next(0.0, INFINITY), eps, ex_under); \ test##prec(next(-0.0, -INFINITY), -eps, ex_under) stest(nextafter, 0x1p-1074, ); stest(nextafterf, 0x1p-149f, f); stest(nextafterl, ldbl_small, l); stest(nexttoward, 0x1p-1074, ); stest(nexttowardf, 0x1p-149f, f); stest(nexttowardl, ldbl_small, l); #undef stest printf("ok 1 - next\n"); /* * `x == y' and NaN tests */ testall(42.0, 42.0, 42.0, 0); testall(-42.0, -42.0, -42.0, 0); testall(INFINITY, INFINITY, INFINITY, 0); testall(-INFINITY, -INFINITY, -INFINITY, 0); testall(NAN, 42.0, NAN, 0); testall(42.0, NAN, NAN, 0); testall(NAN, NAN, NAN, 0); printf("ok 2 - next\n"); /* * Tests where x is an ordinary normalized number */ testboth(1.0, 2.0, 1.0 + DBL_EPSILON, 0, ); testboth(1.0, -INFINITY, 1.0 - DBL_EPSILON/2, 0, ); testboth(1.0, 2.0, 1.0 + FLT_EPSILON, 0, f); testboth(1.0, -INFINITY, 1.0 - FLT_EPSILON/2, 0, f); testboth(1.0, 2.0, 1.0 + ldbl_eps, 0, l); testboth(1.0, -INFINITY, 1.0 - ldbl_eps/2, 0, l); testboth(-1.0, 2.0, -1.0 + DBL_EPSILON/2, 0, ); testboth(-1.0, -INFINITY, -1.0 - DBL_EPSILON, 0, ); testboth(-1.0, 2.0, -1.0 + FLT_EPSILON/2, 0, f); testboth(-1.0, -INFINITY, -1.0 - FLT_EPSILON, 0, f); testboth(-1.0, 2.0, -1.0 + ldbl_eps/2, 0, l); testboth(-1.0, -INFINITY, -1.0 - ldbl_eps, 0, l); /* Cases where nextafter(...) != nexttoward(...) */ test(nexttoward(1.0, 1.0 + ldbl_eps), 1.0 + DBL_EPSILON, 0); testf(nexttowardf(1.0, 1.0 + ldbl_eps), 1.0 + FLT_EPSILON, 0); testl(nexttowardl(1.0, 1.0 + ldbl_eps), 1.0 + ldbl_eps, 0); printf("ok 3 - next\n"); /* * Tests at word boundaries, normalization boundaries, etc. */ testboth(0x1.87654ffffffffp+0, INFINITY, 0x1.87655p+0, 0, ); testboth(0x1.87655p+0, -INFINITY, 0x1.87654ffffffffp+0, 0, ); testboth(0x1.fffffffffffffp+0, INFINITY, 0x1p1, 0, ); testboth(0x1p1, -INFINITY, 0x1.fffffffffffffp+0, 0, ); testboth(0x0.fffffffffffffp-1022, INFINITY, 0x1p-1022, 0, ); testboth(0x1p-1022, -INFINITY, 0x0.fffffffffffffp-1022, ex_under, ); testboth(0x1.fffffep0f, INFINITY, 0x1p1, 0, f); testboth(0x1p1, -INFINITY, 0x1.fffffep0f, 0, f); testboth(0x0.fffffep-126f, INFINITY, 0x1p-126f, 0, f); testboth(0x1p-126f, -INFINITY, 0x0.fffffep-126f, ex_under, f); #if LDBL_MANT_DIG == 53 testboth(0x1.87654ffffffffp+0L, INFINITY, 0x1.87655p+0L, 0, l); testboth(0x1.87655p+0L, -INFINITY, 0x1.87654ffffffffp+0L, 0, l); testboth(0x1.fffffffffffffp+0L, INFINITY, 0x1p1L, 0, l); testboth(0x1p1L, -INFINITY, 0x1.fffffffffffffp+0L, 0, l); testboth(0x0.fffffffffffffp-1022L, INFINITY, 0x1p-1022L, 0, l); testboth(0x1p-1022L, -INFINITY, 0x0.fffffffffffffp-1022L, ex_under, l); #elif LDBL_MANT_DIG == 64 && !defined(__i386) testboth(0x1.87654321fffffffep+0L, INFINITY, 0x1.87654322p+0L, 0, l); testboth(0x1.87654322p+0L, -INFINITY, 0x1.87654321fffffffep+0L, 0, l); testboth(0x1.fffffffffffffffep0L, INFINITY, 0x1p1L, 0, l); testboth(0x1p1L, -INFINITY, 0x1.fffffffffffffffep0L, 0, l); testboth(0x0.fffffffffffffffep-16382L, INFINITY, 0x1p-16382L, 0, l); testboth(0x1p-16382L, -INFINITY, 0x0.fffffffffffffffep-16382L, ex_under, l); #elif LDBL_MANT_DIG == 113 testboth(0x1.876543210987ffffffffffffffffp+0L, INFINITY, 0x1.876543210988p+0, 0, l); testboth(0x1.876543210988p+0L, -INFINITY, 0x1.876543210987ffffffffffffffffp+0L, 0, l); testboth(0x1.ffffffffffffffffffffffffffffp0L, INFINITY, 0x1p1L, 0, l); testboth(0x1p1L, -INFINITY, 0x1.ffffffffffffffffffffffffffffp0L, 0, l); testboth(0x0.ffffffffffffffffffffffffffffp-16382L, INFINITY, 0x1p-16382L, 0, l); testboth(0x1p-16382L, -INFINITY, 0x0.ffffffffffffffffffffffffffffp-16382L, ex_under, l); #endif printf("ok 4 - next\n"); /* * Overflow tests */ test(idd(nextafter(DBL_MAX, INFINITY)), INFINITY, ex_over); test(idd(nextafter(INFINITY, 0.0)), DBL_MAX, 0); test(idd(nexttoward(DBL_MAX, DBL_MAX * 2.0L)), INFINITY, ex_over); #if LDBL_MANT_DIG > 53 test(idd(nexttoward(INFINITY, DBL_MAX * 2.0L)), DBL_MAX, 0); #endif testf(idf(nextafterf(FLT_MAX, INFINITY)), INFINITY, ex_over); testf(idf(nextafterf(INFINITY, 0.0)), FLT_MAX, 0); testf(idf(nexttowardf(FLT_MAX, FLT_MAX * 2.0)), INFINITY, ex_over); testf(idf(nexttowardf(INFINITY, FLT_MAX * 2.0)), FLT_MAX, 0); testboth(ldbl_max, INFINITY, INFINITY, ex_over, l); testboth(INFINITY, 0.0, ldbl_max, 0, l); printf("ok 5 - next\n"); return (0); } static void _testl(const char *exp, int line, long double actual, long double expected, int except) { int actual_except; actual_except = fetestexcept(ALL_STD_EXCEPT); if (!fpequal(actual, expected)) { fprintf(stderr, "%d: %s returned %La, expecting %La\n", line, exp, actual, expected); abort(); } if (actual_except != except) { fprintf(stderr, "%d: %s raised 0x%x, expecting 0x%x\n", line, exp, actual_except, except); abort(); } } /* * The idd() and idf() routines ensure that doubles and floats are * converted to their respective types instead of stored in the FPU * with extra precision. */ static double idd(double x) { return (x); } static float idf(float x) { return (x); } Index: head/lib/msun/tests/rem_test.c =================================================================== --- head/lib/msun/tests/rem_test.c (revision 314649) +++ head/lib/msun/tests/rem_test.c (revision 314650) @@ -1,207 +1,207 @@ /*- * Copyright (c) 2005-2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Test for remainder functions: remainder, remainderf, remainderl, * remquo, remquof, and remquol. * Missing tests: fmod, fmodf. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include static void test_invalid(long double, long double); static void testl(long double, long double, long double, int); static void testd(double, double, double, int); static void testf(float, float, float, int); #define test(x, y, e_r, e_q) do { \ testl(x, y, e_r, e_q); \ testd(x, y, e_r, e_q); \ testf(x, y, e_r, e_q); \ } while (0) int -main(int argc, char *argv[]) +main(void) { printf("1..3\n"); test_invalid(0.0, 0.0); test_invalid(1.0, 0.0); test_invalid(INFINITY, 0.0); test_invalid(INFINITY, 1.0); test_invalid(-INFINITY, 1.0); test_invalid(NAN, 1.0); test_invalid(1.0, NAN); test(4, 4, 0, 1); test(0, 3.0, 0, 0); testd(0x1p-1074, 1, 0x1p-1074, 0); testf(0x1p-149, 1, 0x1p-149, 0); test(3.0, 4, -1, 1); test(3.0, -4, -1, -1); testd(275 * 1193040, 275, 0, 1193040); test(4.5 * 7.5, 4.5, -2.25, 8); /* we should get the even one */ testf(0x1.9044f6p-1, 0x1.ce662ep-1, -0x1.f109cp-4, 1); #if LDBL_MANT_DIG > 53 testl(-0x1.23456789abcdefp-2000L, 0x1.fedcba987654321p-2000L, 0x1.b72ea61d950c862p-2001L, -1); #endif printf("ok 1 - rem\n"); /* * The actual quotient here is 864062210.50000003..., but * double-precision division gets -8.64062210.5, which rounds * the wrong way. This test ensures that remquo() is smart * enough to get the low-order bit right. */ testd(-0x1.98260f22fc6dep-302, 0x1.fb3167c430a13p-332, 0x1.fb3165b82de72p-333, -864062211); /* Even harder cases with greater exponent separation */ test(0x1.fp100, 0x1.ep-40, -0x1.cp-41, 143165577); testd(-0x1.abcdefp120, 0x1.87654321p-120, -0x1.69c78ec4p-121, -63816414); printf("ok 2 - rem\n"); test(0x1.66666cp+120, 0x1p+71, 0.0, 1476395008); testd(-0x1.0000000000003p+0, 0x1.0000000000003p+0, -0.0, -1); testl(-0x1.0000000000003p+0, 0x1.0000000000003p+0, -0.0, -1); testd(-0x1.0000000000001p-749, 0x1.4p-1072, 0x1p-1074, -1288490189); testl(-0x1.0000000000001p-749, 0x1.4p-1072, 0x1p-1074, -1288490189); printf("ok 3 - rem\n"); return (0); } static void test_invalid(long double x, long double y) { int q; q = 0xdeadbeef; assert(isnan(remainder(x, y))); assert(isnan(remquo(x, y, &q))); #ifdef STRICT assert(q == 0xdeadbeef); #endif assert(isnan(remainderf(x, y))); assert(isnan(remquof(x, y, &q))); #ifdef STRICT assert(q == 0xdeadbeef); #endif assert(isnan(remainderl(x, y))); assert(isnan(remquol(x, y, &q))); #ifdef STRICT assert(q == 0xdeadbeef); #endif } /* 0x012345 ==> 0x01ffff */ static inline int mask(int x) { return ((unsigned)~0 >> (32 - fls(x))); } static void testl(long double x, long double y, long double expected_rem, int expected_quo) { int q; long double rem; q = random(); rem = remainderl(x, y); assert(rem == expected_rem); assert(!signbit(rem) == !signbit(expected_rem)); rem = remquol(x, y, &q); assert(rem == expected_rem); assert(!signbit(rem) == !signbit(expected_rem)); assert((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */ assert((q & 0x7) == (expected_quo & 0x7)); if (q != 0) { assert((q > 0) ^ !(expected_quo > 0)); q = abs(q); assert(q == (abs(expected_quo) & mask(q))); } } static void testd(double x, double y, double expected_rem, int expected_quo) { int q; double rem; q = random(); rem = remainder(x, y); assert(rem == expected_rem); assert(!signbit(rem) == !signbit(expected_rem)); rem = remquo(x, y, &q); assert(rem == expected_rem); assert(!signbit(rem) == !signbit(expected_rem)); assert((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */ assert((q & 0x7) == (expected_quo & 0x7)); if (q != 0) { assert((q > 0) ^ !(expected_quo > 0)); q = abs(q); assert(q == (abs(expected_quo) & mask(q))); } } static void testf(float x, float y, float expected_rem, int expected_quo) { int q; float rem; q = random(); rem = remainderf(x, y); assert(rem == expected_rem); assert(!signbit(rem) == !signbit(expected_rem)); rem = remquof(x, y, &q); assert(rem == expected_rem); assert(!signbit(rem) == !signbit(expected_rem)); assert((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */ assert((q & 0x7) == (expected_quo & 0x7)); if (q != 0) { assert((q > 0) ^ !(expected_quo > 0)); q = abs(q); assert((q & mask(q)) == (abs(expected_quo) & mask(q))); } } Index: head/lib/msun/tests/test-utils.h =================================================================== --- head/lib/msun/tests/test-utils.h (revision 314649) +++ head/lib/msun/tests/test-utils.h (revision 314650) @@ -1,174 +1,182 @@ /*- * Copyright (c) 2005-2013 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _TEST_UTILS_H_ #define _TEST_UTILS_H_ #include #include /* * Implementations are permitted to define additional exception flags * not specified in the standard, so it is not necessarily true that * FE_ALL_EXCEPT == ALL_STD_EXCEPT. */ #define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ FE_OVERFLOW | FE_UNDERFLOW) #define OPT_INVALID (ALL_STD_EXCEPT & ~FE_INVALID) #define OPT_INEXACT (ALL_STD_EXCEPT & ~FE_INEXACT) #define FLT_ULP() ldexpl(1.0, 1 - FLT_MANT_DIG) #define DBL_ULP() ldexpl(1.0, 1 - DBL_MANT_DIG) #define LDBL_ULP() ldexpl(1.0, 1 - LDBL_MANT_DIG) /* * Flags that control the behavior of various fpequal* functions. * XXX This is messy due to merging various notions of "close enough" * that are best suited for different functions. * * CS_REAL * CS_IMAG * CS_BOTH * (cfpequal_cs, fpequal_tol, cfpequal_tol) Whether to check the sign of * the real part of the result, the imaginary part, or both. * * FPE_ABS_ZERO * (fpequal_tol, cfpequal_tol) If set, treats the tolerance as an absolute * tolerance when the expected value is 0. This is useful when there is * round-off error in the input, e.g., cos(Pi/2) ~= 0. */ #define CS_REAL 0x01 #define CS_IMAG 0x02 #define CS_BOTH (CS_REAL | CS_IMAG) #define FPE_ABS_ZERO 0x04 #ifdef DEBUG #define debug(...) printf(__VA_ARGS__) #else #define debug(...) (void)0 #endif /* * XXX The ancient version of gcc in the base system doesn't support CMPLXL, * but we can fake it most of the time. */ #ifndef CMPLXL static inline long double complex CMPLXL(long double x, long double y) { long double complex z; __real__ z = x; __imag__ z = y; return (z); } #endif +static int fpequal(long double, long double) __used; +static int cfpequal(long double complex, long double complex) __used; +static int cfpequal_cs(long double complex, long double complex, + int) __used; +static int cfpequal_tol(long double complex, long double complex, + long double, unsigned int) __used; + /* * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. * Fail an assertion if they differ. */ static int fpequal(long double d1, long double d2) { if (d1 != d2) return (isnan(d1) && isnan(d2)); return (copysignl(1.0, d1) == copysignl(1.0, d2)); } /* * Determine whether x and y are equal, with two special rules: * +0.0 != -0.0 * NaN == NaN * If checksign is 0, we compare the absolute values instead. */ static int fpequal_cs(long double x, long double y, int checksign) { if (isnan(x) && isnan(y)) return (1); if (checksign) return (x == y && !signbit(x) == !signbit(y)); else return (fabsl(x) == fabsl(y)); } static int -fpequal_tol(long double x, long double y, long double tol, unsigned int flags) +fpequal_tol(long double x, long double y, long double tol, + unsigned int flags) { fenv_t env; int ret; if (isnan(x) && isnan(y)) return (1); if (!signbit(x) != !signbit(y) && (flags & CS_BOTH)) return (0); if (x == y) return (1); if (tol == 0) return (0); /* Hard case: need to check the tolerance. */ feholdexcept(&env); /* * For our purposes here, if y=0, we interpret tol as an absolute * tolerance. This is to account for roundoff in the input, e.g., * cos(Pi/2) ~= 0. */ if ((flags & FPE_ABS_ZERO) && y == 0.0) ret = fabsl(x - y) <= fabsl(tol); else ret = fabsl(x - y) <= fabsl(y * tol); fesetenv(&env); return (ret); } static int cfpequal(long double complex d1, long double complex d2) { return (fpequal(creall(d1), creall(d2)) && - fpequal(cimagl(d1), cimagl(d2))); + fpequal(cimagl(d1), cimagl(d2))); } static int cfpequal_cs(long double complex x, long double complex y, int checksign) { return (fpequal_cs(creal(x), creal(y), checksign) && fpequal_cs(cimag(x), cimag(y), checksign)); } static int cfpequal_tol(long double complex x, long double complex y, long double tol, - unsigned int flags) + unsigned int flags) { return (fpequal_tol(creal(x), creal(y), tol, flags) && fpequal_tol(cimag(x), cimag(y), tol, flags)); } #endif /* _TEST_UTILS_H_ */ Index: head/lib/msun/tests/trig_test.c =================================================================== --- head/lib/msun/tests/trig_test.c (revision 314649) +++ head/lib/msun/tests/trig_test.c (revision 314650) @@ -1,280 +1,280 @@ /*- * Copyright (c) 2008 David Schultz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Tests for corner cases in trigonometric functions. Some accuracy tests * are included as well, but these are very basic sanity checks, not * intended to be comprehensive. * * The program for generating representable numbers near multiples of pi is * available at http://www.cs.berkeley.edu/~wkahan/testpi/ . */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include "test-utils.h" #pragma STDC FENV_ACCESS ON /* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several * reasons, but mainly because on some architectures it's impossible * to raise FE_OVERFLOW without raising FE_INEXACT. * * These are macros instead of functions so that assert provides more * meaningful error messages. * * XXX The volatile here is to avoid gcc's bogus constant folding and work * around the lack of support for the FENV_ACCESS pragma. */ #define test(func, x, result, exceptmask, excepts) do { \ volatile long double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_d), (result))); \ assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) #define testall(prefix, x, result, exceptmask, excepts) do { \ test(prefix, x, (double)result, exceptmask, excepts); \ test(prefix##f, x, (float)result, exceptmask, excepts); \ test(prefix##l, x, result, exceptmask, excepts); \ } while (0) #define testdf(prefix, x, result, exceptmask, excepts) do { \ test(prefix, x, (double)result, exceptmask, excepts); \ test(prefix##f, x, (float)result, exceptmask, excepts); \ } while (0) /* * Test special cases in sin(), cos(), and tan(). */ static void run_special_tests(void) { /* Values at 0 should be exact. */ testall(tan, 0.0, 0.0, ALL_STD_EXCEPT, 0); testall(tan, -0.0, -0.0, ALL_STD_EXCEPT, 0); testall(cos, 0.0, 1.0, ALL_STD_EXCEPT, 0); testall(cos, -0.0, 1.0, ALL_STD_EXCEPT, 0); testall(sin, 0.0, 0.0, ALL_STD_EXCEPT, 0); testall(sin, -0.0, -0.0, ALL_STD_EXCEPT, 0); /* func(+-Inf) == NaN */ testall(tan, INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(sin, INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(cos, INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(tan, -INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(sin, -INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); testall(cos, -INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID); /* func(NaN) == NaN */ testall(tan, NAN, NAN, ALL_STD_EXCEPT, 0); testall(sin, NAN, NAN, ALL_STD_EXCEPT, 0); testall(cos, NAN, NAN, ALL_STD_EXCEPT, 0); } /* * Tests to ensure argument reduction for large arguments is accurate. */ static void run_reduction_tests(void) { /* floats very close to odd multiples of pi */ static const float f_pi_odd[] = { 85563208.0f, 43998769152.0f, 9.2763667655669323e+25f, 1.5458357838905804e+29f, }; /* doubles very close to odd multiples of pi */ static const double d_pi_odd[] = { 3.1415926535897931, 91.106186954104004, 642615.9188844458, 3397346.5699258847, 6134899525417045.0, 3.0213551960457761e+43, 1.2646209897993783e+295, 6.2083625380677099e+307, }; /* long doubles very close to odd multiples of pi */ #if LDBL_MANT_DIG == 64 static const long double ld_pi_odd[] = { 1.1891886960373841596e+101L, 1.07999475322710967206e+2087L, 6.522151627890431836e+2147L, 8.9368974898260328229e+2484L, 9.2961044110572205863e+2555L, 4.90208421886578286e+3189L, 1.5275546401232615884e+3317L, 1.7227465626338900093e+3565L, 2.4160090594000745334e+3808L, 9.8477555741888350649e+4314L, 1.6061597222105160737e+4326L, }; #elif LDBL_MANT_DIG == 113 static const long double ld_pi_odd[] = { /* XXX */ }; #endif - int i; + unsigned i; for (i = 0; i < nitems(f_pi_odd); i++) { assert(fabs(sinf(f_pi_odd[i])) < FLT_EPSILON); assert(cosf(f_pi_odd[i]) == -1.0); assert(fabs(tan(f_pi_odd[i])) < FLT_EPSILON); assert(fabs(sinf(-f_pi_odd[i])) < FLT_EPSILON); assert(cosf(-f_pi_odd[i]) == -1.0); assert(fabs(tanf(-f_pi_odd[i])) < FLT_EPSILON); assert(fabs(sinf(f_pi_odd[i] * 2)) < FLT_EPSILON); assert(cosf(f_pi_odd[i] * 2) == 1.0); assert(fabs(tanf(f_pi_odd[i] * 2)) < FLT_EPSILON); assert(fabs(sinf(-f_pi_odd[i] * 2)) < FLT_EPSILON); assert(cosf(-f_pi_odd[i] * 2) == 1.0); assert(fabs(tanf(-f_pi_odd[i] * 2)) < FLT_EPSILON); } for (i = 0; i < nitems(d_pi_odd); i++) { assert(fabs(sin(d_pi_odd[i])) < 2 * DBL_EPSILON); assert(cos(d_pi_odd[i]) == -1.0); assert(fabs(tan(d_pi_odd[i])) < 2 * DBL_EPSILON); assert(fabs(sin(-d_pi_odd[i])) < 2 * DBL_EPSILON); assert(cos(-d_pi_odd[i]) == -1.0); assert(fabs(tan(-d_pi_odd[i])) < 2 * DBL_EPSILON); assert(fabs(sin(d_pi_odd[i] * 2)) < 2 * DBL_EPSILON); assert(cos(d_pi_odd[i] * 2) == 1.0); assert(fabs(tan(d_pi_odd[i] * 2)) < 2 * DBL_EPSILON); assert(fabs(sin(-d_pi_odd[i] * 2)) < 2 * DBL_EPSILON); assert(cos(-d_pi_odd[i] * 2) == 1.0); assert(fabs(tan(-d_pi_odd[i] * 2)) < 2 * DBL_EPSILON); } #if LDBL_MANT_DIG > 53 for (i = 0; i < nitems(ld_pi_odd); i++) { assert(fabsl(sinl(ld_pi_odd[i])) < LDBL_EPSILON); assert(cosl(ld_pi_odd[i]) == -1.0); assert(fabsl(tanl(ld_pi_odd[i])) < LDBL_EPSILON); assert(fabsl(sinl(-ld_pi_odd[i])) < LDBL_EPSILON); assert(cosl(-ld_pi_odd[i]) == -1.0); assert(fabsl(tanl(-ld_pi_odd[i])) < LDBL_EPSILON); assert(fabsl(sinl(ld_pi_odd[i] * 2)) < LDBL_EPSILON); assert(cosl(ld_pi_odd[i] * 2) == 1.0); assert(fabsl(tanl(ld_pi_odd[i] * 2)) < LDBL_EPSILON); assert(fabsl(sinl(-ld_pi_odd[i] * 2)) < LDBL_EPSILON); assert(cosl(-ld_pi_odd[i] * 2) == 1.0); assert(fabsl(tanl(-ld_pi_odd[i] * 2)) < LDBL_EPSILON); } #endif } /* * Tests the accuracy of these functions over the primary range. */ static void run_accuracy_tests(void) { /* For small args, sin(x) = tan(x) = x, and cos(x) = 1. */ testall(sin, 0xd.50ee515fe4aea16p-114L, 0xd.50ee515fe4aea16p-114L, ALL_STD_EXCEPT, FE_INEXACT); testall(tan, 0xd.50ee515fe4aea16p-114L, 0xd.50ee515fe4aea16p-114L, ALL_STD_EXCEPT, FE_INEXACT); testall(cos, 0xd.50ee515fe4aea16p-114L, 1.0, ALL_STD_EXCEPT, FE_INEXACT); /* * These tests should pass for f32, d64, and ld80 as long as * the error is <= 0.75 ulp (round to nearest) */ #if LDBL_MANT_DIG <= 64 #define testacc testall #else #define testacc testdf #endif testacc(sin, 0.17255452780841205174L, 0.17169949801444412683L, ALL_STD_EXCEPT, FE_INEXACT); testacc(sin, -0.75431944555904520893L, -0.68479288156557286353L, ALL_STD_EXCEPT, FE_INEXACT); testacc(cos, 0.70556358769838947292L, 0.76124620693117771850L, ALL_STD_EXCEPT, FE_INEXACT); testacc(cos, -0.34061437849088045332L, 0.94254960031831729956L, ALL_STD_EXCEPT, FE_INEXACT); testacc(tan, -0.15862817413325692897L, -0.15997221861309522115L, ALL_STD_EXCEPT, FE_INEXACT); testacc(tan, 0.38374784931303813530L, 0.40376500259976759951L, ALL_STD_EXCEPT, FE_INEXACT); /* * XXX missing: * - tests for ld128 * - tests for other rounding modes (probably won't pass for now) * - tests for large numbers that get reduced to hi+lo with lo!=0 */ } int -main(int argc, char *argv[]) +main(void) { printf("1..3\n"); run_special_tests(); printf("ok 1 - trig\n"); #ifndef __i386__ run_reduction_tests(); #endif printf("ok 2 - trig\n"); #ifndef __i386__ run_accuracy_tests(); #endif printf("ok 3 - trig\n"); return (0); }