xref: /dflybsd-src/tools/regression/lib/libm/test-exponential.c (revision 7f8c68295613ce24cc71827cf210cb3d1e3bc69b)
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