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