1 /* 2 * Copyright (c) 2008 David Schultz <das@FreeBSD.org> 3 * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 /* 29 * Tests for fmaximum{,f,l}(), fminimum{,f,l}(), fmaximum_mag{,f,l}, 30 * fminimum_mag{,f,l}, fmaximum_num{,f,l}, fminimum_num{,f,l}, 31 * fmaximum_mag_num{,f,l} and fminimum_mag_num{,f,l} 32 */ 33 34 #include <sys/cdefs.h> 35 #include <fenv.h> 36 #include <float.h> 37 #include <math.h> 38 39 #include "test-utils.h" 40 41 #pragma STDC FENV_ACCESS ON 42 43 /* 44 * Test whether func(x, y) has the expected result, and make sure no 45 * exceptions are raised. 46 */ 47 #define TEST(func, type, x, y, expected, rmode) do { \ 48 type __x = (x); /* convert before we clear exceptions */ \ 49 type __y = (y); \ 50 ATF_REQUIRE_EQ(0, feclearexcept(ALL_STD_EXCEPT)); \ 51 long double __result = func((__x), (__y)); \ 52 CHECK_FP_EXCEPTIONS_MSG(0, ALL_STD_EXCEPT, \ 53 #func "(%.20Lg, %.20Lg) rmode%d", (x), (y), rmode); \ 54 ATF_CHECK_MSG(fpequal_cs(__result, (expected), true), \ 55 #func "(%.20Lg, %.20Lg) rmode%d = %.20Lg, expected %.20Lg", \ 56 (x), (y), rmode, __result, (expected)); \ 57 } while (0) 58 59 static void 60 testall_r(long double big, long double small, int rmode) 61 { 62 long double expected_max, expected_min; 63 if (isnan(big) || isnan(small)) { 64 expected_max = NAN; 65 expected_min = expected_max; 66 } else { 67 expected_max = big; 68 expected_min = small; 69 } 70 71 TEST(fmaximumf, float, big, small, expected_max, rmode); 72 TEST(fmaximumf, float, small, big, expected_max, rmode); 73 TEST(fmaximum, double, big, small, expected_max, rmode); 74 TEST(fmaximum, double, small, big, expected_max, rmode); 75 TEST(fmaximuml, long double, big, small, expected_max, rmode); 76 TEST(fmaximuml, long double, small, big, expected_max, rmode); 77 TEST(fminimumf, float, big, small, expected_min, rmode); 78 TEST(fminimumf, float, small, big, expected_min, rmode); 79 TEST(fminimum, double, big, small, expected_min, rmode); 80 TEST(fminimum, double, small, big, expected_min, rmode); 81 TEST(fminimuml, long double, big, small, expected_min, rmode); 82 TEST(fminimuml, long double, small, big, expected_min, rmode); 83 } 84 85 static void 86 testall_mag_r(long double big, long double small, int rmode) { 87 long double expected_max_mag, expected_min_mag; 88 if (isnan(big) || isnan(small)) { 89 expected_max_mag = NAN; 90 expected_min_mag = expected_max_mag; 91 } else { 92 if (fabsl(small) > fabsl(big)) { 93 expected_max_mag = small; 94 expected_min_mag = big; 95 } else { 96 expected_max_mag = big; 97 expected_min_mag = small; 98 } 99 } 100 101 TEST(fmaximum_magf, float, big, small, expected_max_mag, rmode); 102 TEST(fmaximum_magf, float, small, big, expected_max_mag, rmode); 103 TEST(fmaximum_mag, double, big, small, expected_max_mag, rmode); 104 TEST(fmaximum_mag, double, small, big, expected_max_mag, rmode); 105 TEST(fmaximum_magl, long double, big, small, expected_max_mag, rmode); 106 TEST(fmaximum_magl, long double, small, big, expected_max_mag, rmode); 107 TEST(fminimum_magf, float, big, small, expected_min_mag, rmode); 108 TEST(fminimum_magf, float, small, big, expected_min_mag, rmode); 109 TEST(fminimum_mag, double, big, small, expected_min_mag, rmode); 110 TEST(fminimum_mag, double, small, big, expected_min_mag, rmode); 111 TEST(fminimum_magl, long double, big, small, expected_min_mag, rmode); 112 TEST(fminimum_magl, long double, small, big, expected_min_mag, rmode); 113 } 114 115 static void 116 testall_num_r(long double big, long double small, int rmode) { 117 long double expected_max_num = isnan(big) ? small : big; 118 long double expected_min_num = isnan(small) ? big : small; 119 120 TEST(fmaximum_numf, float, big, small, expected_max_num, rmode); 121 TEST(fmaximum_numf, float, small, big, expected_max_num, rmode); 122 TEST(fmaximum_num, double, big, small, expected_max_num, rmode); 123 TEST(fmaximum_num, double, small, big, expected_max_num, rmode); 124 TEST(fmaximum_numl, long double, big, small, expected_max_num, rmode); 125 TEST(fmaximum_numl, long double, small, big, expected_max_num, rmode); 126 TEST(fminimum_numf, float, big, small, expected_min_num, rmode); 127 TEST(fminimum_numf, float, small, big, expected_min_num, rmode); 128 TEST(fminimum_num, double, big, small, expected_min_num, rmode); 129 TEST(fminimum_num, double, small, big, expected_min_num, rmode); 130 TEST(fminimum_numl, long double, big, small, expected_min_num, rmode); 131 TEST(fminimum_numl, long double, small, big, expected_min_num, rmode); 132 } 133 134 static void 135 testall_mag_num_r(long double big, long double small, int rmode) { 136 long double expected_max_mag_num = isnan(big) ? small : big; 137 long double expected_min_mag_num = isnan(small) ? big : small; 138 139 if (fabsl(small) > fabsl(big)) { 140 expected_max_mag_num = small; 141 expected_min_mag_num = big; 142 } 143 144 TEST(fmaximum_mag_numf, float, big, small, expected_max_mag_num, rmode); 145 TEST(fmaximum_mag_numf, float, small, big, expected_max_mag_num, rmode); 146 TEST(fmaximum_mag_num, double, big, small, expected_max_mag_num, rmode); 147 TEST(fmaximum_mag_num, double, small, big, expected_max_mag_num, rmode); 148 TEST(fmaximum_mag_numl, long double, big, small, expected_max_mag_num, rmode); 149 TEST(fmaximum_mag_numl, long double, small, big, expected_max_mag_num, rmode); 150 TEST(fminimum_mag_numf, float, big, small, expected_min_mag_num, rmode); 151 TEST(fminimum_mag_numf, float, small, big, expected_min_mag_num, rmode); 152 TEST(fminimum_mag_num, double, big, small, expected_min_mag_num, rmode); 153 TEST(fminimum_mag_num, double, small, big, expected_min_mag_num, rmode); 154 TEST(fminimum_mag_numl, long double, big, small, expected_min_mag_num, rmode); 155 TEST(fminimum_mag_numl, long double, small, big, expected_min_mag_num, rmode); 156 } 157 158 /* 159 * Test all the functions: fmaximumf, fmaximum, fmaximuml, fminimumf, fminimum, fminimuml 160 * in all rounding modes and with the arguments in different orders. 161 * The input 'big' must be >= 'small'. 162 */ 163 static void 164 testall(long double big, long double small) 165 { 166 static const int rmodes[] = { 167 FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO 168 }; 169 int i; 170 171 for (i = 0; i < 4; i++) { 172 fesetround(rmodes[i]); 173 testall_r(big, small, rmodes[i]); 174 testall_mag_r(big, small, rmodes[i]); 175 testall_num_r(big, small, rmodes[i]); 176 testall_mag_num_r(big, small, rmodes[i]); 177 } 178 } 179 180 ATF_TC_WITHOUT_HEAD(test1); 181 ATF_TC_BODY(test1, tc) 182 { 183 testall(1.0, 0.0); 184 } 185 186 ATF_TC_WITHOUT_HEAD(test2); 187 ATF_TC_BODY(test2, tc) 188 { 189 testall(42.0, nextafterf(42.0, -INFINITY)); 190 } 191 ATF_TC_WITHOUT_HEAD(test3); 192 ATF_TC_BODY(test3, tc) 193 { 194 testall(nextafterf(42.0, INFINITY), 42.0); 195 } 196 197 ATF_TC_WITHOUT_HEAD(test4); 198 ATF_TC_BODY(test4, tc) 199 { 200 testall(-5.0, -5.0); 201 } 202 203 ATF_TC_WITHOUT_HEAD(test5); 204 ATF_TC_BODY(test5, tc) 205 { 206 testall(-3.0, -4.0); 207 } 208 209 ATF_TC_WITHOUT_HEAD(test6); 210 ATF_TC_BODY(test6, tc) 211 { 212 testall(1.0, NAN); 213 } 214 ATF_TC_WITHOUT_HEAD(test7); 215 ATF_TC_BODY(test7, tc) 216 { 217 testall(INFINITY, NAN); 218 } 219 220 ATF_TC_WITHOUT_HEAD(test8); 221 ATF_TC_BODY(test8, tc) 222 { 223 testall(INFINITY, 1.0); 224 } 225 226 ATF_TC_WITHOUT_HEAD(test9); 227 ATF_TC_BODY(test9, tc) 228 { 229 testall(-3.0, -INFINITY); 230 } 231 232 ATF_TC_WITHOUT_HEAD(test10); 233 ATF_TC_BODY(test10, tc) 234 { 235 testall(3.0, -INFINITY); 236 } 237 238 ATF_TC_WITHOUT_HEAD(test11); 239 ATF_TC_BODY(test11, tc) 240 { 241 testall(NAN, NAN); 242 } 243 244 ATF_TC_WITHOUT_HEAD(test12); 245 ATF_TC_BODY(test12, tc) 246 { 247 testall(0.0, -0.0); 248 } 249 250 251 ATF_TC_WITHOUT_HEAD(test13); 252 ATF_TC_BODY(test13, tc) 253 { 254 testall(2.0, -2.0); 255 } 256 257 ATF_TC_WITHOUT_HEAD(test14); 258 ATF_TC_BODY(test14, tc) 259 { 260 testall(-0.0, -0.0); 261 } 262 263 ATF_TC_WITHOUT_HEAD(test15); 264 ATF_TC_BODY(test15, tc) 265 { 266 testall(0.0, 0.0); 267 } 268 269 ATF_TP_ADD_TCS(tp) 270 { 271 ATF_TP_ADD_TC(tp, test1); 272 ATF_TP_ADD_TC(tp, test2); 273 ATF_TP_ADD_TC(tp, test3); 274 ATF_TP_ADD_TC(tp, test4); 275 ATF_TP_ADD_TC(tp, test5); 276 ATF_TP_ADD_TC(tp, test6); 277 ATF_TP_ADD_TC(tp, test7); 278 ATF_TP_ADD_TC(tp, test8); 279 ATF_TP_ADD_TC(tp, test9); 280 ATF_TP_ADD_TC(tp, test10); 281 ATF_TP_ADD_TC(tp, test11); 282 ATF_TP_ADD_TC(tp, test12); 283 ATF_TP_ADD_TC(tp, test13); 284 ATF_TP_ADD_TC(tp, test14); 285 ATF_TP_ADD_TC(tp, test15); 286 287 return (atf_no_error()); 288 } 289