1 /* $NetBSD: t_modf.c,v 1.6 2024/05/15 00:02:57 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Joerg Sonnenberger. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __RCSID("$NetBSD: t_modf.c,v 1.6 2024/05/15 00:02:57 riastradh Exp $"); 34 35 #include <atf-c.h> 36 #include <float.h> 37 #include <math.h> 38 39 __CTASSERT(FLT_RADIX == 2); 40 41 static const struct { 42 float x, i, f; 43 } casesf[] = { 44 { 0, 0, 0 }, 45 { FLT_MIN, 0, FLT_MIN }, 46 { 0.5, 0, 0.5 }, 47 { 1 - FLT_EPSILON/2, 0, 1 - FLT_EPSILON/2 }, 48 { 1, 1, 0 }, 49 { 1 + FLT_EPSILON, 1, FLT_EPSILON }, 50 { 0.5/FLT_EPSILON - 0.5, 0.5/FLT_EPSILON - 1, 0.5 }, 51 { 0.5/FLT_EPSILON, 0.5/FLT_EPSILON, 0 }, 52 { 0.5/FLT_EPSILON + 0.5, 0.5/FLT_EPSILON, 0.5 }, 53 { 1/FLT_EPSILON, 1/FLT_EPSILON, 0 }, 54 }; 55 56 static const struct { 57 double x, i, f; 58 } cases[] = { 59 { 0, 0, 0 }, 60 { DBL_MIN, 0, DBL_MIN }, 61 { 0.5, 0, 0.5 }, 62 { 1 - DBL_EPSILON/2, 0, 1 - DBL_EPSILON/2 }, 63 { 1, 1, 0 }, 64 { 1 + DBL_EPSILON, 1, DBL_EPSILON }, 65 { 1/FLT_EPSILON + 0.5, 1/FLT_EPSILON, 0.5 }, 66 { 0.5/DBL_EPSILON - 0.5, 0.5/DBL_EPSILON - 1, 0.5 }, 67 { 0.5/DBL_EPSILON, 0.5/DBL_EPSILON, 0 }, 68 { 0.5/DBL_EPSILON + 0.5, 0.5/DBL_EPSILON, 0.5 }, 69 { 1/DBL_EPSILON, 1/DBL_EPSILON, 0 }, 70 }; 71 72 #ifdef __HAVE_LONG_DOUBLE 73 static const struct { 74 long double x, i, f; 75 } casesl[] = { 76 { 0, 0, 0 }, 77 { LDBL_MIN, 0, LDBL_MIN }, 78 { 0.5, 0, 0.5 }, 79 { 1 - LDBL_EPSILON/2, 0, 1 - LDBL_EPSILON/2 }, 80 { 1, 1, 0 }, 81 { 1 + LDBL_EPSILON, 1, LDBL_EPSILON }, 82 { 1.0L/DBL_EPSILON + 0.5L, 1.0L/DBL_EPSILON, 0.5 }, 83 { 0.5/LDBL_EPSILON - 0.5L, 0.5/LDBL_EPSILON - 1, 0.5 }, 84 { 0.5/LDBL_EPSILON, 0.5/LDBL_EPSILON, 0 }, 85 { 0.5/LDBL_EPSILON + 0.5L, 0.5/LDBL_EPSILON, 0.5 }, 86 { 1/LDBL_EPSILON, 1/LDBL_EPSILON, 0 }, 87 }; 88 #endif /* __HAVE_LONG_DOUBLE */ 89 90 ATF_TC(modff); 91 ATF_TC_HEAD(modff, tc) 92 { 93 atf_tc_set_md_var(tc, "descr", "modff(3)"); 94 } 95 ATF_TC_BODY(modff, tc) 96 { 97 unsigned n; 98 99 for (n = 0; n < __arraycount(casesf); n++) { 100 float x, i, f; 101 102 x = casesf[n].x; 103 f = modff(x, &i); 104 ATF_CHECK_EQ_MSG(i, casesf[n].i, 105 "casesf[%u]: modff %g=%a" 106 " returned integer %g=%a, frac %g=%a;" 107 " expected integer %g=%a, frac %g=%a", 108 n, x, x, i, i, f, f, 109 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 110 ATF_CHECK_EQ_MSG(f, casesf[n].f, 111 "casesf[%u]: modff %g=%a" 112 " returned integer %g=%a, frac %g=%a;" 113 " expected integer %g=%a, frac %g=%a", 114 n, x, x, i, i, f, f, 115 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 116 117 f = modff(-x, &i); 118 ATF_CHECK_EQ_MSG(i, -casesf[n].i, 119 "casesf[%u]: modff %g=%a" 120 " returned integer %g=%a, frac %g=%a;" 121 " expected integer %g=%a, frac %g=%a", 122 n, x, x, i, i, f, f, 123 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 124 ATF_CHECK_EQ_MSG(f, -casesf[n].f, 125 "casesf[%u]: modff %g=%a" 126 " returned integer %g=%a, frac %g=%a;" 127 " expected integer %g=%a, frac %g=%a", 128 n, x, x, i, i, f, f, 129 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 130 } 131 132 if (isinf(INFINITY)) { 133 float x, i, f; 134 135 x = INFINITY; 136 f = modff(x, &i); 137 ATF_CHECK_MSG(f == 0, 138 "modff +inf returned integer %g=%a, frac %g=%a", 139 i, i, f, f); 140 ATF_CHECK_MSG(isinf(i) && i > 0, 141 "modff +inf returned integer %g=%a, frac %g=%a", 142 i, i, f, f); 143 144 x = -INFINITY; 145 f = modff(x, &i); 146 ATF_CHECK_MSG(f == 0, 147 "modff -inf returned integer %g=%a, frac %g=%a", 148 i, i, f, f); 149 ATF_CHECK_MSG(isinf(i) && i < 0, 150 "modff -inf returned integer %g=%a, frac %g=%a", 151 i, i, f, f); 152 } 153 154 #ifdef NAN 155 { 156 float x, i, f; 157 158 x = NAN; 159 f = modff(x, &i); 160 ATF_CHECK_MSG(isnan(f), 161 "modff NaN returned integer %g=%a, frac %g=%a", 162 i, i, f, f); 163 ATF_CHECK_MSG(isnan(i), 164 "modff NaN returned integer %g=%a, frac %g=%a", 165 i, i, f, f); 166 } 167 #endif /* NAN */ 168 } 169 170 ATF_TC(modf); 171 ATF_TC_HEAD(modf, tc) 172 { 173 atf_tc_set_md_var(tc, "descr", "modf(3)"); 174 } 175 ATF_TC_BODY(modf, tc) 176 { 177 unsigned n; 178 179 for (n = 0; n < __arraycount(casesf); n++) { 180 double x, i, f; 181 182 x = casesf[n].x; 183 f = modf(x, &i); 184 ATF_CHECK_EQ_MSG(i, casesf[n].i, 185 "casesf[%u]: modf %g=%a" 186 " returned integer %g=%a, frac %g=%a;" 187 " expected integer %g=%a, frac %g=%a", 188 n, x, x, i, i, f, f, 189 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 190 ATF_CHECK_EQ_MSG(f, casesf[n].f, 191 "casesf[%u]: modf %g=%a" 192 " returned integer %g=%a, frac %g=%a;" 193 " expected integer %g=%a, frac %g=%a", 194 n, x, x, i, i, f, f, 195 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 196 197 f = modf(-x, &i); 198 ATF_CHECK_EQ_MSG(i, -casesf[n].i, 199 "casesf[%u]: modf %g=%a" 200 " returned integer %g=%a, frac %g=%a;" 201 " expected integer %g=%a, frac %g=%a", 202 n, x, x, i, i, f, f, 203 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 204 ATF_CHECK_EQ_MSG(f, -casesf[n].f, 205 "casesf[%u]: modf %g=%a" 206 " returned integer %g=%a, frac %g=%a;" 207 " expected integer %g=%a, frac %g=%a", 208 n, x, x, i, i, f, f, 209 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 210 } 211 212 for (n = 0; n < __arraycount(cases); n++) { 213 double x, i, f; 214 215 x = cases[n].x; 216 f = modf(x, &i); 217 ATF_CHECK_EQ_MSG(i, cases[n].i, 218 "cases[%u]: modf %g=%a" 219 " returned integer %g=%a, frac %g=%a;" 220 " expected integer %g=%a, frac %g=%a", 221 n, x, x, i, i, f, f, 222 cases[n].i, cases[n].i, cases[n].f, cases[n].f); 223 ATF_CHECK_EQ_MSG(f, cases[n].f, 224 "cases[%u]: modf %g=%a" 225 " returned integer %g=%a, frac %g=%a;" 226 " expected integer %g=%a, frac %g=%a", 227 n, x, x, i, i, f, f, 228 cases[n].i, cases[n].i, cases[n].f, cases[n].f); 229 230 f = modf(-x, &i); 231 ATF_CHECK_EQ_MSG(i, -cases[n].i, 232 "cases[%u]: modf %g=%a" 233 " returned integer %g=%a, frac %g=%a;" 234 " expected integer %g=%a, frac %g=%a", 235 n, x, x, i, i, f, f, 236 cases[n].i, cases[n].i, cases[n].f, cases[n].f); 237 ATF_CHECK_EQ_MSG(f, -cases[n].f, 238 "cases[%u]: modf %g=%a" 239 " returned integer %g=%a, frac %g=%a;" 240 " expected integer %g=%a, frac %g=%a", 241 n, x, x, i, i, f, f, 242 cases[n].i, cases[n].i, cases[n].f, cases[n].f); 243 } 244 245 if (isinf(INFINITY)) { 246 double x, i, f; 247 248 x = INFINITY; 249 f = modf(x, &i); 250 ATF_CHECK_MSG(f == 0, 251 "modf +inf returned integer %g=%a, frac %g=%a", 252 i, i, f, f); 253 ATF_CHECK_MSG(isinf(i) && i > 0, 254 "modf +inf returned integer %g=%a, frac %g=%a", 255 i, i, f, f); 256 257 x = -INFINITY; 258 f = modf(x, &i); 259 ATF_CHECK_MSG(f == 0, 260 "modf -inf returned integer %g=%a, frac %g=%a", 261 i, i, f, f); 262 ATF_CHECK_MSG(isinf(i) && i < 0, 263 "modf -inf returned integer %g=%a, frac %g=%a", 264 i, i, f, f); 265 } 266 267 #ifdef NAN 268 { 269 double x, i, f; 270 271 x = NAN; 272 f = modf(x, &i); 273 ATF_CHECK_MSG(isnan(f), 274 "modf NaN returned integer %g=%a, frac %g=%a", 275 i, i, f, f); 276 ATF_CHECK_MSG(isnan(i), 277 "modf NaN returned integer %g=%a, frac %g=%a", 278 i, i, f, f); 279 } 280 #endif /* NAN */ 281 } 282 283 ATF_TC(modfl); 284 ATF_TC_HEAD(modfl, tc) 285 { 286 atf_tc_set_md_var(tc, "descr", "modfl(3)"); 287 } 288 ATF_TC_BODY(modfl, tc) 289 { 290 unsigned n; 291 292 for (n = 0; n < __arraycount(casesf); n++) { 293 long double x, i, f; 294 295 x = casesf[n].x; 296 f = modfl(x, &i); 297 ATF_CHECK_EQ_MSG(i, casesf[n].i, 298 "casesf[%u]: modfl %Lg=%La" 299 " returned integer %Lg=%La, frac %Lg=%La;" 300 " expected integer %g=%a, frac %g=%a", 301 n, x, x, i, i, f, f, 302 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 303 ATF_CHECK_EQ_MSG(f, casesf[n].f, 304 "casesf[%u]: modfl %Lg=%La" 305 " returned integer %Lg=%La, frac %Lg=%La;" 306 " expected integer %g=%a, frac %g=%a", 307 n, x, x, i, i, f, f, 308 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 309 310 f = modfl(-x, &i); 311 ATF_CHECK_EQ_MSG(i, -casesf[n].i, 312 "casesf[%u]: modfl %Lg=%La" 313 " returned integer %Lg=%La, frac %Lg=%La;" 314 " expected integer %g=%a, frac %g=%a", 315 n, x, x, i, i, f, f, 316 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 317 ATF_CHECK_EQ_MSG(f, -casesf[n].f, 318 "casesf[%u]: modfl %Lg=%La" 319 " returned integer %Lg=%La, frac %Lg=%La;" 320 " expected integer %g=%a, frac %g=%a", 321 n, x, x, i, i, f, f, 322 casesf[n].i, casesf[n].i, casesf[n].f, casesf[n].f); 323 } 324 325 for (n = 0; n < __arraycount(cases); n++) { 326 long double x, i, f; 327 328 x = cases[n].x; 329 f = modfl(x, &i); 330 ATF_CHECK_EQ_MSG(i, cases[n].i, 331 "cases[%u]: modfl %Lg=%La" 332 " returned integer %Lg=%La, frac %Lg=%La;" 333 " expected integer %g=%a, frac %g=%a", 334 n, x, x, i, i, f, f, 335 cases[n].i, cases[n].i, cases[n].f, cases[n].f); 336 ATF_CHECK_EQ_MSG(f, cases[n].f, 337 "cases[%u]: modfl %Lg=%La" 338 " returned integer %Lg=%La, frac %Lg=%La;" 339 " expected integer %g=%a, frac %g=%a", 340 n, x, x, i, i, f, f, 341 cases[n].i, cases[n].i, cases[n].f, cases[n].f); 342 343 f = modfl(-x, &i); 344 ATF_CHECK_EQ_MSG(i, -cases[n].i, 345 "cases[%u]: modfl %Lg=%La" 346 " returned integer %Lg=%La, frac %Lg=%La;" 347 " expected integer %g=%a, frac %g=%a", 348 n, x, x, i, i, f, f, 349 cases[n].i, cases[n].i, cases[n].f, cases[n].f); 350 ATF_CHECK_EQ_MSG(f, -cases[n].f, 351 "cases[%u]: modfl %Lg=%La" 352 " returned integer %Lg=%La, frac %Lg=%La;" 353 " expected integer %g=%a, frac %g=%a", 354 n, x, x, i, i, f, f, 355 cases[n].i, cases[n].i, cases[n].f, cases[n].f); 356 } 357 358 #ifdef __HAVE_LONG_DOUBLE 359 for (n = 0; n < __arraycount(casesl); n++) { 360 long double x, i, f; 361 362 x = casesl[n].x; 363 f = modfl(x, &i); 364 ATF_CHECK_EQ_MSG(i, casesl[n].i, 365 "casesl[%u]: modfl %Lg=%La" 366 " returned integer %Lg=%La, frac %Lg=%La;" 367 " expected integer %Lg=%La, frac %Lg=%La", 368 n, x, x, i, i, f, f, 369 casesl[n].i, casesl[n].i, casesl[n].f, casesl[n].f); 370 ATF_CHECK_EQ_MSG(f, casesl[n].f, 371 "casesl[%u]: modfl %Lg=%La" 372 " returned integer %Lg=%La, frac %Lg=%La;" 373 " expected integer %Lg=%La, frac %Lg=%La", 374 n, x, x, i, i, f, f, 375 casesl[n].i, casesl[n].i, casesl[n].f, casesl[n].f); 376 377 f = modfl(-x, &i); 378 ATF_CHECK_EQ_MSG(i, -casesl[n].i, 379 "casesl[%u]: modfl %Lg=%La" 380 " returned integer %Lg=%La, frac %Lg=%La;" 381 " expected integer %Lg=%La, frac %Lg=%La", 382 n, x, x, i, i, f, f, 383 casesl[n].i, casesl[n].i, casesl[n].f, casesl[n].f); 384 ATF_CHECK_EQ_MSG(f, -casesl[n].f, 385 "casesl[%u]: modfl %Lg=%La" 386 " returned integer %Lg=%La, frac %Lg=%La;" 387 " expected integer %Lg=%La, frac %Lg=%La", 388 n, x, x, i, i, f, f, 389 casesl[n].i, casesl[n].i, casesl[n].f, casesl[n].f); 390 } 391 #endif /* __HAVE_LONG_DOUBLE */ 392 393 if (isinf(INFINITY)) { 394 long double x, i, f; 395 396 x = INFINITY; 397 f = modfl(x, &i); 398 ATF_CHECK_MSG(f == 0, 399 "modfl +inf returned integer %Lg=%La, frac %Lg=%La", 400 i, i, f, f); 401 ATF_CHECK_MSG(isinf(i) && i > 0, 402 "modfl +inf returned integer %Lg=%La, frac %Lg=%La", 403 i, i, f, f); 404 405 x = -INFINITY; 406 f = modfl(x, &i); 407 ATF_CHECK_MSG(f == 0, 408 "modfl -inf returned integer %Lg=%La, frac %Lg=%La", 409 i, i, f, f); 410 ATF_CHECK_MSG(isinf(i) && i < 0, 411 "modfl -inf returned integer %Lg=%La, frac %Lg=%La", 412 i, i, f, f); 413 } 414 415 #ifdef NAN 416 { 417 long double x, i, f; 418 419 x = NAN; 420 f = modfl(x, &i); 421 ATF_CHECK_MSG(isnan(f), 422 "modfl NaN returned integer %Lg=%La, frac %Lg=%La", 423 i, i, f, f); 424 ATF_CHECK_MSG(isnan(i), 425 "modfl NaN returned integer %Lg=%La, frac %Lg=%La", 426 i, i, f, f); 427 } 428 #endif /* NAN */ 429 } 430 431 ATF_TP_ADD_TCS(tp) 432 { 433 434 ATF_TP_ADD_TC(tp, modff); 435 ATF_TP_ADD_TC(tp, modf); 436 ATF_TP_ADD_TC(tp, modfl); 437 438 return atf_no_error(); 439 } 440