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