this repo has no description
at fixPythonPipStalling 1125 lines 45 kB view raw
1/* 2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22/******************************************************************************* 23* * 24* File: rndint.c * 25* * 26* Contains: C source code for implementations of floating-point * 27* functions which round to integral value or format, as * 28* defined in C99. In particular, this file contains * 29* implementations of the following functions: * 30* rint, nearbyint, rinttol, round, roundtol, trunc and modf. * 31* * 32* Copyright � 1992-2001 by Apple Computer, Inc. All rights reserved. * 33* * 34* Written by Jon Okada, started on December 1992. * 35* Modified by Paul Finlayson (PAF) for MathLib v2. * 36* Modified by A. Sazegari (ali) for MathLib v3. * 37* Modified and ported by Robert A. Murley (ram) for Mac OS X. * 38* * 39* A MathLib v4 file. * 40* * 41* Change History (most recent first): * 42* * 43* 06 Nov 01 ram commented out warning about Intel architectures. * 44* changed i386 stubs to call abort(). * 45* 02 Nov 01 ram added stubs for i386 routines. * 46* 08 Oct 01 ram removed <Limits.h> and <CoreServices/CoreServices.h>. * 47* changed compiler errors to warnings. * 48* 05 Oct 01 ram added defines for INT32_MAX and INT32_MIN * 49* 18 Sep 01 ali <CoreServices/CoreServices.h> replaced "fp.h" & "fenv.h". * 50* 10 Sep 01 ali added more comments. * 51* 09 Sep 01 ali added macros to detect PowerPC and correct compiler. * 52* 28 Aug 01 ram added #ifdef __ppc__. * 53* 13 Jul 01 ram Replaced __setflm with FEGETENVD/FESETENVD. * 54* replaced DblInHex typedef with hexdouble. * 55* 03 Mar 01 ali first port to os x using gcc, added the crucial * 56* __setflm definition. * 57* 1. removed double_t, put in double for now. * 58* 2. removed iclass from nearbyint. * 59* 3. removed wrong comments in trunc. * 60* 13 May 97 ali made performance improvements in rint, rinttol, * 61* roundtol and trunc by folding some of the taligent * 62* ideas into this implementation. nearbyint is faster * 63* than the one in taligent, rint is more elegant, but * 64* slower by %30 than the taligent one. * 65* 09 Apr 97 ali deleted modfl and deferred to AuxiliaryDD.c * 66* 15 Sep 94 ali Major overhaul and performance improvements of all * 67* functions. * 68* 20 Jul 94 PAF New faster version. * 69* 16 Jul 93 ali Added the modfl function. * 70* 18 Feb 93 ali Changed the return value of fenv functions * 71* feclearexcept and feraiseexcept to their new * 72* NCEG X3J11.1/93-001 definitions. * 73* 16 Dec 92 JPO Removed __itrunc implementation to a separate file. * 74* 15 Dec 92 JPO Added __itrunc implementation and modified rinttol * 75* to include conversion from double to long int format. * 76* Modified roundtol to call __itrunc. * 77* 10 Dec 92 JPO Added modf (double) implementation. * 78* 04 Dec 92 JPO First created. * 79* * 80* W A R N I N G: * 81* These routines require a 64-bit double precision IEEE-754 model. * 82* They are written for PowerPC only and are expecting the compiler * 83* to generate the correct sequence of multiply-add fused instructions. * 84* * 85* These routines are not intended for 32-bit Intel architectures. * 86* * 87* A version of gcc higher than 932 is required. * 88* * 89* GCC compiler options: * 90* optimization level 3 (-O3) * 91* -fschedule-insns -finline-functions -funroll-all-loops * 92* * 93*******************************************************************************/ 94 95#include "math.h" 96#include "fp_private.h" 97#include "fenv_private.h" 98#include "limits.h" 99 100 101static const hexdouble TOWARDZERO = HEXDOUBLE(0x00000000, 0x00000001); 102 103static const float twoTo23 = 0x1.0p+23f; // 8388608.0; 104 105#if !defined(BUILDING_FOR_CARBONCORE_LEGACY) 106 107static const double twoTo52 = 0x1.0p+52; // 4503599627370496.0; 108 109/******************************************************************************* 110* * 111* The function rint rounds its double argument to integral value * 112* according to the current rounding direction and returns the result in * 113* double format. This function signals inexact if an ordered return * 114* value is not equal to the operand. * 115* * 116*******************************************************************************/ 117 118/******************************************************************************* 119* First, an elegant implementation. * 120******************************************************************************** 121* 122*double rint ( double x ) 123* { 124* double y; 125* 126* y = twoTo52.fval; 127* 128* if ( fabs ( x ) >= y ) // huge case is exact 129* return x; 130* if ( x < 0 ) y = -y; // negative case 131* y = ( x + y ) - y; // force rounding 132* if ( y == 0.0 ) // zero results mirror sign of x 133* y = copysign ( y, x ); 134* return ( y ); 135* } 136******************************************************************************** 137* Now a bit twidling version that is about %30 faster. * 138*******************************************************************************/ 139 140double rint ( double x ) 141{ 142 hexdouble argument; 143 register double y; 144 uint32_t xHead; 145 register int target; 146 147 argument.d = x; 148 __NOOP; 149 __NOOP; 150 __NOOP; 151 152 xHead = argument.i.hi & 0x7fffffff; // xHead <- high half of |x| 153 target = ( argument.i.hi < 0x80000000 ); // flags positive sign 154 155 if (likely( xHead < 0x43300000u )) 156/******************************************************************************* 157* Is |x| < 2.0^52? * 158*******************************************************************************/ 159 { 160 if ( xHead < 0x3ff00000 ) 161/******************************************************************************* 162* Is |x| < 1.0? * 163*******************************************************************************/ 164 { 165 if ( target ) 166 y = ( x + twoTo52 ) - twoTo52; // round at binary point 167 else 168 y = ( x - twoTo52 ) + twoTo52; // round at binary point 169 if ( y == 0.0 ) 170 { // fix sign of zero result 171 if ( target ) 172 return ( 0.0 ); 173 else 174 return ( -0.0 ); 175 } 176 return y; 177 } 178 179/******************************************************************************* 180* Is 1.0 < |x| < 2.0^52? * 181*******************************************************************************/ 182 183 if ( target ) 184 return ( ( x + twoTo52 ) - twoTo52 ); // round at binary pt. 185 else 186 return ( ( x - twoTo52 ) + twoTo52 ); 187 } 188 189/******************************************************************************* 190* |x| >= 2.0^52 or x is a NaN. * 191*******************************************************************************/ 192 return ( x ); 193} 194 195float rintf ( float x ) 196{ 197 hexsingle argument; 198 register float y; 199 uint32_t xHead; 200 register int target; 201 202 argument.fval = x; 203 __NOOP; 204 __NOOP; 205 __NOOP; 206 207 xHead = argument.lval & 0x7fffffff; // xHead <- |x| 208 target = ( (uint32_t)argument.lval < 0x80000000u ); // flags positive sign 209 210 if (likely( xHead < 0x4b000000u )) 211/******************************************************************************* 212* Is |x| < 2.0^23? * 213*******************************************************************************/ 214 { 215 if ( xHead < 0x3f800000 ) 216/******************************************************************************* 217* Is |x| < 1.0? * 218*******************************************************************************/ 219 { 220 if ( target ) 221 y = ( x + twoTo23 ) - twoTo23; // round at binary point 222 else 223 y = ( x - twoTo23 ) + twoTo23; // round at binary point 224 if ( y == 0.0 ) 225 { // fix sign of zero result 226 if ( target ) 227 return ( 0.0f ); 228 else 229 { 230#if defined(__GNUC__) && (__GNUC__<3) /* workaround gcc2.x botch of -0 return. */ 231 volatile hexsingle zInHex; 232 zInHex.lval = 0x80000000; 233 return zInHex.fval; 234 235#else 236 return ( -0.0f ); 237#endif 238 } 239 } 240 return y; 241 } 242 243/******************************************************************************* 244* Is 1.0 < |x| < 2.0^23? * 245*******************************************************************************/ 246 247 if ( target ) 248 return ( ( x + twoTo23 ) - twoTo23 ); // round at binary pt. 249 else 250 return ( ( x - twoTo23 ) + twoTo23 ); 251 } 252 253/******************************************************************************* 254* |x| >= 2.0^23 or x is a NaN. * 255*******************************************************************************/ 256 return ( x ); 257} 258 259/******************************************************************************* 260* * 261* The function nearbyint rounds its double argument to integral value * 262* according to the current rounding direction and returns the result in * 263* double format. This function does not signal inexact. * 264* * 265* Functions used in this routine: * 266* fabs and copysign. * 267* * 268*******************************************************************************/ 269 270double nearbyint ( double x ) 271{ 272 double y, OldEnvironment; 273 274 if (unlikely(x != x)) 275 return x; 276 277 y = twoTo52; 278 279 FEGETENVD( OldEnvironment ); /* save the environement */ 280 281 if (unlikely( fabs ( x ) >= y )) /* huge case is exact */ 282 { 283 FESETENVD( OldEnvironment ); /* restore old environment */ 284 return x; 285 } 286 if ( x < 0 ) y = -y; /* negative case */ 287 y = ( x + y ) - y; /* force rounding */ 288 if ( y == 0.0 ) /* zero results mirror sign of x */ 289 y = copysign ( y, x ); 290 FESETENVD( OldEnvironment ); /* restore old environment */ 291 return ( y ); 292} 293 294float nearbyintf ( float x ) 295{ 296 double OldEnvironment; 297 float y; 298 299 if (unlikely(x != x)) 300 return x; 301 302 y = twoTo23; 303 304 FEGETENVD( OldEnvironment ); /* save the environement */ 305 306 if (unlikely( fabsf ( x ) >= y )) /* huge case is exact */ 307 { 308 FESETENVD( OldEnvironment ); /* restore old environment */ 309 return x; 310 } 311 if ( x < 0 ) y = -y; /* negative case */ 312 y = ( x + y ) - y; /* force rounding */ 313 if ( y == 0.0 ) /* zero results mirror sign of x */ 314 y = copysignf ( y, x ); 315 FESETENVD( OldEnvironment ); /* restore old environment */ 316 return ( y ); 317} 318 319long int lrint ( double x ) 320{ 321 if (sizeof(long int) == 4) // PPC32 ABI 322 { 323 hexdouble hx; 324 325 asm volatile ("fctiw %0,%1" : "=f"(hx.d) : "f"(x)); 326 __NOOP; 327 __NOOP; 328 __NOOP; 329 return hx.i.lo; 330 } 331 else // (sizeof(long int) == 8) LP64 ABI 332 { 333 union { double d; uint64_t i;} hx; 334 asm volatile ("fctid %0,%1" : "=f"(hx.d) : "f"(x)); 335 __NOOP; 336 __NOOP; 337 __NOOP; 338 return hx.i; 339 } 340} 341 342long int lrintf ( float x ) 343{ 344 if (sizeof(long int) == 4) // PPC32 ABI 345 { 346 hexdouble hx; 347 348 asm volatile ("fctiw %0,%1" : "=f"(hx.d) : "f"(x)); 349 __NOOP; 350 __NOOP; 351 __NOOP; 352 return hx.i.lo; 353 } 354 else // (sizeof(long int) == 8) LP64 ABI, PPC64 ISA 355 { 356 union { double d; uint64_t i;} hx; 357 asm volatile ("fctid %0,%1" : "=f"(hx.d) : "f"(x)); 358 __NOOP; 359 __NOOP; 360 __NOOP; 361 return hx.i; 362 } 363} 364 365long long int llrint ( double x ) 366{ 367 double t; 368 long long int result; 369 double fenv; 370 371 if (sizeof(long int) == 8) // LP64 ABI, PPC64 ISA 372 { 373 union { double d; uint64_t i;} hx; 374 asm volatile ("fctid %0,%1" : "=f"(hx.d) : "f"(x)); 375 __NOOP; 376 __NOOP; 377 __NOOP; 378 return hx.i; 379 } 380 381 if (unlikely(x != x)) 382 { 383 feraiseexcept(FE_INVALID); 384 return LONG_LONG_MIN; 385 } 386 387 FEGETENVD(fenv); 388 t = rint ( x ); 389 FESETENVD(fenv); 390 391 if ( t < (double)LONG_LONG_MIN ) 392 { 393 feraiseexcept(FE_INVALID); 394 result = LONG_LONG_MIN; 395 } 396 else if ( t > (double)LONG_LONG_MAX ) 397 { 398 feraiseexcept(FE_INVALID); 399 result = LONG_LONG_MAX; 400 } 401 else if (t != x) 402 { 403 feraiseexcept(FE_INEXACT); 404 result = (long long int) t; 405 } 406 else 407 { 408 result = (long long int) t; 409 } 410 411 return result; 412} 413 414long long int llrintf (float x) 415{ 416 float t; 417 long long int result; 418 double fenv; 419 420 if (sizeof(long int) == 8) // LP64 ABI, PPC64 ISA 421 { 422 union { double d; uint64_t i;} hx; 423 asm volatile ("fctid %0,%1" : "=f"(hx.d) : "f"(x)); 424 __NOOP; 425 __NOOP; 426 __NOOP; 427 return hx.i; 428 } 429 430 if (unlikely(x != x)) 431 { 432 feraiseexcept(FE_INVALID); 433 return LONG_LONG_MIN; 434 } 435 436 FEGETENVD(fenv); 437 t = rintf ( x ); 438 FESETENVD(fenv); 439 440 if ( t < (float)LONG_LONG_MIN ) 441 { 442 feraiseexcept(FE_INVALID); 443 result = LONG_LONG_MIN; 444 } 445 else if ( t > (float)LONG_LONG_MAX ) 446 { 447 feraiseexcept(FE_INVALID); 448 result = LONG_LONG_MAX; 449 } 450 else if (t != x) 451 { 452 feraiseexcept(FE_INEXACT); 453 result = (long long int) t; 454 } 455 else 456 { 457 result = (long long int) t; 458 } 459 460 return result; 461} 462 463/******************************************************************************* 464* * 465* The function round rounds its double argument to integral value * 466* according to the "add half to the magnitude and truncate" rounding of * 467* Pascal's Round function and FORTRAN's ANINT function and returns the * 468* result in double format. This function signals inexact if an ordered * 469* return value is not equal to the operand. * 470* * 471*******************************************************************************/ 472 473double round ( double x ) 474{ 475 hexdouble argument, OldEnvironment; 476 register double y, z; 477 uint32_t xHead; 478 register int target; 479 480 argument.d = x; 481 __NOOP; 482 __NOOP; 483 __NOOP; 484 485 xHead = argument.i.hi & 0x7fffffff; // xHead <- high half of |x| 486 target = ( argument.i.hi < 0x80000000 ); // flag positive sign 487 488 if (likely( xHead < 0x43300000u )) 489/******************************************************************************* 490* Is |x| < 2.0^52? * 491*******************************************************************************/ 492 { 493 if ( xHead < 0x3ff00000 ) 494/******************************************************************************* 495* Is |x| < 1.0? * 496*******************************************************************************/ 497 { 498 FEGETENVD( OldEnvironment.d ); // get environment 499 if ( xHead < 0x3fe00000u ) 500/******************************************************************************* 501* Is |x| < 0.5? * 502*******************************************************************************/ 503 { 504 if ( ( xHead | argument.i.lo ) != 0u ) 505 OldEnvironment.i.lo |= FE_INEXACT; 506 FESETENVD_GRP( OldEnvironment.d ); 507 if ( target ) 508 return ( 0.0 ); 509 else 510 return ( -0.0 ); 511 } 512/******************************************************************************* 513* Is 0.5 � |x| < 1.0? * 514*******************************************************************************/ 515 OldEnvironment.i.lo |= FE_INEXACT; 516 FESETENVD_GRP ( OldEnvironment.d ); 517 if ( target ) 518 return ( 1.0 ); 519 else 520 return ( -1.0 ); 521 } 522/******************************************************************************* 523* Is 1.0 < |x| < 2.0^52? * 524*******************************************************************************/ 525 if ( target ) 526 { // positive x 527 y = ( x + twoTo52 ) - twoTo52; // round at binary point 528 if ( y == x ) // exact case 529 return ( x ); 530 z = x + 0.5; // inexact case 531 y = ( z + twoTo52 ) - twoTo52; // round at binary point 532 if ( y > z ) 533 return ( y - 1.0 ); 534 else 535 return ( y ); 536 } 537 538/******************************************************************************* 539* Is x < 0? * 540*******************************************************************************/ 541 else 542 { 543 y = ( x - twoTo52 ) + twoTo52; // round at binary point 544 if ( y == x ) 545 return ( x ); 546 z = x - 0.5; 547 y = ( z - twoTo52 ) + twoTo52; // round at binary point 548 if ( y < z ) 549 return ( y + 1.0 ); 550 else 551 return ( y ); 552 } 553 } 554/******************************************************************************* 555* |x| >= 2.0^52 or x is a NaN. * 556*******************************************************************************/ 557 return ( x ); 558} 559 560float roundf ( float x ) 561{ 562 hexdouble OldEnvironment; 563 hexsingle argument; 564 register float y, z; 565 uint32_t xHead; 566 register int target; 567 568 argument.fval = x; 569 __NOOP; 570 __NOOP; 571 __NOOP; 572 573 xHead = argument.lval & 0x7fffffff; // xHead <- |x| 574 target = ( (uint32_t)argument.lval < 0x80000000u ); // flags positive sign 575 576 if (likely( xHead < 0x4b000000u )) 577/******************************************************************************* 578* Is |x| < 2.0^52? * 579*******************************************************************************/ 580 { 581 if ( xHead < 0x3f800000u ) 582/******************************************************************************* 583* Is |x| < 1.0? * 584*******************************************************************************/ 585 { 586 FEGETENVD( OldEnvironment.d ); // get environment 587 if ( xHead < 0x3f000000u ) 588/******************************************************************************* 589* Is |x| < 0.5? * 590*******************************************************************************/ 591 { 592 if ( xHead != 0u ) 593 OldEnvironment.i.lo |= FE_INEXACT; 594 FESETENVD_GRP( OldEnvironment.d ); 595 if ( target ) 596 return ( 0.0f ); 597 else 598 { 599#if defined(__GNUC__) && (__GNUC__<3) /* workaround gcc2.x botch of -0 return. */ 600 volatile hexsingle zInHex; 601 zInHex.lval = 0x80000000; 602 return zInHex.fval; 603 604#else 605 return ( -0.0f ); 606#endif 607 } 608 } 609/******************************************************************************* 610* Is 0.5 � |x| < 1.0? * 611*******************************************************************************/ 612 OldEnvironment.i.lo |= FE_INEXACT; 613 FESETENVD_GRP ( OldEnvironment.d ); 614 if ( target ) 615 return ( 1.0f ); 616 else 617 return ( -1.0f ); 618 } 619/******************************************************************************* 620* Is 1.0 < |x| < 2.0^23? * 621*******************************************************************************/ 622 if ( target ) 623 { // positive x 624 y = ( x + twoTo23 ) - twoTo23; // round at binary point 625 if ( y == x ) // exact case 626 return ( x ); 627 z = x + 0.5f; // inexact case 628 y = ( z + twoTo23 ) - twoTo23; // round at binary point 629 if ( y > z ) 630 return ( y - 1.0f ); 631 else 632 return ( y ); 633 } 634 635/******************************************************************************* 636* Is x < 0? * 637*******************************************************************************/ 638 else 639 { 640 y = ( x - twoTo23 ) + twoTo23; // round at binary point 641 if ( y == x ) 642 return ( x ); 643 z = x - 0.5f; 644 y = ( z - twoTo23 ) + twoTo23; // round at binary point 645 if ( y < z ) 646 return ( y + 1.0f ); 647 else 648 return ( y ); 649 } 650 } 651/******************************************************************************* 652* |x| >= 2.0^23 or x is a NaN. * 653*******************************************************************************/ 654 return ( x ); 655} 656 657/******************************************************************************* 658* * 659* The function roundtol converts its double argument to integral format * 660* according to the "add half to the magnitude and chop" rounding mode of * 661* Pascal's Round function and FORTRAN's NINT function. This conversion * 662* signals invalid if the argument is a NaN or the rounded intermediate * 663* result is out of range of the destination long int format, and it * 664* delivers an unspecified result in this case. This function signals * 665* inexact if the rounded result is within range of the long int format but * 666* unequal to the operand. * 667* * 668*******************************************************************************/ 669 670// These work just as well for the LP64 ABI 671long int lround ( double x ) 672{ 673 double t; 674 long int result; 675 double fenv; 676 677 if (unlikely(x != x)) 678 { 679 feraiseexcept(FE_INVALID); 680 return LONG_MAX; 681 } 682 683 FEGETENVD(fenv); 684 t = round ( x ); 685 FESETENVD(fenv); 686 687 if ( t < (double)LONG_MIN ) 688 { 689 feraiseexcept(FE_INVALID); 690 result = LONG_MIN; 691 } 692 else if ( t > (double)LONG_MAX ) 693 { 694 feraiseexcept(FE_INVALID); 695 result = LONG_MAX; 696 } 697 else if (t != x) 698 { 699 feraiseexcept(FE_INEXACT); 700 result = (long int) t; 701 } 702 else 703 { 704 result = (long int) t; 705 } 706 707 return result; 708} 709 710long int lroundf ( float x ) 711{ 712 float t; 713 long int result; 714 double fenv; 715 716 if (unlikely(x != x)) 717 { 718 feraiseexcept(FE_INVALID); 719 return LONG_MAX; 720 } 721 722 FEGETENVD(fenv); 723 t = roundf ( x ); 724 FESETENVD(fenv); 725 726 if ( t < (float)LONG_MIN ) 727 { 728 feraiseexcept(FE_INVALID); 729 result = LONG_MIN; 730 } 731 else if ( t > (float)LONG_MAX ) 732 { 733 feraiseexcept(FE_INVALID); 734 result = LONG_MAX; 735 } 736 else if (t != x) 737 { 738 feraiseexcept(FE_INEXACT); 739 result = (long int) t; 740 } 741 else 742 { 743 result = (long int) t; 744 } 745 746 return result; 747} 748 749long long int llround ( double x ) 750{ 751 double t; 752 long long int result; 753 double fenv; 754 755 if (unlikely(x != x)) 756 { 757 feraiseexcept(FE_INVALID); 758 return LONG_LONG_MAX; 759 } 760 761 FEGETENVD(fenv); 762 t = round ( x ); 763 FESETENVD(fenv); 764 765 if ( t < (double)LONG_LONG_MIN ) 766 { 767 feraiseexcept(FE_INVALID); 768 result = LONG_LONG_MIN; 769 } 770 else if ( t > (double)LONG_LONG_MAX ) 771 { 772 feraiseexcept(FE_INVALID); 773 result = LONG_LONG_MAX; 774 } 775 else if (t != x) 776 { 777 feraiseexcept(FE_INEXACT); 778 result = (long long int) t; 779 } 780 else 781 { 782 result = (long long int) t; 783 } 784 785 return result; 786} 787 788long long int llroundf ( float x ) 789{ 790 float t; 791 long long int result; 792 double fenv; 793 794 if (unlikely(x != x)) 795 { 796 feraiseexcept(FE_INVALID); 797 return LONG_LONG_MAX; 798 } 799 800 FEGETENVD(fenv); 801 t = roundf ( x ); 802 FESETENVD(fenv); 803 804 if ( t < (float)LONG_LONG_MIN ) 805 { 806 feraiseexcept(FE_INVALID); 807 result = LONG_LONG_MIN; 808 } 809 else if ( t > (float)LONG_LONG_MAX ) 810 { 811 feraiseexcept(FE_INVALID); 812 result = LONG_LONG_MAX; 813 } 814 else if (t != x) 815 { 816 feraiseexcept(FE_INEXACT); 817 result = (long long int) t; 818 } 819 else 820 { 821 result = (long long int) t; 822 } 823 824 return result; 825} 826 827/******************************************************************************* 828* * 829* The function trunc truncates its double argument to integral value * 830* and returns the result in double format. This function signals * 831* inexact if an ordered return value is not equal to the operand. * 832* * 833*******************************************************************************/ 834 835double trunc ( double x ) 836{ 837 hexdouble argument, OldEnvironment; 838 register double y; 839 uint32_t xhi; 840 register int target; 841 842 argument.d = x; 843 __NOOP; 844 __NOOP; 845 __NOOP; 846 xhi = argument.i.hi & 0x7fffffff; // xhi <- high half of |x| 847 target = ( argument.i.hi < 0x80000000 ); // flag positive sign 848 849 if (likely( xhi < 0x43300000u )) 850/******************************************************************************* 851* Is |x| < 2.0^52? * 852*******************************************************************************/ 853 { 854 if ( xhi < 0x3ff00000u ) 855/******************************************************************************* 856* Is |x| < 1.0? * 857*******************************************************************************/ 858 { 859 if ( ( xhi | argument.i.lo ) != 0u ) 860 { // raise deserved INEXACT 861 FEGETENVD_GRP( OldEnvironment.d ); 862 OldEnvironment.i.lo |= FE_INEXACT; 863 FESETENVD_GRP( OldEnvironment.d ); 864 } 865 if ( target ) // return properly signed zero 866 return ( 0.0 ); 867 else 868 return ( -0.0 ); 869 } 870/******************************************************************************* 871* Is 1.0 < |x| < 2.0^52? * 872*******************************************************************************/ 873 if ( target ) 874 { 875 y = ( x + twoTo52 ) - twoTo52; // round at binary point 876 if ( y > x ) 877 return ( y - 1.0 ); 878 else 879 return ( y ); 880 } 881 else 882 { 883 y = ( x - twoTo52 ) + twoTo52; // round at binary point. 884 if ( y < x ) 885 return ( y + 1.0 ); 886 else 887 return ( y ); 888 } 889 } 890/******************************************************************************* 891* Is |x| >= 2.0^52 or x is a NaN. * 892*******************************************************************************/ 893 return ( x ); 894} 895 896float truncf ( float x ) 897{ 898 hexdouble OldEnvironment; 899 hexsingle argument; 900 register float y; 901 uint32_t xhi; 902 register int target; 903 904 argument.fval = x; 905 __NOOP; 906 __NOOP; 907 __NOOP; 908 909 xhi = argument.lval & 0x7fffffff; // xhi <- |x| 910 target = ( (uint32_t)argument.lval < 0x80000000u ); // flags positive sign 911 912 if (likely( xhi < 0x4b000000u )) 913/******************************************************************************* 914* Is |x| < 2.0^23? * 915*******************************************************************************/ 916 { 917 if ( xhi < 0x3f800000 ) 918/******************************************************************************* 919* Is |x| < 1.0? * 920*******************************************************************************/ 921 { 922 if ( xhi != 0u ) 923 { // raise deserved INEXACT 924 FEGETENVD_GRP( OldEnvironment.d ); 925 OldEnvironment.i.lo |= FE_INEXACT; 926 FESETENVD_GRP( OldEnvironment.d ); 927 } 928 if ( target ) // return properly signed zero 929 return ( 0.0f ); 930 else 931 { 932#if defined(__GNUC__) && (__GNUC__<3) /* workaround gcc2.x botch of -0 return. */ 933 volatile hexsingle zInHex; 934 zInHex.lval = 0x80000000; 935 return zInHex.fval; 936 937#else 938 return ( -0.0f ); 939#endif 940 } 941 } 942/******************************************************************************* 943* Is 1.0 < |x| < 2.0^23? * 944*******************************************************************************/ 945 if ( target ) 946 { 947 y = ( x + twoTo23 ) - twoTo23; // round at binary point 948 if ( y > x ) 949 return ( y - 1.0f ); 950 else 951 return ( y ); 952 } 953 else 954 { 955 y = ( x - twoTo23 ) + twoTo23; // round at binary point. 956 if ( y < x ) 957 return ( y + 1.0f ); 958 else 959 return ( y ); 960 } 961 } 962/******************************************************************************* 963* Is |x| >= 2.0^23 or x is a NaN. * 964*******************************************************************************/ 965 return ( x ); 966} 967 968/******************************************************************************* 969* * 970* The modf family of functions separate a floating-point number into its * 971* fractional and integral parts, returning the fractional part and writing * 972* the integral part in floating-point format to the object pointed to by a * 973* pointer argument. If the input argument is integral or infinite in * 974* value, the return value is a zero with the sign of the input argument. * 975* The modf family of functions raises no floating-point exceptions. older * 976* implemenation set the INVALID flag due to signaling NaN input. * 977* * 978* modf is the double implementation. * 979* * 980*******************************************************************************/ 981 982double modf ( double x, double *iptr ) 983{ 984 register double OldEnvironment, xtrunc; 985 hexdouble argument; 986 987 register double FPR_negZero, FPR_zero, FPR_one, FPR_Two52, FPR_TowardZero, FPR_absx; 988 989 FPR_absx = __FABS( x ); FPR_Two52 = twoTo52; 990 FPR_one = 1.0; argument.d = x; 991 992 FPR_TowardZero = TOWARDZERO.d; FPR_zero = 0.0; 993 994 FPR_negZero = -0.0; __NOOP; 995 996 __ENSURE(FPR_zero, FPR_TowardZero, FPR_Two52); __ENSURE(FPR_zero, FPR_Two52, FPR_one); 997 998/******************************************************************************* 999* Is |x| < 2.0^52? * 1000*******************************************************************************/ 1001 if (likely( FPR_absx < FPR_Two52 )) 1002 { 1003/******************************************************************************* 1004* Is |x| < 1.0? * 1005*******************************************************************************/ 1006 if ( FPR_absx < FPR_one ) 1007 { 1008 if ( argument.i.hi & 0x80000000 ) // isolate sign bit 1009 *iptr = FPR_negZero; // truncate to zero 1010 else 1011 *iptr = FPR_zero; // truncate to zero 1012 return ( x ); 1013 } 1014/******************************************************************************* 1015* Is 1.0 < |x| < 2.0^52? * 1016*******************************************************************************/ 1017 FEGETENVD( OldEnvironment ); // save environment 1018 // round toward zero 1019 FESETENVD( FPR_TowardZero ); 1020 if ( x > FPR_zero ) // truncate to integer 1021 xtrunc = ( x + FPR_Two52 ) - FPR_Two52; 1022 else 1023 xtrunc = ( x - FPR_Two52 ) + FPR_Two52; 1024 *iptr = xtrunc; // store integral part 1025 // restore caller's env 1026 FESETENVD( OldEnvironment ); // restore environment 1027 if ( x != xtrunc ) // nonzero fraction 1028 return ( x - xtrunc ); 1029 else 1030 { // zero with x's sign 1031 if ( argument.i.hi & 0x80000000 ) // isolate sign bit 1032 return FPR_negZero; // truncate to zero 1033 else 1034 return FPR_zero; // truncate to zero 1035 } 1036 } 1037 1038 *iptr = x; // x is integral or NaN 1039 if ( x != x ) // NaN is returned 1040 return x; 1041 else 1042 { // zero with x's sign 1043 if ( argument.i.hi & 0x80000000 ) // isolate sign bit 1044 return FPR_negZero; // truncate to zero 1045 else 1046 return FPR_zero; // truncate to zero 1047 } 1048} 1049 1050#else /* BUILDING_FOR_CARBONCORE_LEGACY */ 1051 1052float modff ( float x, float *iptr ) 1053{ 1054 register double OldEnvironment; 1055 register float xtrunc; 1056 register uint32_t xHead, signBit; 1057 hexsingle argument; 1058 1059 argument.fval = x; 1060 __NOOP; 1061 __NOOP; 1062 __NOOP; 1063 1064 xHead = argument.lval & 0x7fffffff; // |x| high bit pattern 1065 signBit = ( argument.lval & 0x80000000 ); // isolate sign bit 1066 1067 if (likely( xHead < 0x4b000000u )) 1068/******************************************************************************* 1069* Is |x| < 2.0^23? * 1070*******************************************************************************/ 1071 { 1072 if ( xHead < 0x3f800000 ) 1073/******************************************************************************* 1074* Is |x| < 1.0? * 1075*******************************************************************************/ 1076 { 1077 argument.lval = signBit; // truncate to zero 1078 __NOOP; 1079 __NOOP; 1080 __NOOP; 1081 1082 *iptr = argument.fval; 1083 return ( x ); 1084 } 1085/******************************************************************************* 1086* Is 1.0 < |x| < 2.0^23? * 1087*******************************************************************************/ 1088 FEGETENVD( OldEnvironment ); // save environment 1089 // round toward zero 1090 FESETENVD( TOWARDZERO.d ); 1091 if ( signBit == 0u ) // truncate to integer 1092 xtrunc = ( x + twoTo23 ) - twoTo23; 1093 else 1094 xtrunc = ( x - twoTo23 ) + twoTo23; 1095 // restore caller's env 1096 FESETENVD( OldEnvironment ); // restore environment 1097 *iptr = xtrunc; // store integral part 1098 if ( x != xtrunc ) // nonzero fraction 1099 return ( x - xtrunc ); 1100 else 1101 { // zero with x's sign 1102 argument.lval = signBit; 1103 __NOOP; 1104 __NOOP; 1105 __NOOP; 1106 1107 return ( argument.fval ); 1108 } 1109 } 1110 1111 *iptr = x; // x is integral or NaN 1112 if ( x != x ) // NaN is returned 1113 return x; 1114 else 1115 { // zero with x's sign 1116 argument.lval = signBit; 1117 __NOOP; 1118 __NOOP; 1119 __NOOP; 1120 1121 return ( argument.fval ); 1122 } 1123} 1124 1125#endif /* BUILDING_FOR_CARBONCORE_LEGACY */