1 /*
2 * semi.c: test implementations of mathlib seminumerical functions
3 *
4 * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 * See https://llvm.org/LICENSE.txt for license information.
6 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 */
8
9 #include <stdio.h>
10 #include "semi.h"
11
test_rint(uint32 * in,uint32 * out,int isfloor,int isceil)12 static void test_rint(uint32 *in, uint32 *out,
13 int isfloor, int isceil) {
14 int sign = in[0] & 0x80000000;
15 int roundup = (isfloor && sign) || (isceil && !sign);
16 uint32 xh, xl, roundword;
17 int ex = (in[0] >> 20) & 0x7FF; /* exponent */
18 int i;
19
20 if ((ex > 0x3ff + 52 - 1) || /* things this big can't be fractional */
21 ((in[0] & 0x7FFFFFFF) == 0 && in[1] == 0)) { /* zero */
22 /* NaN, Inf, a large integer, or zero: just return the input */
23 out[0] = in[0];
24 out[1] = in[1];
25 return;
26 }
27
28 /*
29 * Special case: ex < 0x3ff, ie our number is in (0,1). Return
30 * 1 or 0 according to roundup.
31 */
32 if (ex < 0x3ff) {
33 out[0] = sign | (roundup ? 0x3FF00000 : 0);
34 out[1] = 0;
35 return;
36 }
37
38 /*
39 * We're not short of time here, so we'll do this the hideously
40 * inefficient way. Shift bit by bit so that the units place is
41 * somewhere predictable, round, and shift back again.
42 */
43 xh = in[0];
44 xl = in[1];
45 roundword = 0;
46 for (i = ex; i < 0x3ff + 52; i++) {
47 if (roundword & 1)
48 roundword |= 2; /* preserve sticky bit */
49 roundword = (roundword >> 1) | ((xl & 1) << 31);
50 xl = (xl >> 1) | ((xh & 1) << 31);
51 xh = xh >> 1;
52 }
53 if (roundword && roundup) {
54 xl++;
55 xh += (xl==0);
56 }
57 for (i = ex; i < 0x3ff + 52; i++) {
58 xh = (xh << 1) | ((xl >> 31) & 1);
59 xl = (xl & 0x7FFFFFFF) << 1;
60 }
61 out[0] = xh;
62 out[1] = xl;
63 }
64
test_ceil(uint32 * in,uint32 * out)65 char *test_ceil(uint32 *in, uint32 *out) {
66 test_rint(in, out, 0, 1);
67 return NULL;
68 }
69
test_floor(uint32 * in,uint32 * out)70 char *test_floor(uint32 *in, uint32 *out) {
71 test_rint(in, out, 1, 0);
72 return NULL;
73 }
74
test_rintf(uint32 * in,uint32 * out,int isfloor,int isceil)75 static void test_rintf(uint32 *in, uint32 *out,
76 int isfloor, int isceil) {
77 int sign = *in & 0x80000000;
78 int roundup = (isfloor && sign) || (isceil && !sign);
79 uint32 x, roundword;
80 int ex = (*in >> 23) & 0xFF; /* exponent */
81 int i;
82
83 if ((ex > 0x7f + 23 - 1) || /* things this big can't be fractional */
84 (*in & 0x7FFFFFFF) == 0) { /* zero */
85 /* NaN, Inf, a large integer, or zero: just return the input */
86 *out = *in;
87 return;
88 }
89
90 /*
91 * Special case: ex < 0x7f, ie our number is in (0,1). Return
92 * 1 or 0 according to roundup.
93 */
94 if (ex < 0x7f) {
95 *out = sign | (roundup ? 0x3F800000 : 0);
96 return;
97 }
98
99 /*
100 * We're not short of time here, so we'll do this the hideously
101 * inefficient way. Shift bit by bit so that the units place is
102 * somewhere predictable, round, and shift back again.
103 */
104 x = *in;
105 roundword = 0;
106 for (i = ex; i < 0x7F + 23; i++) {
107 if (roundword & 1)
108 roundword |= 2; /* preserve sticky bit */
109 roundword = (roundword >> 1) | ((x & 1) << 31);
110 x = x >> 1;
111 }
112 if (roundword && roundup) {
113 x++;
114 }
115 for (i = ex; i < 0x7F + 23; i++) {
116 x = x << 1;
117 }
118 *out = x;
119 }
120
test_ceilf(uint32 * in,uint32 * out)121 char *test_ceilf(uint32 *in, uint32 *out) {
122 test_rintf(in, out, 0, 1);
123 return NULL;
124 }
125
test_floorf(uint32 * in,uint32 * out)126 char *test_floorf(uint32 *in, uint32 *out) {
127 test_rintf(in, out, 1, 0);
128 return NULL;
129 }
130
test_fmod(uint32 * a,uint32 * b,uint32 * out)131 char *test_fmod(uint32 *a, uint32 *b, uint32 *out) {
132 int sign;
133 int32 aex, bex;
134 uint32 am[2], bm[2];
135
136 if (((a[0] & 0x7FFFFFFF) << 1) + !!a[1] > 0xFFE00000 ||
137 ((b[0] & 0x7FFFFFFF) << 1) + !!b[1] > 0xFFE00000) {
138 /* a or b is NaN: return QNaN, optionally with IVO */
139 uint32 an, bn;
140 out[0] = 0x7ff80000;
141 out[1] = 1;
142 an = ((a[0] & 0x7FFFFFFF) << 1) + !!a[1];
143 bn = ((b[0] & 0x7FFFFFFF) << 1) + !!b[1];
144 if ((an > 0xFFE00000 && an < 0xFFF00000) ||
145 (bn > 0xFFE00000 && bn < 0xFFF00000))
146 return "i"; /* at least one SNaN: IVO */
147 else
148 return NULL; /* no SNaNs, but at least 1 QNaN */
149 }
150 if ((b[0] & 0x7FFFFFFF) == 0 && b[1] == 0) { /* b==0: EDOM */
151 out[0] = 0x7ff80000;
152 out[1] = 1;
153 return "EDOM status=i";
154 }
155 if ((a[0] & 0x7FF00000) == 0x7FF00000) { /* a==Inf: EDOM */
156 out[0] = 0x7ff80000;
157 out[1] = 1;
158 return "EDOM status=i";
159 }
160 if ((b[0] & 0x7FF00000) == 0x7FF00000) { /* b==Inf: return a */
161 out[0] = a[0];
162 out[1] = a[1];
163 return NULL;
164 }
165 if ((a[0] & 0x7FFFFFFF) == 0 && a[1] == 0) { /* a==0: return a */
166 out[0] = a[0];
167 out[1] = a[1];
168 return NULL;
169 }
170
171 /*
172 * OK. That's the special cases cleared out of the way. Now we
173 * have finite (though not necessarily normal) a and b.
174 */
175 sign = a[0] & 0x80000000; /* we discard sign of b */
176 test_frexp(a, am, (uint32 *)&aex);
177 test_frexp(b, bm, (uint32 *)&bex);
178 am[0] &= 0xFFFFF, am[0] |= 0x100000;
179 bm[0] &= 0xFFFFF, bm[0] |= 0x100000;
180
181 while (aex >= bex) {
182 if (am[0] > bm[0] || (am[0] == bm[0] && am[1] >= bm[1])) {
183 am[1] -= bm[1];
184 am[0] = am[0] - bm[0] - (am[1] > ~bm[1]);
185 }
186 if (aex > bex) {
187 am[0] = (am[0] << 1) | ((am[1] & 0x80000000) >> 31);
188 am[1] <<= 1;
189 aex--;
190 } else
191 break;
192 }
193
194 /*
195 * Renormalise final result; this can be cunningly done by
196 * passing a denormal to ldexp.
197 */
198 aex += 0x3fd;
199 am[0] |= sign;
200 test_ldexp(am, (uint32 *)&aex, out);
201
202 return NULL; /* FIXME */
203 }
204
test_fmodf(uint32 * a,uint32 * b,uint32 * out)205 char *test_fmodf(uint32 *a, uint32 *b, uint32 *out) {
206 int sign;
207 int32 aex, bex;
208 uint32 am, bm;
209
210 if ((*a & 0x7FFFFFFF) > 0x7F800000 ||
211 (*b & 0x7FFFFFFF) > 0x7F800000) {
212 /* a or b is NaN: return QNaN, optionally with IVO */
213 uint32 an, bn;
214 *out = 0x7fc00001;
215 an = *a & 0x7FFFFFFF;
216 bn = *b & 0x7FFFFFFF;
217 if ((an > 0x7f800000 && an < 0x7fc00000) ||
218 (bn > 0x7f800000 && bn < 0x7fc00000))
219 return "i"; /* at least one SNaN: IVO */
220 else
221 return NULL; /* no SNaNs, but at least 1 QNaN */
222 }
223 if ((*b & 0x7FFFFFFF) == 0) { /* b==0: EDOM */
224 *out = 0x7fc00001;
225 return "EDOM status=i";
226 }
227 if ((*a & 0x7F800000) == 0x7F800000) { /* a==Inf: EDOM */
228 *out = 0x7fc00001;
229 return "EDOM status=i";
230 }
231 if ((*b & 0x7F800000) == 0x7F800000) { /* b==Inf: return a */
232 *out = *a;
233 return NULL;
234 }
235 if ((*a & 0x7FFFFFFF) == 0) { /* a==0: return a */
236 *out = *a;
237 return NULL;
238 }
239
240 /*
241 * OK. That's the special cases cleared out of the way. Now we
242 * have finite (though not necessarily normal) a and b.
243 */
244 sign = a[0] & 0x80000000; /* we discard sign of b */
245 test_frexpf(a, &am, (uint32 *)&aex);
246 test_frexpf(b, &bm, (uint32 *)&bex);
247 am &= 0x7FFFFF, am |= 0x800000;
248 bm &= 0x7FFFFF, bm |= 0x800000;
249
250 while (aex >= bex) {
251 if (am >= bm) {
252 am -= bm;
253 }
254 if (aex > bex) {
255 am <<= 1;
256 aex--;
257 } else
258 break;
259 }
260
261 /*
262 * Renormalise final result; this can be cunningly done by
263 * passing a denormal to ldexp.
264 */
265 aex += 0x7d;
266 am |= sign;
267 test_ldexpf(&am, (uint32 *)&aex, out);
268
269 return NULL; /* FIXME */
270 }
271
test_ldexp(uint32 * x,uint32 * np,uint32 * out)272 char *test_ldexp(uint32 *x, uint32 *np, uint32 *out) {
273 int n = *np;
274 int32 n2;
275 uint32 y[2];
276 int ex = (x[0] >> 20) & 0x7FF; /* exponent */
277 int sign = x[0] & 0x80000000;
278
279 if (ex == 0x7FF) { /* inf/NaN; just return x */
280 out[0] = x[0];
281 out[1] = x[1];
282 return NULL;
283 }
284 if ((x[0] & 0x7FFFFFFF) == 0 && x[1] == 0) { /* zero: return x */
285 out[0] = x[0];
286 out[1] = x[1];
287 return NULL;
288 }
289
290 test_frexp(x, y, (uint32 *)&n2);
291 ex = n + n2;
292 if (ex > 0x400) { /* overflow */
293 out[0] = sign | 0x7FF00000;
294 out[1] = 0;
295 return "overflow";
296 }
297 /*
298 * Underflow. 2^-1074 is 00000000.00000001; so if ex == -1074
299 * then we have something [2^-1075,2^-1074). Under round-to-
300 * nearest-even, this whole interval rounds up to 2^-1074,
301 * except for the bottom endpoint which rounds to even and is
302 * an underflow condition.
303 *
304 * So, ex < -1074 is definite underflow, and ex == -1074 is
305 * underflow iff all mantissa bits are zero.
306 */
307 if (ex < -1074 || (ex == -1074 && (y[0] & 0xFFFFF) == 0 && y[1] == 0)) {
308 out[0] = sign; /* underflow: correctly signed zero */
309 out[1] = 0;
310 return "underflow";
311 }
312
313 /*
314 * No overflow or underflow; should be nice and simple, unless
315 * we have to denormalise and round the result.
316 */
317 if (ex < -1021) { /* denormalise and round */
318 uint32 roundword;
319 y[0] &= 0x000FFFFF;
320 y[0] |= 0x00100000; /* set leading bit */
321 roundword = 0;
322 while (ex < -1021) {
323 if (roundword & 1)
324 roundword |= 2; /* preserve sticky bit */
325 roundword = (roundword >> 1) | ((y[1] & 1) << 31);
326 y[1] = (y[1] >> 1) | ((y[0] & 1) << 31);
327 y[0] = y[0] >> 1;
328 ex++;
329 }
330 if (roundword > 0x80000000 || /* round up */
331 (roundword == 0x80000000 && (y[1] & 1))) { /* round up to even */
332 y[1]++;
333 y[0] += (y[1] == 0);
334 }
335 out[0] = sign | y[0];
336 out[1] = y[1];
337 /* Proper ERANGE underflow was handled earlier, but we still
338 * expect an IEEE Underflow exception if this partially
339 * underflowed result is not exact. */
340 if (roundword)
341 return "u";
342 return NULL; /* underflow was handled earlier */
343 } else {
344 out[0] = y[0] + (ex << 20);
345 out[1] = y[1];
346 return NULL;
347 }
348 }
349
test_ldexpf(uint32 * x,uint32 * np,uint32 * out)350 char *test_ldexpf(uint32 *x, uint32 *np, uint32 *out) {
351 int n = *np;
352 int32 n2;
353 uint32 y;
354 int ex = (*x >> 23) & 0xFF; /* exponent */
355 int sign = *x & 0x80000000;
356
357 if (ex == 0xFF) { /* inf/NaN; just return x */
358 *out = *x;
359 return NULL;
360 }
361 if ((*x & 0x7FFFFFFF) == 0) { /* zero: return x */
362 *out = *x;
363 return NULL;
364 }
365
366 test_frexpf(x, &y, (uint32 *)&n2);
367 ex = n + n2;
368 if (ex > 0x80) { /* overflow */
369 *out = sign | 0x7F800000;
370 return "overflow";
371 }
372 /*
373 * Underflow. 2^-149 is 00000001; so if ex == -149 then we have
374 * something [2^-150,2^-149). Under round-to- nearest-even,
375 * this whole interval rounds up to 2^-149, except for the
376 * bottom endpoint which rounds to even and is an underflow
377 * condition.
378 *
379 * So, ex < -149 is definite underflow, and ex == -149 is
380 * underflow iff all mantissa bits are zero.
381 */
382 if (ex < -149 || (ex == -149 && (y & 0x7FFFFF) == 0)) {
383 *out = sign; /* underflow: correctly signed zero */
384 return "underflow";
385 }
386
387 /*
388 * No overflow or underflow; should be nice and simple, unless
389 * we have to denormalise and round the result.
390 */
391 if (ex < -125) { /* denormalise and round */
392 uint32 roundword;
393 y &= 0x007FFFFF;
394 y |= 0x00800000; /* set leading bit */
395 roundword = 0;
396 while (ex < -125) {
397 if (roundword & 1)
398 roundword |= 2; /* preserve sticky bit */
399 roundword = (roundword >> 1) | ((y & 1) << 31);
400 y = y >> 1;
401 ex++;
402 }
403 if (roundword > 0x80000000 || /* round up */
404 (roundword == 0x80000000 && (y & 1))) { /* round up to even */
405 y++;
406 }
407 *out = sign | y;
408 /* Proper ERANGE underflow was handled earlier, but we still
409 * expect an IEEE Underflow exception if this partially
410 * underflowed result is not exact. */
411 if (roundword)
412 return "u";
413 return NULL; /* underflow was handled earlier */
414 } else {
415 *out = y + (ex << 23);
416 return NULL;
417 }
418 }
419
test_frexp(uint32 * x,uint32 * out,uint32 * nout)420 char *test_frexp(uint32 *x, uint32 *out, uint32 *nout) {
421 int ex = (x[0] >> 20) & 0x7FF; /* exponent */
422 if (ex == 0x7FF) { /* inf/NaN; return x/0 */
423 out[0] = x[0];
424 out[1] = x[1];
425 nout[0] = 0;
426 return NULL;
427 }
428 if (ex == 0) { /* denormals/zeros */
429 int sign;
430 uint32 xh, xl;
431 if ((x[0] & 0x7FFFFFFF) == 0 && x[1] == 0) {
432 /* zero: return x/0 */
433 out[0] = x[0];
434 out[1] = x[1];
435 nout[0] = 0;
436 return NULL;
437 }
438 sign = x[0] & 0x80000000;
439 xh = x[0] & 0x7FFFFFFF;
440 xl = x[1];
441 ex = 1;
442 while (!(xh & 0x100000)) {
443 ex--;
444 xh = (xh << 1) | ((xl >> 31) & 1);
445 xl = (xl & 0x7FFFFFFF) << 1;
446 }
447 out[0] = sign | 0x3FE00000 | (xh & 0xFFFFF);
448 out[1] = xl;
449 nout[0] = ex - 0x3FE;
450 return NULL;
451 }
452 out[0] = 0x3FE00000 | (x[0] & 0x800FFFFF);
453 out[1] = x[1];
454 nout[0] = ex - 0x3FE;
455 return NULL; /* ordinary number; no error */
456 }
457
test_frexpf(uint32 * x,uint32 * out,uint32 * nout)458 char *test_frexpf(uint32 *x, uint32 *out, uint32 *nout) {
459 int ex = (*x >> 23) & 0xFF; /* exponent */
460 if (ex == 0xFF) { /* inf/NaN; return x/0 */
461 *out = *x;
462 nout[0] = 0;
463 return NULL;
464 }
465 if (ex == 0) { /* denormals/zeros */
466 int sign;
467 uint32 xv;
468 if ((*x & 0x7FFFFFFF) == 0) {
469 /* zero: return x/0 */
470 *out = *x;
471 nout[0] = 0;
472 return NULL;
473 }
474 sign = *x & 0x80000000;
475 xv = *x & 0x7FFFFFFF;
476 ex = 1;
477 while (!(xv & 0x800000)) {
478 ex--;
479 xv = xv << 1;
480 }
481 *out = sign | 0x3F000000 | (xv & 0x7FFFFF);
482 nout[0] = ex - 0x7E;
483 return NULL;
484 }
485 *out = 0x3F000000 | (*x & 0x807FFFFF);
486 nout[0] = ex - 0x7E;
487 return NULL; /* ordinary number; no error */
488 }
489
test_modf(uint32 * x,uint32 * fout,uint32 * iout)490 char *test_modf(uint32 *x, uint32 *fout, uint32 *iout) {
491 int ex = (x[0] >> 20) & 0x7FF; /* exponent */
492 int sign = x[0] & 0x80000000;
493 uint32 fh, fl;
494
495 if (((x[0] & 0x7FFFFFFF) | (!!x[1])) > 0x7FF00000) {
496 /*
497 * NaN input: return the same in _both_ outputs.
498 */
499 fout[0] = iout[0] = x[0];
500 fout[1] = iout[1] = x[1];
501 return NULL;
502 }
503
504 test_rint(x, iout, 0, 0);
505 fh = x[0] - iout[0];
506 fl = x[1] - iout[1];
507 if (!fh && !fl) { /* no fraction part */
508 fout[0] = sign;
509 fout[1] = 0;
510 return NULL;
511 }
512 if (!(iout[0] & 0x7FFFFFFF) && !iout[1]) { /* no integer part */
513 fout[0] = x[0];
514 fout[1] = x[1];
515 return NULL;
516 }
517 while (!(fh & 0x100000)) {
518 ex--;
519 fh = (fh << 1) | ((fl >> 31) & 1);
520 fl = (fl & 0x7FFFFFFF) << 1;
521 }
522 fout[0] = sign | (ex << 20) | (fh & 0xFFFFF);
523 fout[1] = fl;
524 return NULL;
525 }
526
test_modff(uint32 * x,uint32 * fout,uint32 * iout)527 char *test_modff(uint32 *x, uint32 *fout, uint32 *iout) {
528 int ex = (*x >> 23) & 0xFF; /* exponent */
529 int sign = *x & 0x80000000;
530 uint32 f;
531
532 if ((*x & 0x7FFFFFFF) > 0x7F800000) {
533 /*
534 * NaN input: return the same in _both_ outputs.
535 */
536 *fout = *iout = *x;
537 return NULL;
538 }
539
540 test_rintf(x, iout, 0, 0);
541 f = *x - *iout;
542 if (!f) { /* no fraction part */
543 *fout = sign;
544 return NULL;
545 }
546 if (!(*iout & 0x7FFFFFFF)) { /* no integer part */
547 *fout = *x;
548 return NULL;
549 }
550 while (!(f & 0x800000)) {
551 ex--;
552 f = f << 1;
553 }
554 *fout = sign | (ex << 23) | (f & 0x7FFFFF);
555 return NULL;
556 }
557
test_copysign(uint32 * x,uint32 * y,uint32 * out)558 char *test_copysign(uint32 *x, uint32 *y, uint32 *out)
559 {
560 int ysign = y[0] & 0x80000000;
561 int xhigh = x[0] & 0x7fffffff;
562
563 out[0] = ysign | xhigh;
564 out[1] = x[1];
565
566 /* There can be no error */
567 return NULL;
568 }
569
test_copysignf(uint32 * x,uint32 * y,uint32 * out)570 char *test_copysignf(uint32 *x, uint32 *y, uint32 *out)
571 {
572 int ysign = y[0] & 0x80000000;
573 int xhigh = x[0] & 0x7fffffff;
574
575 out[0] = ysign | xhigh;
576
577 /* There can be no error */
578 return NULL;
579 }
580
test_isfinite(uint32 * x,uint32 * out)581 char *test_isfinite(uint32 *x, uint32 *out)
582 {
583 int xhigh = x[0];
584 /* Being finite means that the exponent is not 0x7ff */
585 if ((xhigh & 0x7ff00000) == 0x7ff00000) out[0] = 0;
586 else out[0] = 1;
587 return NULL;
588 }
589
test_isfinitef(uint32 * x,uint32 * out)590 char *test_isfinitef(uint32 *x, uint32 *out)
591 {
592 /* Being finite means that the exponent is not 0xff */
593 if ((x[0] & 0x7f800000) == 0x7f800000) out[0] = 0;
594 else out[0] = 1;
595 return NULL;
596 }
597
test_isinff(uint32 * x,uint32 * out)598 char *test_isinff(uint32 *x, uint32 *out)
599 {
600 /* Being infinite means that our bottom 30 bits equate to 0x7f800000 */
601 if ((x[0] & 0x7fffffff) == 0x7f800000) out[0] = 1;
602 else out[0] = 0;
603 return NULL;
604 }
605
test_isinf(uint32 * x,uint32 * out)606 char *test_isinf(uint32 *x, uint32 *out)
607 {
608 int xhigh = x[0];
609 int xlow = x[1];
610 /* Being infinite means that our fraction is zero and exponent is 0x7ff */
611 if (((xhigh & 0x7fffffff) == 0x7ff00000) && (xlow == 0)) out[0] = 1;
612 else out[0] = 0;
613 return NULL;
614 }
615
test_isnanf(uint32 * x,uint32 * out)616 char *test_isnanf(uint32 *x, uint32 *out)
617 {
618 /* Being NaN means that our exponent is 0xff and non-0 fraction */
619 int exponent = x[0] & 0x7f800000;
620 int fraction = x[0] & 0x007fffff;
621 if ((exponent == 0x7f800000) && (fraction != 0)) out[0] = 1;
622 else out[0] = 0;
623 return NULL;
624 }
625
test_isnan(uint32 * x,uint32 * out)626 char *test_isnan(uint32 *x, uint32 *out)
627 {
628 /* Being NaN means that our exponent is 0x7ff and non-0 fraction */
629 int exponent = x[0] & 0x7ff00000;
630 int fractionhigh = x[0] & 0x000fffff;
631 if ((exponent == 0x7ff00000) && ((fractionhigh != 0) || x[1] != 0))
632 out[0] = 1;
633 else out[0] = 0;
634 return NULL;
635 }
636
test_isnormalf(uint32 * x,uint32 * out)637 char *test_isnormalf(uint32 *x, uint32 *out)
638 {
639 /* Being normal means exponent is not 0 and is not 0xff */
640 int exponent = x[0] & 0x7f800000;
641 if (exponent == 0x7f800000) out[0] = 0;
642 else if (exponent == 0) out[0] = 0;
643 else out[0] = 1;
644 return NULL;
645 }
646
test_isnormal(uint32 * x,uint32 * out)647 char *test_isnormal(uint32 *x, uint32 *out)
648 {
649 /* Being normal means exponent is not 0 and is not 0x7ff */
650 int exponent = x[0] & 0x7ff00000;
651 if (exponent == 0x7ff00000) out[0] = 0;
652 else if (exponent == 0) out[0] = 0;
653 else out[0] = 1;
654 return NULL;
655 }
656
test_signbitf(uint32 * x,uint32 * out)657 char *test_signbitf(uint32 *x, uint32 *out)
658 {
659 /* Sign bit is bit 31 */
660 out[0] = (x[0] >> 31) & 1;
661 return NULL;
662 }
663
test_signbit(uint32 * x,uint32 * out)664 char *test_signbit(uint32 *x, uint32 *out)
665 {
666 /* Sign bit is bit 31 */
667 out[0] = (x[0] >> 31) & 1;
668 return NULL;
669 }
670
test_fpclassify(uint32 * x,uint32 * out)671 char *test_fpclassify(uint32 *x, uint32 *out)
672 {
673 int exponent = (x[0] & 0x7ff00000) >> 20;
674 int fraction = (x[0] & 0x000fffff) | x[1];
675
676 if ((exponent == 0x00) && (fraction == 0)) out[0] = 0;
677 else if ((exponent == 0x00) && (fraction != 0)) out[0] = 4;
678 else if ((exponent == 0x7ff) && (fraction == 0)) out[0] = 3;
679 else if ((exponent == 0x7ff) && (fraction != 0)) out[0] = 7;
680 else out[0] = 5;
681 return NULL;
682 }
683
test_fpclassifyf(uint32 * x,uint32 * out)684 char *test_fpclassifyf(uint32 *x, uint32 *out)
685 {
686 int exponent = (x[0] & 0x7f800000) >> 23;
687 int fraction = x[0] & 0x007fffff;
688
689 if ((exponent == 0x000) && (fraction == 0)) out[0] = 0;
690 else if ((exponent == 0x000) && (fraction != 0)) out[0] = 4;
691 else if ((exponent == 0xff) && (fraction == 0)) out[0] = 3;
692 else if ((exponent == 0xff) && (fraction != 0)) out[0] = 7;
693 else out[0] = 5;
694 return NULL;
695 }
696
697 /*
698 * Internal function that compares doubles in x & y and returns -3, -2, -1, 0,
699 * 1 if they compare to be signaling, unordered, less than, equal or greater
700 * than.
701 */
fpcmp4(uint32 * x,uint32 * y)702 static int fpcmp4(uint32 *x, uint32 *y)
703 {
704 int result = 0;
705
706 /*
707 * Sort out whether results are ordered or not to begin with
708 * NaNs have exponent 0x7ff, and non-zero fraction. Signaling NaNs take
709 * higher priority than quiet ones.
710 */
711 if ((x[0] & 0x7fffffff) >= 0x7ff80000) result = -2;
712 else if ((x[0] & 0x7fffffff) > 0x7ff00000) result = -3;
713 else if (((x[0] & 0x7fffffff) == 0x7ff00000) && (x[1] != 0)) result = -3;
714 if ((y[0] & 0x7fffffff) >= 0x7ff80000 && result != -3) result = -2;
715 else if ((y[0] & 0x7fffffff) > 0x7ff00000) result = -3;
716 else if (((y[0] & 0x7fffffff) == 0x7ff00000) && (y[1] != 0)) result = -3;
717 if (result != 0) return result;
718
719 /*
720 * The two forms of zero are equal
721 */
722 if (((x[0] & 0x7fffffff) == 0) && x[1] == 0 &&
723 ((y[0] & 0x7fffffff) == 0) && y[1] == 0)
724 return 0;
725
726 /*
727 * If x and y have different signs we can tell that they're not equal
728 * If x is +ve we have x > y return 1 - otherwise y is +ve return -1
729 */
730 if ((x[0] >> 31) != (y[0] >> 31))
731 return ((x[0] >> 31) == 0) - ((y[0] >> 31) == 0);
732
733 /*
734 * Now we have both signs the same, let's do an initial compare of the
735 * values.
736 *
737 * Whoever designed IEEE754's floating point formats is very clever and
738 * earns my undying admiration. Once you remove the sign-bit, the
739 * floating point numbers can be ordered using the standard <, ==, >
740 * operators will treating the fp-numbers as integers with that bit-
741 * pattern.
742 */
743 if ((x[0] & 0x7fffffff) < (y[0] & 0x7fffffff)) result = -1;
744 else if ((x[0] & 0x7fffffff) > (y[0] & 0x7fffffff)) result = 1;
745 else if (x[1] < y[1]) result = -1;
746 else if (x[1] > y[1]) result = 1;
747 else result = 0;
748
749 /*
750 * Now we return the result - is x is positive (and therefore so is y) we
751 * return the plain result - otherwise we negate it and return.
752 */
753 if ((x[0] >> 31) == 0) return result;
754 else return -result;
755 }
756
757 /*
758 * Internal function that compares floats in x & y and returns -3, -2, -1, 0,
759 * 1 if they compare to be signaling, unordered, less than, equal or greater
760 * than.
761 */
fpcmp4f(uint32 * x,uint32 * y)762 static int fpcmp4f(uint32 *x, uint32 *y)
763 {
764 int result = 0;
765
766 /*
767 * Sort out whether results are ordered or not to begin with
768 * NaNs have exponent 0xff, and non-zero fraction - we have to handle all
769 * signaling cases over the quiet ones
770 */
771 if ((x[0] & 0x7fffffff) >= 0x7fc00000) result = -2;
772 else if ((x[0] & 0x7fffffff) > 0x7f800000) result = -3;
773 if ((y[0] & 0x7fffffff) >= 0x7fc00000 && result != -3) result = -2;
774 else if ((y[0] & 0x7fffffff) > 0x7f800000) result = -3;
775 if (result != 0) return result;
776
777 /*
778 * The two forms of zero are equal
779 */
780 if (((x[0] & 0x7fffffff) == 0) && ((y[0] & 0x7fffffff) == 0))
781 return 0;
782
783 /*
784 * If x and y have different signs we can tell that they're not equal
785 * If x is +ve we have x > y return 1 - otherwise y is +ve return -1
786 */
787 if ((x[0] >> 31) != (y[0] >> 31))
788 return ((x[0] >> 31) == 0) - ((y[0] >> 31) == 0);
789
790 /*
791 * Now we have both signs the same, let's do an initial compare of the
792 * values.
793 *
794 * Whoever designed IEEE754's floating point formats is very clever and
795 * earns my undying admiration. Once you remove the sign-bit, the
796 * floating point numbers can be ordered using the standard <, ==, >
797 * operators will treating the fp-numbers as integers with that bit-
798 * pattern.
799 */
800 if ((x[0] & 0x7fffffff) < (y[0] & 0x7fffffff)) result = -1;
801 else if ((x[0] & 0x7fffffff) > (y[0] & 0x7fffffff)) result = 1;
802 else result = 0;
803
804 /*
805 * Now we return the result - is x is positive (and therefore so is y) we
806 * return the plain result - otherwise we negate it and return.
807 */
808 if ((x[0] >> 31) == 0) return result;
809 else return -result;
810 }
811
test_isgreater(uint32 * x,uint32 * y,uint32 * out)812 char *test_isgreater(uint32 *x, uint32 *y, uint32 *out)
813 {
814 int result = fpcmp4(x, y);
815 *out = (result == 1);
816 return result == -3 ? "i" : NULL;
817 }
818
test_isgreaterequal(uint32 * x,uint32 * y,uint32 * out)819 char *test_isgreaterequal(uint32 *x, uint32 *y, uint32 *out)
820 {
821 int result = fpcmp4(x, y);
822 *out = (result >= 0);
823 return result == -3 ? "i" : NULL;
824 }
825
test_isless(uint32 * x,uint32 * y,uint32 * out)826 char *test_isless(uint32 *x, uint32 *y, uint32 *out)
827 {
828 int result = fpcmp4(x, y);
829 *out = (result == -1);
830 return result == -3 ? "i" : NULL;
831 }
832
test_islessequal(uint32 * x,uint32 * y,uint32 * out)833 char *test_islessequal(uint32 *x, uint32 *y, uint32 *out)
834 {
835 int result = fpcmp4(x, y);
836 *out = (result == -1) || (result == 0);
837 return result == -3 ? "i" : NULL;
838 }
839
test_islessgreater(uint32 * x,uint32 * y,uint32 * out)840 char *test_islessgreater(uint32 *x, uint32 *y, uint32 *out)
841 {
842 int result = fpcmp4(x, y);
843 *out = (result == -1) || (result == 1);
844 return result == -3 ? "i" : NULL;
845 }
846
test_isunordered(uint32 * x,uint32 * y,uint32 * out)847 char *test_isunordered(uint32 *x, uint32 *y, uint32 *out)
848 {
849 int normal = 0;
850 int result = fpcmp4(x, y);
851
852 test_isnormal(x, out);
853 normal |= *out;
854 test_isnormal(y, out);
855 normal |= *out;
856 *out = (result == -2) || (result == -3);
857 return result == -3 ? "i" : NULL;
858 }
859
test_isgreaterf(uint32 * x,uint32 * y,uint32 * out)860 char *test_isgreaterf(uint32 *x, uint32 *y, uint32 *out)
861 {
862 int result = fpcmp4f(x, y);
863 *out = (result == 1);
864 return result == -3 ? "i" : NULL;
865 }
866
test_isgreaterequalf(uint32 * x,uint32 * y,uint32 * out)867 char *test_isgreaterequalf(uint32 *x, uint32 *y, uint32 *out)
868 {
869 int result = fpcmp4f(x, y);
870 *out = (result >= 0);
871 return result == -3 ? "i" : NULL;
872 }
873
test_islessf(uint32 * x,uint32 * y,uint32 * out)874 char *test_islessf(uint32 *x, uint32 *y, uint32 *out)
875 {
876 int result = fpcmp4f(x, y);
877 *out = (result == -1);
878 return result == -3 ? "i" : NULL;
879 }
880
test_islessequalf(uint32 * x,uint32 * y,uint32 * out)881 char *test_islessequalf(uint32 *x, uint32 *y, uint32 *out)
882 {
883 int result = fpcmp4f(x, y);
884 *out = (result == -1) || (result == 0);
885 return result == -3 ? "i" : NULL;
886 }
887
test_islessgreaterf(uint32 * x,uint32 * y,uint32 * out)888 char *test_islessgreaterf(uint32 *x, uint32 *y, uint32 *out)
889 {
890 int result = fpcmp4f(x, y);
891 *out = (result == -1) || (result == 1);
892 return result == -3 ? "i" : NULL;
893 }
894
test_isunorderedf(uint32 * x,uint32 * y,uint32 * out)895 char *test_isunorderedf(uint32 *x, uint32 *y, uint32 *out)
896 {
897 int normal = 0;
898 int result = fpcmp4f(x, y);
899
900 test_isnormalf(x, out);
901 normal |= *out;
902 test_isnormalf(y, out);
903 normal |= *out;
904 *out = (result == -2) || (result == -3);
905 return result == -3 ? "i" : NULL;
906 }
907