1*7f8c6829SSascha Wildner /*-
2*7f8c6829SSascha Wildner * Copyright (c) 2008 David Schultz <das@FreeBSD.org>
3*7f8c6829SSascha Wildner * All rights reserved.
4*7f8c6829SSascha Wildner *
5*7f8c6829SSascha Wildner * Redistribution and use in source and binary forms, with or without
6*7f8c6829SSascha Wildner * modification, are permitted provided that the following conditions
7*7f8c6829SSascha Wildner * are met:
8*7f8c6829SSascha Wildner * 1. Redistributions of source code must retain the above copyright
9*7f8c6829SSascha Wildner * notice, this list of conditions and the following disclaimer.
10*7f8c6829SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
11*7f8c6829SSascha Wildner * notice, this list of conditions and the following disclaimer in the
12*7f8c6829SSascha Wildner * documentation and/or other materials provided with the distribution.
13*7f8c6829SSascha Wildner *
14*7f8c6829SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*7f8c6829SSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*7f8c6829SSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*7f8c6829SSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*7f8c6829SSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*7f8c6829SSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*7f8c6829SSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*7f8c6829SSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*7f8c6829SSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*7f8c6829SSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*7f8c6829SSascha Wildner * SUCH DAMAGE.
25*7f8c6829SSascha Wildner *
26*7f8c6829SSascha Wildner * $FreeBSD: src/tools/regression/lib/msun/test-exponential.c,v 1.4 2010/12/06 00:02:49 das Exp $
27*7f8c6829SSascha Wildner */
28*7f8c6829SSascha Wildner
29*7f8c6829SSascha Wildner /*
30*7f8c6829SSascha Wildner * Tests for corner cases in exp*().
31*7f8c6829SSascha Wildner */
32*7f8c6829SSascha Wildner
33*7f8c6829SSascha Wildner #include <assert.h>
34*7f8c6829SSascha Wildner #include <fenv.h>
35*7f8c6829SSascha Wildner #include <float.h>
36*7f8c6829SSascha Wildner #include <math.h>
37*7f8c6829SSascha Wildner #include <stdio.h>
38*7f8c6829SSascha Wildner
39*7f8c6829SSascha Wildner #ifdef __i386__
40*7f8c6829SSascha Wildner #include <ieeefp.h>
41*7f8c6829SSascha Wildner #endif
42*7f8c6829SSascha Wildner
43*7f8c6829SSascha Wildner #define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
44*7f8c6829SSascha Wildner FE_OVERFLOW | FE_UNDERFLOW)
45*7f8c6829SSascha Wildner
46*7f8c6829SSascha Wildner #pragma STDC FENV_ACCESS ON
47*7f8c6829SSascha Wildner
48*7f8c6829SSascha Wildner /*
49*7f8c6829SSascha Wildner * Test that a function returns the correct value and sets the
50*7f8c6829SSascha Wildner * exception flags correctly. The exceptmask specifies which
51*7f8c6829SSascha Wildner * exceptions we should check. We need to be lenient for several
52*7f8c6829SSascha Wildner * reasoons, but mainly because on some architectures it's impossible
53*7f8c6829SSascha Wildner * to raise FE_OVERFLOW without raising FE_INEXACT.
54*7f8c6829SSascha Wildner *
55*7f8c6829SSascha Wildner * These are macros instead of functions so that assert provides more
56*7f8c6829SSascha Wildner * meaningful error messages.
57*7f8c6829SSascha Wildner *
58*7f8c6829SSascha Wildner * XXX The volatile here is to avoid gcc's bogus constant folding and work
59*7f8c6829SSascha Wildner * around the lack of support for the FENV_ACCESS pragma.
60*7f8c6829SSascha Wildner */
61*7f8c6829SSascha Wildner #define test(func, x, result, exceptmask, excepts) do { \
62*7f8c6829SSascha Wildner volatile long double _d = x; \
63*7f8c6829SSascha Wildner assert(feclearexcept(FE_ALL_EXCEPT) == 0); \
64*7f8c6829SSascha Wildner assert(fpequal((func)(_d), (result))); \
65*7f8c6829SSascha Wildner assert(((func), fetestexcept(exceptmask) == (excepts))); \
66*7f8c6829SSascha Wildner } while (0)
67*7f8c6829SSascha Wildner
68*7f8c6829SSascha Wildner /* Test all the functions that compute b^x. */
69*7f8c6829SSascha Wildner #define testall0(x, result, exceptmask, excepts) do { \
70*7f8c6829SSascha Wildner test(exp, x, result, exceptmask, excepts); \
71*7f8c6829SSascha Wildner test(expf, x, result, exceptmask, excepts); \
72*7f8c6829SSascha Wildner test(exp2, x, result, exceptmask, excepts); \
73*7f8c6829SSascha Wildner test(exp2f, x, result, exceptmask, excepts); \
74*7f8c6829SSascha Wildner test(exp2l, x, result, exceptmask, excepts); \
75*7f8c6829SSascha Wildner } while (0)
76*7f8c6829SSascha Wildner
77*7f8c6829SSascha Wildner /* Test all the functions that compute b^x - 1. */
78*7f8c6829SSascha Wildner #define testall1(x, result, exceptmask, excepts) do { \
79*7f8c6829SSascha Wildner test(expm1, x, result, exceptmask, excepts); \
80*7f8c6829SSascha Wildner test(expm1f, x, result, exceptmask, excepts); \
81*7f8c6829SSascha Wildner } while (0)
82*7f8c6829SSascha Wildner
83*7f8c6829SSascha Wildner /*
84*7f8c6829SSascha Wildner * Determine whether x and y are equal, with two special rules:
85*7f8c6829SSascha Wildner * +0.0 != -0.0
86*7f8c6829SSascha Wildner * NaN == NaN
87*7f8c6829SSascha Wildner */
88*7f8c6829SSascha Wildner int
fpequal(long double x,long double y)89*7f8c6829SSascha Wildner fpequal(long double x, long double y)
90*7f8c6829SSascha Wildner {
91*7f8c6829SSascha Wildner return ((x == y && !signbit(x) == !signbit(y)) || isnan(x) && isnan(y));
92*7f8c6829SSascha Wildner }
93*7f8c6829SSascha Wildner
94*7f8c6829SSascha Wildner void
run_generic_tests(void)95*7f8c6829SSascha Wildner run_generic_tests(void)
96*7f8c6829SSascha Wildner {
97*7f8c6829SSascha Wildner
98*7f8c6829SSascha Wildner /* exp(0) == 1, no exceptions raised */
99*7f8c6829SSascha Wildner testall0(0.0, 1.0, ALL_STD_EXCEPT, 0);
100*7f8c6829SSascha Wildner testall1(0.0, 0.0, ALL_STD_EXCEPT, 0);
101*7f8c6829SSascha Wildner testall0(-0.0, 1.0, ALL_STD_EXCEPT, 0);
102*7f8c6829SSascha Wildner testall1(-0.0, -0.0, ALL_STD_EXCEPT, 0);
103*7f8c6829SSascha Wildner
104*7f8c6829SSascha Wildner /* exp(NaN) == NaN, no exceptions raised */
105*7f8c6829SSascha Wildner testall0(NAN, NAN, ALL_STD_EXCEPT, 0);
106*7f8c6829SSascha Wildner testall1(NAN, NAN, ALL_STD_EXCEPT, 0);
107*7f8c6829SSascha Wildner
108*7f8c6829SSascha Wildner /* exp(Inf) == Inf, no exceptions raised */
109*7f8c6829SSascha Wildner testall0(INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
110*7f8c6829SSascha Wildner testall1(INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
111*7f8c6829SSascha Wildner
112*7f8c6829SSascha Wildner /* exp(-Inf) == 0, no exceptions raised */
113*7f8c6829SSascha Wildner testall0(-INFINITY, 0.0, ALL_STD_EXCEPT, 0);
114*7f8c6829SSascha Wildner testall1(-INFINITY, -1.0, ALL_STD_EXCEPT, 0);
115*7f8c6829SSascha Wildner
116*7f8c6829SSascha Wildner /* exp(big) == Inf, overflow exception */
117*7f8c6829SSascha Wildner testall0(50000.0, INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_OVERFLOW);
118*7f8c6829SSascha Wildner testall1(50000.0, INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_OVERFLOW);
119*7f8c6829SSascha Wildner
120*7f8c6829SSascha Wildner /* exp(small) == 0, underflow and inexact exceptions */
121*7f8c6829SSascha Wildner testall0(-50000.0, 0.0, ALL_STD_EXCEPT, FE_UNDERFLOW | FE_INEXACT);
122*7f8c6829SSascha Wildner testall1(-50000.0, -1.0, ALL_STD_EXCEPT, FE_INEXACT);
123*7f8c6829SSascha Wildner }
124*7f8c6829SSascha Wildner
125*7f8c6829SSascha Wildner void
run_exp2_tests(void)126*7f8c6829SSascha Wildner run_exp2_tests(void)
127*7f8c6829SSascha Wildner {
128*7f8c6829SSascha Wildner int i;
129*7f8c6829SSascha Wildner
130*7f8c6829SSascha Wildner /*
131*7f8c6829SSascha Wildner * We should insist that exp2() return exactly the correct
132*7f8c6829SSascha Wildner * result and not raise an inexact exception for integer
133*7f8c6829SSascha Wildner * arguments.
134*7f8c6829SSascha Wildner */
135*7f8c6829SSascha Wildner feclearexcept(FE_ALL_EXCEPT);
136*7f8c6829SSascha Wildner for (i = FLT_MIN_EXP - FLT_MANT_DIG; i < FLT_MAX_EXP; i++) {
137*7f8c6829SSascha Wildner assert(exp2f(i) == ldexpf(1.0, i));
138*7f8c6829SSascha Wildner assert(fetestexcept(ALL_STD_EXCEPT) == 0);
139*7f8c6829SSascha Wildner }
140*7f8c6829SSascha Wildner for (i = DBL_MIN_EXP - DBL_MANT_DIG; i < DBL_MAX_EXP; i++) {
141*7f8c6829SSascha Wildner assert(exp2(i) == ldexp(1.0, i));
142*7f8c6829SSascha Wildner assert(fetestexcept(ALL_STD_EXCEPT) == 0);
143*7f8c6829SSascha Wildner }
144*7f8c6829SSascha Wildner for (i = LDBL_MIN_EXP - LDBL_MANT_DIG; i < LDBL_MAX_EXP; i++) {
145*7f8c6829SSascha Wildner assert(exp2l(i) == ldexpl(1.0, i));
146*7f8c6829SSascha Wildner assert(fetestexcept(ALL_STD_EXCEPT) == 0);
147*7f8c6829SSascha Wildner }
148*7f8c6829SSascha Wildner }
149*7f8c6829SSascha Wildner
150*7f8c6829SSascha Wildner int
main(int argc,char * argv[])151*7f8c6829SSascha Wildner main(int argc, char *argv[])
152*7f8c6829SSascha Wildner {
153*7f8c6829SSascha Wildner
154*7f8c6829SSascha Wildner printf("1..3\n");
155*7f8c6829SSascha Wildner
156*7f8c6829SSascha Wildner run_generic_tests();
157*7f8c6829SSascha Wildner printf("ok 1 - exponential\n");
158*7f8c6829SSascha Wildner
159*7f8c6829SSascha Wildner #ifdef __i386__
160*7f8c6829SSascha Wildner fpsetprec(FP_PE);
161*7f8c6829SSascha Wildner run_generic_tests();
162*7f8c6829SSascha Wildner #endif
163*7f8c6829SSascha Wildner printf("ok 2 - exponential\n");
164*7f8c6829SSascha Wildner
165*7f8c6829SSascha Wildner run_exp2_tests();
166*7f8c6829SSascha Wildner printf("ok 3 - exponential\n");
167*7f8c6829SSascha Wildner
168*7f8c6829SSascha Wildner return (0);
169*7f8c6829SSascha Wildner }
170