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