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 fma{,f,l}(). 298a7d0e8cSEnji Cooper */ 308a7d0e8cSEnji Cooper 318a7d0e8cSEnji Cooper #include <sys/cdefs.h> 328a7d0e8cSEnji Cooper __FBSDID("$FreeBSD$"); 338a7d0e8cSEnji Cooper 348a7d0e8cSEnji Cooper #include <sys/param.h> 358a7d0e8cSEnji Cooper #include <fenv.h> 368a7d0e8cSEnji Cooper #include <float.h> 378a7d0e8cSEnji Cooper #include <math.h> 388a7d0e8cSEnji Cooper #include <stdio.h> 398a7d0e8cSEnji Cooper #include <stdlib.h> 408a7d0e8cSEnji Cooper 418a7d0e8cSEnji Cooper #include "test-utils.h" 428a7d0e8cSEnji Cooper 438a7d0e8cSEnji Cooper #pragma STDC FENV_ACCESS ON 448a7d0e8cSEnji Cooper 458a7d0e8cSEnji Cooper /* 468a7d0e8cSEnji Cooper * Test that a function returns the correct value and sets the 478a7d0e8cSEnji Cooper * exception flags correctly. The exceptmask specifies which 488a7d0e8cSEnji Cooper * exceptions we should check. We need to be lenient for several 498a7d0e8cSEnji Cooper * reasons, but mainly because on some architectures it's impossible 508a7d0e8cSEnji Cooper * to raise FE_OVERFLOW without raising FE_INEXACT. 518a7d0e8cSEnji Cooper * 528a7d0e8cSEnji Cooper * These are macros instead of functions so that assert provides more 538a7d0e8cSEnji Cooper * meaningful error messages. 548a7d0e8cSEnji Cooper */ 558a7d0e8cSEnji Cooper #define test(func, x, y, z, result, exceptmask, excepts) do { \ 568a7d0e8cSEnji Cooper volatile long double _vx = (x), _vy = (y), _vz = (z); \ 57*133bc645SAlex Richardson ATF_CHECK(feclearexcept(FE_ALL_EXCEPT) == 0); \ 58*133bc645SAlex Richardson ATF_CHECK(fpequal((func)(_vx, _vy, _vz), (result))); \ 59*133bc645SAlex Richardson CHECK_FP_EXCEPTIONS_MSG(excepts, exceptmask, "for %s(%s)", \ 60*133bc645SAlex Richardson #func, #x); \ 618a7d0e8cSEnji Cooper } while (0) 628a7d0e8cSEnji Cooper 638a7d0e8cSEnji Cooper #define testall(x, y, z, result, exceptmask, excepts) do { \ 648a7d0e8cSEnji Cooper test(fma, (double)(x), (double)(y), (double)(z), \ 658a7d0e8cSEnji Cooper (double)(result), (exceptmask), (excepts)); \ 668a7d0e8cSEnji Cooper test(fmaf, (float)(x), (float)(y), (float)(z), \ 678a7d0e8cSEnji Cooper (float)(result), (exceptmask), (excepts)); \ 688a7d0e8cSEnji Cooper test(fmal, (x), (y), (z), (result), (exceptmask), (excepts)); \ 698a7d0e8cSEnji Cooper } while (0) 708a7d0e8cSEnji Cooper 718a7d0e8cSEnji Cooper /* Test in all rounding modes. */ 728a7d0e8cSEnji Cooper #define testrnd(func, x, y, z, rn, ru, rd, rz, exceptmask, excepts) do { \ 738a7d0e8cSEnji Cooper fesetround(FE_TONEAREST); \ 748a7d0e8cSEnji Cooper test((func), (x), (y), (z), (rn), (exceptmask), (excepts)); \ 758a7d0e8cSEnji Cooper fesetround(FE_UPWARD); \ 768a7d0e8cSEnji Cooper test((func), (x), (y), (z), (ru), (exceptmask), (excepts)); \ 778a7d0e8cSEnji Cooper fesetround(FE_DOWNWARD); \ 788a7d0e8cSEnji Cooper test((func), (x), (y), (z), (rd), (exceptmask), (excepts)); \ 798a7d0e8cSEnji Cooper fesetround(FE_TOWARDZERO); \ 808a7d0e8cSEnji Cooper test((func), (x), (y), (z), (rz), (exceptmask), (excepts)); \ 818a7d0e8cSEnji Cooper } while (0) 828a7d0e8cSEnji Cooper 838a7d0e8cSEnji Cooper /* 848a7d0e8cSEnji Cooper * This is needed because clang constant-folds fma in ways that are incorrect 858a7d0e8cSEnji Cooper * in rounding modes other than FE_TONEAREST. 868a7d0e8cSEnji Cooper */ 87abe427afSEnji Cooper static volatile double one = 1.0; 888a7d0e8cSEnji Cooper 898a7d0e8cSEnji Cooper static void 908a7d0e8cSEnji Cooper test_zeroes(void) 918a7d0e8cSEnji Cooper { 928a7d0e8cSEnji Cooper const int rd = (fegetround() == FE_DOWNWARD); 938a7d0e8cSEnji Cooper 948a7d0e8cSEnji Cooper testall(0.0, 0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0); 958a7d0e8cSEnji Cooper testall(1.0, 0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0); 968a7d0e8cSEnji Cooper testall(0.0, 1.0, 0.0, 0.0, ALL_STD_EXCEPT, 0); 978a7d0e8cSEnji Cooper testall(0.0, 0.0, 1.0, 1.0, ALL_STD_EXCEPT, 0); 988a7d0e8cSEnji Cooper 998a7d0e8cSEnji Cooper testall(-0.0, 0.0, 0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); 1008a7d0e8cSEnji Cooper testall(0.0, -0.0, 0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); 1018a7d0e8cSEnji Cooper testall(-0.0, -0.0, 0.0, 0.0, ALL_STD_EXCEPT, 0); 1028a7d0e8cSEnji Cooper testall(0.0, 0.0, -0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); 1038a7d0e8cSEnji Cooper testall(-0.0, -0.0, -0.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); 1048a7d0e8cSEnji Cooper 1058a7d0e8cSEnji Cooper testall(-0.0, 0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0); 1068a7d0e8cSEnji Cooper testall(0.0, -0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0); 1078a7d0e8cSEnji Cooper 1088a7d0e8cSEnji Cooper testall(-one, one, one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); 1098a7d0e8cSEnji Cooper testall(one, -one, one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); 1108a7d0e8cSEnji Cooper testall(-one, -one, -one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); 1118a7d0e8cSEnji Cooper 1128a7d0e8cSEnji Cooper switch (fegetround()) { 1138a7d0e8cSEnji Cooper case FE_TONEAREST: 1148a7d0e8cSEnji Cooper case FE_TOWARDZERO: 1158a7d0e8cSEnji Cooper test(fmaf, -FLT_MIN, FLT_MIN, 0.0, -0.0, 1168a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW); 1178a7d0e8cSEnji Cooper test(fma, -DBL_MIN, DBL_MIN, 0.0, -0.0, 1188a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW); 1198a7d0e8cSEnji Cooper test(fmal, -LDBL_MIN, LDBL_MIN, 0.0, -0.0, 1208a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT | FE_UNDERFLOW); 1218a7d0e8cSEnji Cooper } 1228a7d0e8cSEnji Cooper } 1238a7d0e8cSEnji Cooper 1248a7d0e8cSEnji Cooper static void 1258a7d0e8cSEnji Cooper test_infinities(void) 1268a7d0e8cSEnji Cooper { 1278a7d0e8cSEnji Cooper testall(INFINITY, 1.0, -1.0, INFINITY, ALL_STD_EXCEPT, 0); 1288a7d0e8cSEnji Cooper testall(-1.0, INFINITY, 0.0, -INFINITY, ALL_STD_EXCEPT, 0); 1298a7d0e8cSEnji Cooper testall(0.0, 0.0, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); 1308a7d0e8cSEnji Cooper testall(1.0, 1.0, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); 1318a7d0e8cSEnji Cooper testall(1.0, 1.0, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0); 1328a7d0e8cSEnji Cooper 1338a7d0e8cSEnji Cooper testall(INFINITY, -INFINITY, 1.0, -INFINITY, ALL_STD_EXCEPT, 0); 1348a7d0e8cSEnji Cooper testall(INFINITY, INFINITY, 1.0, INFINITY, ALL_STD_EXCEPT, 0); 1358a7d0e8cSEnji Cooper testall(-INFINITY, -INFINITY, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); 1368a7d0e8cSEnji Cooper 1378a7d0e8cSEnji Cooper testall(0.0, INFINITY, 1.0, NAN, ALL_STD_EXCEPT, FE_INVALID); 1388a7d0e8cSEnji Cooper testall(INFINITY, 0.0, -0.0, NAN, ALL_STD_EXCEPT, FE_INVALID); 1398a7d0e8cSEnji Cooper 1408a7d0e8cSEnji Cooper /* The invalid exception is optional in this case. */ 1418a7d0e8cSEnji Cooper testall(INFINITY, 0.0, NAN, NAN, ALL_STD_EXCEPT & ~FE_INVALID, 0); 1428a7d0e8cSEnji Cooper 1438a7d0e8cSEnji Cooper testall(INFINITY, INFINITY, -INFINITY, NAN, 1448a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INVALID); 1458a7d0e8cSEnji Cooper testall(-INFINITY, INFINITY, INFINITY, NAN, 1468a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INVALID); 1478a7d0e8cSEnji Cooper testall(INFINITY, -1.0, INFINITY, NAN, 1488a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INVALID); 1498a7d0e8cSEnji Cooper 1508a7d0e8cSEnji Cooper test(fmaf, FLT_MAX, FLT_MAX, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0); 1518a7d0e8cSEnji Cooper test(fma, DBL_MAX, DBL_MAX, -INFINITY, -INFINITY, ALL_STD_EXCEPT, 0); 1528a7d0e8cSEnji Cooper test(fmal, LDBL_MAX, LDBL_MAX, -INFINITY, -INFINITY, 1538a7d0e8cSEnji Cooper ALL_STD_EXCEPT, 0); 1548a7d0e8cSEnji Cooper test(fmaf, FLT_MAX, -FLT_MAX, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); 1558a7d0e8cSEnji Cooper test(fma, DBL_MAX, -DBL_MAX, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); 1568a7d0e8cSEnji Cooper test(fmal, LDBL_MAX, -LDBL_MAX, INFINITY, INFINITY, 1578a7d0e8cSEnji Cooper ALL_STD_EXCEPT, 0); 1588a7d0e8cSEnji Cooper } 1598a7d0e8cSEnji Cooper 1608a7d0e8cSEnji Cooper static void 1618a7d0e8cSEnji Cooper test_nans(void) 1628a7d0e8cSEnji Cooper { 1638a7d0e8cSEnji Cooper testall(NAN, 0.0, 0.0, NAN, ALL_STD_EXCEPT, 0); 1648a7d0e8cSEnji Cooper testall(1.0, NAN, 1.0, NAN, ALL_STD_EXCEPT, 0); 1658a7d0e8cSEnji Cooper testall(1.0, -1.0, NAN, NAN, ALL_STD_EXCEPT, 0); 1668a7d0e8cSEnji Cooper testall(0.0, 0.0, NAN, NAN, ALL_STD_EXCEPT, 0); 1678a7d0e8cSEnji Cooper testall(NAN, NAN, NAN, NAN, ALL_STD_EXCEPT, 0); 1688a7d0e8cSEnji Cooper 1698a7d0e8cSEnji Cooper /* x*y should not raise an inexact/overflow/underflow if z is NaN. */ 1708a7d0e8cSEnji Cooper testall(M_PI, M_PI, NAN, NAN, ALL_STD_EXCEPT, 0); 1718a7d0e8cSEnji Cooper test(fmaf, FLT_MIN, FLT_MIN, NAN, NAN, ALL_STD_EXCEPT, 0); 1728a7d0e8cSEnji Cooper test(fma, DBL_MIN, DBL_MIN, NAN, NAN, ALL_STD_EXCEPT, 0); 1738a7d0e8cSEnji Cooper test(fmal, LDBL_MIN, LDBL_MIN, NAN, NAN, ALL_STD_EXCEPT, 0); 1748a7d0e8cSEnji Cooper test(fmaf, FLT_MAX, FLT_MAX, NAN, NAN, ALL_STD_EXCEPT, 0); 1758a7d0e8cSEnji Cooper test(fma, DBL_MAX, DBL_MAX, NAN, NAN, ALL_STD_EXCEPT, 0); 1768a7d0e8cSEnji Cooper test(fmal, LDBL_MAX, LDBL_MAX, NAN, NAN, ALL_STD_EXCEPT, 0); 1778a7d0e8cSEnji Cooper } 1788a7d0e8cSEnji Cooper 1798a7d0e8cSEnji Cooper /* 1808a7d0e8cSEnji Cooper * Tests for cases where z is very small compared to x*y. 1818a7d0e8cSEnji Cooper */ 1828a7d0e8cSEnji Cooper static void 1838a7d0e8cSEnji Cooper test_small_z(void) 1848a7d0e8cSEnji Cooper { 1858a7d0e8cSEnji Cooper /* x*y positive, z positive */ 1868a7d0e8cSEnji Cooper if (fegetround() == FE_UPWARD) { 1878a7d0e8cSEnji Cooper test(fmaf, one, one, 0x1.0p-100, 1.0 + FLT_EPSILON, 1888a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 1898a7d0e8cSEnji Cooper test(fma, one, one, 0x1.0p-200, 1.0 + DBL_EPSILON, 1908a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 1918a7d0e8cSEnji Cooper test(fmal, one, one, 0x1.0p-200, 1.0 + LDBL_EPSILON, 1928a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 1938a7d0e8cSEnji Cooper } else { 1948a7d0e8cSEnji Cooper testall(0x1.0p100, one, 0x1.0p-100, 0x1.0p100, 1958a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 1968a7d0e8cSEnji Cooper } 1978a7d0e8cSEnji Cooper 1988a7d0e8cSEnji Cooper /* x*y negative, z negative */ 1998a7d0e8cSEnji Cooper if (fegetround() == FE_DOWNWARD) { 2008a7d0e8cSEnji Cooper test(fmaf, -one, one, -0x1.0p-100, -(1.0 + FLT_EPSILON), 2018a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2028a7d0e8cSEnji Cooper test(fma, -one, one, -0x1.0p-200, -(1.0 + DBL_EPSILON), 2038a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2048a7d0e8cSEnji Cooper test(fmal, -one, one, -0x1.0p-200, -(1.0 + LDBL_EPSILON), 2058a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2068a7d0e8cSEnji Cooper } else { 2078a7d0e8cSEnji Cooper testall(0x1.0p100, -one, -0x1.0p-100, -0x1.0p100, 2088a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2098a7d0e8cSEnji Cooper } 2108a7d0e8cSEnji Cooper 2118a7d0e8cSEnji Cooper /* x*y positive, z negative */ 2128a7d0e8cSEnji Cooper if (fegetround() == FE_DOWNWARD || fegetround() == FE_TOWARDZERO) { 2138a7d0e8cSEnji Cooper test(fmaf, one, one, -0x1.0p-100, 1.0 - FLT_EPSILON / 2, 2148a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2158a7d0e8cSEnji Cooper test(fma, one, one, -0x1.0p-200, 1.0 - DBL_EPSILON / 2, 2168a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2178a7d0e8cSEnji Cooper test(fmal, one, one, -0x1.0p-200, 1.0 - LDBL_EPSILON / 2, 2188a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2198a7d0e8cSEnji Cooper } else { 2208a7d0e8cSEnji Cooper testall(0x1.0p100, one, -0x1.0p-100, 0x1.0p100, 2218a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2228a7d0e8cSEnji Cooper } 2238a7d0e8cSEnji Cooper 2248a7d0e8cSEnji Cooper /* x*y negative, z positive */ 2258a7d0e8cSEnji Cooper if (fegetround() == FE_UPWARD || fegetround() == FE_TOWARDZERO) { 2268a7d0e8cSEnji Cooper test(fmaf, -one, one, 0x1.0p-100, -1.0 + FLT_EPSILON / 2, 2278a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2288a7d0e8cSEnji Cooper test(fma, -one, one, 0x1.0p-200, -1.0 + DBL_EPSILON / 2, 2298a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2308a7d0e8cSEnji Cooper test(fmal, -one, one, 0x1.0p-200, -1.0 + LDBL_EPSILON / 2, 2318a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2328a7d0e8cSEnji Cooper } else { 2338a7d0e8cSEnji Cooper testall(-0x1.0p100, one, 0x1.0p-100, -0x1.0p100, 2348a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2358a7d0e8cSEnji Cooper } 2368a7d0e8cSEnji Cooper } 2378a7d0e8cSEnji Cooper 2388a7d0e8cSEnji Cooper /* 2398a7d0e8cSEnji Cooper * Tests for cases where z is very large compared to x*y. 2408a7d0e8cSEnji Cooper */ 2418a7d0e8cSEnji Cooper static void 2428a7d0e8cSEnji Cooper test_big_z(void) 2438a7d0e8cSEnji Cooper { 2448a7d0e8cSEnji Cooper /* z positive, x*y positive */ 2458a7d0e8cSEnji Cooper if (fegetround() == FE_UPWARD) { 2468a7d0e8cSEnji Cooper test(fmaf, 0x1.0p-50, 0x1.0p-50, 1.0, 1.0 + FLT_EPSILON, 2478a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2488a7d0e8cSEnji Cooper test(fma, 0x1.0p-100, 0x1.0p-100, 1.0, 1.0 + DBL_EPSILON, 2498a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2508a7d0e8cSEnji Cooper test(fmal, 0x1.0p-100, 0x1.0p-100, 1.0, 1.0 + LDBL_EPSILON, 2518a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2528a7d0e8cSEnji Cooper } else { 2538a7d0e8cSEnji Cooper testall(-0x1.0p-50, -0x1.0p-50, 0x1.0p100, 0x1.0p100, 2548a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2558a7d0e8cSEnji Cooper } 2568a7d0e8cSEnji Cooper 2578a7d0e8cSEnji Cooper /* z negative, x*y negative */ 2588a7d0e8cSEnji Cooper if (fegetround() == FE_DOWNWARD) { 2598a7d0e8cSEnji Cooper test(fmaf, -0x1.0p-50, 0x1.0p-50, -1.0, -(1.0 + FLT_EPSILON), 2608a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2618a7d0e8cSEnji Cooper test(fma, -0x1.0p-100, 0x1.0p-100, -1.0, -(1.0 + DBL_EPSILON), 2628a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2638a7d0e8cSEnji Cooper test(fmal, -0x1.0p-100, 0x1.0p-100, -1.0, -(1.0 + LDBL_EPSILON), 2648a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2658a7d0e8cSEnji Cooper } else { 2668a7d0e8cSEnji Cooper testall(0x1.0p-50, -0x1.0p-50, -0x1.0p100, -0x1.0p100, 2678a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2688a7d0e8cSEnji Cooper } 2698a7d0e8cSEnji Cooper 2708a7d0e8cSEnji Cooper /* z negative, x*y positive */ 2718a7d0e8cSEnji Cooper if (fegetround() == FE_UPWARD || fegetround() == FE_TOWARDZERO) { 2728a7d0e8cSEnji Cooper test(fmaf, -0x1.0p-50, -0x1.0p-50, -1.0, 2738a7d0e8cSEnji Cooper -1.0 + FLT_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); 2748a7d0e8cSEnji Cooper test(fma, -0x1.0p-100, -0x1.0p-100, -1.0, 2758a7d0e8cSEnji Cooper -1.0 + DBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); 2768a7d0e8cSEnji Cooper test(fmal, -0x1.0p-100, -0x1.0p-100, -1.0, 2778a7d0e8cSEnji Cooper -1.0 + LDBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); 2788a7d0e8cSEnji Cooper } else { 2798a7d0e8cSEnji Cooper testall(0x1.0p-50, 0x1.0p-50, -0x1.0p100, -0x1.0p100, 2808a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2818a7d0e8cSEnji Cooper } 2828a7d0e8cSEnji Cooper 2838a7d0e8cSEnji Cooper /* z positive, x*y negative */ 2848a7d0e8cSEnji Cooper if (fegetround() == FE_DOWNWARD || fegetround() == FE_TOWARDZERO) { 2858a7d0e8cSEnji Cooper test(fmaf, 0x1.0p-50, -0x1.0p-50, 1.0, 1.0 - FLT_EPSILON / 2, 2868a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2878a7d0e8cSEnji Cooper test(fma, 0x1.0p-100, -0x1.0p-100, 1.0, 1.0 - DBL_EPSILON / 2, 2888a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2898a7d0e8cSEnji Cooper test(fmal, 0x1.0p-100, -0x1.0p-100, 1.0, 1.0 - LDBL_EPSILON / 2, 2908a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2918a7d0e8cSEnji Cooper } else { 2928a7d0e8cSEnji Cooper testall(-0x1.0p-50, 0x1.0p-50, 0x1.0p100, 0x1.0p100, 2938a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 2948a7d0e8cSEnji Cooper } 2958a7d0e8cSEnji Cooper } 2968a7d0e8cSEnji Cooper 2978a7d0e8cSEnji Cooper static void 2988a7d0e8cSEnji Cooper test_accuracy(void) 2998a7d0e8cSEnji Cooper { 3008a7d0e8cSEnji Cooper 3018a7d0e8cSEnji Cooper /* ilogb(x*y) - ilogb(z) = 20 */ 3028a7d0e8cSEnji Cooper testrnd(fmaf, -0x1.c139d8p-51, -0x1.600e7ap32, 0x1.26558cp-38, 3038a7d0e8cSEnji Cooper 0x1.34e48ap-18, 0x1.34e48cp-18, 0x1.34e48ap-18, 0x1.34e48ap-18, 3048a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 3058a7d0e8cSEnji Cooper testrnd(fma, -0x1.c139d7b84f1a3p-51, -0x1.600e7a2a16484p32, 3068a7d0e8cSEnji Cooper 0x1.26558cac31580p-38, 0x1.34e48a78aae97p-18, 3078a7d0e8cSEnji Cooper 0x1.34e48a78aae97p-18, 0x1.34e48a78aae96p-18, 3088a7d0e8cSEnji Cooper 0x1.34e48a78aae96p-18, ALL_STD_EXCEPT, FE_INEXACT); 3098a7d0e8cSEnji Cooper #if LDBL_MANT_DIG == 113 3108a7d0e8cSEnji Cooper testrnd(fmal, -0x1.c139d7b84f1a3079263afcc5bae3p-51L, 3118a7d0e8cSEnji Cooper -0x1.600e7a2a164840edbe2e7d301a72p32L, 3128a7d0e8cSEnji Cooper 0x1.26558cac315807eb07e448042101p-38L, 3138a7d0e8cSEnji Cooper 0x1.34e48a78aae96c76ed36077dd387p-18L, 3148a7d0e8cSEnji Cooper 0x1.34e48a78aae96c76ed36077dd388p-18L, 3158a7d0e8cSEnji Cooper 0x1.34e48a78aae96c76ed36077dd387p-18L, 3168a7d0e8cSEnji Cooper 0x1.34e48a78aae96c76ed36077dd387p-18L, 3178a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 3188a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 64 3198a7d0e8cSEnji Cooper testrnd(fmal, -0x1.c139d7b84f1a307ap-51L, -0x1.600e7a2a164840eep32L, 3208a7d0e8cSEnji Cooper 0x1.26558cac315807ecp-38L, 0x1.34e48a78aae96c78p-18L, 3218a7d0e8cSEnji Cooper 0x1.34e48a78aae96c78p-18L, 0x1.34e48a78aae96c76p-18L, 3228a7d0e8cSEnji Cooper 0x1.34e48a78aae96c76p-18L, ALL_STD_EXCEPT, FE_INEXACT); 3238a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 53 3248a7d0e8cSEnji Cooper testrnd(fmal, -0x1.c139d7b84f1a3p-51L, -0x1.600e7a2a16484p32L, 3258a7d0e8cSEnji Cooper 0x1.26558cac31580p-38L, 0x1.34e48a78aae97p-18L, 3268a7d0e8cSEnji Cooper 0x1.34e48a78aae97p-18L, 0x1.34e48a78aae96p-18L, 3278a7d0e8cSEnji Cooper 0x1.34e48a78aae96p-18L, ALL_STD_EXCEPT, FE_INEXACT); 3288a7d0e8cSEnji Cooper #endif 3298a7d0e8cSEnji Cooper 3308a7d0e8cSEnji Cooper /* ilogb(x*y) - ilogb(z) = -40 */ 3318a7d0e8cSEnji Cooper testrnd(fmaf, 0x1.98210ap53, 0x1.9556acp-24, 0x1.d87da4p70, 3328a7d0e8cSEnji Cooper 0x1.d87da4p70, 0x1.d87da6p70, 0x1.d87da4p70, 0x1.d87da4p70, 3338a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 3348a7d0e8cSEnji Cooper testrnd(fma, 0x1.98210ac83fe2bp53, 0x1.9556ac1475f0fp-24, 3358a7d0e8cSEnji Cooper 0x1.d87da3aafc60ep70, 0x1.d87da3aafda40p70, 3368a7d0e8cSEnji Cooper 0x1.d87da3aafda40p70, 0x1.d87da3aafda3fp70, 3378a7d0e8cSEnji Cooper 0x1.d87da3aafda3fp70, ALL_STD_EXCEPT, FE_INEXACT); 3388a7d0e8cSEnji Cooper #if LDBL_MANT_DIG == 113 3398a7d0e8cSEnji Cooper testrnd(fmal, 0x1.98210ac83fe2a8f65b6278b74cebp53L, 3408a7d0e8cSEnji Cooper 0x1.9556ac1475f0f28968b61d0de65ap-24L, 3418a7d0e8cSEnji Cooper 0x1.d87da3aafc60d830aa4c6d73b749p70L, 3428a7d0e8cSEnji Cooper 0x1.d87da3aafda3f36a69eb86488224p70L, 3438a7d0e8cSEnji Cooper 0x1.d87da3aafda3f36a69eb86488225p70L, 3448a7d0e8cSEnji Cooper 0x1.d87da3aafda3f36a69eb86488224p70L, 3458a7d0e8cSEnji Cooper 0x1.d87da3aafda3f36a69eb86488224p70L, 3468a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 3478a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 64 3488a7d0e8cSEnji Cooper testrnd(fmal, 0x1.98210ac83fe2a8f6p53L, 0x1.9556ac1475f0f28ap-24L, 3498a7d0e8cSEnji Cooper 0x1.d87da3aafc60d83p70L, 0x1.d87da3aafda3f36ap70L, 3508a7d0e8cSEnji Cooper 0x1.d87da3aafda3f36ap70L, 0x1.d87da3aafda3f368p70L, 3518a7d0e8cSEnji Cooper 0x1.d87da3aafda3f368p70L, ALL_STD_EXCEPT, FE_INEXACT); 3528a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 53 3538a7d0e8cSEnji Cooper testrnd(fmal, 0x1.98210ac83fe2bp53L, 0x1.9556ac1475f0fp-24L, 3548a7d0e8cSEnji Cooper 0x1.d87da3aafc60ep70L, 0x1.d87da3aafda40p70L, 3558a7d0e8cSEnji Cooper 0x1.d87da3aafda40p70L, 0x1.d87da3aafda3fp70L, 3568a7d0e8cSEnji Cooper 0x1.d87da3aafda3fp70L, ALL_STD_EXCEPT, FE_INEXACT); 3578a7d0e8cSEnji Cooper #endif 3588a7d0e8cSEnji Cooper 3598a7d0e8cSEnji Cooper /* ilogb(x*y) - ilogb(z) = 0 */ 3608a7d0e8cSEnji Cooper testrnd(fmaf, 0x1.31ad02p+100, 0x1.2fbf7ap-42, -0x1.c3e106p+58, 3618a7d0e8cSEnji Cooper -0x1.64c27cp+56, -0x1.64c27ap+56, -0x1.64c27cp+56, 3628a7d0e8cSEnji Cooper -0x1.64c27ap+56, ALL_STD_EXCEPT, FE_INEXACT); 3638a7d0e8cSEnji Cooper testrnd(fma, 0x1.31ad012ede8aap+100, 0x1.2fbf79c839067p-42, 3648a7d0e8cSEnji Cooper -0x1.c3e106929056ep+58, -0x1.64c282b970a5fp+56, 3658a7d0e8cSEnji Cooper -0x1.64c282b970a5ep+56, -0x1.64c282b970a5fp+56, 3668a7d0e8cSEnji Cooper -0x1.64c282b970a5ep+56, ALL_STD_EXCEPT, FE_INEXACT); 3678a7d0e8cSEnji Cooper #if LDBL_MANT_DIG == 113 3688a7d0e8cSEnji Cooper testrnd(fmal, 0x1.31ad012ede8aa282fa1c19376d16p+100L, 3698a7d0e8cSEnji Cooper 0x1.2fbf79c839066f0f5c68f6d2e814p-42L, 3708a7d0e8cSEnji Cooper -0x1.c3e106929056ec19de72bfe64215p+58L, 3718a7d0e8cSEnji Cooper -0x1.64c282b970a612598fc025ca8cddp+56L, 3728a7d0e8cSEnji Cooper -0x1.64c282b970a612598fc025ca8cddp+56L, 3738a7d0e8cSEnji Cooper -0x1.64c282b970a612598fc025ca8cdep+56L, 3748a7d0e8cSEnji Cooper -0x1.64c282b970a612598fc025ca8cddp+56L, 3758a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 3768a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 64 3778a7d0e8cSEnji Cooper testrnd(fmal, 0x1.31ad012ede8aa4eap+100L, 0x1.2fbf79c839066aeap-42L, 3788a7d0e8cSEnji Cooper -0x1.c3e106929056e61p+58L, -0x1.64c282b970a60298p+56L, 3798a7d0e8cSEnji Cooper -0x1.64c282b970a60298p+56L, -0x1.64c282b970a6029ap+56L, 3808a7d0e8cSEnji Cooper -0x1.64c282b970a60298p+56L, ALL_STD_EXCEPT, FE_INEXACT); 3818a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 53 3828a7d0e8cSEnji Cooper testrnd(fmal, 0x1.31ad012ede8aap+100L, 0x1.2fbf79c839067p-42L, 3838a7d0e8cSEnji Cooper -0x1.c3e106929056ep+58L, -0x1.64c282b970a5fp+56L, 3848a7d0e8cSEnji Cooper -0x1.64c282b970a5ep+56L, -0x1.64c282b970a5fp+56L, 3858a7d0e8cSEnji Cooper -0x1.64c282b970a5ep+56L, ALL_STD_EXCEPT, FE_INEXACT); 3868a7d0e8cSEnji Cooper #endif 3878a7d0e8cSEnji Cooper 3888a7d0e8cSEnji Cooper /* x*y (rounded) ~= -z */ 3898a7d0e8cSEnji Cooper /* XXX spurious inexact exceptions */ 3908a7d0e8cSEnji Cooper testrnd(fmaf, 0x1.bbffeep-30, -0x1.1d164cp-74, 0x1.ee7296p-104, 3918a7d0e8cSEnji Cooper -0x1.c46ea8p-128, -0x1.c46ea8p-128, -0x1.c46ea8p-128, 3928a7d0e8cSEnji Cooper -0x1.c46ea8p-128, ALL_STD_EXCEPT & ~FE_INEXACT, 0); 3938a7d0e8cSEnji Cooper testrnd(fma, 0x1.bbffeea6fc7d6p-30, 0x1.1d164c6cbf078p-74, 3948a7d0e8cSEnji Cooper -0x1.ee72993aff948p-104, -0x1.71f72ac7d9d8p-159, 3958a7d0e8cSEnji Cooper -0x1.71f72ac7d9d8p-159, -0x1.71f72ac7d9d8p-159, 3968a7d0e8cSEnji Cooper -0x1.71f72ac7d9d8p-159, ALL_STD_EXCEPT & ~FE_INEXACT, 0); 3978a7d0e8cSEnji Cooper #if LDBL_MANT_DIG == 113 3988a7d0e8cSEnji Cooper testrnd(fmal, 0x1.bbffeea6fc7d65927d147f437675p-30L, 3998a7d0e8cSEnji Cooper 0x1.1d164c6cbf078b7a22607d1cd6a2p-74L, 4008a7d0e8cSEnji Cooper -0x1.ee72993aff94973876031bec0944p-104L, 4018a7d0e8cSEnji Cooper 0x1.64e086175b3a2adc36e607058814p-217L, 4028a7d0e8cSEnji Cooper 0x1.64e086175b3a2adc36e607058814p-217L, 4038a7d0e8cSEnji Cooper 0x1.64e086175b3a2adc36e607058814p-217L, 4048a7d0e8cSEnji Cooper 0x1.64e086175b3a2adc36e607058814p-217L, 4058a7d0e8cSEnji Cooper ALL_STD_EXCEPT & ~FE_INEXACT, 0); 4068a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 64 4078a7d0e8cSEnji Cooper testrnd(fmal, 0x1.bbffeea6fc7d6592p-30L, 0x1.1d164c6cbf078b7ap-74L, 4088a7d0e8cSEnji Cooper -0x1.ee72993aff949736p-104L, 0x1.af190e7a1ee6ad94p-168L, 4098a7d0e8cSEnji Cooper 0x1.af190e7a1ee6ad94p-168L, 0x1.af190e7a1ee6ad94p-168L, 4108a7d0e8cSEnji Cooper 0x1.af190e7a1ee6ad94p-168L, ALL_STD_EXCEPT & ~FE_INEXACT, 0); 4118a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 53 4128a7d0e8cSEnji Cooper testrnd(fmal, 0x1.bbffeea6fc7d6p-30L, 0x1.1d164c6cbf078p-74L, 4138a7d0e8cSEnji Cooper -0x1.ee72993aff948p-104L, -0x1.71f72ac7d9d8p-159L, 4148a7d0e8cSEnji Cooper -0x1.71f72ac7d9d8p-159L, -0x1.71f72ac7d9d8p-159L, 4158a7d0e8cSEnji Cooper -0x1.71f72ac7d9d8p-159L, ALL_STD_EXCEPT & ~FE_INEXACT, 0); 4168a7d0e8cSEnji Cooper #endif 4178a7d0e8cSEnji Cooper } 4188a7d0e8cSEnji Cooper 4198a7d0e8cSEnji Cooper static void 4208a7d0e8cSEnji Cooper test_double_rounding(void) 4218a7d0e8cSEnji Cooper { 4228a7d0e8cSEnji Cooper 4238a7d0e8cSEnji Cooper /* 4248a7d0e8cSEnji Cooper * a = 0x1.8000000000001p0 4258a7d0e8cSEnji Cooper * b = 0x1.8000000000001p0 4268a7d0e8cSEnji Cooper * c = -0x0.0000000000000000000000000080...1p+1 4278a7d0e8cSEnji Cooper * a * b = 0x1.2000000000001800000000000080p+1 4288a7d0e8cSEnji Cooper * 4298a7d0e8cSEnji Cooper * The correct behavior is to round DOWN to 0x1.2000000000001p+1 in 4308a7d0e8cSEnji Cooper * round-to-nearest mode. An implementation that computes a*b+c in 4318a7d0e8cSEnji Cooper * double+double precision, however, will get 0x1.20000000000018p+1, 4328a7d0e8cSEnji Cooper * and then round UP. 4338a7d0e8cSEnji Cooper */ 4348a7d0e8cSEnji Cooper fesetround(FE_TONEAREST); 4358a7d0e8cSEnji Cooper test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0, 4368a7d0e8cSEnji Cooper -0x1.0000000000001p-104, 0x1.2000000000001p+1, 4378a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 4388a7d0e8cSEnji Cooper fesetround(FE_DOWNWARD); 4398a7d0e8cSEnji Cooper test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0, 4408a7d0e8cSEnji Cooper -0x1.0000000000001p-104, 0x1.2000000000001p+1, 4418a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 4428a7d0e8cSEnji Cooper fesetround(FE_UPWARD); 4438a7d0e8cSEnji Cooper test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0, 4448a7d0e8cSEnji Cooper -0x1.0000000000001p-104, 0x1.2000000000002p+1, 4458a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 4468a7d0e8cSEnji Cooper 4478a7d0e8cSEnji Cooper fesetround(FE_TONEAREST); 4488a7d0e8cSEnji Cooper test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200002p+1, 4498a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 4508a7d0e8cSEnji Cooper fesetround(FE_DOWNWARD); 4518a7d0e8cSEnji Cooper test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200002p+1, 4528a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 4538a7d0e8cSEnji Cooper fesetround(FE_UPWARD); 4548a7d0e8cSEnji Cooper test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200004p+1, 4558a7d0e8cSEnji Cooper ALL_STD_EXCEPT, FE_INEXACT); 4568a7d0e8cSEnji Cooper 4578a7d0e8cSEnji Cooper fesetround(FE_TONEAREST); 4588a7d0e8cSEnji Cooper #if LDBL_MANT_DIG == 64 4598a7d0e8cSEnji Cooper test(fmal, 0x1.4p+0L, 0x1.0000000000000004p+0L, 0x1p-128L, 4608a7d0e8cSEnji Cooper 0x1.4000000000000006p+0L, ALL_STD_EXCEPT, FE_INEXACT); 4618a7d0e8cSEnji Cooper #elif LDBL_MANT_DIG == 113 4628a7d0e8cSEnji Cooper test(fmal, 0x1.8000000000000000000000000001p+0L, 4638a7d0e8cSEnji Cooper 0x1.8000000000000000000000000001p+0L, 4648a7d0e8cSEnji Cooper -0x1.0000000000000000000000000001p-224L, 4658a7d0e8cSEnji Cooper 0x1.2000000000000000000000000001p+1L, ALL_STD_EXCEPT, FE_INEXACT); 4668a7d0e8cSEnji Cooper #endif 4678a7d0e8cSEnji Cooper 4688a7d0e8cSEnji Cooper } 4698a7d0e8cSEnji Cooper 470*133bc645SAlex Richardson static const int rmodes[] = { 471*133bc645SAlex Richardson FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO 472*133bc645SAlex Richardson }; 473*133bc645SAlex Richardson 474*133bc645SAlex Richardson ATF_TC_WITHOUT_HEAD(zeroes); 475*133bc645SAlex Richardson ATF_TC_BODY(zeroes, tc) 4768a7d0e8cSEnji Cooper { 477*133bc645SAlex Richardson for (size_t i = 0; i < nitems(rmodes); i++) { 4788a7d0e8cSEnji Cooper printf("rmode = %d\n", rmodes[i]); 4798a7d0e8cSEnji Cooper fesetround(rmodes[i]); 4808a7d0e8cSEnji Cooper test_zeroes(); 481*133bc645SAlex Richardson } 4828a7d0e8cSEnji Cooper } 4838a7d0e8cSEnji Cooper 484*133bc645SAlex Richardson ATF_TC_WITHOUT_HEAD(infinities); 485*133bc645SAlex Richardson ATF_TC_BODY(infinities, tc) 486*133bc645SAlex Richardson { 4878a7d0e8cSEnji Cooper #if defined(__amd64__) 488*133bc645SAlex Richardson if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false)) 489*133bc645SAlex Richardson atf_tc_expect_fail("https://bugs.freebsd.org/205448"); 490*133bc645SAlex Richardson #endif 491*133bc645SAlex Richardson for (size_t i = 0; i < nitems(rmodes); i++) { 4928a7d0e8cSEnji Cooper printf("rmode = %d\n", rmodes[i]); 4938a7d0e8cSEnji Cooper fesetround(rmodes[i]); 4948a7d0e8cSEnji Cooper test_infinities(); 495*133bc645SAlex Richardson } 4968a7d0e8cSEnji Cooper } 4978a7d0e8cSEnji Cooper 498*133bc645SAlex Richardson ATF_TC_WITHOUT_HEAD(nans); 499*133bc645SAlex Richardson ATF_TC_BODY(nans, tc) 500*133bc645SAlex Richardson { 5018a7d0e8cSEnji Cooper fesetround(FE_TONEAREST); 5028a7d0e8cSEnji Cooper test_nans(); 503*133bc645SAlex Richardson } 5048a7d0e8cSEnji Cooper 505*133bc645SAlex Richardson 506*133bc645SAlex Richardson ATF_TC_WITHOUT_HEAD(small_z); 507*133bc645SAlex Richardson ATF_TC_BODY(small_z, tc) 508*133bc645SAlex Richardson { 509*133bc645SAlex Richardson for (size_t i = 0; i < nitems(rmodes); i++) { 5108a7d0e8cSEnji Cooper printf("rmode = %d\n", rmodes[i]); 5118a7d0e8cSEnji Cooper fesetround(rmodes[i]); 5128a7d0e8cSEnji Cooper test_small_z(); 513*133bc645SAlex Richardson } 5148a7d0e8cSEnji Cooper } 5158a7d0e8cSEnji Cooper 516*133bc645SAlex Richardson 517*133bc645SAlex Richardson ATF_TC_WITHOUT_HEAD(big_z); 518*133bc645SAlex Richardson ATF_TC_BODY(big_z, tc) 519*133bc645SAlex Richardson { 520*133bc645SAlex Richardson for (size_t i = 0; i < nitems(rmodes); i++) { 5218a7d0e8cSEnji Cooper printf("rmode = %d\n", rmodes[i]); 5228a7d0e8cSEnji Cooper fesetround(rmodes[i]); 5238a7d0e8cSEnji Cooper test_big_z(); 524*133bc645SAlex Richardson } 5258a7d0e8cSEnji Cooper } 5268a7d0e8cSEnji Cooper 527*133bc645SAlex Richardson ATF_TC_WITHOUT_HEAD(accuracy); 528*133bc645SAlex Richardson ATF_TC_BODY(accuracy, tc) 529*133bc645SAlex Richardson { 5308a7d0e8cSEnji Cooper fesetround(FE_TONEAREST); 5318a7d0e8cSEnji Cooper test_accuracy(); 532*133bc645SAlex Richardson } 5338a7d0e8cSEnji Cooper 534*133bc645SAlex Richardson ATF_TC_WITHOUT_HEAD(double_rounding); 535*133bc645SAlex Richardson ATF_TC_BODY(double_rounding, tc) { 5368a7d0e8cSEnji Cooper test_double_rounding(); 537*133bc645SAlex Richardson } 5388a7d0e8cSEnji Cooper 539*133bc645SAlex Richardson ATF_TP_ADD_TCS(tp) 540*133bc645SAlex Richardson { 541*133bc645SAlex Richardson ATF_TP_ADD_TC(tp, zeroes); 542*133bc645SAlex Richardson ATF_TP_ADD_TC(tp, infinities); 543*133bc645SAlex Richardson ATF_TP_ADD_TC(tp, nans); 544*133bc645SAlex Richardson ATF_TP_ADD_TC(tp, small_z); 545*133bc645SAlex Richardson ATF_TP_ADD_TC(tp, big_z); 546*133bc645SAlex Richardson ATF_TP_ADD_TC(tp, accuracy); 547*133bc645SAlex Richardson ATF_TP_ADD_TC(tp, double_rounding); 5488a7d0e8cSEnji Cooper /* 5498a7d0e8cSEnji Cooper * TODO: 5508a7d0e8cSEnji Cooper * - Tests for subnormals 5518a7d0e8cSEnji Cooper * - Cancellation tests (e.g., z = (double)x*y, but x*y is inexact) 5528a7d0e8cSEnji Cooper */ 553*133bc645SAlex Richardson return (atf_no_error()); 5548a7d0e8cSEnji Cooper } 555