xref: /dflybsd-src/tools/regression/lib/libm/test-logarithm.c (revision 7f8c68295613ce24cc71827cf210cb3d1e3bc69b)
1*7f8c6829SSascha Wildner /*-
2*7f8c6829SSascha Wildner  * Copyright (c) 2008-2010 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-logarithm.c,v 1.3 2011/10/15 05:28:13 das Exp $
27*7f8c6829SSascha Wildner  */
28*7f8c6829SSascha Wildner 
29*7f8c6829SSascha Wildner /*
30*7f8c6829SSascha Wildner  * Tests for corner cases in log*().
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 log(x). */
69*7f8c6829SSascha Wildner #define	testall0(x, result, exceptmask, excepts)	do {		\
70*7f8c6829SSascha Wildner 	test(log, x, result, exceptmask, excepts);			\
71*7f8c6829SSascha Wildner 	test(logf, x, result, exceptmask, excepts);			\
72*7f8c6829SSascha Wildner 	test(log2, x, result, exceptmask, excepts);			\
73*7f8c6829SSascha Wildner 	test(log2f, x, result, exceptmask, excepts);			\
74*7f8c6829SSascha Wildner 	test(log10, x, result, exceptmask, excepts);			\
75*7f8c6829SSascha Wildner 	test(log10f, x, result, exceptmask, excepts);			\
76*7f8c6829SSascha Wildner } while (0)
77*7f8c6829SSascha Wildner 
78*7f8c6829SSascha Wildner /* Test all the functions that compute log(1+x). */
79*7f8c6829SSascha Wildner #define	testall1(x, result, exceptmask, excepts)	do {		\
80*7f8c6829SSascha Wildner 	test(log1p, x, result, exceptmask, excepts);			\
81*7f8c6829SSascha Wildner 	test(log1pf, x, result, exceptmask, excepts);			\
82*7f8c6829SSascha Wildner } while (0)
83*7f8c6829SSascha Wildner 
84*7f8c6829SSascha Wildner /*
85*7f8c6829SSascha Wildner  * Determine whether x and y are equal, with two special rules:
86*7f8c6829SSascha Wildner  *	+0.0 != -0.0
87*7f8c6829SSascha Wildner  *	 NaN == NaN
88*7f8c6829SSascha Wildner  */
89*7f8c6829SSascha Wildner int
fpequal(long double x,long double y)90*7f8c6829SSascha Wildner fpequal(long double x, long double y)
91*7f8c6829SSascha Wildner {
92*7f8c6829SSascha Wildner 	return ((x == y && !signbit(x) == !signbit(y)) || isnan(x) && isnan(y));
93*7f8c6829SSascha Wildner }
94*7f8c6829SSascha Wildner 
95*7f8c6829SSascha Wildner void
run_generic_tests(void)96*7f8c6829SSascha Wildner run_generic_tests(void)
97*7f8c6829SSascha Wildner {
98*7f8c6829SSascha Wildner 
99*7f8c6829SSascha Wildner 	/* log(1) == 0, no exceptions raised */
100*7f8c6829SSascha Wildner 	testall0(1.0, 0.0, ALL_STD_EXCEPT, 0);
101*7f8c6829SSascha Wildner 	testall1(0.0, 0.0, ALL_STD_EXCEPT, 0);
102*7f8c6829SSascha Wildner 	testall1(-0.0, -0.0, ALL_STD_EXCEPT, 0);
103*7f8c6829SSascha Wildner 
104*7f8c6829SSascha Wildner 	/* log(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 	/* log(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 	/* log(x) == NaN for x < 0, invalid exception raised */
113*7f8c6829SSascha Wildner 	testall0(-INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID);
114*7f8c6829SSascha Wildner 	testall1(-INFINITY, NAN, ALL_STD_EXCEPT, FE_INVALID);
115*7f8c6829SSascha Wildner 	testall0(-1.0, NAN, ALL_STD_EXCEPT, FE_INVALID);
116*7f8c6829SSascha Wildner 	testall1(-1.5, NAN, ALL_STD_EXCEPT, FE_INVALID);
117*7f8c6829SSascha Wildner 
118*7f8c6829SSascha Wildner 	/* log(0) == -Inf, divide-by-zero exception */
119*7f8c6829SSascha Wildner 	testall0(0.0, -INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_DIVBYZERO);
120*7f8c6829SSascha Wildner 	testall0(-0.0, -INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_DIVBYZERO);
121*7f8c6829SSascha Wildner 	testall1(-1.0, -INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_DIVBYZERO);
122*7f8c6829SSascha Wildner }
123*7f8c6829SSascha Wildner 
124*7f8c6829SSascha Wildner void
run_log2_tests(void)125*7f8c6829SSascha Wildner run_log2_tests(void)
126*7f8c6829SSascha Wildner {
127*7f8c6829SSascha Wildner 	int i;
128*7f8c6829SSascha Wildner 
129*7f8c6829SSascha Wildner 	/*
130*7f8c6829SSascha Wildner 	 * We should insist that log2() return exactly the correct
131*7f8c6829SSascha Wildner 	 * result and not raise an inexact exception for powers of 2.
132*7f8c6829SSascha Wildner 	 */
133*7f8c6829SSascha Wildner 	feclearexcept(FE_ALL_EXCEPT);
134*7f8c6829SSascha Wildner 	for (i = FLT_MIN_EXP - FLT_MANT_DIG; i < FLT_MAX_EXP; i++) {
135*7f8c6829SSascha Wildner 		assert(log2f(ldexpf(1.0, i)) == i);
136*7f8c6829SSascha Wildner 		assert(fetestexcept(ALL_STD_EXCEPT) == 0);
137*7f8c6829SSascha Wildner 	}
138*7f8c6829SSascha Wildner 	for (i = DBL_MIN_EXP - DBL_MANT_DIG; i < DBL_MAX_EXP; i++) {
139*7f8c6829SSascha Wildner 		assert(log2(ldexp(1.0, i)) == i);
140*7f8c6829SSascha Wildner 		assert(fetestexcept(ALL_STD_EXCEPT) == 0);
141*7f8c6829SSascha Wildner 	}
142*7f8c6829SSascha Wildner }
143*7f8c6829SSascha Wildner 
144*7f8c6829SSascha Wildner void
run_roundingmode_tests(void)145*7f8c6829SSascha Wildner run_roundingmode_tests(void)
146*7f8c6829SSascha Wildner {
147*7f8c6829SSascha Wildner 
148*7f8c6829SSascha Wildner 	/*
149*7f8c6829SSascha Wildner 	 * Corner cases in other rounding modes.
150*7f8c6829SSascha Wildner 	 */
151*7f8c6829SSascha Wildner 	fesetround(FE_DOWNWARD);
152*7f8c6829SSascha Wildner 	/* These are still positive per IEEE 754R */
153*7f8c6829SSascha Wildner 	testall0(1.0, 0.0, ALL_STD_EXCEPT, 0);
154*7f8c6829SSascha Wildner 	testall1(0.0, 0.0, ALL_STD_EXCEPT, 0);
155*7f8c6829SSascha Wildner 	fesetround(FE_TOWARDZERO);
156*7f8c6829SSascha Wildner 	testall0(1.0, 0.0, ALL_STD_EXCEPT, 0);
157*7f8c6829SSascha Wildner 	testall1(0.0, 0.0, ALL_STD_EXCEPT, 0);
158*7f8c6829SSascha Wildner 
159*7f8c6829SSascha Wildner 	fesetround(FE_UPWARD);
160*7f8c6829SSascha Wildner 	testall0(1.0, 0.0, ALL_STD_EXCEPT, 0);
161*7f8c6829SSascha Wildner 	testall1(0.0, 0.0, ALL_STD_EXCEPT, 0);
162*7f8c6829SSascha Wildner 	/* log1p(-0.0) == -0.0 even when rounding upwards */
163*7f8c6829SSascha Wildner 	testall1(-0.0, -0.0, ALL_STD_EXCEPT, 0);
164*7f8c6829SSascha Wildner 
165*7f8c6829SSascha Wildner 	fesetround(FE_TONEAREST);
166*7f8c6829SSascha Wildner }
167*7f8c6829SSascha Wildner 
168*7f8c6829SSascha Wildner int
main(int argc,char * argv[])169*7f8c6829SSascha Wildner main(int argc, char *argv[])
170*7f8c6829SSascha Wildner {
171*7f8c6829SSascha Wildner 
172*7f8c6829SSascha Wildner 	printf("1..3\n");
173*7f8c6829SSascha Wildner 
174*7f8c6829SSascha Wildner 	run_generic_tests();
175*7f8c6829SSascha Wildner 	printf("ok 1 - logarithm\n");
176*7f8c6829SSascha Wildner 
177*7f8c6829SSascha Wildner 	run_log2_tests();
178*7f8c6829SSascha Wildner 	printf("ok 2 - logarithm\n");
179*7f8c6829SSascha Wildner 
180*7f8c6829SSascha Wildner 	run_roundingmode_tests();
181*7f8c6829SSascha Wildner 	printf("ok 3 - logarithm\n");
182*7f8c6829SSascha Wildner 
183*7f8c6829SSascha Wildner 	return (0);
184*7f8c6829SSascha Wildner }
185