Home | History | Annotate | Line # | Download | only in libm
      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