xref: /netbsd-src/tests/lib/libm/t_modf.c (revision 906e271cb392171a4b91e8a35d76013244a2813f)
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);
ATF_TC_HEAD(modff,tc)91 ATF_TC_HEAD(modff, tc)
92 {
93 	atf_tc_set_md_var(tc, "descr", "modff(3)");
94 }
ATF_TC_BODY(modff,tc)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);
ATF_TC_HEAD(modf,tc)171 ATF_TC_HEAD(modf, tc)
172 {
173 	atf_tc_set_md_var(tc, "descr", "modf(3)");
174 }
ATF_TC_BODY(modf,tc)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);
ATF_TC_HEAD(modfl,tc)284 ATF_TC_HEAD(modfl, tc)
285 {
286 	atf_tc_set_md_var(tc, "descr", "modfl(3)");
287 }
ATF_TC_BODY(modfl,tc)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 
ATF_TP_ADD_TCS(tp)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