18a7d0e8cSEnji Cooper /*- 28a7d0e8cSEnji Cooper * Copyright (c) 2008 David Schultz <das@FreeBSD.org> 38a7d0e8cSEnji Cooper * All rights reserved. 48a7d0e8cSEnji Cooper * 58a7d0e8cSEnji Cooper * Redistribution and use in source and binary forms, with or without 68a7d0e8cSEnji Cooper * modification, are permitted provided that the following conditions 78a7d0e8cSEnji Cooper * are met: 88a7d0e8cSEnji Cooper * 1. Redistributions of source code must retain the above copyright 98a7d0e8cSEnji Cooper * notice, this list of conditions and the following disclaimer. 108a7d0e8cSEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 118a7d0e8cSEnji Cooper * notice, this list of conditions and the following disclaimer in the 128a7d0e8cSEnji Cooper * documentation and/or other materials provided with the distribution. 138a7d0e8cSEnji Cooper * 148a7d0e8cSEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 158a7d0e8cSEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 168a7d0e8cSEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 178a7d0e8cSEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 188a7d0e8cSEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 198a7d0e8cSEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 208a7d0e8cSEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 218a7d0e8cSEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 228a7d0e8cSEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 238a7d0e8cSEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 248a7d0e8cSEnji Cooper * SUCH DAMAGE. 258a7d0e8cSEnji Cooper */ 268a7d0e8cSEnji Cooper 278a7d0e8cSEnji Cooper /* 288a7d0e8cSEnji Cooper * Tests for corner cases in exp*(). 298a7d0e8cSEnji Cooper */ 308a7d0e8cSEnji Cooper 318a7d0e8cSEnji Cooper #include <sys/cdefs.h> 328a7d0e8cSEnji Cooper __FBSDID("$FreeBSD$"); 338a7d0e8cSEnji Cooper 348a7d0e8cSEnji Cooper #include <assert.h> 358a7d0e8cSEnji Cooper #include <fenv.h> 368a7d0e8cSEnji Cooper #include <float.h> 378a7d0e8cSEnji Cooper #include <math.h> 388a7d0e8cSEnji Cooper #include <stdio.h> 398a7d0e8cSEnji Cooper 408a7d0e8cSEnji Cooper #ifdef __i386__ 418a7d0e8cSEnji Cooper #include <ieeefp.h> 428a7d0e8cSEnji Cooper #endif 438a7d0e8cSEnji Cooper 448a7d0e8cSEnji Cooper #include "test-utils.h" 458a7d0e8cSEnji Cooper 468a7d0e8cSEnji Cooper #pragma STDC FENV_ACCESS ON 478a7d0e8cSEnji Cooper 488a7d0e8cSEnji Cooper /* 498a7d0e8cSEnji Cooper * Test that a function returns the correct value and sets the 508a7d0e8cSEnji Cooper * exception flags correctly. The exceptmask specifies which 518a7d0e8cSEnji Cooper * exceptions we should check. We need to be lenient for several 528a7d0e8cSEnji Cooper * reasoons, but mainly because on some architectures it's impossible 538a7d0e8cSEnji Cooper * to raise FE_OVERFLOW without raising FE_INEXACT. 548a7d0e8cSEnji Cooper * 558a7d0e8cSEnji Cooper * These are macros instead of functions so that assert provides more 568a7d0e8cSEnji Cooper * meaningful error messages. 578a7d0e8cSEnji Cooper * 588a7d0e8cSEnji Cooper * XXX The volatile here is to avoid gcc's bogus constant folding and work 598a7d0e8cSEnji Cooper * around the lack of support for the FENV_ACCESS pragma. 608a7d0e8cSEnji Cooper */ 618a7d0e8cSEnji Cooper #define test(func, x, result, exceptmask, excepts) do { \ 628a7d0e8cSEnji Cooper volatile long double _d = x; \ 638a7d0e8cSEnji Cooper assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ 648a7d0e8cSEnji Cooper assert(fpequal((func)(_d), (result))); \ 658a7d0e8cSEnji Cooper assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ 668a7d0e8cSEnji Cooper } while (0) 678a7d0e8cSEnji Cooper 688a7d0e8cSEnji Cooper /* Test all the functions that compute b^x. */ 698a7d0e8cSEnji Cooper #define _testall0(x, result, exceptmask, excepts) do { \ 708a7d0e8cSEnji Cooper test(exp, x, result, exceptmask, excepts); \ 718a7d0e8cSEnji Cooper test(expf, x, result, exceptmask, excepts); \ 728a7d0e8cSEnji Cooper test(exp2, x, result, exceptmask, excepts); \ 738a7d0e8cSEnji Cooper test(exp2f, x, result, exceptmask, excepts); \ 748a7d0e8cSEnji Cooper } while (0) 758a7d0e8cSEnji Cooper 768a7d0e8cSEnji Cooper /* Skip over exp2l on platforms that don't support it. */ 778a7d0e8cSEnji Cooper #if LDBL_PREC == 53 788a7d0e8cSEnji Cooper #define testall0 _testall0 798a7d0e8cSEnji Cooper #else 808a7d0e8cSEnji Cooper #define testall0(x, result, exceptmask, excepts) do { \ 818a7d0e8cSEnji Cooper _testall0(x, result, exceptmask, excepts); \ 828a7d0e8cSEnji Cooper test(exp2l, x, result, exceptmask, excepts); \ 838a7d0e8cSEnji Cooper } while (0) 848a7d0e8cSEnji Cooper #endif 858a7d0e8cSEnji Cooper 868a7d0e8cSEnji Cooper /* Test all the functions that compute b^x - 1. */ 878a7d0e8cSEnji Cooper #define testall1(x, result, exceptmask, excepts) do { \ 888a7d0e8cSEnji Cooper test(expm1, x, result, exceptmask, excepts); \ 898a7d0e8cSEnji Cooper test(expm1f, x, result, exceptmask, excepts); \ 908a7d0e8cSEnji Cooper } while (0) 918a7d0e8cSEnji Cooper 92*abe427afSEnji Cooper static void 938a7d0e8cSEnji Cooper run_generic_tests(void) 948a7d0e8cSEnji Cooper { 958a7d0e8cSEnji Cooper 968a7d0e8cSEnji Cooper /* exp(0) == 1, no exceptions raised */ 978a7d0e8cSEnji Cooper testall0(0.0, 1.0, ALL_STD_EXCEPT, 0); 988a7d0e8cSEnji Cooper testall1(0.0, 0.0, ALL_STD_EXCEPT, 0); 998a7d0e8cSEnji Cooper testall0(-0.0, 1.0, ALL_STD_EXCEPT, 0); 1008a7d0e8cSEnji Cooper testall1(-0.0, -0.0, ALL_STD_EXCEPT, 0); 1018a7d0e8cSEnji Cooper 1028a7d0e8cSEnji Cooper /* exp(NaN) == NaN, no exceptions raised */ 1038a7d0e8cSEnji Cooper testall0(NAN, NAN, ALL_STD_EXCEPT, 0); 1048a7d0e8cSEnji Cooper testall1(NAN, NAN, ALL_STD_EXCEPT, 0); 1058a7d0e8cSEnji Cooper 1068a7d0e8cSEnji Cooper /* exp(Inf) == Inf, no exceptions raised */ 1078a7d0e8cSEnji Cooper testall0(INFINITY, INFINITY, ALL_STD_EXCEPT, 0); 1088a7d0e8cSEnji Cooper testall1(INFINITY, INFINITY, ALL_STD_EXCEPT, 0); 1098a7d0e8cSEnji Cooper 1108a7d0e8cSEnji Cooper /* exp(-Inf) == 0, no exceptions raised */ 1118a7d0e8cSEnji Cooper testall0(-INFINITY, 0.0, ALL_STD_EXCEPT, 0); 1128a7d0e8cSEnji Cooper testall1(-INFINITY, -1.0, ALL_STD_EXCEPT, 0); 1138a7d0e8cSEnji Cooper 1148a7d0e8cSEnji Cooper #if !defined(__i386__) 1158a7d0e8cSEnji Cooper /* exp(big) == Inf, overflow exception */ 1168a7d0e8cSEnji Cooper testall0(50000.0, INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_OVERFLOW); 1178a7d0e8cSEnji Cooper testall1(50000.0, INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_OVERFLOW); 1188a7d0e8cSEnji Cooper 1198a7d0e8cSEnji Cooper /* exp(small) == 0, underflow and inexact exceptions */ 1208a7d0e8cSEnji Cooper testall0(-50000.0, 0.0, ALL_STD_EXCEPT, FE_UNDERFLOW | FE_INEXACT); 1218a7d0e8cSEnji Cooper #endif 1228a7d0e8cSEnji Cooper testall1(-50000.0, -1.0, ALL_STD_EXCEPT, FE_INEXACT); 1238a7d0e8cSEnji Cooper } 1248a7d0e8cSEnji Cooper 125*abe427afSEnji Cooper static void 1268a7d0e8cSEnji Cooper run_exp2_tests(void) 1278a7d0e8cSEnji Cooper { 128*abe427afSEnji Cooper unsigned i; 1298a7d0e8cSEnji Cooper 1308a7d0e8cSEnji Cooper /* 1318a7d0e8cSEnji Cooper * We should insist that exp2() return exactly the correct 1328a7d0e8cSEnji Cooper * result and not raise an inexact exception for integer 1338a7d0e8cSEnji Cooper * arguments. 1348a7d0e8cSEnji Cooper */ 1358a7d0e8cSEnji Cooper feclearexcept(FE_ALL_EXCEPT); 1368a7d0e8cSEnji Cooper for (i = FLT_MIN_EXP - FLT_MANT_DIG; i < FLT_MAX_EXP; i++) { 1378a7d0e8cSEnji Cooper assert(exp2f(i) == ldexpf(1.0, i)); 1388a7d0e8cSEnji Cooper assert(fetestexcept(ALL_STD_EXCEPT) == 0); 1398a7d0e8cSEnji Cooper } 1408a7d0e8cSEnji Cooper for (i = DBL_MIN_EXP - DBL_MANT_DIG; i < DBL_MAX_EXP; i++) { 1418a7d0e8cSEnji Cooper assert(exp2(i) == ldexp(1.0, i)); 1428a7d0e8cSEnji Cooper assert(fetestexcept(ALL_STD_EXCEPT) == 0); 1438a7d0e8cSEnji Cooper } 1448a7d0e8cSEnji Cooper for (i = LDBL_MIN_EXP - LDBL_MANT_DIG; i < LDBL_MAX_EXP; i++) { 1458a7d0e8cSEnji Cooper assert(exp2l(i) == ldexpl(1.0, i)); 1468a7d0e8cSEnji Cooper assert(fetestexcept(ALL_STD_EXCEPT) == 0); 1478a7d0e8cSEnji Cooper } 1488a7d0e8cSEnji Cooper } 1498a7d0e8cSEnji Cooper 1508a7d0e8cSEnji Cooper int 151*abe427afSEnji Cooper main(void) 1528a7d0e8cSEnji Cooper { 1538a7d0e8cSEnji Cooper 1548a7d0e8cSEnji Cooper printf("1..3\n"); 1558a7d0e8cSEnji Cooper 1568a7d0e8cSEnji Cooper run_generic_tests(); 1578a7d0e8cSEnji Cooper printf("ok 1 - exponential\n"); 1588a7d0e8cSEnji Cooper 1598a7d0e8cSEnji Cooper #ifdef __i386__ 1608a7d0e8cSEnji Cooper fpsetprec(FP_PE); 1618a7d0e8cSEnji Cooper run_generic_tests(); 1628a7d0e8cSEnji Cooper #endif 1638a7d0e8cSEnji Cooper printf("ok 2 - exponential\n"); 1648a7d0e8cSEnji Cooper 1658a7d0e8cSEnji Cooper run_exp2_tests(); 1668a7d0e8cSEnji Cooper printf("ok 3 - exponential\n"); 1678a7d0e8cSEnji Cooper 1688a7d0e8cSEnji Cooper return (0); 1698a7d0e8cSEnji Cooper } 170