1 /* 2 * semi.c: test implementations of mathlib seminumerical functions 3 * 4 * Copyright (c) 1999-2019, Arm Limited. 5 * SPDX-License-Identifier: MIT 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