18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci=============================================================================== 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ciThis C source file is part of the SoftFloat IEC/IEEE Floating-point 58c2ecf20Sopenharmony_ciArithmetic Package, Release 2. 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ciWritten by John R. Hauser. This work was made possible in part by the 88c2ecf20Sopenharmony_ciInternational Computer Science Institute, located at Suite 600, 1947 Center 98c2ecf20Sopenharmony_ciStreet, Berkeley, California 94704. Funding was partially provided by the 108c2ecf20Sopenharmony_ciNational Science Foundation under grant MIP-9311980. The original version 118c2ecf20Sopenharmony_ciof this code was written as part of a project to build a fixed-point vector 128c2ecf20Sopenharmony_ciprocessor in collaboration with the University of California at Berkeley, 138c2ecf20Sopenharmony_cioverseen by Profs. Nelson Morgan and John Wawrzynek. More information 148c2ecf20Sopenharmony_ciis available through the web page 158c2ecf20Sopenharmony_cihttp://www.jhauser.us/arithmetic/SoftFloat-2b/SoftFloat-source.txt 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ciTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 188c2ecf20Sopenharmony_cihas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 198c2ecf20Sopenharmony_ciTIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 208c2ecf20Sopenharmony_ciPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 218c2ecf20Sopenharmony_ciAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ciDerivative works are acceptable, even for commercial purposes, so long as 248c2ecf20Sopenharmony_ci(1) they include prominent notice that the work is derivative, and (2) they 258c2ecf20Sopenharmony_ciinclude prominent notice akin to these three paragraphs for those parts of 268c2ecf20Sopenharmony_cithis code that are retained. 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci=============================================================================== 298c2ecf20Sopenharmony_ci*/ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include <asm/div64.h> 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include "fpa11.h" 348c2ecf20Sopenharmony_ci//#include "milieu.h" 358c2ecf20Sopenharmony_ci//#include "softfloat.h" 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci/* 388c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 398c2ecf20Sopenharmony_ciPrimitive arithmetic functions, including multi-word arithmetic, and 408c2ecf20Sopenharmony_cidivision and square root approximations. (Can be specialized to target if 418c2ecf20Sopenharmony_cidesired.) 428c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 438c2ecf20Sopenharmony_ci*/ 448c2ecf20Sopenharmony_ci#include "softfloat-macros" 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* 478c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 488c2ecf20Sopenharmony_ciFunctions and definitions to determine: (1) whether tininess for underflow 498c2ecf20Sopenharmony_ciis detected before or after rounding by default, (2) what (if anything) 508c2ecf20Sopenharmony_cihappens when exceptions are raised, (3) how signaling NaNs are distinguished 518c2ecf20Sopenharmony_cifrom quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs 528c2ecf20Sopenharmony_ciare propagated from function inputs to output. These details are target- 538c2ecf20Sopenharmony_cispecific. 548c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 558c2ecf20Sopenharmony_ci*/ 568c2ecf20Sopenharmony_ci#include "softfloat-specialize" 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* 598c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 608c2ecf20Sopenharmony_ciTakes a 64-bit fixed-point value `absZ' with binary point between bits 6 618c2ecf20Sopenharmony_ciand 7, and returns the properly rounded 32-bit integer corresponding to the 628c2ecf20Sopenharmony_ciinput. If `zSign' is nonzero, the input is negated before being converted 638c2ecf20Sopenharmony_cito an integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point 648c2ecf20Sopenharmony_ciinput is simply rounded to an integer, with the inexact exception raised if 658c2ecf20Sopenharmony_cithe input cannot be represented exactly as an integer. If the fixed-point 668c2ecf20Sopenharmony_ciinput is too large, however, the invalid exception is raised and the largest 678c2ecf20Sopenharmony_cipositive or negative integer is returned. 688c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 698c2ecf20Sopenharmony_ci*/ 708c2ecf20Sopenharmony_cistatic int32 roundAndPackInt32( struct roundingData *roundData, flag zSign, bits64 absZ ) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci int8 roundingMode; 738c2ecf20Sopenharmony_ci flag roundNearestEven; 748c2ecf20Sopenharmony_ci int8 roundIncrement, roundBits; 758c2ecf20Sopenharmony_ci int32 z; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci roundingMode = roundData->mode; 788c2ecf20Sopenharmony_ci roundNearestEven = ( roundingMode == float_round_nearest_even ); 798c2ecf20Sopenharmony_ci roundIncrement = 0x40; 808c2ecf20Sopenharmony_ci if ( ! roundNearestEven ) { 818c2ecf20Sopenharmony_ci if ( roundingMode == float_round_to_zero ) { 828c2ecf20Sopenharmony_ci roundIncrement = 0; 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci else { 858c2ecf20Sopenharmony_ci roundIncrement = 0x7F; 868c2ecf20Sopenharmony_ci if ( zSign ) { 878c2ecf20Sopenharmony_ci if ( roundingMode == float_round_up ) roundIncrement = 0; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci else { 908c2ecf20Sopenharmony_ci if ( roundingMode == float_round_down ) roundIncrement = 0; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci roundBits = absZ & 0x7F; 958c2ecf20Sopenharmony_ci absZ = ( absZ + roundIncrement )>>7; 968c2ecf20Sopenharmony_ci absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); 978c2ecf20Sopenharmony_ci z = absZ; 988c2ecf20Sopenharmony_ci if ( zSign ) z = - z; 998c2ecf20Sopenharmony_ci if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { 1008c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 1018c2ecf20Sopenharmony_ci return zSign ? 0x80000000 : 0x7FFFFFFF; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci if ( roundBits ) roundData->exception |= float_flag_inexact; 1048c2ecf20Sopenharmony_ci return z; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* 1098c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 1108c2ecf20Sopenharmony_ciReturns the fraction bits of the single-precision floating-point value `a'. 1118c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 1128c2ecf20Sopenharmony_ci*/ 1138c2ecf20Sopenharmony_ciINLINE bits32 extractFloat32Frac( float32 a ) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci return a & 0x007FFFFF; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/* 1218c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 1228c2ecf20Sopenharmony_ciReturns the exponent bits of the single-precision floating-point value `a'. 1238c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 1248c2ecf20Sopenharmony_ci*/ 1258c2ecf20Sopenharmony_ciINLINE int16 extractFloat32Exp( float32 a ) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci return ( a>>23 ) & 0xFF; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci/* 1338c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 1348c2ecf20Sopenharmony_ciReturns the sign bit of the single-precision floating-point value `a'. 1358c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 1368c2ecf20Sopenharmony_ci*/ 1378c2ecf20Sopenharmony_ci#if 0 /* in softfloat.h */ 1388c2ecf20Sopenharmony_ciINLINE flag extractFloat32Sign( float32 a ) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci return a>>31; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci#endif 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci/* 1478c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 1488c2ecf20Sopenharmony_ciNormalizes the subnormal single-precision floating-point value represented 1498c2ecf20Sopenharmony_ciby the denormalized significand `aSig'. The normalized exponent and 1508c2ecf20Sopenharmony_cisignificand are stored at the locations pointed to by `zExpPtr' and 1518c2ecf20Sopenharmony_ci`zSigPtr', respectively. 1528c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 1538c2ecf20Sopenharmony_ci*/ 1548c2ecf20Sopenharmony_cistatic void 1558c2ecf20Sopenharmony_ci normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci int8 shiftCount; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci shiftCount = countLeadingZeros32( aSig ) - 8; 1608c2ecf20Sopenharmony_ci *zSigPtr = aSig<<shiftCount; 1618c2ecf20Sopenharmony_ci *zExpPtr = 1 - shiftCount; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/* 1668c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 1678c2ecf20Sopenharmony_ciPacks the sign `zSign', exponent `zExp', and significand `zSig' into a 1688c2ecf20Sopenharmony_cisingle-precision floating-point value, returning the result. After being 1698c2ecf20Sopenharmony_cishifted into the proper positions, the three fields are simply added 1708c2ecf20Sopenharmony_citogether to form the result. This means that any integer portion of `zSig' 1718c2ecf20Sopenharmony_ciwill be added into the exponent. Since a properly normalized significand 1728c2ecf20Sopenharmony_ciwill have an integer portion equal to 1, the `zExp' input should be 1 less 1738c2ecf20Sopenharmony_cithan the desired result exponent whenever `zSig' is a complete, normalized 1748c2ecf20Sopenharmony_cisignificand. 1758c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 1768c2ecf20Sopenharmony_ci*/ 1778c2ecf20Sopenharmony_ciINLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig ) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci#if 0 1808c2ecf20Sopenharmony_ci float32 f; 1818c2ecf20Sopenharmony_ci __asm__("@ packFloat32 \n\ 1828c2ecf20Sopenharmony_ci mov %0, %1, asl #31 \n\ 1838c2ecf20Sopenharmony_ci orr %0, %2, asl #23 \n\ 1848c2ecf20Sopenharmony_ci orr %0, %3" 1858c2ecf20Sopenharmony_ci : /* no outputs */ 1868c2ecf20Sopenharmony_ci : "g" (f), "g" (zSign), "g" (zExp), "g" (zSig) 1878c2ecf20Sopenharmony_ci : "cc"); 1888c2ecf20Sopenharmony_ci return f; 1898c2ecf20Sopenharmony_ci#else 1908c2ecf20Sopenharmony_ci return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig; 1918c2ecf20Sopenharmony_ci#endif 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci/* 1958c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 1968c2ecf20Sopenharmony_ciTakes an abstract floating-point value having sign `zSign', exponent `zExp', 1978c2ecf20Sopenharmony_ciand significand `zSig', and returns the proper single-precision floating- 1988c2ecf20Sopenharmony_cipoint value corresponding to the abstract input. Ordinarily, the abstract 1998c2ecf20Sopenharmony_civalue is simply rounded and packed into the single-precision format, with 2008c2ecf20Sopenharmony_cithe inexact exception raised if the abstract input cannot be represented 2018c2ecf20Sopenharmony_ciexactly. If the abstract value is too large, however, the overflow and 2028c2ecf20Sopenharmony_ciinexact exceptions are raised and an infinity or maximal finite value is 2038c2ecf20Sopenharmony_cireturned. If the abstract value is too small, the input value is rounded to 2048c2ecf20Sopenharmony_cia subnormal number, and the underflow and inexact exceptions are raised if 2058c2ecf20Sopenharmony_cithe abstract input cannot be represented exactly as a subnormal single- 2068c2ecf20Sopenharmony_ciprecision floating-point number. 2078c2ecf20Sopenharmony_ci The input significand `zSig' has its binary point between bits 30 2088c2ecf20Sopenharmony_ciand 29, which is 7 bits to the left of the usual location. This shifted 2098c2ecf20Sopenharmony_cisignificand must be normalized or smaller. If `zSig' is not normalized, 2108c2ecf20Sopenharmony_ci`zExp' must be 0; in that case, the result returned is a subnormal number, 2118c2ecf20Sopenharmony_ciand it must not require rounding. In the usual case that `zSig' is 2128c2ecf20Sopenharmony_cinormalized, `zExp' must be 1 less than the ``true'' floating-point exponent. 2138c2ecf20Sopenharmony_ciThe handling of underflow and overflow follows the IEC/IEEE Standard for 2148c2ecf20Sopenharmony_ciBinary Floating-point Arithmetic. 2158c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 2168c2ecf20Sopenharmony_ci*/ 2178c2ecf20Sopenharmony_cistatic float32 roundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig ) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci int8 roundingMode; 2208c2ecf20Sopenharmony_ci flag roundNearestEven; 2218c2ecf20Sopenharmony_ci int8 roundIncrement, roundBits; 2228c2ecf20Sopenharmony_ci flag isTiny; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci roundingMode = roundData->mode; 2258c2ecf20Sopenharmony_ci roundNearestEven = ( roundingMode == float_round_nearest_even ); 2268c2ecf20Sopenharmony_ci roundIncrement = 0x40; 2278c2ecf20Sopenharmony_ci if ( ! roundNearestEven ) { 2288c2ecf20Sopenharmony_ci if ( roundingMode == float_round_to_zero ) { 2298c2ecf20Sopenharmony_ci roundIncrement = 0; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci else { 2328c2ecf20Sopenharmony_ci roundIncrement = 0x7F; 2338c2ecf20Sopenharmony_ci if ( zSign ) { 2348c2ecf20Sopenharmony_ci if ( roundingMode == float_round_up ) roundIncrement = 0; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci else { 2378c2ecf20Sopenharmony_ci if ( roundingMode == float_round_down ) roundIncrement = 0; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci roundBits = zSig & 0x7F; 2428c2ecf20Sopenharmony_ci if ( 0xFD <= (bits16) zExp ) { 2438c2ecf20Sopenharmony_ci if ( ( 0xFD < zExp ) 2448c2ecf20Sopenharmony_ci || ( ( zExp == 0xFD ) 2458c2ecf20Sopenharmony_ci && ( (sbits32) ( zSig + roundIncrement ) < 0 ) ) 2468c2ecf20Sopenharmony_ci ) { 2478c2ecf20Sopenharmony_ci roundData->exception |= float_flag_overflow | float_flag_inexact; 2488c2ecf20Sopenharmony_ci return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 ); 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci if ( zExp < 0 ) { 2518c2ecf20Sopenharmony_ci isTiny = 2528c2ecf20Sopenharmony_ci ( float_detect_tininess == float_tininess_before_rounding ) 2538c2ecf20Sopenharmony_ci || ( zExp < -1 ) 2548c2ecf20Sopenharmony_ci || ( zSig + roundIncrement < 0x80000000 ); 2558c2ecf20Sopenharmony_ci shift32RightJamming( zSig, - zExp, &zSig ); 2568c2ecf20Sopenharmony_ci zExp = 0; 2578c2ecf20Sopenharmony_ci roundBits = zSig & 0x7F; 2588c2ecf20Sopenharmony_ci if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci if ( roundBits ) roundData->exception |= float_flag_inexact; 2628c2ecf20Sopenharmony_ci zSig = ( zSig + roundIncrement )>>7; 2638c2ecf20Sopenharmony_ci zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); 2648c2ecf20Sopenharmony_ci if ( zSig == 0 ) zExp = 0; 2658c2ecf20Sopenharmony_ci return packFloat32( zSign, zExp, zSig ); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci/* 2708c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 2718c2ecf20Sopenharmony_ciTakes an abstract floating-point value having sign `zSign', exponent `zExp', 2728c2ecf20Sopenharmony_ciand significand `zSig', and returns the proper single-precision floating- 2738c2ecf20Sopenharmony_cipoint value corresponding to the abstract input. This routine is just like 2748c2ecf20Sopenharmony_ci`roundAndPackFloat32' except that `zSig' does not have to be normalized in 2758c2ecf20Sopenharmony_ciany way. In all cases, `zExp' must be 1 less than the ``true'' floating- 2768c2ecf20Sopenharmony_cipoint exponent. 2778c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 2788c2ecf20Sopenharmony_ci*/ 2798c2ecf20Sopenharmony_cistatic float32 2808c2ecf20Sopenharmony_ci normalizeRoundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig ) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci int8 shiftCount; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci shiftCount = countLeadingZeros32( zSig ) - 1; 2858c2ecf20Sopenharmony_ci return roundAndPackFloat32( roundData, zSign, zExp - shiftCount, zSig<<shiftCount ); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci/* 2908c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 2918c2ecf20Sopenharmony_ciReturns the fraction bits of the double-precision floating-point value `a'. 2928c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 2938c2ecf20Sopenharmony_ci*/ 2948c2ecf20Sopenharmony_ciINLINE bits64 extractFloat64Frac( float64 a ) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci return a & LIT64( 0x000FFFFFFFFFFFFF ); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci/* 3028c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 3038c2ecf20Sopenharmony_ciReturns the exponent bits of the double-precision floating-point value `a'. 3048c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 3058c2ecf20Sopenharmony_ci*/ 3068c2ecf20Sopenharmony_ciINLINE int16 extractFloat64Exp( float64 a ) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci return ( a>>52 ) & 0x7FF; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci/* 3148c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 3158c2ecf20Sopenharmony_ciReturns the sign bit of the double-precision floating-point value `a'. 3168c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 3178c2ecf20Sopenharmony_ci*/ 3188c2ecf20Sopenharmony_ci#if 0 /* in softfloat.h */ 3198c2ecf20Sopenharmony_ciINLINE flag extractFloat64Sign( float64 a ) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci return a>>63; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci#endif 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci/* 3288c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 3298c2ecf20Sopenharmony_ciNormalizes the subnormal double-precision floating-point value represented 3308c2ecf20Sopenharmony_ciby the denormalized significand `aSig'. The normalized exponent and 3318c2ecf20Sopenharmony_cisignificand are stored at the locations pointed to by `zExpPtr' and 3328c2ecf20Sopenharmony_ci`zSigPtr', respectively. 3338c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 3348c2ecf20Sopenharmony_ci*/ 3358c2ecf20Sopenharmony_cistatic void 3368c2ecf20Sopenharmony_ci normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci int8 shiftCount; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci shiftCount = countLeadingZeros64( aSig ) - 11; 3418c2ecf20Sopenharmony_ci *zSigPtr = aSig<<shiftCount; 3428c2ecf20Sopenharmony_ci *zExpPtr = 1 - shiftCount; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci/* 3478c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 3488c2ecf20Sopenharmony_ciPacks the sign `zSign', exponent `zExp', and significand `zSig' into a 3498c2ecf20Sopenharmony_cidouble-precision floating-point value, returning the result. After being 3508c2ecf20Sopenharmony_cishifted into the proper positions, the three fields are simply added 3518c2ecf20Sopenharmony_citogether to form the result. This means that any integer portion of `zSig' 3528c2ecf20Sopenharmony_ciwill be added into the exponent. Since a properly normalized significand 3538c2ecf20Sopenharmony_ciwill have an integer portion equal to 1, the `zExp' input should be 1 less 3548c2ecf20Sopenharmony_cithan the desired result exponent whenever `zSig' is a complete, normalized 3558c2ecf20Sopenharmony_cisignificand. 3568c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 3578c2ecf20Sopenharmony_ci*/ 3588c2ecf20Sopenharmony_ciINLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig ) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci return ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<52 ) + zSig; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci/* 3668c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 3678c2ecf20Sopenharmony_ciTakes an abstract floating-point value having sign `zSign', exponent `zExp', 3688c2ecf20Sopenharmony_ciand significand `zSig', and returns the proper double-precision floating- 3698c2ecf20Sopenharmony_cipoint value corresponding to the abstract input. Ordinarily, the abstract 3708c2ecf20Sopenharmony_civalue is simply rounded and packed into the double-precision format, with 3718c2ecf20Sopenharmony_cithe inexact exception raised if the abstract input cannot be represented 3728c2ecf20Sopenharmony_ciexactly. If the abstract value is too large, however, the overflow and 3738c2ecf20Sopenharmony_ciinexact exceptions are raised and an infinity or maximal finite value is 3748c2ecf20Sopenharmony_cireturned. If the abstract value is too small, the input value is rounded to 3758c2ecf20Sopenharmony_cia subnormal number, and the underflow and inexact exceptions are raised if 3768c2ecf20Sopenharmony_cithe abstract input cannot be represented exactly as a subnormal double- 3778c2ecf20Sopenharmony_ciprecision floating-point number. 3788c2ecf20Sopenharmony_ci The input significand `zSig' has its binary point between bits 62 3798c2ecf20Sopenharmony_ciand 61, which is 10 bits to the left of the usual location. This shifted 3808c2ecf20Sopenharmony_cisignificand must be normalized or smaller. If `zSig' is not normalized, 3818c2ecf20Sopenharmony_ci`zExp' must be 0; in that case, the result returned is a subnormal number, 3828c2ecf20Sopenharmony_ciand it must not require rounding. In the usual case that `zSig' is 3838c2ecf20Sopenharmony_cinormalized, `zExp' must be 1 less than the ``true'' floating-point exponent. 3848c2ecf20Sopenharmony_ciThe handling of underflow and overflow follows the IEC/IEEE Standard for 3858c2ecf20Sopenharmony_ciBinary Floating-point Arithmetic. 3868c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 3878c2ecf20Sopenharmony_ci*/ 3888c2ecf20Sopenharmony_cistatic float64 roundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig ) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci int8 roundingMode; 3918c2ecf20Sopenharmony_ci flag roundNearestEven; 3928c2ecf20Sopenharmony_ci int16 roundIncrement, roundBits; 3938c2ecf20Sopenharmony_ci flag isTiny; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci roundingMode = roundData->mode; 3968c2ecf20Sopenharmony_ci roundNearestEven = ( roundingMode == float_round_nearest_even ); 3978c2ecf20Sopenharmony_ci roundIncrement = 0x200; 3988c2ecf20Sopenharmony_ci if ( ! roundNearestEven ) { 3998c2ecf20Sopenharmony_ci if ( roundingMode == float_round_to_zero ) { 4008c2ecf20Sopenharmony_ci roundIncrement = 0; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci else { 4038c2ecf20Sopenharmony_ci roundIncrement = 0x3FF; 4048c2ecf20Sopenharmony_ci if ( zSign ) { 4058c2ecf20Sopenharmony_ci if ( roundingMode == float_round_up ) roundIncrement = 0; 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci else { 4088c2ecf20Sopenharmony_ci if ( roundingMode == float_round_down ) roundIncrement = 0; 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci roundBits = zSig & 0x3FF; 4138c2ecf20Sopenharmony_ci if ( 0x7FD <= (bits16) zExp ) { 4148c2ecf20Sopenharmony_ci if ( ( 0x7FD < zExp ) 4158c2ecf20Sopenharmony_ci || ( ( zExp == 0x7FD ) 4168c2ecf20Sopenharmony_ci && ( (sbits64) ( zSig + roundIncrement ) < 0 ) ) 4178c2ecf20Sopenharmony_ci ) { 4188c2ecf20Sopenharmony_ci //register int lr = __builtin_return_address(0); 4198c2ecf20Sopenharmony_ci //printk("roundAndPackFloat64 called from 0x%08x\n",lr); 4208c2ecf20Sopenharmony_ci roundData->exception |= float_flag_overflow | float_flag_inexact; 4218c2ecf20Sopenharmony_ci return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 ); 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci if ( zExp < 0 ) { 4248c2ecf20Sopenharmony_ci isTiny = 4258c2ecf20Sopenharmony_ci ( float_detect_tininess == float_tininess_before_rounding ) 4268c2ecf20Sopenharmony_ci || ( zExp < -1 ) 4278c2ecf20Sopenharmony_ci || ( zSig + roundIncrement < LIT64( 0x8000000000000000 ) ); 4288c2ecf20Sopenharmony_ci shift64RightJamming( zSig, - zExp, &zSig ); 4298c2ecf20Sopenharmony_ci zExp = 0; 4308c2ecf20Sopenharmony_ci roundBits = zSig & 0x3FF; 4318c2ecf20Sopenharmony_ci if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci if ( roundBits ) roundData->exception |= float_flag_inexact; 4358c2ecf20Sopenharmony_ci zSig = ( zSig + roundIncrement )>>10; 4368c2ecf20Sopenharmony_ci zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); 4378c2ecf20Sopenharmony_ci if ( zSig == 0 ) zExp = 0; 4388c2ecf20Sopenharmony_ci return packFloat64( zSign, zExp, zSig ); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci} 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci/* 4438c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 4448c2ecf20Sopenharmony_ciTakes an abstract floating-point value having sign `zSign', exponent `zExp', 4458c2ecf20Sopenharmony_ciand significand `zSig', and returns the proper double-precision floating- 4468c2ecf20Sopenharmony_cipoint value corresponding to the abstract input. This routine is just like 4478c2ecf20Sopenharmony_ci`roundAndPackFloat64' except that `zSig' does not have to be normalized in 4488c2ecf20Sopenharmony_ciany way. In all cases, `zExp' must be 1 less than the ``true'' floating- 4498c2ecf20Sopenharmony_cipoint exponent. 4508c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 4518c2ecf20Sopenharmony_ci*/ 4528c2ecf20Sopenharmony_cistatic float64 4538c2ecf20Sopenharmony_ci normalizeRoundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig ) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci int8 shiftCount; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci shiftCount = countLeadingZeros64( zSig ) - 1; 4588c2ecf20Sopenharmony_ci return roundAndPackFloat64( roundData, zSign, zExp - shiftCount, zSig<<shiftCount ); 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci#ifdef FLOATX80 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci/* 4658c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 4668c2ecf20Sopenharmony_ciReturns the fraction bits of the extended double-precision floating-point 4678c2ecf20Sopenharmony_civalue `a'. 4688c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 4698c2ecf20Sopenharmony_ci*/ 4708c2ecf20Sopenharmony_ciINLINE bits64 extractFloatx80Frac( floatx80 a ) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci return a.low; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci} 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci/* 4788c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 4798c2ecf20Sopenharmony_ciReturns the exponent bits of the extended double-precision floating-point 4808c2ecf20Sopenharmony_civalue `a'. 4818c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 4828c2ecf20Sopenharmony_ci*/ 4838c2ecf20Sopenharmony_ciINLINE int32 extractFloatx80Exp( floatx80 a ) 4848c2ecf20Sopenharmony_ci{ 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci return a.high & 0x7FFF; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci} 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci/* 4918c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 4928c2ecf20Sopenharmony_ciReturns the sign bit of the extended double-precision floating-point value 4938c2ecf20Sopenharmony_ci`a'. 4948c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 4958c2ecf20Sopenharmony_ci*/ 4968c2ecf20Sopenharmony_ciINLINE flag extractFloatx80Sign( floatx80 a ) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci return a.high>>15; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci/* 5048c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 5058c2ecf20Sopenharmony_ciNormalizes the subnormal extended double-precision floating-point value 5068c2ecf20Sopenharmony_cirepresented by the denormalized significand `aSig'. The normalized exponent 5078c2ecf20Sopenharmony_ciand significand are stored at the locations pointed to by `zExpPtr' and 5088c2ecf20Sopenharmony_ci`zSigPtr', respectively. 5098c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 5108c2ecf20Sopenharmony_ci*/ 5118c2ecf20Sopenharmony_cistatic void 5128c2ecf20Sopenharmony_ci normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr ) 5138c2ecf20Sopenharmony_ci{ 5148c2ecf20Sopenharmony_ci int8 shiftCount; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci shiftCount = countLeadingZeros64( aSig ); 5178c2ecf20Sopenharmony_ci *zSigPtr = aSig<<shiftCount; 5188c2ecf20Sopenharmony_ci *zExpPtr = 1 - shiftCount; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci} 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci/* 5238c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 5248c2ecf20Sopenharmony_ciPacks the sign `zSign', exponent `zExp', and significand `zSig' into an 5258c2ecf20Sopenharmony_ciextended double-precision floating-point value, returning the result. 5268c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 5278c2ecf20Sopenharmony_ci*/ 5288c2ecf20Sopenharmony_ciINLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig ) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci floatx80 z; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci z.low = zSig; 5338c2ecf20Sopenharmony_ci z.high = ( ( (bits16) zSign )<<15 ) + zExp; 5348c2ecf20Sopenharmony_ci z.__padding = 0; 5358c2ecf20Sopenharmony_ci return z; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci} 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci/* 5408c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 5418c2ecf20Sopenharmony_ciTakes an abstract floating-point value having sign `zSign', exponent `zExp', 5428c2ecf20Sopenharmony_ciand extended significand formed by the concatenation of `zSig0' and `zSig1', 5438c2ecf20Sopenharmony_ciand returns the proper extended double-precision floating-point value 5448c2ecf20Sopenharmony_cicorresponding to the abstract input. Ordinarily, the abstract value is 5458c2ecf20Sopenharmony_cirounded and packed into the extended double-precision format, with the 5468c2ecf20Sopenharmony_ciinexact exception raised if the abstract input cannot be represented 5478c2ecf20Sopenharmony_ciexactly. If the abstract value is too large, however, the overflow and 5488c2ecf20Sopenharmony_ciinexact exceptions are raised and an infinity or maximal finite value is 5498c2ecf20Sopenharmony_cireturned. If the abstract value is too small, the input value is rounded to 5508c2ecf20Sopenharmony_cia subnormal number, and the underflow and inexact exceptions are raised if 5518c2ecf20Sopenharmony_cithe abstract input cannot be represented exactly as a subnormal extended 5528c2ecf20Sopenharmony_cidouble-precision floating-point number. 5538c2ecf20Sopenharmony_ci If `roundingPrecision' is 32 or 64, the result is rounded to the same 5548c2ecf20Sopenharmony_cinumber of bits as single or double precision, respectively. Otherwise, the 5558c2ecf20Sopenharmony_ciresult is rounded to the full precision of the extended double-precision 5568c2ecf20Sopenharmony_ciformat. 5578c2ecf20Sopenharmony_ci The input significand must be normalized or smaller. If the input 5588c2ecf20Sopenharmony_cisignificand is not normalized, `zExp' must be 0; in that case, the result 5598c2ecf20Sopenharmony_cireturned is a subnormal number, and it must not require rounding. The 5608c2ecf20Sopenharmony_cihandling of underflow and overflow follows the IEC/IEEE Standard for Binary 5618c2ecf20Sopenharmony_ciFloating-point Arithmetic. 5628c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 5638c2ecf20Sopenharmony_ci*/ 5648c2ecf20Sopenharmony_cistatic floatx80 5658c2ecf20Sopenharmony_ci roundAndPackFloatx80( 5668c2ecf20Sopenharmony_ci struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 5678c2ecf20Sopenharmony_ci ) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci int8 roundingMode, roundingPrecision; 5708c2ecf20Sopenharmony_ci flag roundNearestEven, increment, isTiny; 5718c2ecf20Sopenharmony_ci int64 roundIncrement, roundMask, roundBits; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci roundingMode = roundData->mode; 5748c2ecf20Sopenharmony_ci roundingPrecision = roundData->precision; 5758c2ecf20Sopenharmony_ci roundNearestEven = ( roundingMode == float_round_nearest_even ); 5768c2ecf20Sopenharmony_ci if ( roundingPrecision == 80 ) goto precision80; 5778c2ecf20Sopenharmony_ci if ( roundingPrecision == 64 ) { 5788c2ecf20Sopenharmony_ci roundIncrement = LIT64( 0x0000000000000400 ); 5798c2ecf20Sopenharmony_ci roundMask = LIT64( 0x00000000000007FF ); 5808c2ecf20Sopenharmony_ci } 5818c2ecf20Sopenharmony_ci else if ( roundingPrecision == 32 ) { 5828c2ecf20Sopenharmony_ci roundIncrement = LIT64( 0x0000008000000000 ); 5838c2ecf20Sopenharmony_ci roundMask = LIT64( 0x000000FFFFFFFFFF ); 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci else { 5868c2ecf20Sopenharmony_ci goto precision80; 5878c2ecf20Sopenharmony_ci } 5888c2ecf20Sopenharmony_ci zSig0 |= ( zSig1 != 0 ); 5898c2ecf20Sopenharmony_ci if ( ! roundNearestEven ) { 5908c2ecf20Sopenharmony_ci if ( roundingMode == float_round_to_zero ) { 5918c2ecf20Sopenharmony_ci roundIncrement = 0; 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci else { 5948c2ecf20Sopenharmony_ci roundIncrement = roundMask; 5958c2ecf20Sopenharmony_ci if ( zSign ) { 5968c2ecf20Sopenharmony_ci if ( roundingMode == float_round_up ) roundIncrement = 0; 5978c2ecf20Sopenharmony_ci } 5988c2ecf20Sopenharmony_ci else { 5998c2ecf20Sopenharmony_ci if ( roundingMode == float_round_down ) roundIncrement = 0; 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci } 6038c2ecf20Sopenharmony_ci roundBits = zSig0 & roundMask; 6048c2ecf20Sopenharmony_ci if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) { 6058c2ecf20Sopenharmony_ci if ( ( 0x7FFE < zExp ) 6068c2ecf20Sopenharmony_ci || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) ) 6078c2ecf20Sopenharmony_ci ) { 6088c2ecf20Sopenharmony_ci goto overflow; 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci if ( zExp <= 0 ) { 6118c2ecf20Sopenharmony_ci isTiny = 6128c2ecf20Sopenharmony_ci ( float_detect_tininess == float_tininess_before_rounding ) 6138c2ecf20Sopenharmony_ci || ( zExp < 0 ) 6148c2ecf20Sopenharmony_ci || ( zSig0 <= zSig0 + roundIncrement ); 6158c2ecf20Sopenharmony_ci shift64RightJamming( zSig0, 1 - zExp, &zSig0 ); 6168c2ecf20Sopenharmony_ci zExp = 0; 6178c2ecf20Sopenharmony_ci roundBits = zSig0 & roundMask; 6188c2ecf20Sopenharmony_ci if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; 6198c2ecf20Sopenharmony_ci if ( roundBits ) roundData->exception |= float_flag_inexact; 6208c2ecf20Sopenharmony_ci zSig0 += roundIncrement; 6218c2ecf20Sopenharmony_ci if ( (sbits64) zSig0 < 0 ) zExp = 1; 6228c2ecf20Sopenharmony_ci roundIncrement = roundMask + 1; 6238c2ecf20Sopenharmony_ci if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) { 6248c2ecf20Sopenharmony_ci roundMask |= roundIncrement; 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci zSig0 &= ~ roundMask; 6278c2ecf20Sopenharmony_ci return packFloatx80( zSign, zExp, zSig0 ); 6288c2ecf20Sopenharmony_ci } 6298c2ecf20Sopenharmony_ci } 6308c2ecf20Sopenharmony_ci if ( roundBits ) roundData->exception |= float_flag_inexact; 6318c2ecf20Sopenharmony_ci zSig0 += roundIncrement; 6328c2ecf20Sopenharmony_ci if ( zSig0 < roundIncrement ) { 6338c2ecf20Sopenharmony_ci ++zExp; 6348c2ecf20Sopenharmony_ci zSig0 = LIT64( 0x8000000000000000 ); 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci roundIncrement = roundMask + 1; 6378c2ecf20Sopenharmony_ci if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) { 6388c2ecf20Sopenharmony_ci roundMask |= roundIncrement; 6398c2ecf20Sopenharmony_ci } 6408c2ecf20Sopenharmony_ci zSig0 &= ~ roundMask; 6418c2ecf20Sopenharmony_ci if ( zSig0 == 0 ) zExp = 0; 6428c2ecf20Sopenharmony_ci return packFloatx80( zSign, zExp, zSig0 ); 6438c2ecf20Sopenharmony_ci precision80: 6448c2ecf20Sopenharmony_ci increment = ( (sbits64) zSig1 < 0 ); 6458c2ecf20Sopenharmony_ci if ( ! roundNearestEven ) { 6468c2ecf20Sopenharmony_ci if ( roundingMode == float_round_to_zero ) { 6478c2ecf20Sopenharmony_ci increment = 0; 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci else { 6508c2ecf20Sopenharmony_ci if ( zSign ) { 6518c2ecf20Sopenharmony_ci increment = ( roundingMode == float_round_down ) && zSig1; 6528c2ecf20Sopenharmony_ci } 6538c2ecf20Sopenharmony_ci else { 6548c2ecf20Sopenharmony_ci increment = ( roundingMode == float_round_up ) && zSig1; 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci } 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) { 6598c2ecf20Sopenharmony_ci if ( ( 0x7FFE < zExp ) 6608c2ecf20Sopenharmony_ci || ( ( zExp == 0x7FFE ) 6618c2ecf20Sopenharmony_ci && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) ) 6628c2ecf20Sopenharmony_ci && increment 6638c2ecf20Sopenharmony_ci ) 6648c2ecf20Sopenharmony_ci ) { 6658c2ecf20Sopenharmony_ci roundMask = 0; 6668c2ecf20Sopenharmony_ci overflow: 6678c2ecf20Sopenharmony_ci roundData->exception |= float_flag_overflow | float_flag_inexact; 6688c2ecf20Sopenharmony_ci if ( ( roundingMode == float_round_to_zero ) 6698c2ecf20Sopenharmony_ci || ( zSign && ( roundingMode == float_round_up ) ) 6708c2ecf20Sopenharmony_ci || ( ! zSign && ( roundingMode == float_round_down ) ) 6718c2ecf20Sopenharmony_ci ) { 6728c2ecf20Sopenharmony_ci return packFloatx80( zSign, 0x7FFE, ~ roundMask ); 6738c2ecf20Sopenharmony_ci } 6748c2ecf20Sopenharmony_ci return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci if ( zExp <= 0 ) { 6778c2ecf20Sopenharmony_ci isTiny = 6788c2ecf20Sopenharmony_ci ( float_detect_tininess == float_tininess_before_rounding ) 6798c2ecf20Sopenharmony_ci || ( zExp < 0 ) 6808c2ecf20Sopenharmony_ci || ! increment 6818c2ecf20Sopenharmony_ci || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) ); 6828c2ecf20Sopenharmony_ci shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 ); 6838c2ecf20Sopenharmony_ci zExp = 0; 6848c2ecf20Sopenharmony_ci if ( isTiny && zSig1 ) roundData->exception |= float_flag_underflow; 6858c2ecf20Sopenharmony_ci if ( zSig1 ) roundData->exception |= float_flag_inexact; 6868c2ecf20Sopenharmony_ci if ( roundNearestEven ) { 6878c2ecf20Sopenharmony_ci increment = ( (sbits64) zSig1 < 0 ); 6888c2ecf20Sopenharmony_ci } 6898c2ecf20Sopenharmony_ci else { 6908c2ecf20Sopenharmony_ci if ( zSign ) { 6918c2ecf20Sopenharmony_ci increment = ( roundingMode == float_round_down ) && zSig1; 6928c2ecf20Sopenharmony_ci } 6938c2ecf20Sopenharmony_ci else { 6948c2ecf20Sopenharmony_ci increment = ( roundingMode == float_round_up ) && zSig1; 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci } 6978c2ecf20Sopenharmony_ci if ( increment ) { 6988c2ecf20Sopenharmony_ci ++zSig0; 6998c2ecf20Sopenharmony_ci zSig0 &= ~ ( ( zSig1 + zSig1 == 0 ) & roundNearestEven ); 7008c2ecf20Sopenharmony_ci if ( (sbits64) zSig0 < 0 ) zExp = 1; 7018c2ecf20Sopenharmony_ci } 7028c2ecf20Sopenharmony_ci return packFloatx80( zSign, zExp, zSig0 ); 7038c2ecf20Sopenharmony_ci } 7048c2ecf20Sopenharmony_ci } 7058c2ecf20Sopenharmony_ci if ( zSig1 ) roundData->exception |= float_flag_inexact; 7068c2ecf20Sopenharmony_ci if ( increment ) { 7078c2ecf20Sopenharmony_ci ++zSig0; 7088c2ecf20Sopenharmony_ci if ( zSig0 == 0 ) { 7098c2ecf20Sopenharmony_ci ++zExp; 7108c2ecf20Sopenharmony_ci zSig0 = LIT64( 0x8000000000000000 ); 7118c2ecf20Sopenharmony_ci } 7128c2ecf20Sopenharmony_ci else { 7138c2ecf20Sopenharmony_ci zSig0 &= ~ ( ( zSig1 + zSig1 == 0 ) & roundNearestEven ); 7148c2ecf20Sopenharmony_ci } 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci else { 7178c2ecf20Sopenharmony_ci if ( zSig0 == 0 ) zExp = 0; 7188c2ecf20Sopenharmony_ci } 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci return packFloatx80( zSign, zExp, zSig0 ); 7218c2ecf20Sopenharmony_ci} 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci/* 7248c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 7258c2ecf20Sopenharmony_ciTakes an abstract floating-point value having sign `zSign', exponent 7268c2ecf20Sopenharmony_ci`zExp', and significand formed by the concatenation of `zSig0' and `zSig1', 7278c2ecf20Sopenharmony_ciand returns the proper extended double-precision floating-point value 7288c2ecf20Sopenharmony_cicorresponding to the abstract input. This routine is just like 7298c2ecf20Sopenharmony_ci`roundAndPackFloatx80' except that the input significand does not have to be 7308c2ecf20Sopenharmony_cinormalized. 7318c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 7328c2ecf20Sopenharmony_ci*/ 7338c2ecf20Sopenharmony_cistatic floatx80 7348c2ecf20Sopenharmony_ci normalizeRoundAndPackFloatx80( 7358c2ecf20Sopenharmony_ci struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 7368c2ecf20Sopenharmony_ci ) 7378c2ecf20Sopenharmony_ci{ 7388c2ecf20Sopenharmony_ci int8 shiftCount; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci if ( zSig0 == 0 ) { 7418c2ecf20Sopenharmony_ci zSig0 = zSig1; 7428c2ecf20Sopenharmony_ci zSig1 = 0; 7438c2ecf20Sopenharmony_ci zExp -= 64; 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci shiftCount = countLeadingZeros64( zSig0 ); 7468c2ecf20Sopenharmony_ci shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); 7478c2ecf20Sopenharmony_ci zExp -= shiftCount; 7488c2ecf20Sopenharmony_ci return 7498c2ecf20Sopenharmony_ci roundAndPackFloatx80( roundData, zSign, zExp, zSig0, zSig1 ); 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci} 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci#endif 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci/* 7568c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 7578c2ecf20Sopenharmony_ciReturns the result of converting the 32-bit two's complement integer `a' to 7588c2ecf20Sopenharmony_cithe single-precision floating-point format. The conversion is performed 7598c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 7608c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 7618c2ecf20Sopenharmony_ci*/ 7628c2ecf20Sopenharmony_cifloat32 int32_to_float32(struct roundingData *roundData, int32 a) 7638c2ecf20Sopenharmony_ci{ 7648c2ecf20Sopenharmony_ci flag zSign; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci if ( a == 0 ) return 0; 7678c2ecf20Sopenharmony_ci if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 ); 7688c2ecf20Sopenharmony_ci zSign = ( a < 0 ); 7698c2ecf20Sopenharmony_ci return normalizeRoundAndPackFloat32( roundData, zSign, 0x9C, zSign ? - a : a ); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci} 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci/* 7748c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 7758c2ecf20Sopenharmony_ciReturns the result of converting the 32-bit two's complement integer `a' to 7768c2ecf20Sopenharmony_cithe double-precision floating-point format. The conversion is performed 7778c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 7788c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 7798c2ecf20Sopenharmony_ci*/ 7808c2ecf20Sopenharmony_cifloat64 int32_to_float64( int32 a ) 7818c2ecf20Sopenharmony_ci{ 7828c2ecf20Sopenharmony_ci flag aSign; 7838c2ecf20Sopenharmony_ci uint32 absA; 7848c2ecf20Sopenharmony_ci int8 shiftCount; 7858c2ecf20Sopenharmony_ci bits64 zSig; 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci if ( a == 0 ) return 0; 7888c2ecf20Sopenharmony_ci aSign = ( a < 0 ); 7898c2ecf20Sopenharmony_ci absA = aSign ? - a : a; 7908c2ecf20Sopenharmony_ci shiftCount = countLeadingZeros32( absA ) + 21; 7918c2ecf20Sopenharmony_ci zSig = absA; 7928c2ecf20Sopenharmony_ci return packFloat64( aSign, 0x432 - shiftCount, zSig<<shiftCount ); 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci} 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci#ifdef FLOATX80 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci/* 7998c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 8008c2ecf20Sopenharmony_ciReturns the result of converting the 32-bit two's complement integer `a' 8018c2ecf20Sopenharmony_cito the extended double-precision floating-point format. The conversion 8028c2ecf20Sopenharmony_ciis performed according to the IEC/IEEE Standard for Binary Floating-point 8038c2ecf20Sopenharmony_ciArithmetic. 8048c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 8058c2ecf20Sopenharmony_ci*/ 8068c2ecf20Sopenharmony_cifloatx80 int32_to_floatx80( int32 a ) 8078c2ecf20Sopenharmony_ci{ 8088c2ecf20Sopenharmony_ci flag zSign; 8098c2ecf20Sopenharmony_ci uint32 absA; 8108c2ecf20Sopenharmony_ci int8 shiftCount; 8118c2ecf20Sopenharmony_ci bits64 zSig; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci if ( a == 0 ) return packFloatx80( 0, 0, 0 ); 8148c2ecf20Sopenharmony_ci zSign = ( a < 0 ); 8158c2ecf20Sopenharmony_ci absA = zSign ? - a : a; 8168c2ecf20Sopenharmony_ci shiftCount = countLeadingZeros32( absA ) + 32; 8178c2ecf20Sopenharmony_ci zSig = absA; 8188c2ecf20Sopenharmony_ci return packFloatx80( zSign, 0x403E - shiftCount, zSig<<shiftCount ); 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci} 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci#endif 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci/* 8258c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 8268c2ecf20Sopenharmony_ciReturns the result of converting the single-precision floating-point value 8278c2ecf20Sopenharmony_ci`a' to the 32-bit two's complement integer format. The conversion is 8288c2ecf20Sopenharmony_ciperformed according to the IEC/IEEE Standard for Binary Floating-point 8298c2ecf20Sopenharmony_ciArithmetic---which means in particular that the conversion is rounded 8308c2ecf20Sopenharmony_ciaccording to the current rounding mode. If `a' is a NaN, the largest 8318c2ecf20Sopenharmony_cipositive integer is returned. Otherwise, if the conversion overflows, the 8328c2ecf20Sopenharmony_cilargest integer with the same sign as `a' is returned. 8338c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 8348c2ecf20Sopenharmony_ci*/ 8358c2ecf20Sopenharmony_ciint32 float32_to_int32( struct roundingData *roundData, float32 a ) 8368c2ecf20Sopenharmony_ci{ 8378c2ecf20Sopenharmony_ci flag aSign; 8388c2ecf20Sopenharmony_ci int16 aExp, shiftCount; 8398c2ecf20Sopenharmony_ci bits32 aSig; 8408c2ecf20Sopenharmony_ci bits64 zSig; 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci aSig = extractFloat32Frac( a ); 8438c2ecf20Sopenharmony_ci aExp = extractFloat32Exp( a ); 8448c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 8458c2ecf20Sopenharmony_ci if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; 8468c2ecf20Sopenharmony_ci if ( aExp ) aSig |= 0x00800000; 8478c2ecf20Sopenharmony_ci shiftCount = 0xAF - aExp; 8488c2ecf20Sopenharmony_ci zSig = aSig; 8498c2ecf20Sopenharmony_ci zSig <<= 32; 8508c2ecf20Sopenharmony_ci if ( 0 < shiftCount ) shift64RightJamming( zSig, shiftCount, &zSig ); 8518c2ecf20Sopenharmony_ci return roundAndPackInt32( roundData, aSign, zSig ); 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci} 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci/* 8568c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 8578c2ecf20Sopenharmony_ciReturns the result of converting the single-precision floating-point value 8588c2ecf20Sopenharmony_ci`a' to the 32-bit two's complement integer format. The conversion is 8598c2ecf20Sopenharmony_ciperformed according to the IEC/IEEE Standard for Binary Floating-point 8608c2ecf20Sopenharmony_ciArithmetic, except that the conversion is always rounded toward zero. If 8618c2ecf20Sopenharmony_ci`a' is a NaN, the largest positive integer is returned. Otherwise, if the 8628c2ecf20Sopenharmony_ciconversion overflows, the largest integer with the same sign as `a' is 8638c2ecf20Sopenharmony_cireturned. 8648c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 8658c2ecf20Sopenharmony_ci*/ 8668c2ecf20Sopenharmony_ciint32 float32_to_int32_round_to_zero( float32 a ) 8678c2ecf20Sopenharmony_ci{ 8688c2ecf20Sopenharmony_ci flag aSign; 8698c2ecf20Sopenharmony_ci int16 aExp, shiftCount; 8708c2ecf20Sopenharmony_ci bits32 aSig; 8718c2ecf20Sopenharmony_ci int32 z; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci aSig = extractFloat32Frac( a ); 8748c2ecf20Sopenharmony_ci aExp = extractFloat32Exp( a ); 8758c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 8768c2ecf20Sopenharmony_ci shiftCount = aExp - 0x9E; 8778c2ecf20Sopenharmony_ci if ( 0 <= shiftCount ) { 8788c2ecf20Sopenharmony_ci if ( a == 0xCF000000 ) return 0x80000000; 8798c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 8808c2ecf20Sopenharmony_ci if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF; 8818c2ecf20Sopenharmony_ci return 0x80000000; 8828c2ecf20Sopenharmony_ci } 8838c2ecf20Sopenharmony_ci else if ( aExp <= 0x7E ) { 8848c2ecf20Sopenharmony_ci if ( aExp | aSig ) float_raise( float_flag_inexact ); 8858c2ecf20Sopenharmony_ci return 0; 8868c2ecf20Sopenharmony_ci } 8878c2ecf20Sopenharmony_ci aSig = ( aSig | 0x00800000 )<<8; 8888c2ecf20Sopenharmony_ci z = aSig>>( - shiftCount ); 8898c2ecf20Sopenharmony_ci if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { 8908c2ecf20Sopenharmony_ci float_raise( float_flag_inexact ); 8918c2ecf20Sopenharmony_ci } 8928c2ecf20Sopenharmony_ci return aSign ? - z : z; 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci} 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci/* 8978c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 8988c2ecf20Sopenharmony_ciReturns the result of converting the single-precision floating-point value 8998c2ecf20Sopenharmony_ci`a' to the double-precision floating-point format. The conversion is 9008c2ecf20Sopenharmony_ciperformed according to the IEC/IEEE Standard for Binary Floating-point 9018c2ecf20Sopenharmony_ciArithmetic. 9028c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 9038c2ecf20Sopenharmony_ci*/ 9048c2ecf20Sopenharmony_cifloat64 float32_to_float64( float32 a ) 9058c2ecf20Sopenharmony_ci{ 9068c2ecf20Sopenharmony_ci flag aSign; 9078c2ecf20Sopenharmony_ci int16 aExp; 9088c2ecf20Sopenharmony_ci bits32 aSig; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci aSig = extractFloat32Frac( a ); 9118c2ecf20Sopenharmony_ci aExp = extractFloat32Exp( a ); 9128c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 9138c2ecf20Sopenharmony_ci if ( aExp == 0xFF ) { 9148c2ecf20Sopenharmony_ci if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) ); 9158c2ecf20Sopenharmony_ci return packFloat64( aSign, 0x7FF, 0 ); 9168c2ecf20Sopenharmony_ci } 9178c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 9188c2ecf20Sopenharmony_ci if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); 9198c2ecf20Sopenharmony_ci normalizeFloat32Subnormal( aSig, &aExp, &aSig ); 9208c2ecf20Sopenharmony_ci --aExp; 9218c2ecf20Sopenharmony_ci } 9228c2ecf20Sopenharmony_ci return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 ); 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci} 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci#ifdef FLOATX80 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci/* 9298c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 9308c2ecf20Sopenharmony_ciReturns the result of converting the single-precision floating-point value 9318c2ecf20Sopenharmony_ci`a' to the extended double-precision floating-point format. The conversion 9328c2ecf20Sopenharmony_ciis performed according to the IEC/IEEE Standard for Binary Floating-point 9338c2ecf20Sopenharmony_ciArithmetic. 9348c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 9358c2ecf20Sopenharmony_ci*/ 9368c2ecf20Sopenharmony_cifloatx80 float32_to_floatx80( float32 a ) 9378c2ecf20Sopenharmony_ci{ 9388c2ecf20Sopenharmony_ci flag aSign; 9398c2ecf20Sopenharmony_ci int16 aExp; 9408c2ecf20Sopenharmony_ci bits32 aSig; 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci aSig = extractFloat32Frac( a ); 9438c2ecf20Sopenharmony_ci aExp = extractFloat32Exp( a ); 9448c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 9458c2ecf20Sopenharmony_ci if ( aExp == 0xFF ) { 9468c2ecf20Sopenharmony_ci if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); 9478c2ecf20Sopenharmony_ci return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); 9488c2ecf20Sopenharmony_ci } 9498c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 9508c2ecf20Sopenharmony_ci if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); 9518c2ecf20Sopenharmony_ci normalizeFloat32Subnormal( aSig, &aExp, &aSig ); 9528c2ecf20Sopenharmony_ci } 9538c2ecf20Sopenharmony_ci aSig |= 0x00800000; 9548c2ecf20Sopenharmony_ci return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 ); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci} 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci#endif 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci/* 9618c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 9628c2ecf20Sopenharmony_ciRounds the single-precision floating-point value `a' to an integer, and 9638c2ecf20Sopenharmony_cireturns the result as a single-precision floating-point value. The 9648c2ecf20Sopenharmony_cioperation is performed according to the IEC/IEEE Standard for Binary 9658c2ecf20Sopenharmony_ciFloating-point Arithmetic. 9668c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 9678c2ecf20Sopenharmony_ci*/ 9688c2ecf20Sopenharmony_cifloat32 float32_round_to_int( struct roundingData *roundData, float32 a ) 9698c2ecf20Sopenharmony_ci{ 9708c2ecf20Sopenharmony_ci flag aSign; 9718c2ecf20Sopenharmony_ci int16 aExp; 9728c2ecf20Sopenharmony_ci bits32 lastBitMask, roundBitsMask; 9738c2ecf20Sopenharmony_ci int8 roundingMode; 9748c2ecf20Sopenharmony_ci float32 z; 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci aExp = extractFloat32Exp( a ); 9778c2ecf20Sopenharmony_ci if ( 0x96 <= aExp ) { 9788c2ecf20Sopenharmony_ci if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { 9798c2ecf20Sopenharmony_ci return propagateFloat32NaN( a, a ); 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_ci return a; 9828c2ecf20Sopenharmony_ci } 9838c2ecf20Sopenharmony_ci roundingMode = roundData->mode; 9848c2ecf20Sopenharmony_ci if ( aExp <= 0x7E ) { 9858c2ecf20Sopenharmony_ci if ( (bits32) ( a<<1 ) == 0 ) return a; 9868c2ecf20Sopenharmony_ci roundData->exception |= float_flag_inexact; 9878c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 9888c2ecf20Sopenharmony_ci switch ( roundingMode ) { 9898c2ecf20Sopenharmony_ci case float_round_nearest_even: 9908c2ecf20Sopenharmony_ci if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { 9918c2ecf20Sopenharmony_ci return packFloat32( aSign, 0x7F, 0 ); 9928c2ecf20Sopenharmony_ci } 9938c2ecf20Sopenharmony_ci break; 9948c2ecf20Sopenharmony_ci case float_round_down: 9958c2ecf20Sopenharmony_ci return aSign ? 0xBF800000 : 0; 9968c2ecf20Sopenharmony_ci case float_round_up: 9978c2ecf20Sopenharmony_ci return aSign ? 0x80000000 : 0x3F800000; 9988c2ecf20Sopenharmony_ci } 9998c2ecf20Sopenharmony_ci return packFloat32( aSign, 0, 0 ); 10008c2ecf20Sopenharmony_ci } 10018c2ecf20Sopenharmony_ci lastBitMask = 1; 10028c2ecf20Sopenharmony_ci lastBitMask <<= 0x96 - aExp; 10038c2ecf20Sopenharmony_ci roundBitsMask = lastBitMask - 1; 10048c2ecf20Sopenharmony_ci z = a; 10058c2ecf20Sopenharmony_ci if ( roundingMode == float_round_nearest_even ) { 10068c2ecf20Sopenharmony_ci z += lastBitMask>>1; 10078c2ecf20Sopenharmony_ci if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci else if ( roundingMode != float_round_to_zero ) { 10108c2ecf20Sopenharmony_ci if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) { 10118c2ecf20Sopenharmony_ci z += roundBitsMask; 10128c2ecf20Sopenharmony_ci } 10138c2ecf20Sopenharmony_ci } 10148c2ecf20Sopenharmony_ci z &= ~ roundBitsMask; 10158c2ecf20Sopenharmony_ci if ( z != a ) roundData->exception |= float_flag_inexact; 10168c2ecf20Sopenharmony_ci return z; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci} 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci/* 10218c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 10228c2ecf20Sopenharmony_ciReturns the result of adding the absolute values of the single-precision 10238c2ecf20Sopenharmony_cifloating-point values `a' and `b'. If `zSign' is true, the sum is negated 10248c2ecf20Sopenharmony_cibefore being returned. `zSign' is ignored if the result is a NaN. The 10258c2ecf20Sopenharmony_ciaddition is performed according to the IEC/IEEE Standard for Binary 10268c2ecf20Sopenharmony_ciFloating-point Arithmetic. 10278c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 10288c2ecf20Sopenharmony_ci*/ 10298c2ecf20Sopenharmony_cistatic float32 addFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign ) 10308c2ecf20Sopenharmony_ci{ 10318c2ecf20Sopenharmony_ci int16 aExp, bExp, zExp; 10328c2ecf20Sopenharmony_ci bits32 aSig, bSig, zSig; 10338c2ecf20Sopenharmony_ci int16 expDiff; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci aSig = extractFloat32Frac( a ); 10368c2ecf20Sopenharmony_ci aExp = extractFloat32Exp( a ); 10378c2ecf20Sopenharmony_ci bSig = extractFloat32Frac( b ); 10388c2ecf20Sopenharmony_ci bExp = extractFloat32Exp( b ); 10398c2ecf20Sopenharmony_ci expDiff = aExp - bExp; 10408c2ecf20Sopenharmony_ci aSig <<= 6; 10418c2ecf20Sopenharmony_ci bSig <<= 6; 10428c2ecf20Sopenharmony_ci if ( 0 < expDiff ) { 10438c2ecf20Sopenharmony_ci if ( aExp == 0xFF ) { 10448c2ecf20Sopenharmony_ci if ( aSig ) return propagateFloat32NaN( a, b ); 10458c2ecf20Sopenharmony_ci return a; 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 10488c2ecf20Sopenharmony_ci --expDiff; 10498c2ecf20Sopenharmony_ci } 10508c2ecf20Sopenharmony_ci else { 10518c2ecf20Sopenharmony_ci bSig |= 0x20000000; 10528c2ecf20Sopenharmony_ci } 10538c2ecf20Sopenharmony_ci shift32RightJamming( bSig, expDiff, &bSig ); 10548c2ecf20Sopenharmony_ci zExp = aExp; 10558c2ecf20Sopenharmony_ci } 10568c2ecf20Sopenharmony_ci else if ( expDiff < 0 ) { 10578c2ecf20Sopenharmony_ci if ( bExp == 0xFF ) { 10588c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat32NaN( a, b ); 10598c2ecf20Sopenharmony_ci return packFloat32( zSign, 0xFF, 0 ); 10608c2ecf20Sopenharmony_ci } 10618c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 10628c2ecf20Sopenharmony_ci ++expDiff; 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci else { 10658c2ecf20Sopenharmony_ci aSig |= 0x20000000; 10668c2ecf20Sopenharmony_ci } 10678c2ecf20Sopenharmony_ci shift32RightJamming( aSig, - expDiff, &aSig ); 10688c2ecf20Sopenharmony_ci zExp = bExp; 10698c2ecf20Sopenharmony_ci } 10708c2ecf20Sopenharmony_ci else { 10718c2ecf20Sopenharmony_ci if ( aExp == 0xFF ) { 10728c2ecf20Sopenharmony_ci if ( aSig | bSig ) return propagateFloat32NaN( a, b ); 10738c2ecf20Sopenharmony_ci return a; 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); 10768c2ecf20Sopenharmony_ci zSig = 0x40000000 + aSig + bSig; 10778c2ecf20Sopenharmony_ci zExp = aExp; 10788c2ecf20Sopenharmony_ci goto roundAndPack; 10798c2ecf20Sopenharmony_ci } 10808c2ecf20Sopenharmony_ci aSig |= 0x20000000; 10818c2ecf20Sopenharmony_ci zSig = ( aSig + bSig )<<1; 10828c2ecf20Sopenharmony_ci --zExp; 10838c2ecf20Sopenharmony_ci if ( (sbits32) zSig < 0 ) { 10848c2ecf20Sopenharmony_ci zSig = aSig + bSig; 10858c2ecf20Sopenharmony_ci ++zExp; 10868c2ecf20Sopenharmony_ci } 10878c2ecf20Sopenharmony_ci roundAndPack: 10888c2ecf20Sopenharmony_ci return roundAndPackFloat32( roundData, zSign, zExp, zSig ); 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci} 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci/* 10938c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 10948c2ecf20Sopenharmony_ciReturns the result of subtracting the absolute values of the single- 10958c2ecf20Sopenharmony_ciprecision floating-point values `a' and `b'. If `zSign' is true, the 10968c2ecf20Sopenharmony_cidifference is negated before being returned. `zSign' is ignored if the 10978c2ecf20Sopenharmony_ciresult is a NaN. The subtraction is performed according to the IEC/IEEE 10988c2ecf20Sopenharmony_ciStandard for Binary Floating-point Arithmetic. 10998c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 11008c2ecf20Sopenharmony_ci*/ 11018c2ecf20Sopenharmony_cistatic float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign ) 11028c2ecf20Sopenharmony_ci{ 11038c2ecf20Sopenharmony_ci int16 aExp, bExp, zExp; 11048c2ecf20Sopenharmony_ci bits32 aSig, bSig, zSig; 11058c2ecf20Sopenharmony_ci int16 expDiff; 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci aSig = extractFloat32Frac( a ); 11088c2ecf20Sopenharmony_ci aExp = extractFloat32Exp( a ); 11098c2ecf20Sopenharmony_ci bSig = extractFloat32Frac( b ); 11108c2ecf20Sopenharmony_ci bExp = extractFloat32Exp( b ); 11118c2ecf20Sopenharmony_ci expDiff = aExp - bExp; 11128c2ecf20Sopenharmony_ci aSig <<= 7; 11138c2ecf20Sopenharmony_ci bSig <<= 7; 11148c2ecf20Sopenharmony_ci if ( 0 < expDiff ) goto aExpBigger; 11158c2ecf20Sopenharmony_ci if ( expDiff < 0 ) goto bExpBigger; 11168c2ecf20Sopenharmony_ci if ( aExp == 0xFF ) { 11178c2ecf20Sopenharmony_ci if ( aSig | bSig ) return propagateFloat32NaN( a, b ); 11188c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 11198c2ecf20Sopenharmony_ci return float32_default_nan; 11208c2ecf20Sopenharmony_ci } 11218c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 11228c2ecf20Sopenharmony_ci aExp = 1; 11238c2ecf20Sopenharmony_ci bExp = 1; 11248c2ecf20Sopenharmony_ci } 11258c2ecf20Sopenharmony_ci if ( bSig < aSig ) goto aBigger; 11268c2ecf20Sopenharmony_ci if ( aSig < bSig ) goto bBigger; 11278c2ecf20Sopenharmony_ci return packFloat32( roundData->mode == float_round_down, 0, 0 ); 11288c2ecf20Sopenharmony_ci bExpBigger: 11298c2ecf20Sopenharmony_ci if ( bExp == 0xFF ) { 11308c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat32NaN( a, b ); 11318c2ecf20Sopenharmony_ci return packFloat32( zSign ^ 1, 0xFF, 0 ); 11328c2ecf20Sopenharmony_ci } 11338c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 11348c2ecf20Sopenharmony_ci ++expDiff; 11358c2ecf20Sopenharmony_ci } 11368c2ecf20Sopenharmony_ci else { 11378c2ecf20Sopenharmony_ci aSig |= 0x40000000; 11388c2ecf20Sopenharmony_ci } 11398c2ecf20Sopenharmony_ci shift32RightJamming( aSig, - expDiff, &aSig ); 11408c2ecf20Sopenharmony_ci bSig |= 0x40000000; 11418c2ecf20Sopenharmony_ci bBigger: 11428c2ecf20Sopenharmony_ci zSig = bSig - aSig; 11438c2ecf20Sopenharmony_ci zExp = bExp; 11448c2ecf20Sopenharmony_ci zSign ^= 1; 11458c2ecf20Sopenharmony_ci goto normalizeRoundAndPack; 11468c2ecf20Sopenharmony_ci aExpBigger: 11478c2ecf20Sopenharmony_ci if ( aExp == 0xFF ) { 11488c2ecf20Sopenharmony_ci if ( aSig ) return propagateFloat32NaN( a, b ); 11498c2ecf20Sopenharmony_ci return a; 11508c2ecf20Sopenharmony_ci } 11518c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 11528c2ecf20Sopenharmony_ci --expDiff; 11538c2ecf20Sopenharmony_ci } 11548c2ecf20Sopenharmony_ci else { 11558c2ecf20Sopenharmony_ci bSig |= 0x40000000; 11568c2ecf20Sopenharmony_ci } 11578c2ecf20Sopenharmony_ci shift32RightJamming( bSig, expDiff, &bSig ); 11588c2ecf20Sopenharmony_ci aSig |= 0x40000000; 11598c2ecf20Sopenharmony_ci aBigger: 11608c2ecf20Sopenharmony_ci zSig = aSig - bSig; 11618c2ecf20Sopenharmony_ci zExp = aExp; 11628c2ecf20Sopenharmony_ci normalizeRoundAndPack: 11638c2ecf20Sopenharmony_ci --zExp; 11648c2ecf20Sopenharmony_ci return normalizeRoundAndPackFloat32( roundData, zSign, zExp, zSig ); 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci} 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci/* 11698c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 11708c2ecf20Sopenharmony_ciReturns the result of adding the single-precision floating-point values `a' 11718c2ecf20Sopenharmony_ciand `b'. The operation is performed according to the IEC/IEEE Standard for 11728c2ecf20Sopenharmony_ciBinary Floating-point Arithmetic. 11738c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 11748c2ecf20Sopenharmony_ci*/ 11758c2ecf20Sopenharmony_cifloat32 float32_add( struct roundingData *roundData, float32 a, float32 b ) 11768c2ecf20Sopenharmony_ci{ 11778c2ecf20Sopenharmony_ci flag aSign, bSign; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 11808c2ecf20Sopenharmony_ci bSign = extractFloat32Sign( b ); 11818c2ecf20Sopenharmony_ci if ( aSign == bSign ) { 11828c2ecf20Sopenharmony_ci return addFloat32Sigs( roundData, a, b, aSign ); 11838c2ecf20Sopenharmony_ci } 11848c2ecf20Sopenharmony_ci else { 11858c2ecf20Sopenharmony_ci return subFloat32Sigs( roundData, a, b, aSign ); 11868c2ecf20Sopenharmony_ci } 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci} 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci/* 11918c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 11928c2ecf20Sopenharmony_ciReturns the result of subtracting the single-precision floating-point values 11938c2ecf20Sopenharmony_ci`a' and `b'. The operation is performed according to the IEC/IEEE Standard 11948c2ecf20Sopenharmony_cifor Binary Floating-point Arithmetic. 11958c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 11968c2ecf20Sopenharmony_ci*/ 11978c2ecf20Sopenharmony_cifloat32 float32_sub( struct roundingData *roundData, float32 a, float32 b ) 11988c2ecf20Sopenharmony_ci{ 11998c2ecf20Sopenharmony_ci flag aSign, bSign; 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 12028c2ecf20Sopenharmony_ci bSign = extractFloat32Sign( b ); 12038c2ecf20Sopenharmony_ci if ( aSign == bSign ) { 12048c2ecf20Sopenharmony_ci return subFloat32Sigs( roundData, a, b, aSign ); 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci else { 12078c2ecf20Sopenharmony_ci return addFloat32Sigs( roundData, a, b, aSign ); 12088c2ecf20Sopenharmony_ci } 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci} 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci/* 12138c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 12148c2ecf20Sopenharmony_ciReturns the result of multiplying the single-precision floating-point values 12158c2ecf20Sopenharmony_ci`a' and `b'. The operation is performed according to the IEC/IEEE Standard 12168c2ecf20Sopenharmony_cifor Binary Floating-point Arithmetic. 12178c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 12188c2ecf20Sopenharmony_ci*/ 12198c2ecf20Sopenharmony_cifloat32 float32_mul( struct roundingData *roundData, float32 a, float32 b ) 12208c2ecf20Sopenharmony_ci{ 12218c2ecf20Sopenharmony_ci flag aSign, bSign, zSign; 12228c2ecf20Sopenharmony_ci int16 aExp, bExp, zExp; 12238c2ecf20Sopenharmony_ci bits32 aSig, bSig; 12248c2ecf20Sopenharmony_ci bits64 zSig64; 12258c2ecf20Sopenharmony_ci bits32 zSig; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci aSig = extractFloat32Frac( a ); 12288c2ecf20Sopenharmony_ci aExp = extractFloat32Exp( a ); 12298c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 12308c2ecf20Sopenharmony_ci bSig = extractFloat32Frac( b ); 12318c2ecf20Sopenharmony_ci bExp = extractFloat32Exp( b ); 12328c2ecf20Sopenharmony_ci bSign = extractFloat32Sign( b ); 12338c2ecf20Sopenharmony_ci zSign = aSign ^ bSign; 12348c2ecf20Sopenharmony_ci if ( aExp == 0xFF ) { 12358c2ecf20Sopenharmony_ci if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { 12368c2ecf20Sopenharmony_ci return propagateFloat32NaN( a, b ); 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci if ( ( bExp | bSig ) == 0 ) { 12398c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 12408c2ecf20Sopenharmony_ci return float32_default_nan; 12418c2ecf20Sopenharmony_ci } 12428c2ecf20Sopenharmony_ci return packFloat32( zSign, 0xFF, 0 ); 12438c2ecf20Sopenharmony_ci } 12448c2ecf20Sopenharmony_ci if ( bExp == 0xFF ) { 12458c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat32NaN( a, b ); 12468c2ecf20Sopenharmony_ci if ( ( aExp | aSig ) == 0 ) { 12478c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 12488c2ecf20Sopenharmony_ci return float32_default_nan; 12498c2ecf20Sopenharmony_ci } 12508c2ecf20Sopenharmony_ci return packFloat32( zSign, 0xFF, 0 ); 12518c2ecf20Sopenharmony_ci } 12528c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 12538c2ecf20Sopenharmony_ci if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); 12548c2ecf20Sopenharmony_ci normalizeFloat32Subnormal( aSig, &aExp, &aSig ); 12558c2ecf20Sopenharmony_ci } 12568c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 12578c2ecf20Sopenharmony_ci if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); 12588c2ecf20Sopenharmony_ci normalizeFloat32Subnormal( bSig, &bExp, &bSig ); 12598c2ecf20Sopenharmony_ci } 12608c2ecf20Sopenharmony_ci zExp = aExp + bExp - 0x7F; 12618c2ecf20Sopenharmony_ci aSig = ( aSig | 0x00800000 )<<7; 12628c2ecf20Sopenharmony_ci bSig = ( bSig | 0x00800000 )<<8; 12638c2ecf20Sopenharmony_ci shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 ); 12648c2ecf20Sopenharmony_ci zSig = zSig64; 12658c2ecf20Sopenharmony_ci if ( 0 <= (sbits32) ( zSig<<1 ) ) { 12668c2ecf20Sopenharmony_ci zSig <<= 1; 12678c2ecf20Sopenharmony_ci --zExp; 12688c2ecf20Sopenharmony_ci } 12698c2ecf20Sopenharmony_ci return roundAndPackFloat32( roundData, zSign, zExp, zSig ); 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci} 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci/* 12748c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 12758c2ecf20Sopenharmony_ciReturns the result of dividing the single-precision floating-point value `a' 12768c2ecf20Sopenharmony_ciby the corresponding value `b'. The operation is performed according to the 12778c2ecf20Sopenharmony_ciIEC/IEEE Standard for Binary Floating-point Arithmetic. 12788c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 12798c2ecf20Sopenharmony_ci*/ 12808c2ecf20Sopenharmony_cifloat32 float32_div( struct roundingData *roundData, float32 a, float32 b ) 12818c2ecf20Sopenharmony_ci{ 12828c2ecf20Sopenharmony_ci flag aSign, bSign, zSign; 12838c2ecf20Sopenharmony_ci int16 aExp, bExp, zExp; 12848c2ecf20Sopenharmony_ci bits32 aSig, bSig, zSig; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci aSig = extractFloat32Frac( a ); 12878c2ecf20Sopenharmony_ci aExp = extractFloat32Exp( a ); 12888c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 12898c2ecf20Sopenharmony_ci bSig = extractFloat32Frac( b ); 12908c2ecf20Sopenharmony_ci bExp = extractFloat32Exp( b ); 12918c2ecf20Sopenharmony_ci bSign = extractFloat32Sign( b ); 12928c2ecf20Sopenharmony_ci zSign = aSign ^ bSign; 12938c2ecf20Sopenharmony_ci if ( aExp == 0xFF ) { 12948c2ecf20Sopenharmony_ci if ( aSig ) return propagateFloat32NaN( a, b ); 12958c2ecf20Sopenharmony_ci if ( bExp == 0xFF ) { 12968c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat32NaN( a, b ); 12978c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 12988c2ecf20Sopenharmony_ci return float32_default_nan; 12998c2ecf20Sopenharmony_ci } 13008c2ecf20Sopenharmony_ci return packFloat32( zSign, 0xFF, 0 ); 13018c2ecf20Sopenharmony_ci } 13028c2ecf20Sopenharmony_ci if ( bExp == 0xFF ) { 13038c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat32NaN( a, b ); 13048c2ecf20Sopenharmony_ci return packFloat32( zSign, 0, 0 ); 13058c2ecf20Sopenharmony_ci } 13068c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 13078c2ecf20Sopenharmony_ci if ( bSig == 0 ) { 13088c2ecf20Sopenharmony_ci if ( ( aExp | aSig ) == 0 ) { 13098c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 13108c2ecf20Sopenharmony_ci return float32_default_nan; 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci roundData->exception |= float_flag_divbyzero; 13138c2ecf20Sopenharmony_ci return packFloat32( zSign, 0xFF, 0 ); 13148c2ecf20Sopenharmony_ci } 13158c2ecf20Sopenharmony_ci normalizeFloat32Subnormal( bSig, &bExp, &bSig ); 13168c2ecf20Sopenharmony_ci } 13178c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 13188c2ecf20Sopenharmony_ci if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); 13198c2ecf20Sopenharmony_ci normalizeFloat32Subnormal( aSig, &aExp, &aSig ); 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci zExp = aExp - bExp + 0x7D; 13228c2ecf20Sopenharmony_ci aSig = ( aSig | 0x00800000 )<<7; 13238c2ecf20Sopenharmony_ci bSig = ( bSig | 0x00800000 )<<8; 13248c2ecf20Sopenharmony_ci if ( bSig <= ( aSig + aSig ) ) { 13258c2ecf20Sopenharmony_ci aSig >>= 1; 13268c2ecf20Sopenharmony_ci ++zExp; 13278c2ecf20Sopenharmony_ci } 13288c2ecf20Sopenharmony_ci { 13298c2ecf20Sopenharmony_ci bits64 tmp = ( (bits64) aSig )<<32; 13308c2ecf20Sopenharmony_ci do_div( tmp, bSig ); 13318c2ecf20Sopenharmony_ci zSig = tmp; 13328c2ecf20Sopenharmony_ci } 13338c2ecf20Sopenharmony_ci if ( ( zSig & 0x3F ) == 0 ) { 13348c2ecf20Sopenharmony_ci zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 ); 13358c2ecf20Sopenharmony_ci } 13368c2ecf20Sopenharmony_ci return roundAndPackFloat32( roundData, zSign, zExp, zSig ); 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci} 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci/* 13418c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 13428c2ecf20Sopenharmony_ciReturns the remainder of the single-precision floating-point value `a' 13438c2ecf20Sopenharmony_ciwith respect to the corresponding value `b'. The operation is performed 13448c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 13458c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 13468c2ecf20Sopenharmony_ci*/ 13478c2ecf20Sopenharmony_cifloat32 float32_rem( struct roundingData *roundData, float32 a, float32 b ) 13488c2ecf20Sopenharmony_ci{ 13498c2ecf20Sopenharmony_ci flag aSign, bSign, zSign; 13508c2ecf20Sopenharmony_ci int16 aExp, bExp, expDiff; 13518c2ecf20Sopenharmony_ci bits32 aSig, bSig; 13528c2ecf20Sopenharmony_ci bits32 q; 13538c2ecf20Sopenharmony_ci bits64 aSig64, bSig64, q64; 13548c2ecf20Sopenharmony_ci bits32 alternateASig; 13558c2ecf20Sopenharmony_ci sbits32 sigMean; 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci aSig = extractFloat32Frac( a ); 13588c2ecf20Sopenharmony_ci aExp = extractFloat32Exp( a ); 13598c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 13608c2ecf20Sopenharmony_ci bSig = extractFloat32Frac( b ); 13618c2ecf20Sopenharmony_ci bExp = extractFloat32Exp( b ); 13628c2ecf20Sopenharmony_ci bSign = extractFloat32Sign( b ); 13638c2ecf20Sopenharmony_ci if ( aExp == 0xFF ) { 13648c2ecf20Sopenharmony_ci if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { 13658c2ecf20Sopenharmony_ci return propagateFloat32NaN( a, b ); 13668c2ecf20Sopenharmony_ci } 13678c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 13688c2ecf20Sopenharmony_ci return float32_default_nan; 13698c2ecf20Sopenharmony_ci } 13708c2ecf20Sopenharmony_ci if ( bExp == 0xFF ) { 13718c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat32NaN( a, b ); 13728c2ecf20Sopenharmony_ci return a; 13738c2ecf20Sopenharmony_ci } 13748c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 13758c2ecf20Sopenharmony_ci if ( bSig == 0 ) { 13768c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 13778c2ecf20Sopenharmony_ci return float32_default_nan; 13788c2ecf20Sopenharmony_ci } 13798c2ecf20Sopenharmony_ci normalizeFloat32Subnormal( bSig, &bExp, &bSig ); 13808c2ecf20Sopenharmony_ci } 13818c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 13828c2ecf20Sopenharmony_ci if ( aSig == 0 ) return a; 13838c2ecf20Sopenharmony_ci normalizeFloat32Subnormal( aSig, &aExp, &aSig ); 13848c2ecf20Sopenharmony_ci } 13858c2ecf20Sopenharmony_ci expDiff = aExp - bExp; 13868c2ecf20Sopenharmony_ci aSig |= 0x00800000; 13878c2ecf20Sopenharmony_ci bSig |= 0x00800000; 13888c2ecf20Sopenharmony_ci if ( expDiff < 32 ) { 13898c2ecf20Sopenharmony_ci aSig <<= 8; 13908c2ecf20Sopenharmony_ci bSig <<= 8; 13918c2ecf20Sopenharmony_ci if ( expDiff < 0 ) { 13928c2ecf20Sopenharmony_ci if ( expDiff < -1 ) return a; 13938c2ecf20Sopenharmony_ci aSig >>= 1; 13948c2ecf20Sopenharmony_ci } 13958c2ecf20Sopenharmony_ci q = ( bSig <= aSig ); 13968c2ecf20Sopenharmony_ci if ( q ) aSig -= bSig; 13978c2ecf20Sopenharmony_ci if ( 0 < expDiff ) { 13988c2ecf20Sopenharmony_ci bits64 tmp = ( (bits64) aSig )<<32; 13998c2ecf20Sopenharmony_ci do_div( tmp, bSig ); 14008c2ecf20Sopenharmony_ci q = tmp; 14018c2ecf20Sopenharmony_ci q >>= 32 - expDiff; 14028c2ecf20Sopenharmony_ci bSig >>= 2; 14038c2ecf20Sopenharmony_ci aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; 14048c2ecf20Sopenharmony_ci } 14058c2ecf20Sopenharmony_ci else { 14068c2ecf20Sopenharmony_ci aSig >>= 2; 14078c2ecf20Sopenharmony_ci bSig >>= 2; 14088c2ecf20Sopenharmony_ci } 14098c2ecf20Sopenharmony_ci } 14108c2ecf20Sopenharmony_ci else { 14118c2ecf20Sopenharmony_ci if ( bSig <= aSig ) aSig -= bSig; 14128c2ecf20Sopenharmony_ci aSig64 = ( (bits64) aSig )<<40; 14138c2ecf20Sopenharmony_ci bSig64 = ( (bits64) bSig )<<40; 14148c2ecf20Sopenharmony_ci expDiff -= 64; 14158c2ecf20Sopenharmony_ci while ( 0 < expDiff ) { 14168c2ecf20Sopenharmony_ci q64 = estimateDiv128To64( aSig64, 0, bSig64 ); 14178c2ecf20Sopenharmony_ci q64 = ( 2 < q64 ) ? q64 - 2 : 0; 14188c2ecf20Sopenharmony_ci aSig64 = - ( ( bSig * q64 )<<38 ); 14198c2ecf20Sopenharmony_ci expDiff -= 62; 14208c2ecf20Sopenharmony_ci } 14218c2ecf20Sopenharmony_ci expDiff += 64; 14228c2ecf20Sopenharmony_ci q64 = estimateDiv128To64( aSig64, 0, bSig64 ); 14238c2ecf20Sopenharmony_ci q64 = ( 2 < q64 ) ? q64 - 2 : 0; 14248c2ecf20Sopenharmony_ci q = q64>>( 64 - expDiff ); 14258c2ecf20Sopenharmony_ci bSig <<= 6; 14268c2ecf20Sopenharmony_ci aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q; 14278c2ecf20Sopenharmony_ci } 14288c2ecf20Sopenharmony_ci do { 14298c2ecf20Sopenharmony_ci alternateASig = aSig; 14308c2ecf20Sopenharmony_ci ++q; 14318c2ecf20Sopenharmony_ci aSig -= bSig; 14328c2ecf20Sopenharmony_ci } while ( 0 <= (sbits32) aSig ); 14338c2ecf20Sopenharmony_ci sigMean = aSig + alternateASig; 14348c2ecf20Sopenharmony_ci if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { 14358c2ecf20Sopenharmony_ci aSig = alternateASig; 14368c2ecf20Sopenharmony_ci } 14378c2ecf20Sopenharmony_ci zSign = ( (sbits32) aSig < 0 ); 14388c2ecf20Sopenharmony_ci if ( zSign ) aSig = - aSig; 14398c2ecf20Sopenharmony_ci return normalizeRoundAndPackFloat32( roundData, aSign ^ zSign, bExp, aSig ); 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci} 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci/* 14448c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 14458c2ecf20Sopenharmony_ciReturns the square root of the single-precision floating-point value `a'. 14468c2ecf20Sopenharmony_ciThe operation is performed according to the IEC/IEEE Standard for Binary 14478c2ecf20Sopenharmony_ciFloating-point Arithmetic. 14488c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 14498c2ecf20Sopenharmony_ci*/ 14508c2ecf20Sopenharmony_cifloat32 float32_sqrt( struct roundingData *roundData, float32 a ) 14518c2ecf20Sopenharmony_ci{ 14528c2ecf20Sopenharmony_ci flag aSign; 14538c2ecf20Sopenharmony_ci int16 aExp, zExp; 14548c2ecf20Sopenharmony_ci bits32 aSig, zSig; 14558c2ecf20Sopenharmony_ci bits64 rem, term; 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci aSig = extractFloat32Frac( a ); 14588c2ecf20Sopenharmony_ci aExp = extractFloat32Exp( a ); 14598c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 14608c2ecf20Sopenharmony_ci if ( aExp == 0xFF ) { 14618c2ecf20Sopenharmony_ci if ( aSig ) return propagateFloat32NaN( a, 0 ); 14628c2ecf20Sopenharmony_ci if ( ! aSign ) return a; 14638c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 14648c2ecf20Sopenharmony_ci return float32_default_nan; 14658c2ecf20Sopenharmony_ci } 14668c2ecf20Sopenharmony_ci if ( aSign ) { 14678c2ecf20Sopenharmony_ci if ( ( aExp | aSig ) == 0 ) return a; 14688c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 14698c2ecf20Sopenharmony_ci return float32_default_nan; 14708c2ecf20Sopenharmony_ci } 14718c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 14728c2ecf20Sopenharmony_ci if ( aSig == 0 ) return 0; 14738c2ecf20Sopenharmony_ci normalizeFloat32Subnormal( aSig, &aExp, &aSig ); 14748c2ecf20Sopenharmony_ci } 14758c2ecf20Sopenharmony_ci zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; 14768c2ecf20Sopenharmony_ci aSig = ( aSig | 0x00800000 )<<8; 14778c2ecf20Sopenharmony_ci zSig = estimateSqrt32( aExp, aSig ) + 2; 14788c2ecf20Sopenharmony_ci if ( ( zSig & 0x7F ) <= 5 ) { 14798c2ecf20Sopenharmony_ci if ( zSig < 2 ) { 14808c2ecf20Sopenharmony_ci zSig = 0xFFFFFFFF; 14818c2ecf20Sopenharmony_ci } 14828c2ecf20Sopenharmony_ci else { 14838c2ecf20Sopenharmony_ci aSig >>= aExp & 1; 14848c2ecf20Sopenharmony_ci term = ( (bits64) zSig ) * zSig; 14858c2ecf20Sopenharmony_ci rem = ( ( (bits64) aSig )<<32 ) - term; 14868c2ecf20Sopenharmony_ci while ( (sbits64) rem < 0 ) { 14878c2ecf20Sopenharmony_ci --zSig; 14888c2ecf20Sopenharmony_ci rem += ( ( (bits64) zSig )<<1 ) | 1; 14898c2ecf20Sopenharmony_ci } 14908c2ecf20Sopenharmony_ci zSig |= ( rem != 0 ); 14918c2ecf20Sopenharmony_ci } 14928c2ecf20Sopenharmony_ci } 14938c2ecf20Sopenharmony_ci shift32RightJamming( zSig, 1, &zSig ); 14948c2ecf20Sopenharmony_ci return roundAndPackFloat32( roundData, 0, zExp, zSig ); 14958c2ecf20Sopenharmony_ci 14968c2ecf20Sopenharmony_ci} 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci/* 14998c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 15008c2ecf20Sopenharmony_ciReturns 1 if the single-precision floating-point value `a' is equal to the 15018c2ecf20Sopenharmony_cicorresponding value `b', and 0 otherwise. The comparison is performed 15028c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 15038c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 15048c2ecf20Sopenharmony_ci*/ 15058c2ecf20Sopenharmony_ciflag float32_eq( float32 a, float32 b ) 15068c2ecf20Sopenharmony_ci{ 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) 15098c2ecf20Sopenharmony_ci || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) 15108c2ecf20Sopenharmony_ci ) { 15118c2ecf20Sopenharmony_ci if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { 15128c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 15138c2ecf20Sopenharmony_ci } 15148c2ecf20Sopenharmony_ci return 0; 15158c2ecf20Sopenharmony_ci } 15168c2ecf20Sopenharmony_ci return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci} 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci/* 15218c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 15228c2ecf20Sopenharmony_ciReturns 1 if the single-precision floating-point value `a' is less than or 15238c2ecf20Sopenharmony_ciequal to the corresponding value `b', and 0 otherwise. The comparison is 15248c2ecf20Sopenharmony_ciperformed according to the IEC/IEEE Standard for Binary Floating-point 15258c2ecf20Sopenharmony_ciArithmetic. 15268c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 15278c2ecf20Sopenharmony_ci*/ 15288c2ecf20Sopenharmony_ciflag float32_le( float32 a, float32 b ) 15298c2ecf20Sopenharmony_ci{ 15308c2ecf20Sopenharmony_ci flag aSign, bSign; 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) 15338c2ecf20Sopenharmony_ci || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) 15348c2ecf20Sopenharmony_ci ) { 15358c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 15368c2ecf20Sopenharmony_ci return 0; 15378c2ecf20Sopenharmony_ci } 15388c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 15398c2ecf20Sopenharmony_ci bSign = extractFloat32Sign( b ); 15408c2ecf20Sopenharmony_ci if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); 15418c2ecf20Sopenharmony_ci return ( a == b ) || ( aSign ^ ( a < b ) ); 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci} 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci/* 15468c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 15478c2ecf20Sopenharmony_ciReturns 1 if the single-precision floating-point value `a' is less than 15488c2ecf20Sopenharmony_cithe corresponding value `b', and 0 otherwise. The comparison is performed 15498c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 15508c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 15518c2ecf20Sopenharmony_ci*/ 15528c2ecf20Sopenharmony_ciflag float32_lt( float32 a, float32 b ) 15538c2ecf20Sopenharmony_ci{ 15548c2ecf20Sopenharmony_ci flag aSign, bSign; 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) 15578c2ecf20Sopenharmony_ci || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) 15588c2ecf20Sopenharmony_ci ) { 15598c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 15608c2ecf20Sopenharmony_ci return 0; 15618c2ecf20Sopenharmony_ci } 15628c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 15638c2ecf20Sopenharmony_ci bSign = extractFloat32Sign( b ); 15648c2ecf20Sopenharmony_ci if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); 15658c2ecf20Sopenharmony_ci return ( a != b ) && ( aSign ^ ( a < b ) ); 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci} 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci/* 15708c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 15718c2ecf20Sopenharmony_ciReturns 1 if the single-precision floating-point value `a' is equal to the 15728c2ecf20Sopenharmony_cicorresponding value `b', and 0 otherwise. The invalid exception is raised 15738c2ecf20Sopenharmony_ciif either operand is a NaN. Otherwise, the comparison is performed 15748c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 15758c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 15768c2ecf20Sopenharmony_ci*/ 15778c2ecf20Sopenharmony_ciflag float32_eq_signaling( float32 a, float32 b ) 15788c2ecf20Sopenharmony_ci{ 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) 15818c2ecf20Sopenharmony_ci || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) 15828c2ecf20Sopenharmony_ci ) { 15838c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 15848c2ecf20Sopenharmony_ci return 0; 15858c2ecf20Sopenharmony_ci } 15868c2ecf20Sopenharmony_ci return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci} 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci/* 15918c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 15928c2ecf20Sopenharmony_ciReturns 1 if the single-precision floating-point value `a' is less than or 15938c2ecf20Sopenharmony_ciequal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not 15948c2ecf20Sopenharmony_cicause an exception. Otherwise, the comparison is performed according to the 15958c2ecf20Sopenharmony_ciIEC/IEEE Standard for Binary Floating-point Arithmetic. 15968c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 15978c2ecf20Sopenharmony_ci*/ 15988c2ecf20Sopenharmony_ciflag float32_le_quiet( float32 a, float32 b ) 15998c2ecf20Sopenharmony_ci{ 16008c2ecf20Sopenharmony_ci flag aSign, bSign; 16018c2ecf20Sopenharmony_ci //int16 aExp, bExp; 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) 16048c2ecf20Sopenharmony_ci || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) 16058c2ecf20Sopenharmony_ci ) { 16068c2ecf20Sopenharmony_ci /* Do nothing, even if NaN as we're quiet */ 16078c2ecf20Sopenharmony_ci return 0; 16088c2ecf20Sopenharmony_ci } 16098c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 16108c2ecf20Sopenharmony_ci bSign = extractFloat32Sign( b ); 16118c2ecf20Sopenharmony_ci if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); 16128c2ecf20Sopenharmony_ci return ( a == b ) || ( aSign ^ ( a < b ) ); 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci} 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci/* 16178c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 16188c2ecf20Sopenharmony_ciReturns 1 if the single-precision floating-point value `a' is less than 16198c2ecf20Sopenharmony_cithe corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an 16208c2ecf20Sopenharmony_ciexception. Otherwise, the comparison is performed according to the IEC/IEEE 16218c2ecf20Sopenharmony_ciStandard for Binary Floating-point Arithmetic. 16228c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 16238c2ecf20Sopenharmony_ci*/ 16248c2ecf20Sopenharmony_ciflag float32_lt_quiet( float32 a, float32 b ) 16258c2ecf20Sopenharmony_ci{ 16268c2ecf20Sopenharmony_ci flag aSign, bSign; 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) 16298c2ecf20Sopenharmony_ci || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) 16308c2ecf20Sopenharmony_ci ) { 16318c2ecf20Sopenharmony_ci /* Do nothing, even if NaN as we're quiet */ 16328c2ecf20Sopenharmony_ci return 0; 16338c2ecf20Sopenharmony_ci } 16348c2ecf20Sopenharmony_ci aSign = extractFloat32Sign( a ); 16358c2ecf20Sopenharmony_ci bSign = extractFloat32Sign( b ); 16368c2ecf20Sopenharmony_ci if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); 16378c2ecf20Sopenharmony_ci return ( a != b ) && ( aSign ^ ( a < b ) ); 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci} 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci/* 16428c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 16438c2ecf20Sopenharmony_ciReturns the result of converting the double-precision floating-point value 16448c2ecf20Sopenharmony_ci`a' to the 32-bit two's complement integer format. The conversion is 16458c2ecf20Sopenharmony_ciperformed according to the IEC/IEEE Standard for Binary Floating-point 16468c2ecf20Sopenharmony_ciArithmetic---which means in particular that the conversion is rounded 16478c2ecf20Sopenharmony_ciaccording to the current rounding mode. If `a' is a NaN, the largest 16488c2ecf20Sopenharmony_cipositive integer is returned. Otherwise, if the conversion overflows, the 16498c2ecf20Sopenharmony_cilargest integer with the same sign as `a' is returned. 16508c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 16518c2ecf20Sopenharmony_ci*/ 16528c2ecf20Sopenharmony_ciint32 float64_to_int32( struct roundingData *roundData, float64 a ) 16538c2ecf20Sopenharmony_ci{ 16548c2ecf20Sopenharmony_ci flag aSign; 16558c2ecf20Sopenharmony_ci int16 aExp, shiftCount; 16568c2ecf20Sopenharmony_ci bits64 aSig; 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 16598c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 16608c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 16618c2ecf20Sopenharmony_ci if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; 16628c2ecf20Sopenharmony_ci if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); 16638c2ecf20Sopenharmony_ci shiftCount = 0x42C - aExp; 16648c2ecf20Sopenharmony_ci if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); 16658c2ecf20Sopenharmony_ci return roundAndPackInt32( roundData, aSign, aSig ); 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci} 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci/* 16708c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 16718c2ecf20Sopenharmony_ciReturns the result of converting the double-precision floating-point value 16728c2ecf20Sopenharmony_ci`a' to the 32-bit two's complement integer format. The conversion is 16738c2ecf20Sopenharmony_ciperformed according to the IEC/IEEE Standard for Binary Floating-point 16748c2ecf20Sopenharmony_ciArithmetic, except that the conversion is always rounded toward zero. If 16758c2ecf20Sopenharmony_ci`a' is a NaN, the largest positive integer is returned. Otherwise, if the 16768c2ecf20Sopenharmony_ciconversion overflows, the largest integer with the same sign as `a' is 16778c2ecf20Sopenharmony_cireturned. 16788c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 16798c2ecf20Sopenharmony_ci*/ 16808c2ecf20Sopenharmony_ciint32 float64_to_int32_round_to_zero( float64 a ) 16818c2ecf20Sopenharmony_ci{ 16828c2ecf20Sopenharmony_ci flag aSign; 16838c2ecf20Sopenharmony_ci int16 aExp, shiftCount; 16848c2ecf20Sopenharmony_ci bits64 aSig, savedASig; 16858c2ecf20Sopenharmony_ci int32 z; 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 16888c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 16898c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 16908c2ecf20Sopenharmony_ci shiftCount = 0x433 - aExp; 16918c2ecf20Sopenharmony_ci if ( shiftCount < 21 ) { 16928c2ecf20Sopenharmony_ci if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; 16938c2ecf20Sopenharmony_ci goto invalid; 16948c2ecf20Sopenharmony_ci } 16958c2ecf20Sopenharmony_ci else if ( 52 < shiftCount ) { 16968c2ecf20Sopenharmony_ci if ( aExp || aSig ) float_raise( float_flag_inexact ); 16978c2ecf20Sopenharmony_ci return 0; 16988c2ecf20Sopenharmony_ci } 16998c2ecf20Sopenharmony_ci aSig |= LIT64( 0x0010000000000000 ); 17008c2ecf20Sopenharmony_ci savedASig = aSig; 17018c2ecf20Sopenharmony_ci aSig >>= shiftCount; 17028c2ecf20Sopenharmony_ci z = aSig; 17038c2ecf20Sopenharmony_ci if ( aSign ) z = - z; 17048c2ecf20Sopenharmony_ci if ( ( z < 0 ) ^ aSign ) { 17058c2ecf20Sopenharmony_ci invalid: 17068c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 17078c2ecf20Sopenharmony_ci return aSign ? 0x80000000 : 0x7FFFFFFF; 17088c2ecf20Sopenharmony_ci } 17098c2ecf20Sopenharmony_ci if ( ( aSig<<shiftCount ) != savedASig ) { 17108c2ecf20Sopenharmony_ci float_raise( float_flag_inexact ); 17118c2ecf20Sopenharmony_ci } 17128c2ecf20Sopenharmony_ci return z; 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci} 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci/* 17178c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 17188c2ecf20Sopenharmony_ciReturns the result of converting the double-precision floating-point value 17198c2ecf20Sopenharmony_ci`a' to the 32-bit two's complement unsigned integer format. The conversion 17208c2ecf20Sopenharmony_ciis performed according to the IEC/IEEE Standard for Binary Floating-point 17218c2ecf20Sopenharmony_ciArithmetic---which means in particular that the conversion is rounded 17228c2ecf20Sopenharmony_ciaccording to the current rounding mode. If `a' is a NaN, the largest 17238c2ecf20Sopenharmony_cipositive integer is returned. Otherwise, if the conversion overflows, the 17248c2ecf20Sopenharmony_cilargest positive integer is returned. 17258c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 17268c2ecf20Sopenharmony_ci*/ 17278c2ecf20Sopenharmony_ciint32 float64_to_uint32( struct roundingData *roundData, float64 a ) 17288c2ecf20Sopenharmony_ci{ 17298c2ecf20Sopenharmony_ci flag aSign; 17308c2ecf20Sopenharmony_ci int16 aExp, shiftCount; 17318c2ecf20Sopenharmony_ci bits64 aSig; 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 17348c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 17358c2ecf20Sopenharmony_ci aSign = 0; //extractFloat64Sign( a ); 17368c2ecf20Sopenharmony_ci //if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; 17378c2ecf20Sopenharmony_ci if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); 17388c2ecf20Sopenharmony_ci shiftCount = 0x42C - aExp; 17398c2ecf20Sopenharmony_ci if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); 17408c2ecf20Sopenharmony_ci return roundAndPackInt32( roundData, aSign, aSig ); 17418c2ecf20Sopenharmony_ci} 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci/* 17448c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 17458c2ecf20Sopenharmony_ciReturns the result of converting the double-precision floating-point value 17468c2ecf20Sopenharmony_ci`a' to the 32-bit two's complement integer format. The conversion is 17478c2ecf20Sopenharmony_ciperformed according to the IEC/IEEE Standard for Binary Floating-point 17488c2ecf20Sopenharmony_ciArithmetic, except that the conversion is always rounded toward zero. If 17498c2ecf20Sopenharmony_ci`a' is a NaN, the largest positive integer is returned. Otherwise, if the 17508c2ecf20Sopenharmony_ciconversion overflows, the largest positive integer is returned. 17518c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 17528c2ecf20Sopenharmony_ci*/ 17538c2ecf20Sopenharmony_ciint32 float64_to_uint32_round_to_zero( float64 a ) 17548c2ecf20Sopenharmony_ci{ 17558c2ecf20Sopenharmony_ci flag aSign; 17568c2ecf20Sopenharmony_ci int16 aExp, shiftCount; 17578c2ecf20Sopenharmony_ci bits64 aSig, savedASig; 17588c2ecf20Sopenharmony_ci int32 z; 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 17618c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 17628c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 17638c2ecf20Sopenharmony_ci shiftCount = 0x433 - aExp; 17648c2ecf20Sopenharmony_ci if ( shiftCount < 21 ) { 17658c2ecf20Sopenharmony_ci if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; 17668c2ecf20Sopenharmony_ci goto invalid; 17678c2ecf20Sopenharmony_ci } 17688c2ecf20Sopenharmony_ci else if ( 52 < shiftCount ) { 17698c2ecf20Sopenharmony_ci if ( aExp || aSig ) float_raise( float_flag_inexact ); 17708c2ecf20Sopenharmony_ci return 0; 17718c2ecf20Sopenharmony_ci } 17728c2ecf20Sopenharmony_ci aSig |= LIT64( 0x0010000000000000 ); 17738c2ecf20Sopenharmony_ci savedASig = aSig; 17748c2ecf20Sopenharmony_ci aSig >>= shiftCount; 17758c2ecf20Sopenharmony_ci z = aSig; 17768c2ecf20Sopenharmony_ci if ( aSign ) z = - z; 17778c2ecf20Sopenharmony_ci if ( ( z < 0 ) ^ aSign ) { 17788c2ecf20Sopenharmony_ci invalid: 17798c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 17808c2ecf20Sopenharmony_ci return aSign ? 0x80000000 : 0x7FFFFFFF; 17818c2ecf20Sopenharmony_ci } 17828c2ecf20Sopenharmony_ci if ( ( aSig<<shiftCount ) != savedASig ) { 17838c2ecf20Sopenharmony_ci float_raise( float_flag_inexact ); 17848c2ecf20Sopenharmony_ci } 17858c2ecf20Sopenharmony_ci return z; 17868c2ecf20Sopenharmony_ci} 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci/* 17898c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 17908c2ecf20Sopenharmony_ciReturns the result of converting the double-precision floating-point value 17918c2ecf20Sopenharmony_ci`a' to the single-precision floating-point format. The conversion is 17928c2ecf20Sopenharmony_ciperformed according to the IEC/IEEE Standard for Binary Floating-point 17938c2ecf20Sopenharmony_ciArithmetic. 17948c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 17958c2ecf20Sopenharmony_ci*/ 17968c2ecf20Sopenharmony_cifloat32 float64_to_float32( struct roundingData *roundData, float64 a ) 17978c2ecf20Sopenharmony_ci{ 17988c2ecf20Sopenharmony_ci flag aSign; 17998c2ecf20Sopenharmony_ci int16 aExp; 18008c2ecf20Sopenharmony_ci bits64 aSig; 18018c2ecf20Sopenharmony_ci bits32 zSig; 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 18048c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 18058c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 18068c2ecf20Sopenharmony_ci if ( aExp == 0x7FF ) { 18078c2ecf20Sopenharmony_ci if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) ); 18088c2ecf20Sopenharmony_ci return packFloat32( aSign, 0xFF, 0 ); 18098c2ecf20Sopenharmony_ci } 18108c2ecf20Sopenharmony_ci shift64RightJamming( aSig, 22, &aSig ); 18118c2ecf20Sopenharmony_ci zSig = aSig; 18128c2ecf20Sopenharmony_ci if ( aExp || zSig ) { 18138c2ecf20Sopenharmony_ci zSig |= 0x40000000; 18148c2ecf20Sopenharmony_ci aExp -= 0x381; 18158c2ecf20Sopenharmony_ci } 18168c2ecf20Sopenharmony_ci return roundAndPackFloat32( roundData, aSign, aExp, zSig ); 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci} 18198c2ecf20Sopenharmony_ci 18208c2ecf20Sopenharmony_ci#ifdef FLOATX80 18218c2ecf20Sopenharmony_ci 18228c2ecf20Sopenharmony_ci/* 18238c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 18248c2ecf20Sopenharmony_ciReturns the result of converting the double-precision floating-point value 18258c2ecf20Sopenharmony_ci`a' to the extended double-precision floating-point format. The conversion 18268c2ecf20Sopenharmony_ciis performed according to the IEC/IEEE Standard for Binary Floating-point 18278c2ecf20Sopenharmony_ciArithmetic. 18288c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 18298c2ecf20Sopenharmony_ci*/ 18308c2ecf20Sopenharmony_cifloatx80 float64_to_floatx80( float64 a ) 18318c2ecf20Sopenharmony_ci{ 18328c2ecf20Sopenharmony_ci flag aSign; 18338c2ecf20Sopenharmony_ci int16 aExp; 18348c2ecf20Sopenharmony_ci bits64 aSig; 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 18378c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 18388c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 18398c2ecf20Sopenharmony_ci if ( aExp == 0x7FF ) { 18408c2ecf20Sopenharmony_ci if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) ); 18418c2ecf20Sopenharmony_ci return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); 18428c2ecf20Sopenharmony_ci } 18438c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 18448c2ecf20Sopenharmony_ci if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); 18458c2ecf20Sopenharmony_ci normalizeFloat64Subnormal( aSig, &aExp, &aSig ); 18468c2ecf20Sopenharmony_ci } 18478c2ecf20Sopenharmony_ci return 18488c2ecf20Sopenharmony_ci packFloatx80( 18498c2ecf20Sopenharmony_ci aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); 18508c2ecf20Sopenharmony_ci 18518c2ecf20Sopenharmony_ci} 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci#endif 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci/* 18568c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 18578c2ecf20Sopenharmony_ciRounds the double-precision floating-point value `a' to an integer, and 18588c2ecf20Sopenharmony_cireturns the result as a double-precision floating-point value. The 18598c2ecf20Sopenharmony_cioperation is performed according to the IEC/IEEE Standard for Binary 18608c2ecf20Sopenharmony_ciFloating-point Arithmetic. 18618c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 18628c2ecf20Sopenharmony_ci*/ 18638c2ecf20Sopenharmony_cifloat64 float64_round_to_int( struct roundingData *roundData, float64 a ) 18648c2ecf20Sopenharmony_ci{ 18658c2ecf20Sopenharmony_ci flag aSign; 18668c2ecf20Sopenharmony_ci int16 aExp; 18678c2ecf20Sopenharmony_ci bits64 lastBitMask, roundBitsMask; 18688c2ecf20Sopenharmony_ci int8 roundingMode; 18698c2ecf20Sopenharmony_ci float64 z; 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 18728c2ecf20Sopenharmony_ci if ( 0x433 <= aExp ) { 18738c2ecf20Sopenharmony_ci if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { 18748c2ecf20Sopenharmony_ci return propagateFloat64NaN( a, a ); 18758c2ecf20Sopenharmony_ci } 18768c2ecf20Sopenharmony_ci return a; 18778c2ecf20Sopenharmony_ci } 18788c2ecf20Sopenharmony_ci if ( aExp <= 0x3FE ) { 18798c2ecf20Sopenharmony_ci if ( (bits64) ( a<<1 ) == 0 ) return a; 18808c2ecf20Sopenharmony_ci roundData->exception |= float_flag_inexact; 18818c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 18828c2ecf20Sopenharmony_ci switch ( roundData->mode ) { 18838c2ecf20Sopenharmony_ci case float_round_nearest_even: 18848c2ecf20Sopenharmony_ci if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { 18858c2ecf20Sopenharmony_ci return packFloat64( aSign, 0x3FF, 0 ); 18868c2ecf20Sopenharmony_ci } 18878c2ecf20Sopenharmony_ci break; 18888c2ecf20Sopenharmony_ci case float_round_down: 18898c2ecf20Sopenharmony_ci return aSign ? LIT64( 0xBFF0000000000000 ) : 0; 18908c2ecf20Sopenharmony_ci case float_round_up: 18918c2ecf20Sopenharmony_ci return 18928c2ecf20Sopenharmony_ci aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ); 18938c2ecf20Sopenharmony_ci } 18948c2ecf20Sopenharmony_ci return packFloat64( aSign, 0, 0 ); 18958c2ecf20Sopenharmony_ci } 18968c2ecf20Sopenharmony_ci lastBitMask = 1; 18978c2ecf20Sopenharmony_ci lastBitMask <<= 0x433 - aExp; 18988c2ecf20Sopenharmony_ci roundBitsMask = lastBitMask - 1; 18998c2ecf20Sopenharmony_ci z = a; 19008c2ecf20Sopenharmony_ci roundingMode = roundData->mode; 19018c2ecf20Sopenharmony_ci if ( roundingMode == float_round_nearest_even ) { 19028c2ecf20Sopenharmony_ci z += lastBitMask>>1; 19038c2ecf20Sopenharmony_ci if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; 19048c2ecf20Sopenharmony_ci } 19058c2ecf20Sopenharmony_ci else if ( roundingMode != float_round_to_zero ) { 19068c2ecf20Sopenharmony_ci if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) { 19078c2ecf20Sopenharmony_ci z += roundBitsMask; 19088c2ecf20Sopenharmony_ci } 19098c2ecf20Sopenharmony_ci } 19108c2ecf20Sopenharmony_ci z &= ~ roundBitsMask; 19118c2ecf20Sopenharmony_ci if ( z != a ) roundData->exception |= float_flag_inexact; 19128c2ecf20Sopenharmony_ci return z; 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci} 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci/* 19178c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 19188c2ecf20Sopenharmony_ciReturns the result of adding the absolute values of the double-precision 19198c2ecf20Sopenharmony_cifloating-point values `a' and `b'. If `zSign' is true, the sum is negated 19208c2ecf20Sopenharmony_cibefore being returned. `zSign' is ignored if the result is a NaN. The 19218c2ecf20Sopenharmony_ciaddition is performed according to the IEC/IEEE Standard for Binary 19228c2ecf20Sopenharmony_ciFloating-point Arithmetic. 19238c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 19248c2ecf20Sopenharmony_ci*/ 19258c2ecf20Sopenharmony_cistatic float64 addFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign ) 19268c2ecf20Sopenharmony_ci{ 19278c2ecf20Sopenharmony_ci int16 aExp, bExp, zExp; 19288c2ecf20Sopenharmony_ci bits64 aSig, bSig, zSig; 19298c2ecf20Sopenharmony_ci int16 expDiff; 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 19328c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 19338c2ecf20Sopenharmony_ci bSig = extractFloat64Frac( b ); 19348c2ecf20Sopenharmony_ci bExp = extractFloat64Exp( b ); 19358c2ecf20Sopenharmony_ci expDiff = aExp - bExp; 19368c2ecf20Sopenharmony_ci aSig <<= 9; 19378c2ecf20Sopenharmony_ci bSig <<= 9; 19388c2ecf20Sopenharmony_ci if ( 0 < expDiff ) { 19398c2ecf20Sopenharmony_ci if ( aExp == 0x7FF ) { 19408c2ecf20Sopenharmony_ci if ( aSig ) return propagateFloat64NaN( a, b ); 19418c2ecf20Sopenharmony_ci return a; 19428c2ecf20Sopenharmony_ci } 19438c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 19448c2ecf20Sopenharmony_ci --expDiff; 19458c2ecf20Sopenharmony_ci } 19468c2ecf20Sopenharmony_ci else { 19478c2ecf20Sopenharmony_ci bSig |= LIT64( 0x2000000000000000 ); 19488c2ecf20Sopenharmony_ci } 19498c2ecf20Sopenharmony_ci shift64RightJamming( bSig, expDiff, &bSig ); 19508c2ecf20Sopenharmony_ci zExp = aExp; 19518c2ecf20Sopenharmony_ci } 19528c2ecf20Sopenharmony_ci else if ( expDiff < 0 ) { 19538c2ecf20Sopenharmony_ci if ( bExp == 0x7FF ) { 19548c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat64NaN( a, b ); 19558c2ecf20Sopenharmony_ci return packFloat64( zSign, 0x7FF, 0 ); 19568c2ecf20Sopenharmony_ci } 19578c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 19588c2ecf20Sopenharmony_ci ++expDiff; 19598c2ecf20Sopenharmony_ci } 19608c2ecf20Sopenharmony_ci else { 19618c2ecf20Sopenharmony_ci aSig |= LIT64( 0x2000000000000000 ); 19628c2ecf20Sopenharmony_ci } 19638c2ecf20Sopenharmony_ci shift64RightJamming( aSig, - expDiff, &aSig ); 19648c2ecf20Sopenharmony_ci zExp = bExp; 19658c2ecf20Sopenharmony_ci } 19668c2ecf20Sopenharmony_ci else { 19678c2ecf20Sopenharmony_ci if ( aExp == 0x7FF ) { 19688c2ecf20Sopenharmony_ci if ( aSig | bSig ) return propagateFloat64NaN( a, b ); 19698c2ecf20Sopenharmony_ci return a; 19708c2ecf20Sopenharmony_ci } 19718c2ecf20Sopenharmony_ci if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); 19728c2ecf20Sopenharmony_ci zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; 19738c2ecf20Sopenharmony_ci zExp = aExp; 19748c2ecf20Sopenharmony_ci goto roundAndPack; 19758c2ecf20Sopenharmony_ci } 19768c2ecf20Sopenharmony_ci aSig |= LIT64( 0x2000000000000000 ); 19778c2ecf20Sopenharmony_ci zSig = ( aSig + bSig )<<1; 19788c2ecf20Sopenharmony_ci --zExp; 19798c2ecf20Sopenharmony_ci if ( (sbits64) zSig < 0 ) { 19808c2ecf20Sopenharmony_ci zSig = aSig + bSig; 19818c2ecf20Sopenharmony_ci ++zExp; 19828c2ecf20Sopenharmony_ci } 19838c2ecf20Sopenharmony_ci roundAndPack: 19848c2ecf20Sopenharmony_ci return roundAndPackFloat64( roundData, zSign, zExp, zSig ); 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_ci} 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_ci/* 19898c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 19908c2ecf20Sopenharmony_ciReturns the result of subtracting the absolute values of the double- 19918c2ecf20Sopenharmony_ciprecision floating-point values `a' and `b'. If `zSign' is true, the 19928c2ecf20Sopenharmony_cidifference is negated before being returned. `zSign' is ignored if the 19938c2ecf20Sopenharmony_ciresult is a NaN. The subtraction is performed according to the IEC/IEEE 19948c2ecf20Sopenharmony_ciStandard for Binary Floating-point Arithmetic. 19958c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 19968c2ecf20Sopenharmony_ci*/ 19978c2ecf20Sopenharmony_cistatic float64 subFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign ) 19988c2ecf20Sopenharmony_ci{ 19998c2ecf20Sopenharmony_ci int16 aExp, bExp, zExp; 20008c2ecf20Sopenharmony_ci bits64 aSig, bSig, zSig; 20018c2ecf20Sopenharmony_ci int16 expDiff; 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 20048c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 20058c2ecf20Sopenharmony_ci bSig = extractFloat64Frac( b ); 20068c2ecf20Sopenharmony_ci bExp = extractFloat64Exp( b ); 20078c2ecf20Sopenharmony_ci expDiff = aExp - bExp; 20088c2ecf20Sopenharmony_ci aSig <<= 10; 20098c2ecf20Sopenharmony_ci bSig <<= 10; 20108c2ecf20Sopenharmony_ci if ( 0 < expDiff ) goto aExpBigger; 20118c2ecf20Sopenharmony_ci if ( expDiff < 0 ) goto bExpBigger; 20128c2ecf20Sopenharmony_ci if ( aExp == 0x7FF ) { 20138c2ecf20Sopenharmony_ci if ( aSig | bSig ) return propagateFloat64NaN( a, b ); 20148c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 20158c2ecf20Sopenharmony_ci return float64_default_nan; 20168c2ecf20Sopenharmony_ci } 20178c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 20188c2ecf20Sopenharmony_ci aExp = 1; 20198c2ecf20Sopenharmony_ci bExp = 1; 20208c2ecf20Sopenharmony_ci } 20218c2ecf20Sopenharmony_ci if ( bSig < aSig ) goto aBigger; 20228c2ecf20Sopenharmony_ci if ( aSig < bSig ) goto bBigger; 20238c2ecf20Sopenharmony_ci return packFloat64( roundData->mode == float_round_down, 0, 0 ); 20248c2ecf20Sopenharmony_ci bExpBigger: 20258c2ecf20Sopenharmony_ci if ( bExp == 0x7FF ) { 20268c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat64NaN( a, b ); 20278c2ecf20Sopenharmony_ci return packFloat64( zSign ^ 1, 0x7FF, 0 ); 20288c2ecf20Sopenharmony_ci } 20298c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 20308c2ecf20Sopenharmony_ci ++expDiff; 20318c2ecf20Sopenharmony_ci } 20328c2ecf20Sopenharmony_ci else { 20338c2ecf20Sopenharmony_ci aSig |= LIT64( 0x4000000000000000 ); 20348c2ecf20Sopenharmony_ci } 20358c2ecf20Sopenharmony_ci shift64RightJamming( aSig, - expDiff, &aSig ); 20368c2ecf20Sopenharmony_ci bSig |= LIT64( 0x4000000000000000 ); 20378c2ecf20Sopenharmony_ci bBigger: 20388c2ecf20Sopenharmony_ci zSig = bSig - aSig; 20398c2ecf20Sopenharmony_ci zExp = bExp; 20408c2ecf20Sopenharmony_ci zSign ^= 1; 20418c2ecf20Sopenharmony_ci goto normalizeRoundAndPack; 20428c2ecf20Sopenharmony_ci aExpBigger: 20438c2ecf20Sopenharmony_ci if ( aExp == 0x7FF ) { 20448c2ecf20Sopenharmony_ci if ( aSig ) return propagateFloat64NaN( a, b ); 20458c2ecf20Sopenharmony_ci return a; 20468c2ecf20Sopenharmony_ci } 20478c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 20488c2ecf20Sopenharmony_ci --expDiff; 20498c2ecf20Sopenharmony_ci } 20508c2ecf20Sopenharmony_ci else { 20518c2ecf20Sopenharmony_ci bSig |= LIT64( 0x4000000000000000 ); 20528c2ecf20Sopenharmony_ci } 20538c2ecf20Sopenharmony_ci shift64RightJamming( bSig, expDiff, &bSig ); 20548c2ecf20Sopenharmony_ci aSig |= LIT64( 0x4000000000000000 ); 20558c2ecf20Sopenharmony_ci aBigger: 20568c2ecf20Sopenharmony_ci zSig = aSig - bSig; 20578c2ecf20Sopenharmony_ci zExp = aExp; 20588c2ecf20Sopenharmony_ci normalizeRoundAndPack: 20598c2ecf20Sopenharmony_ci --zExp; 20608c2ecf20Sopenharmony_ci return normalizeRoundAndPackFloat64( roundData, zSign, zExp, zSig ); 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci} 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_ci/* 20658c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 20668c2ecf20Sopenharmony_ciReturns the result of adding the double-precision floating-point values `a' 20678c2ecf20Sopenharmony_ciand `b'. The operation is performed according to the IEC/IEEE Standard for 20688c2ecf20Sopenharmony_ciBinary Floating-point Arithmetic. 20698c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 20708c2ecf20Sopenharmony_ci*/ 20718c2ecf20Sopenharmony_cifloat64 float64_add( struct roundingData *roundData, float64 a, float64 b ) 20728c2ecf20Sopenharmony_ci{ 20738c2ecf20Sopenharmony_ci flag aSign, bSign; 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 20768c2ecf20Sopenharmony_ci bSign = extractFloat64Sign( b ); 20778c2ecf20Sopenharmony_ci if ( aSign == bSign ) { 20788c2ecf20Sopenharmony_ci return addFloat64Sigs( roundData, a, b, aSign ); 20798c2ecf20Sopenharmony_ci } 20808c2ecf20Sopenharmony_ci else { 20818c2ecf20Sopenharmony_ci return subFloat64Sigs( roundData, a, b, aSign ); 20828c2ecf20Sopenharmony_ci } 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci} 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci/* 20878c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 20888c2ecf20Sopenharmony_ciReturns the result of subtracting the double-precision floating-point values 20898c2ecf20Sopenharmony_ci`a' and `b'. The operation is performed according to the IEC/IEEE Standard 20908c2ecf20Sopenharmony_cifor Binary Floating-point Arithmetic. 20918c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 20928c2ecf20Sopenharmony_ci*/ 20938c2ecf20Sopenharmony_cifloat64 float64_sub( struct roundingData *roundData, float64 a, float64 b ) 20948c2ecf20Sopenharmony_ci{ 20958c2ecf20Sopenharmony_ci flag aSign, bSign; 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 20988c2ecf20Sopenharmony_ci bSign = extractFloat64Sign( b ); 20998c2ecf20Sopenharmony_ci if ( aSign == bSign ) { 21008c2ecf20Sopenharmony_ci return subFloat64Sigs( roundData, a, b, aSign ); 21018c2ecf20Sopenharmony_ci } 21028c2ecf20Sopenharmony_ci else { 21038c2ecf20Sopenharmony_ci return addFloat64Sigs( roundData, a, b, aSign ); 21048c2ecf20Sopenharmony_ci } 21058c2ecf20Sopenharmony_ci 21068c2ecf20Sopenharmony_ci} 21078c2ecf20Sopenharmony_ci 21088c2ecf20Sopenharmony_ci/* 21098c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 21108c2ecf20Sopenharmony_ciReturns the result of multiplying the double-precision floating-point values 21118c2ecf20Sopenharmony_ci`a' and `b'. The operation is performed according to the IEC/IEEE Standard 21128c2ecf20Sopenharmony_cifor Binary Floating-point Arithmetic. 21138c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 21148c2ecf20Sopenharmony_ci*/ 21158c2ecf20Sopenharmony_cifloat64 float64_mul( struct roundingData *roundData, float64 a, float64 b ) 21168c2ecf20Sopenharmony_ci{ 21178c2ecf20Sopenharmony_ci flag aSign, bSign, zSign; 21188c2ecf20Sopenharmony_ci int16 aExp, bExp, zExp; 21198c2ecf20Sopenharmony_ci bits64 aSig, bSig, zSig0, zSig1; 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 21228c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 21238c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 21248c2ecf20Sopenharmony_ci bSig = extractFloat64Frac( b ); 21258c2ecf20Sopenharmony_ci bExp = extractFloat64Exp( b ); 21268c2ecf20Sopenharmony_ci bSign = extractFloat64Sign( b ); 21278c2ecf20Sopenharmony_ci zSign = aSign ^ bSign; 21288c2ecf20Sopenharmony_ci if ( aExp == 0x7FF ) { 21298c2ecf20Sopenharmony_ci if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { 21308c2ecf20Sopenharmony_ci return propagateFloat64NaN( a, b ); 21318c2ecf20Sopenharmony_ci } 21328c2ecf20Sopenharmony_ci if ( ( bExp | bSig ) == 0 ) { 21338c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 21348c2ecf20Sopenharmony_ci return float64_default_nan; 21358c2ecf20Sopenharmony_ci } 21368c2ecf20Sopenharmony_ci return packFloat64( zSign, 0x7FF, 0 ); 21378c2ecf20Sopenharmony_ci } 21388c2ecf20Sopenharmony_ci if ( bExp == 0x7FF ) { 21398c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat64NaN( a, b ); 21408c2ecf20Sopenharmony_ci if ( ( aExp | aSig ) == 0 ) { 21418c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 21428c2ecf20Sopenharmony_ci return float64_default_nan; 21438c2ecf20Sopenharmony_ci } 21448c2ecf20Sopenharmony_ci return packFloat64( zSign, 0x7FF, 0 ); 21458c2ecf20Sopenharmony_ci } 21468c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 21478c2ecf20Sopenharmony_ci if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); 21488c2ecf20Sopenharmony_ci normalizeFloat64Subnormal( aSig, &aExp, &aSig ); 21498c2ecf20Sopenharmony_ci } 21508c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 21518c2ecf20Sopenharmony_ci if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); 21528c2ecf20Sopenharmony_ci normalizeFloat64Subnormal( bSig, &bExp, &bSig ); 21538c2ecf20Sopenharmony_ci } 21548c2ecf20Sopenharmony_ci zExp = aExp + bExp - 0x3FF; 21558c2ecf20Sopenharmony_ci aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; 21568c2ecf20Sopenharmony_ci bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; 21578c2ecf20Sopenharmony_ci mul64To128( aSig, bSig, &zSig0, &zSig1 ); 21588c2ecf20Sopenharmony_ci zSig0 |= ( zSig1 != 0 ); 21598c2ecf20Sopenharmony_ci if ( 0 <= (sbits64) ( zSig0<<1 ) ) { 21608c2ecf20Sopenharmony_ci zSig0 <<= 1; 21618c2ecf20Sopenharmony_ci --zExp; 21628c2ecf20Sopenharmony_ci } 21638c2ecf20Sopenharmony_ci return roundAndPackFloat64( roundData, zSign, zExp, zSig0 ); 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci} 21668c2ecf20Sopenharmony_ci 21678c2ecf20Sopenharmony_ci/* 21688c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 21698c2ecf20Sopenharmony_ciReturns the result of dividing the double-precision floating-point value `a' 21708c2ecf20Sopenharmony_ciby the corresponding value `b'. The operation is performed according to 21718c2ecf20Sopenharmony_cithe IEC/IEEE Standard for Binary Floating-point Arithmetic. 21728c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 21738c2ecf20Sopenharmony_ci*/ 21748c2ecf20Sopenharmony_cifloat64 float64_div( struct roundingData *roundData, float64 a, float64 b ) 21758c2ecf20Sopenharmony_ci{ 21768c2ecf20Sopenharmony_ci flag aSign, bSign, zSign; 21778c2ecf20Sopenharmony_ci int16 aExp, bExp, zExp; 21788c2ecf20Sopenharmony_ci bits64 aSig, bSig, zSig; 21798c2ecf20Sopenharmony_ci bits64 rem0, rem1; 21808c2ecf20Sopenharmony_ci bits64 term0, term1; 21818c2ecf20Sopenharmony_ci 21828c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 21838c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 21848c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 21858c2ecf20Sopenharmony_ci bSig = extractFloat64Frac( b ); 21868c2ecf20Sopenharmony_ci bExp = extractFloat64Exp( b ); 21878c2ecf20Sopenharmony_ci bSign = extractFloat64Sign( b ); 21888c2ecf20Sopenharmony_ci zSign = aSign ^ bSign; 21898c2ecf20Sopenharmony_ci if ( aExp == 0x7FF ) { 21908c2ecf20Sopenharmony_ci if ( aSig ) return propagateFloat64NaN( a, b ); 21918c2ecf20Sopenharmony_ci if ( bExp == 0x7FF ) { 21928c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat64NaN( a, b ); 21938c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 21948c2ecf20Sopenharmony_ci return float64_default_nan; 21958c2ecf20Sopenharmony_ci } 21968c2ecf20Sopenharmony_ci return packFloat64( zSign, 0x7FF, 0 ); 21978c2ecf20Sopenharmony_ci } 21988c2ecf20Sopenharmony_ci if ( bExp == 0x7FF ) { 21998c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat64NaN( a, b ); 22008c2ecf20Sopenharmony_ci return packFloat64( zSign, 0, 0 ); 22018c2ecf20Sopenharmony_ci } 22028c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 22038c2ecf20Sopenharmony_ci if ( bSig == 0 ) { 22048c2ecf20Sopenharmony_ci if ( ( aExp | aSig ) == 0 ) { 22058c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 22068c2ecf20Sopenharmony_ci return float64_default_nan; 22078c2ecf20Sopenharmony_ci } 22088c2ecf20Sopenharmony_ci roundData->exception |= float_flag_divbyzero; 22098c2ecf20Sopenharmony_ci return packFloat64( zSign, 0x7FF, 0 ); 22108c2ecf20Sopenharmony_ci } 22118c2ecf20Sopenharmony_ci normalizeFloat64Subnormal( bSig, &bExp, &bSig ); 22128c2ecf20Sopenharmony_ci } 22138c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 22148c2ecf20Sopenharmony_ci if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); 22158c2ecf20Sopenharmony_ci normalizeFloat64Subnormal( aSig, &aExp, &aSig ); 22168c2ecf20Sopenharmony_ci } 22178c2ecf20Sopenharmony_ci zExp = aExp - bExp + 0x3FD; 22188c2ecf20Sopenharmony_ci aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; 22198c2ecf20Sopenharmony_ci bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; 22208c2ecf20Sopenharmony_ci if ( bSig <= ( aSig + aSig ) ) { 22218c2ecf20Sopenharmony_ci aSig >>= 1; 22228c2ecf20Sopenharmony_ci ++zExp; 22238c2ecf20Sopenharmony_ci } 22248c2ecf20Sopenharmony_ci zSig = estimateDiv128To64( aSig, 0, bSig ); 22258c2ecf20Sopenharmony_ci if ( ( zSig & 0x1FF ) <= 2 ) { 22268c2ecf20Sopenharmony_ci mul64To128( bSig, zSig, &term0, &term1 ); 22278c2ecf20Sopenharmony_ci sub128( aSig, 0, term0, term1, &rem0, &rem1 ); 22288c2ecf20Sopenharmony_ci while ( (sbits64) rem0 < 0 ) { 22298c2ecf20Sopenharmony_ci --zSig; 22308c2ecf20Sopenharmony_ci add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); 22318c2ecf20Sopenharmony_ci } 22328c2ecf20Sopenharmony_ci zSig |= ( rem1 != 0 ); 22338c2ecf20Sopenharmony_ci } 22348c2ecf20Sopenharmony_ci return roundAndPackFloat64( roundData, zSign, zExp, zSig ); 22358c2ecf20Sopenharmony_ci 22368c2ecf20Sopenharmony_ci} 22378c2ecf20Sopenharmony_ci 22388c2ecf20Sopenharmony_ci/* 22398c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 22408c2ecf20Sopenharmony_ciReturns the remainder of the double-precision floating-point value `a' 22418c2ecf20Sopenharmony_ciwith respect to the corresponding value `b'. The operation is performed 22428c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 22438c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 22448c2ecf20Sopenharmony_ci*/ 22458c2ecf20Sopenharmony_cifloat64 float64_rem( struct roundingData *roundData, float64 a, float64 b ) 22468c2ecf20Sopenharmony_ci{ 22478c2ecf20Sopenharmony_ci flag aSign, bSign, zSign; 22488c2ecf20Sopenharmony_ci int16 aExp, bExp, expDiff; 22498c2ecf20Sopenharmony_ci bits64 aSig, bSig; 22508c2ecf20Sopenharmony_ci bits64 q, alternateASig; 22518c2ecf20Sopenharmony_ci sbits64 sigMean; 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 22548c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 22558c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 22568c2ecf20Sopenharmony_ci bSig = extractFloat64Frac( b ); 22578c2ecf20Sopenharmony_ci bExp = extractFloat64Exp( b ); 22588c2ecf20Sopenharmony_ci bSign = extractFloat64Sign( b ); 22598c2ecf20Sopenharmony_ci if ( aExp == 0x7FF ) { 22608c2ecf20Sopenharmony_ci if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { 22618c2ecf20Sopenharmony_ci return propagateFloat64NaN( a, b ); 22628c2ecf20Sopenharmony_ci } 22638c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 22648c2ecf20Sopenharmony_ci return float64_default_nan; 22658c2ecf20Sopenharmony_ci } 22668c2ecf20Sopenharmony_ci if ( bExp == 0x7FF ) { 22678c2ecf20Sopenharmony_ci if ( bSig ) return propagateFloat64NaN( a, b ); 22688c2ecf20Sopenharmony_ci return a; 22698c2ecf20Sopenharmony_ci } 22708c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 22718c2ecf20Sopenharmony_ci if ( bSig == 0 ) { 22728c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 22738c2ecf20Sopenharmony_ci return float64_default_nan; 22748c2ecf20Sopenharmony_ci } 22758c2ecf20Sopenharmony_ci normalizeFloat64Subnormal( bSig, &bExp, &bSig ); 22768c2ecf20Sopenharmony_ci } 22778c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 22788c2ecf20Sopenharmony_ci if ( aSig == 0 ) return a; 22798c2ecf20Sopenharmony_ci normalizeFloat64Subnormal( aSig, &aExp, &aSig ); 22808c2ecf20Sopenharmony_ci } 22818c2ecf20Sopenharmony_ci expDiff = aExp - bExp; 22828c2ecf20Sopenharmony_ci aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; 22838c2ecf20Sopenharmony_ci bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; 22848c2ecf20Sopenharmony_ci if ( expDiff < 0 ) { 22858c2ecf20Sopenharmony_ci if ( expDiff < -1 ) return a; 22868c2ecf20Sopenharmony_ci aSig >>= 1; 22878c2ecf20Sopenharmony_ci } 22888c2ecf20Sopenharmony_ci q = ( bSig <= aSig ); 22898c2ecf20Sopenharmony_ci if ( q ) aSig -= bSig; 22908c2ecf20Sopenharmony_ci expDiff -= 64; 22918c2ecf20Sopenharmony_ci while ( 0 < expDiff ) { 22928c2ecf20Sopenharmony_ci q = estimateDiv128To64( aSig, 0, bSig ); 22938c2ecf20Sopenharmony_ci q = ( 2 < q ) ? q - 2 : 0; 22948c2ecf20Sopenharmony_ci aSig = - ( ( bSig>>2 ) * q ); 22958c2ecf20Sopenharmony_ci expDiff -= 62; 22968c2ecf20Sopenharmony_ci } 22978c2ecf20Sopenharmony_ci expDiff += 64; 22988c2ecf20Sopenharmony_ci if ( 0 < expDiff ) { 22998c2ecf20Sopenharmony_ci q = estimateDiv128To64( aSig, 0, bSig ); 23008c2ecf20Sopenharmony_ci q = ( 2 < q ) ? q - 2 : 0; 23018c2ecf20Sopenharmony_ci q >>= 64 - expDiff; 23028c2ecf20Sopenharmony_ci bSig >>= 2; 23038c2ecf20Sopenharmony_ci aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; 23048c2ecf20Sopenharmony_ci } 23058c2ecf20Sopenharmony_ci else { 23068c2ecf20Sopenharmony_ci aSig >>= 2; 23078c2ecf20Sopenharmony_ci bSig >>= 2; 23088c2ecf20Sopenharmony_ci } 23098c2ecf20Sopenharmony_ci do { 23108c2ecf20Sopenharmony_ci alternateASig = aSig; 23118c2ecf20Sopenharmony_ci ++q; 23128c2ecf20Sopenharmony_ci aSig -= bSig; 23138c2ecf20Sopenharmony_ci } while ( 0 <= (sbits64) aSig ); 23148c2ecf20Sopenharmony_ci sigMean = aSig + alternateASig; 23158c2ecf20Sopenharmony_ci if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { 23168c2ecf20Sopenharmony_ci aSig = alternateASig; 23178c2ecf20Sopenharmony_ci } 23188c2ecf20Sopenharmony_ci zSign = ( (sbits64) aSig < 0 ); 23198c2ecf20Sopenharmony_ci if ( zSign ) aSig = - aSig; 23208c2ecf20Sopenharmony_ci return normalizeRoundAndPackFloat64( roundData, aSign ^ zSign, bExp, aSig ); 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci} 23238c2ecf20Sopenharmony_ci 23248c2ecf20Sopenharmony_ci/* 23258c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 23268c2ecf20Sopenharmony_ciReturns the square root of the double-precision floating-point value `a'. 23278c2ecf20Sopenharmony_ciThe operation is performed according to the IEC/IEEE Standard for Binary 23288c2ecf20Sopenharmony_ciFloating-point Arithmetic. 23298c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 23308c2ecf20Sopenharmony_ci*/ 23318c2ecf20Sopenharmony_cifloat64 float64_sqrt( struct roundingData *roundData, float64 a ) 23328c2ecf20Sopenharmony_ci{ 23338c2ecf20Sopenharmony_ci flag aSign; 23348c2ecf20Sopenharmony_ci int16 aExp, zExp; 23358c2ecf20Sopenharmony_ci bits64 aSig, zSig; 23368c2ecf20Sopenharmony_ci bits64 rem0, rem1, term0, term1; //, shiftedRem; 23378c2ecf20Sopenharmony_ci //float64 z; 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_ci aSig = extractFloat64Frac( a ); 23408c2ecf20Sopenharmony_ci aExp = extractFloat64Exp( a ); 23418c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 23428c2ecf20Sopenharmony_ci if ( aExp == 0x7FF ) { 23438c2ecf20Sopenharmony_ci if ( aSig ) return propagateFloat64NaN( a, a ); 23448c2ecf20Sopenharmony_ci if ( ! aSign ) return a; 23458c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 23468c2ecf20Sopenharmony_ci return float64_default_nan; 23478c2ecf20Sopenharmony_ci } 23488c2ecf20Sopenharmony_ci if ( aSign ) { 23498c2ecf20Sopenharmony_ci if ( ( aExp | aSig ) == 0 ) return a; 23508c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 23518c2ecf20Sopenharmony_ci return float64_default_nan; 23528c2ecf20Sopenharmony_ci } 23538c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 23548c2ecf20Sopenharmony_ci if ( aSig == 0 ) return 0; 23558c2ecf20Sopenharmony_ci normalizeFloat64Subnormal( aSig, &aExp, &aSig ); 23568c2ecf20Sopenharmony_ci } 23578c2ecf20Sopenharmony_ci zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; 23588c2ecf20Sopenharmony_ci aSig |= LIT64( 0x0010000000000000 ); 23598c2ecf20Sopenharmony_ci zSig = estimateSqrt32( aExp, aSig>>21 ); 23608c2ecf20Sopenharmony_ci zSig <<= 31; 23618c2ecf20Sopenharmony_ci aSig <<= 9 - ( aExp & 1 ); 23628c2ecf20Sopenharmony_ci zSig = estimateDiv128To64( aSig, 0, zSig ) + zSig + 2; 23638c2ecf20Sopenharmony_ci if ( ( zSig & 0x3FF ) <= 5 ) { 23648c2ecf20Sopenharmony_ci if ( zSig < 2 ) { 23658c2ecf20Sopenharmony_ci zSig = LIT64( 0xFFFFFFFFFFFFFFFF ); 23668c2ecf20Sopenharmony_ci } 23678c2ecf20Sopenharmony_ci else { 23688c2ecf20Sopenharmony_ci aSig <<= 2; 23698c2ecf20Sopenharmony_ci mul64To128( zSig, zSig, &term0, &term1 ); 23708c2ecf20Sopenharmony_ci sub128( aSig, 0, term0, term1, &rem0, &rem1 ); 23718c2ecf20Sopenharmony_ci while ( (sbits64) rem0 < 0 ) { 23728c2ecf20Sopenharmony_ci --zSig; 23738c2ecf20Sopenharmony_ci shortShift128Left( 0, zSig, 1, &term0, &term1 ); 23748c2ecf20Sopenharmony_ci term1 |= 1; 23758c2ecf20Sopenharmony_ci add128( rem0, rem1, term0, term1, &rem0, &rem1 ); 23768c2ecf20Sopenharmony_ci } 23778c2ecf20Sopenharmony_ci zSig |= ( ( rem0 | rem1 ) != 0 ); 23788c2ecf20Sopenharmony_ci } 23798c2ecf20Sopenharmony_ci } 23808c2ecf20Sopenharmony_ci shift64RightJamming( zSig, 1, &zSig ); 23818c2ecf20Sopenharmony_ci return roundAndPackFloat64( roundData, 0, zExp, zSig ); 23828c2ecf20Sopenharmony_ci 23838c2ecf20Sopenharmony_ci} 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci/* 23868c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 23878c2ecf20Sopenharmony_ciReturns 1 if the double-precision floating-point value `a' is equal to the 23888c2ecf20Sopenharmony_cicorresponding value `b', and 0 otherwise. The comparison is performed 23898c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 23908c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 23918c2ecf20Sopenharmony_ci*/ 23928c2ecf20Sopenharmony_ciflag float64_eq( float64 a, float64 b ) 23938c2ecf20Sopenharmony_ci{ 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_ci if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) 23968c2ecf20Sopenharmony_ci || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) 23978c2ecf20Sopenharmony_ci ) { 23988c2ecf20Sopenharmony_ci if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { 23998c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 24008c2ecf20Sopenharmony_ci } 24018c2ecf20Sopenharmony_ci return 0; 24028c2ecf20Sopenharmony_ci } 24038c2ecf20Sopenharmony_ci return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_ci} 24068c2ecf20Sopenharmony_ci 24078c2ecf20Sopenharmony_ci/* 24088c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 24098c2ecf20Sopenharmony_ciReturns 1 if the double-precision floating-point value `a' is less than or 24108c2ecf20Sopenharmony_ciequal to the corresponding value `b', and 0 otherwise. The comparison is 24118c2ecf20Sopenharmony_ciperformed according to the IEC/IEEE Standard for Binary Floating-point 24128c2ecf20Sopenharmony_ciArithmetic. 24138c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 24148c2ecf20Sopenharmony_ci*/ 24158c2ecf20Sopenharmony_ciflag float64_le( float64 a, float64 b ) 24168c2ecf20Sopenharmony_ci{ 24178c2ecf20Sopenharmony_ci flag aSign, bSign; 24188c2ecf20Sopenharmony_ci 24198c2ecf20Sopenharmony_ci if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) 24208c2ecf20Sopenharmony_ci || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) 24218c2ecf20Sopenharmony_ci ) { 24228c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 24238c2ecf20Sopenharmony_ci return 0; 24248c2ecf20Sopenharmony_ci } 24258c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 24268c2ecf20Sopenharmony_ci bSign = extractFloat64Sign( b ); 24278c2ecf20Sopenharmony_ci if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); 24288c2ecf20Sopenharmony_ci return ( a == b ) || ( aSign ^ ( a < b ) ); 24298c2ecf20Sopenharmony_ci 24308c2ecf20Sopenharmony_ci} 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ci/* 24338c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 24348c2ecf20Sopenharmony_ciReturns 1 if the double-precision floating-point value `a' is less than 24358c2ecf20Sopenharmony_cithe corresponding value `b', and 0 otherwise. The comparison is performed 24368c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 24378c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 24388c2ecf20Sopenharmony_ci*/ 24398c2ecf20Sopenharmony_ciflag float64_lt( float64 a, float64 b ) 24408c2ecf20Sopenharmony_ci{ 24418c2ecf20Sopenharmony_ci flag aSign, bSign; 24428c2ecf20Sopenharmony_ci 24438c2ecf20Sopenharmony_ci if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) 24448c2ecf20Sopenharmony_ci || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) 24458c2ecf20Sopenharmony_ci ) { 24468c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 24478c2ecf20Sopenharmony_ci return 0; 24488c2ecf20Sopenharmony_ci } 24498c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 24508c2ecf20Sopenharmony_ci bSign = extractFloat64Sign( b ); 24518c2ecf20Sopenharmony_ci if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); 24528c2ecf20Sopenharmony_ci return ( a != b ) && ( aSign ^ ( a < b ) ); 24538c2ecf20Sopenharmony_ci 24548c2ecf20Sopenharmony_ci} 24558c2ecf20Sopenharmony_ci 24568c2ecf20Sopenharmony_ci/* 24578c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 24588c2ecf20Sopenharmony_ciReturns 1 if the double-precision floating-point value `a' is equal to the 24598c2ecf20Sopenharmony_cicorresponding value `b', and 0 otherwise. The invalid exception is raised 24608c2ecf20Sopenharmony_ciif either operand is a NaN. Otherwise, the comparison is performed 24618c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 24628c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 24638c2ecf20Sopenharmony_ci*/ 24648c2ecf20Sopenharmony_ciflag float64_eq_signaling( float64 a, float64 b ) 24658c2ecf20Sopenharmony_ci{ 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) 24688c2ecf20Sopenharmony_ci || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) 24698c2ecf20Sopenharmony_ci ) { 24708c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 24718c2ecf20Sopenharmony_ci return 0; 24728c2ecf20Sopenharmony_ci } 24738c2ecf20Sopenharmony_ci return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); 24748c2ecf20Sopenharmony_ci 24758c2ecf20Sopenharmony_ci} 24768c2ecf20Sopenharmony_ci 24778c2ecf20Sopenharmony_ci/* 24788c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 24798c2ecf20Sopenharmony_ciReturns 1 if the double-precision floating-point value `a' is less than or 24808c2ecf20Sopenharmony_ciequal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not 24818c2ecf20Sopenharmony_cicause an exception. Otherwise, the comparison is performed according to the 24828c2ecf20Sopenharmony_ciIEC/IEEE Standard for Binary Floating-point Arithmetic. 24838c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 24848c2ecf20Sopenharmony_ci*/ 24858c2ecf20Sopenharmony_ciflag float64_le_quiet( float64 a, float64 b ) 24868c2ecf20Sopenharmony_ci{ 24878c2ecf20Sopenharmony_ci flag aSign, bSign; 24888c2ecf20Sopenharmony_ci //int16 aExp, bExp; 24898c2ecf20Sopenharmony_ci 24908c2ecf20Sopenharmony_ci if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) 24918c2ecf20Sopenharmony_ci || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) 24928c2ecf20Sopenharmony_ci ) { 24938c2ecf20Sopenharmony_ci /* Do nothing, even if NaN as we're quiet */ 24948c2ecf20Sopenharmony_ci return 0; 24958c2ecf20Sopenharmony_ci } 24968c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 24978c2ecf20Sopenharmony_ci bSign = extractFloat64Sign( b ); 24988c2ecf20Sopenharmony_ci if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); 24998c2ecf20Sopenharmony_ci return ( a == b ) || ( aSign ^ ( a < b ) ); 25008c2ecf20Sopenharmony_ci 25018c2ecf20Sopenharmony_ci} 25028c2ecf20Sopenharmony_ci 25038c2ecf20Sopenharmony_ci/* 25048c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 25058c2ecf20Sopenharmony_ciReturns 1 if the double-precision floating-point value `a' is less than 25068c2ecf20Sopenharmony_cithe corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an 25078c2ecf20Sopenharmony_ciexception. Otherwise, the comparison is performed according to the IEC/IEEE 25088c2ecf20Sopenharmony_ciStandard for Binary Floating-point Arithmetic. 25098c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 25108c2ecf20Sopenharmony_ci*/ 25118c2ecf20Sopenharmony_ciflag float64_lt_quiet( float64 a, float64 b ) 25128c2ecf20Sopenharmony_ci{ 25138c2ecf20Sopenharmony_ci flag aSign, bSign; 25148c2ecf20Sopenharmony_ci 25158c2ecf20Sopenharmony_ci if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) 25168c2ecf20Sopenharmony_ci || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) 25178c2ecf20Sopenharmony_ci ) { 25188c2ecf20Sopenharmony_ci /* Do nothing, even if NaN as we're quiet */ 25198c2ecf20Sopenharmony_ci return 0; 25208c2ecf20Sopenharmony_ci } 25218c2ecf20Sopenharmony_ci aSign = extractFloat64Sign( a ); 25228c2ecf20Sopenharmony_ci bSign = extractFloat64Sign( b ); 25238c2ecf20Sopenharmony_ci if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); 25248c2ecf20Sopenharmony_ci return ( a != b ) && ( aSign ^ ( a < b ) ); 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci} 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_ci#ifdef FLOATX80 25298c2ecf20Sopenharmony_ci 25308c2ecf20Sopenharmony_ci/* 25318c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 25328c2ecf20Sopenharmony_ciReturns the result of converting the extended double-precision floating- 25338c2ecf20Sopenharmony_cipoint value `a' to the 32-bit two's complement integer format. The 25348c2ecf20Sopenharmony_ciconversion is performed according to the IEC/IEEE Standard for Binary 25358c2ecf20Sopenharmony_ciFloating-point Arithmetic---which means in particular that the conversion 25368c2ecf20Sopenharmony_ciis rounded according to the current rounding mode. If `a' is a NaN, the 25378c2ecf20Sopenharmony_cilargest positive integer is returned. Otherwise, if the conversion 25388c2ecf20Sopenharmony_cioverflows, the largest integer with the same sign as `a' is returned. 25398c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 25408c2ecf20Sopenharmony_ci*/ 25418c2ecf20Sopenharmony_ciint32 floatx80_to_int32( struct roundingData *roundData, floatx80 a ) 25428c2ecf20Sopenharmony_ci{ 25438c2ecf20Sopenharmony_ci flag aSign; 25448c2ecf20Sopenharmony_ci int32 aExp, shiftCount; 25458c2ecf20Sopenharmony_ci bits64 aSig; 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci aSig = extractFloatx80Frac( a ); 25488c2ecf20Sopenharmony_ci aExp = extractFloatx80Exp( a ); 25498c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 25508c2ecf20Sopenharmony_ci if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; 25518c2ecf20Sopenharmony_ci shiftCount = 0x4037 - aExp; 25528c2ecf20Sopenharmony_ci if ( shiftCount <= 0 ) shiftCount = 1; 25538c2ecf20Sopenharmony_ci shift64RightJamming( aSig, shiftCount, &aSig ); 25548c2ecf20Sopenharmony_ci return roundAndPackInt32( roundData, aSign, aSig ); 25558c2ecf20Sopenharmony_ci 25568c2ecf20Sopenharmony_ci} 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_ci/* 25598c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 25608c2ecf20Sopenharmony_ciReturns the result of converting the extended double-precision floating- 25618c2ecf20Sopenharmony_cipoint value `a' to the 32-bit two's complement integer format. The 25628c2ecf20Sopenharmony_ciconversion is performed according to the IEC/IEEE Standard for Binary 25638c2ecf20Sopenharmony_ciFloating-point Arithmetic, except that the conversion is always rounded 25648c2ecf20Sopenharmony_citoward zero. If `a' is a NaN, the largest positive integer is returned. 25658c2ecf20Sopenharmony_ciOtherwise, if the conversion overflows, the largest integer with the same 25668c2ecf20Sopenharmony_cisign as `a' is returned. 25678c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 25688c2ecf20Sopenharmony_ci*/ 25698c2ecf20Sopenharmony_ciint32 floatx80_to_int32_round_to_zero( floatx80 a ) 25708c2ecf20Sopenharmony_ci{ 25718c2ecf20Sopenharmony_ci flag aSign; 25728c2ecf20Sopenharmony_ci int32 aExp, shiftCount; 25738c2ecf20Sopenharmony_ci bits64 aSig, savedASig; 25748c2ecf20Sopenharmony_ci int32 z; 25758c2ecf20Sopenharmony_ci 25768c2ecf20Sopenharmony_ci aSig = extractFloatx80Frac( a ); 25778c2ecf20Sopenharmony_ci aExp = extractFloatx80Exp( a ); 25788c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 25798c2ecf20Sopenharmony_ci shiftCount = 0x403E - aExp; 25808c2ecf20Sopenharmony_ci if ( shiftCount < 32 ) { 25818c2ecf20Sopenharmony_ci if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; 25828c2ecf20Sopenharmony_ci goto invalid; 25838c2ecf20Sopenharmony_ci } 25848c2ecf20Sopenharmony_ci else if ( 63 < shiftCount ) { 25858c2ecf20Sopenharmony_ci if ( aExp || aSig ) float_raise( float_flag_inexact ); 25868c2ecf20Sopenharmony_ci return 0; 25878c2ecf20Sopenharmony_ci } 25888c2ecf20Sopenharmony_ci savedASig = aSig; 25898c2ecf20Sopenharmony_ci aSig >>= shiftCount; 25908c2ecf20Sopenharmony_ci z = aSig; 25918c2ecf20Sopenharmony_ci if ( aSign ) z = - z; 25928c2ecf20Sopenharmony_ci if ( ( z < 0 ) ^ aSign ) { 25938c2ecf20Sopenharmony_ci invalid: 25948c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 25958c2ecf20Sopenharmony_ci return aSign ? 0x80000000 : 0x7FFFFFFF; 25968c2ecf20Sopenharmony_ci } 25978c2ecf20Sopenharmony_ci if ( ( aSig<<shiftCount ) != savedASig ) { 25988c2ecf20Sopenharmony_ci float_raise( float_flag_inexact ); 25998c2ecf20Sopenharmony_ci } 26008c2ecf20Sopenharmony_ci return z; 26018c2ecf20Sopenharmony_ci 26028c2ecf20Sopenharmony_ci} 26038c2ecf20Sopenharmony_ci 26048c2ecf20Sopenharmony_ci/* 26058c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 26068c2ecf20Sopenharmony_ciReturns the result of converting the extended double-precision floating- 26078c2ecf20Sopenharmony_cipoint value `a' to the single-precision floating-point format. The 26088c2ecf20Sopenharmony_ciconversion is performed according to the IEC/IEEE Standard for Binary 26098c2ecf20Sopenharmony_ciFloating-point Arithmetic. 26108c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 26118c2ecf20Sopenharmony_ci*/ 26128c2ecf20Sopenharmony_cifloat32 floatx80_to_float32( struct roundingData *roundData, floatx80 a ) 26138c2ecf20Sopenharmony_ci{ 26148c2ecf20Sopenharmony_ci flag aSign; 26158c2ecf20Sopenharmony_ci int32 aExp; 26168c2ecf20Sopenharmony_ci bits64 aSig; 26178c2ecf20Sopenharmony_ci 26188c2ecf20Sopenharmony_ci aSig = extractFloatx80Frac( a ); 26198c2ecf20Sopenharmony_ci aExp = extractFloatx80Exp( a ); 26208c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 26218c2ecf20Sopenharmony_ci if ( aExp == 0x7FFF ) { 26228c2ecf20Sopenharmony_ci if ( (bits64) ( aSig<<1 ) ) { 26238c2ecf20Sopenharmony_ci return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); 26248c2ecf20Sopenharmony_ci } 26258c2ecf20Sopenharmony_ci return packFloat32( aSign, 0xFF, 0 ); 26268c2ecf20Sopenharmony_ci } 26278c2ecf20Sopenharmony_ci shift64RightJamming( aSig, 33, &aSig ); 26288c2ecf20Sopenharmony_ci if ( aExp || aSig ) aExp -= 0x3F81; 26298c2ecf20Sopenharmony_ci return roundAndPackFloat32( roundData, aSign, aExp, aSig ); 26308c2ecf20Sopenharmony_ci 26318c2ecf20Sopenharmony_ci} 26328c2ecf20Sopenharmony_ci 26338c2ecf20Sopenharmony_ci/* 26348c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 26358c2ecf20Sopenharmony_ciReturns the result of converting the extended double-precision floating- 26368c2ecf20Sopenharmony_cipoint value `a' to the double-precision floating-point format. The 26378c2ecf20Sopenharmony_ciconversion is performed according to the IEC/IEEE Standard for Binary 26388c2ecf20Sopenharmony_ciFloating-point Arithmetic. 26398c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 26408c2ecf20Sopenharmony_ci*/ 26418c2ecf20Sopenharmony_cifloat64 floatx80_to_float64( struct roundingData *roundData, floatx80 a ) 26428c2ecf20Sopenharmony_ci{ 26438c2ecf20Sopenharmony_ci flag aSign; 26448c2ecf20Sopenharmony_ci int32 aExp; 26458c2ecf20Sopenharmony_ci bits64 aSig, zSig; 26468c2ecf20Sopenharmony_ci 26478c2ecf20Sopenharmony_ci aSig = extractFloatx80Frac( a ); 26488c2ecf20Sopenharmony_ci aExp = extractFloatx80Exp( a ); 26498c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 26508c2ecf20Sopenharmony_ci if ( aExp == 0x7FFF ) { 26518c2ecf20Sopenharmony_ci if ( (bits64) ( aSig<<1 ) ) { 26528c2ecf20Sopenharmony_ci return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); 26538c2ecf20Sopenharmony_ci } 26548c2ecf20Sopenharmony_ci return packFloat64( aSign, 0x7FF, 0 ); 26558c2ecf20Sopenharmony_ci } 26568c2ecf20Sopenharmony_ci shift64RightJamming( aSig, 1, &zSig ); 26578c2ecf20Sopenharmony_ci if ( aExp || aSig ) aExp -= 0x3C01; 26588c2ecf20Sopenharmony_ci return roundAndPackFloat64( roundData, aSign, aExp, zSig ); 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci} 26618c2ecf20Sopenharmony_ci 26628c2ecf20Sopenharmony_ci/* 26638c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 26648c2ecf20Sopenharmony_ciRounds the extended double-precision floating-point value `a' to an integer, 26658c2ecf20Sopenharmony_ciand returns the result as an extended quadruple-precision floating-point 26668c2ecf20Sopenharmony_civalue. The operation is performed according to the IEC/IEEE Standard for 26678c2ecf20Sopenharmony_ciBinary Floating-point Arithmetic. 26688c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 26698c2ecf20Sopenharmony_ci*/ 26708c2ecf20Sopenharmony_cifloatx80 floatx80_round_to_int( struct roundingData *roundData, floatx80 a ) 26718c2ecf20Sopenharmony_ci{ 26728c2ecf20Sopenharmony_ci flag aSign; 26738c2ecf20Sopenharmony_ci int32 aExp; 26748c2ecf20Sopenharmony_ci bits64 lastBitMask, roundBitsMask; 26758c2ecf20Sopenharmony_ci int8 roundingMode; 26768c2ecf20Sopenharmony_ci floatx80 z; 26778c2ecf20Sopenharmony_ci 26788c2ecf20Sopenharmony_ci aExp = extractFloatx80Exp( a ); 26798c2ecf20Sopenharmony_ci if ( 0x403E <= aExp ) { 26808c2ecf20Sopenharmony_ci if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { 26818c2ecf20Sopenharmony_ci return propagateFloatx80NaN( a, a ); 26828c2ecf20Sopenharmony_ci } 26838c2ecf20Sopenharmony_ci return a; 26848c2ecf20Sopenharmony_ci } 26858c2ecf20Sopenharmony_ci if ( aExp <= 0x3FFE ) { 26868c2ecf20Sopenharmony_ci if ( ( aExp == 0 ) 26878c2ecf20Sopenharmony_ci && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { 26888c2ecf20Sopenharmony_ci return a; 26898c2ecf20Sopenharmony_ci } 26908c2ecf20Sopenharmony_ci roundData->exception |= float_flag_inexact; 26918c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 26928c2ecf20Sopenharmony_ci switch ( roundData->mode ) { 26938c2ecf20Sopenharmony_ci case float_round_nearest_even: 26948c2ecf20Sopenharmony_ci if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) 26958c2ecf20Sopenharmony_ci ) { 26968c2ecf20Sopenharmony_ci return 26978c2ecf20Sopenharmony_ci packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); 26988c2ecf20Sopenharmony_ci } 26998c2ecf20Sopenharmony_ci break; 27008c2ecf20Sopenharmony_ci case float_round_down: 27018c2ecf20Sopenharmony_ci return 27028c2ecf20Sopenharmony_ci aSign ? 27038c2ecf20Sopenharmony_ci packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) 27048c2ecf20Sopenharmony_ci : packFloatx80( 0, 0, 0 ); 27058c2ecf20Sopenharmony_ci case float_round_up: 27068c2ecf20Sopenharmony_ci return 27078c2ecf20Sopenharmony_ci aSign ? packFloatx80( 1, 0, 0 ) 27088c2ecf20Sopenharmony_ci : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); 27098c2ecf20Sopenharmony_ci } 27108c2ecf20Sopenharmony_ci return packFloatx80( aSign, 0, 0 ); 27118c2ecf20Sopenharmony_ci } 27128c2ecf20Sopenharmony_ci lastBitMask = 1; 27138c2ecf20Sopenharmony_ci lastBitMask <<= 0x403E - aExp; 27148c2ecf20Sopenharmony_ci roundBitsMask = lastBitMask - 1; 27158c2ecf20Sopenharmony_ci z = a; 27168c2ecf20Sopenharmony_ci roundingMode = roundData->mode; 27178c2ecf20Sopenharmony_ci if ( roundingMode == float_round_nearest_even ) { 27188c2ecf20Sopenharmony_ci z.low += lastBitMask>>1; 27198c2ecf20Sopenharmony_ci if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; 27208c2ecf20Sopenharmony_ci } 27218c2ecf20Sopenharmony_ci else if ( roundingMode != float_round_to_zero ) { 27228c2ecf20Sopenharmony_ci if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { 27238c2ecf20Sopenharmony_ci z.low += roundBitsMask; 27248c2ecf20Sopenharmony_ci } 27258c2ecf20Sopenharmony_ci } 27268c2ecf20Sopenharmony_ci z.low &= ~ roundBitsMask; 27278c2ecf20Sopenharmony_ci if ( z.low == 0 ) { 27288c2ecf20Sopenharmony_ci ++z.high; 27298c2ecf20Sopenharmony_ci z.low = LIT64( 0x8000000000000000 ); 27308c2ecf20Sopenharmony_ci } 27318c2ecf20Sopenharmony_ci if ( z.low != a.low ) roundData->exception |= float_flag_inexact; 27328c2ecf20Sopenharmony_ci return z; 27338c2ecf20Sopenharmony_ci 27348c2ecf20Sopenharmony_ci} 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci/* 27378c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 27388c2ecf20Sopenharmony_ciReturns the result of adding the absolute values of the extended double- 27398c2ecf20Sopenharmony_ciprecision floating-point values `a' and `b'. If `zSign' is true, the sum is 27408c2ecf20Sopenharmony_cinegated before being returned. `zSign' is ignored if the result is a NaN. 27418c2ecf20Sopenharmony_ciThe addition is performed according to the IEC/IEEE Standard for Binary 27428c2ecf20Sopenharmony_ciFloating-point Arithmetic. 27438c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 27448c2ecf20Sopenharmony_ci*/ 27458c2ecf20Sopenharmony_cistatic floatx80 addFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign ) 27468c2ecf20Sopenharmony_ci{ 27478c2ecf20Sopenharmony_ci int32 aExp, bExp, zExp; 27488c2ecf20Sopenharmony_ci bits64 aSig, bSig, zSig0, zSig1; 27498c2ecf20Sopenharmony_ci int32 expDiff; 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_ci aSig = extractFloatx80Frac( a ); 27528c2ecf20Sopenharmony_ci aExp = extractFloatx80Exp( a ); 27538c2ecf20Sopenharmony_ci bSig = extractFloatx80Frac( b ); 27548c2ecf20Sopenharmony_ci bExp = extractFloatx80Exp( b ); 27558c2ecf20Sopenharmony_ci expDiff = aExp - bExp; 27568c2ecf20Sopenharmony_ci if ( 0 < expDiff ) { 27578c2ecf20Sopenharmony_ci if ( aExp == 0x7FFF ) { 27588c2ecf20Sopenharmony_ci if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); 27598c2ecf20Sopenharmony_ci return a; 27608c2ecf20Sopenharmony_ci } 27618c2ecf20Sopenharmony_ci if ( bExp == 0 ) --expDiff; 27628c2ecf20Sopenharmony_ci shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); 27638c2ecf20Sopenharmony_ci zExp = aExp; 27648c2ecf20Sopenharmony_ci } 27658c2ecf20Sopenharmony_ci else if ( expDiff < 0 ) { 27668c2ecf20Sopenharmony_ci if ( bExp == 0x7FFF ) { 27678c2ecf20Sopenharmony_ci if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); 27688c2ecf20Sopenharmony_ci return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); 27698c2ecf20Sopenharmony_ci } 27708c2ecf20Sopenharmony_ci if ( aExp == 0 ) ++expDiff; 27718c2ecf20Sopenharmony_ci shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); 27728c2ecf20Sopenharmony_ci zExp = bExp; 27738c2ecf20Sopenharmony_ci } 27748c2ecf20Sopenharmony_ci else { 27758c2ecf20Sopenharmony_ci if ( aExp == 0x7FFF ) { 27768c2ecf20Sopenharmony_ci if ( (bits64) ( ( aSig | bSig )<<1 ) ) { 27778c2ecf20Sopenharmony_ci return propagateFloatx80NaN( a, b ); 27788c2ecf20Sopenharmony_ci } 27798c2ecf20Sopenharmony_ci return a; 27808c2ecf20Sopenharmony_ci } 27818c2ecf20Sopenharmony_ci zSig1 = 0; 27828c2ecf20Sopenharmony_ci zSig0 = aSig + bSig; 27838c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 27848c2ecf20Sopenharmony_ci normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); 27858c2ecf20Sopenharmony_ci goto roundAndPack; 27868c2ecf20Sopenharmony_ci } 27878c2ecf20Sopenharmony_ci zExp = aExp; 27888c2ecf20Sopenharmony_ci goto shiftRight1; 27898c2ecf20Sopenharmony_ci } 27908c2ecf20Sopenharmony_ci 27918c2ecf20Sopenharmony_ci zSig0 = aSig + bSig; 27928c2ecf20Sopenharmony_ci 27938c2ecf20Sopenharmony_ci if ( (sbits64) zSig0 < 0 ) goto roundAndPack; 27948c2ecf20Sopenharmony_ci shiftRight1: 27958c2ecf20Sopenharmony_ci shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); 27968c2ecf20Sopenharmony_ci zSig0 |= LIT64( 0x8000000000000000 ); 27978c2ecf20Sopenharmony_ci ++zExp; 27988c2ecf20Sopenharmony_ci roundAndPack: 27998c2ecf20Sopenharmony_ci return 28008c2ecf20Sopenharmony_ci roundAndPackFloatx80( 28018c2ecf20Sopenharmony_ci roundData, zSign, zExp, zSig0, zSig1 ); 28028c2ecf20Sopenharmony_ci 28038c2ecf20Sopenharmony_ci} 28048c2ecf20Sopenharmony_ci 28058c2ecf20Sopenharmony_ci/* 28068c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 28078c2ecf20Sopenharmony_ciReturns the result of subtracting the absolute values of the extended 28088c2ecf20Sopenharmony_cidouble-precision floating-point values `a' and `b'. If `zSign' is true, 28098c2ecf20Sopenharmony_cithe difference is negated before being returned. `zSign' is ignored if the 28108c2ecf20Sopenharmony_ciresult is a NaN. The subtraction is performed according to the IEC/IEEE 28118c2ecf20Sopenharmony_ciStandard for Binary Floating-point Arithmetic. 28128c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 28138c2ecf20Sopenharmony_ci*/ 28148c2ecf20Sopenharmony_cistatic floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign ) 28158c2ecf20Sopenharmony_ci{ 28168c2ecf20Sopenharmony_ci int32 aExp, bExp, zExp; 28178c2ecf20Sopenharmony_ci bits64 aSig, bSig, zSig0, zSig1; 28188c2ecf20Sopenharmony_ci int32 expDiff; 28198c2ecf20Sopenharmony_ci floatx80 z; 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ci aSig = extractFloatx80Frac( a ); 28228c2ecf20Sopenharmony_ci aExp = extractFloatx80Exp( a ); 28238c2ecf20Sopenharmony_ci bSig = extractFloatx80Frac( b ); 28248c2ecf20Sopenharmony_ci bExp = extractFloatx80Exp( b ); 28258c2ecf20Sopenharmony_ci expDiff = aExp - bExp; 28268c2ecf20Sopenharmony_ci if ( 0 < expDiff ) goto aExpBigger; 28278c2ecf20Sopenharmony_ci if ( expDiff < 0 ) goto bExpBigger; 28288c2ecf20Sopenharmony_ci if ( aExp == 0x7FFF ) { 28298c2ecf20Sopenharmony_ci if ( (bits64) ( ( aSig | bSig )<<1 ) ) { 28308c2ecf20Sopenharmony_ci return propagateFloatx80NaN( a, b ); 28318c2ecf20Sopenharmony_ci } 28328c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 28338c2ecf20Sopenharmony_ci z.low = floatx80_default_nan_low; 28348c2ecf20Sopenharmony_ci z.high = floatx80_default_nan_high; 28358c2ecf20Sopenharmony_ci z.__padding = 0; 28368c2ecf20Sopenharmony_ci return z; 28378c2ecf20Sopenharmony_ci } 28388c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 28398c2ecf20Sopenharmony_ci aExp = 1; 28408c2ecf20Sopenharmony_ci bExp = 1; 28418c2ecf20Sopenharmony_ci } 28428c2ecf20Sopenharmony_ci zSig1 = 0; 28438c2ecf20Sopenharmony_ci if ( bSig < aSig ) goto aBigger; 28448c2ecf20Sopenharmony_ci if ( aSig < bSig ) goto bBigger; 28458c2ecf20Sopenharmony_ci return packFloatx80( roundData->mode == float_round_down, 0, 0 ); 28468c2ecf20Sopenharmony_ci bExpBigger: 28478c2ecf20Sopenharmony_ci if ( bExp == 0x7FFF ) { 28488c2ecf20Sopenharmony_ci if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); 28498c2ecf20Sopenharmony_ci return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); 28508c2ecf20Sopenharmony_ci } 28518c2ecf20Sopenharmony_ci if ( aExp == 0 ) ++expDiff; 28528c2ecf20Sopenharmony_ci shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); 28538c2ecf20Sopenharmony_ci bBigger: 28548c2ecf20Sopenharmony_ci sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); 28558c2ecf20Sopenharmony_ci zExp = bExp; 28568c2ecf20Sopenharmony_ci zSign ^= 1; 28578c2ecf20Sopenharmony_ci goto normalizeRoundAndPack; 28588c2ecf20Sopenharmony_ci aExpBigger: 28598c2ecf20Sopenharmony_ci if ( aExp == 0x7FFF ) { 28608c2ecf20Sopenharmony_ci if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); 28618c2ecf20Sopenharmony_ci return a; 28628c2ecf20Sopenharmony_ci } 28638c2ecf20Sopenharmony_ci if ( bExp == 0 ) --expDiff; 28648c2ecf20Sopenharmony_ci shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); 28658c2ecf20Sopenharmony_ci aBigger: 28668c2ecf20Sopenharmony_ci sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); 28678c2ecf20Sopenharmony_ci zExp = aExp; 28688c2ecf20Sopenharmony_ci normalizeRoundAndPack: 28698c2ecf20Sopenharmony_ci return 28708c2ecf20Sopenharmony_ci normalizeRoundAndPackFloatx80( 28718c2ecf20Sopenharmony_ci roundData, zSign, zExp, zSig0, zSig1 ); 28728c2ecf20Sopenharmony_ci 28738c2ecf20Sopenharmony_ci} 28748c2ecf20Sopenharmony_ci 28758c2ecf20Sopenharmony_ci/* 28768c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 28778c2ecf20Sopenharmony_ciReturns the result of adding the extended double-precision floating-point 28788c2ecf20Sopenharmony_civalues `a' and `b'. The operation is performed according to the IEC/IEEE 28798c2ecf20Sopenharmony_ciStandard for Binary Floating-point Arithmetic. 28808c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 28818c2ecf20Sopenharmony_ci*/ 28828c2ecf20Sopenharmony_cifloatx80 floatx80_add( struct roundingData *roundData, floatx80 a, floatx80 b ) 28838c2ecf20Sopenharmony_ci{ 28848c2ecf20Sopenharmony_ci flag aSign, bSign; 28858c2ecf20Sopenharmony_ci 28868c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 28878c2ecf20Sopenharmony_ci bSign = extractFloatx80Sign( b ); 28888c2ecf20Sopenharmony_ci if ( aSign == bSign ) { 28898c2ecf20Sopenharmony_ci return addFloatx80Sigs( roundData, a, b, aSign ); 28908c2ecf20Sopenharmony_ci } 28918c2ecf20Sopenharmony_ci else { 28928c2ecf20Sopenharmony_ci return subFloatx80Sigs( roundData, a, b, aSign ); 28938c2ecf20Sopenharmony_ci } 28948c2ecf20Sopenharmony_ci 28958c2ecf20Sopenharmony_ci} 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_ci/* 28988c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 28998c2ecf20Sopenharmony_ciReturns the result of subtracting the extended double-precision floating- 29008c2ecf20Sopenharmony_cipoint values `a' and `b'. The operation is performed according to the 29018c2ecf20Sopenharmony_ciIEC/IEEE Standard for Binary Floating-point Arithmetic. 29028c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 29038c2ecf20Sopenharmony_ci*/ 29048c2ecf20Sopenharmony_cifloatx80 floatx80_sub( struct roundingData *roundData, floatx80 a, floatx80 b ) 29058c2ecf20Sopenharmony_ci{ 29068c2ecf20Sopenharmony_ci flag aSign, bSign; 29078c2ecf20Sopenharmony_ci 29088c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 29098c2ecf20Sopenharmony_ci bSign = extractFloatx80Sign( b ); 29108c2ecf20Sopenharmony_ci if ( aSign == bSign ) { 29118c2ecf20Sopenharmony_ci return subFloatx80Sigs( roundData, a, b, aSign ); 29128c2ecf20Sopenharmony_ci } 29138c2ecf20Sopenharmony_ci else { 29148c2ecf20Sopenharmony_ci return addFloatx80Sigs( roundData, a, b, aSign ); 29158c2ecf20Sopenharmony_ci } 29168c2ecf20Sopenharmony_ci 29178c2ecf20Sopenharmony_ci} 29188c2ecf20Sopenharmony_ci 29198c2ecf20Sopenharmony_ci/* 29208c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 29218c2ecf20Sopenharmony_ciReturns the result of multiplying the extended double-precision floating- 29228c2ecf20Sopenharmony_cipoint values `a' and `b'. The operation is performed according to the 29238c2ecf20Sopenharmony_ciIEC/IEEE Standard for Binary Floating-point Arithmetic. 29248c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 29258c2ecf20Sopenharmony_ci*/ 29268c2ecf20Sopenharmony_cifloatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b ) 29278c2ecf20Sopenharmony_ci{ 29288c2ecf20Sopenharmony_ci flag aSign, bSign, zSign; 29298c2ecf20Sopenharmony_ci int32 aExp, bExp, zExp; 29308c2ecf20Sopenharmony_ci bits64 aSig, bSig, zSig0, zSig1; 29318c2ecf20Sopenharmony_ci floatx80 z; 29328c2ecf20Sopenharmony_ci 29338c2ecf20Sopenharmony_ci aSig = extractFloatx80Frac( a ); 29348c2ecf20Sopenharmony_ci aExp = extractFloatx80Exp( a ); 29358c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 29368c2ecf20Sopenharmony_ci bSig = extractFloatx80Frac( b ); 29378c2ecf20Sopenharmony_ci bExp = extractFloatx80Exp( b ); 29388c2ecf20Sopenharmony_ci bSign = extractFloatx80Sign( b ); 29398c2ecf20Sopenharmony_ci zSign = aSign ^ bSign; 29408c2ecf20Sopenharmony_ci if ( aExp == 0x7FFF ) { 29418c2ecf20Sopenharmony_ci if ( (bits64) ( aSig<<1 ) 29428c2ecf20Sopenharmony_ci || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { 29438c2ecf20Sopenharmony_ci return propagateFloatx80NaN( a, b ); 29448c2ecf20Sopenharmony_ci } 29458c2ecf20Sopenharmony_ci if ( ( bExp | bSig ) == 0 ) goto invalid; 29468c2ecf20Sopenharmony_ci return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); 29478c2ecf20Sopenharmony_ci } 29488c2ecf20Sopenharmony_ci if ( bExp == 0x7FFF ) { 29498c2ecf20Sopenharmony_ci if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); 29508c2ecf20Sopenharmony_ci if ( ( aExp | aSig ) == 0 ) { 29518c2ecf20Sopenharmony_ci invalid: 29528c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 29538c2ecf20Sopenharmony_ci z.low = floatx80_default_nan_low; 29548c2ecf20Sopenharmony_ci z.high = floatx80_default_nan_high; 29558c2ecf20Sopenharmony_ci z.__padding = 0; 29568c2ecf20Sopenharmony_ci return z; 29578c2ecf20Sopenharmony_ci } 29588c2ecf20Sopenharmony_ci return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); 29598c2ecf20Sopenharmony_ci } 29608c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 29618c2ecf20Sopenharmony_ci if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); 29628c2ecf20Sopenharmony_ci normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); 29638c2ecf20Sopenharmony_ci } 29648c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 29658c2ecf20Sopenharmony_ci if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); 29668c2ecf20Sopenharmony_ci normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); 29678c2ecf20Sopenharmony_ci } 29688c2ecf20Sopenharmony_ci zExp = aExp + bExp - 0x3FFE; 29698c2ecf20Sopenharmony_ci mul64To128( aSig, bSig, &zSig0, &zSig1 ); 29708c2ecf20Sopenharmony_ci if ( 0 < (sbits64) zSig0 ) { 29718c2ecf20Sopenharmony_ci shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); 29728c2ecf20Sopenharmony_ci --zExp; 29738c2ecf20Sopenharmony_ci } 29748c2ecf20Sopenharmony_ci return 29758c2ecf20Sopenharmony_ci roundAndPackFloatx80( 29768c2ecf20Sopenharmony_ci roundData, zSign, zExp, zSig0, zSig1 ); 29778c2ecf20Sopenharmony_ci 29788c2ecf20Sopenharmony_ci} 29798c2ecf20Sopenharmony_ci 29808c2ecf20Sopenharmony_ci/* 29818c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 29828c2ecf20Sopenharmony_ciReturns the result of dividing the extended double-precision floating-point 29838c2ecf20Sopenharmony_civalue `a' by the corresponding value `b'. The operation is performed 29848c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 29858c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 29868c2ecf20Sopenharmony_ci*/ 29878c2ecf20Sopenharmony_cifloatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b ) 29888c2ecf20Sopenharmony_ci{ 29898c2ecf20Sopenharmony_ci flag aSign, bSign, zSign; 29908c2ecf20Sopenharmony_ci int32 aExp, bExp, zExp; 29918c2ecf20Sopenharmony_ci bits64 aSig, bSig, zSig0, zSig1; 29928c2ecf20Sopenharmony_ci bits64 rem0, rem1, rem2, term0, term1, term2; 29938c2ecf20Sopenharmony_ci floatx80 z; 29948c2ecf20Sopenharmony_ci 29958c2ecf20Sopenharmony_ci aSig = extractFloatx80Frac( a ); 29968c2ecf20Sopenharmony_ci aExp = extractFloatx80Exp( a ); 29978c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 29988c2ecf20Sopenharmony_ci bSig = extractFloatx80Frac( b ); 29998c2ecf20Sopenharmony_ci bExp = extractFloatx80Exp( b ); 30008c2ecf20Sopenharmony_ci bSign = extractFloatx80Sign( b ); 30018c2ecf20Sopenharmony_ci zSign = aSign ^ bSign; 30028c2ecf20Sopenharmony_ci if ( aExp == 0x7FFF ) { 30038c2ecf20Sopenharmony_ci if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); 30048c2ecf20Sopenharmony_ci if ( bExp == 0x7FFF ) { 30058c2ecf20Sopenharmony_ci if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); 30068c2ecf20Sopenharmony_ci goto invalid; 30078c2ecf20Sopenharmony_ci } 30088c2ecf20Sopenharmony_ci return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); 30098c2ecf20Sopenharmony_ci } 30108c2ecf20Sopenharmony_ci if ( bExp == 0x7FFF ) { 30118c2ecf20Sopenharmony_ci if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); 30128c2ecf20Sopenharmony_ci return packFloatx80( zSign, 0, 0 ); 30138c2ecf20Sopenharmony_ci } 30148c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 30158c2ecf20Sopenharmony_ci if ( bSig == 0 ) { 30168c2ecf20Sopenharmony_ci if ( ( aExp | aSig ) == 0 ) { 30178c2ecf20Sopenharmony_ci invalid: 30188c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 30198c2ecf20Sopenharmony_ci z.low = floatx80_default_nan_low; 30208c2ecf20Sopenharmony_ci z.high = floatx80_default_nan_high; 30218c2ecf20Sopenharmony_ci z.__padding = 0; 30228c2ecf20Sopenharmony_ci return z; 30238c2ecf20Sopenharmony_ci } 30248c2ecf20Sopenharmony_ci roundData->exception |= float_flag_divbyzero; 30258c2ecf20Sopenharmony_ci return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); 30268c2ecf20Sopenharmony_ci } 30278c2ecf20Sopenharmony_ci normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); 30288c2ecf20Sopenharmony_ci } 30298c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 30308c2ecf20Sopenharmony_ci if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); 30318c2ecf20Sopenharmony_ci normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); 30328c2ecf20Sopenharmony_ci } 30338c2ecf20Sopenharmony_ci zExp = aExp - bExp + 0x3FFE; 30348c2ecf20Sopenharmony_ci rem1 = 0; 30358c2ecf20Sopenharmony_ci if ( bSig <= aSig ) { 30368c2ecf20Sopenharmony_ci shift128Right( aSig, 0, 1, &aSig, &rem1 ); 30378c2ecf20Sopenharmony_ci ++zExp; 30388c2ecf20Sopenharmony_ci } 30398c2ecf20Sopenharmony_ci zSig0 = estimateDiv128To64( aSig, rem1, bSig ); 30408c2ecf20Sopenharmony_ci mul64To128( bSig, zSig0, &term0, &term1 ); 30418c2ecf20Sopenharmony_ci sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); 30428c2ecf20Sopenharmony_ci while ( (sbits64) rem0 < 0 ) { 30438c2ecf20Sopenharmony_ci --zSig0; 30448c2ecf20Sopenharmony_ci add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); 30458c2ecf20Sopenharmony_ci } 30468c2ecf20Sopenharmony_ci zSig1 = estimateDiv128To64( rem1, 0, bSig ); 30478c2ecf20Sopenharmony_ci if ( (bits64) ( zSig1<<1 ) <= 8 ) { 30488c2ecf20Sopenharmony_ci mul64To128( bSig, zSig1, &term1, &term2 ); 30498c2ecf20Sopenharmony_ci sub128( rem1, 0, term1, term2, &rem1, &rem2 ); 30508c2ecf20Sopenharmony_ci while ( (sbits64) rem1 < 0 ) { 30518c2ecf20Sopenharmony_ci --zSig1; 30528c2ecf20Sopenharmony_ci add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); 30538c2ecf20Sopenharmony_ci } 30548c2ecf20Sopenharmony_ci zSig1 |= ( ( rem1 | rem2 ) != 0 ); 30558c2ecf20Sopenharmony_ci } 30568c2ecf20Sopenharmony_ci return 30578c2ecf20Sopenharmony_ci roundAndPackFloatx80( 30588c2ecf20Sopenharmony_ci roundData, zSign, zExp, zSig0, zSig1 ); 30598c2ecf20Sopenharmony_ci 30608c2ecf20Sopenharmony_ci} 30618c2ecf20Sopenharmony_ci 30628c2ecf20Sopenharmony_ci/* 30638c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 30648c2ecf20Sopenharmony_ciReturns the remainder of the extended double-precision floating-point value 30658c2ecf20Sopenharmony_ci`a' with respect to the corresponding value `b'. The operation is performed 30668c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 30678c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 30688c2ecf20Sopenharmony_ci*/ 30698c2ecf20Sopenharmony_cifloatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b ) 30708c2ecf20Sopenharmony_ci{ 30718c2ecf20Sopenharmony_ci flag aSign, bSign, zSign; 30728c2ecf20Sopenharmony_ci int32 aExp, bExp, expDiff; 30738c2ecf20Sopenharmony_ci bits64 aSig0, aSig1, bSig; 30748c2ecf20Sopenharmony_ci bits64 q, term0, term1, alternateASig0, alternateASig1; 30758c2ecf20Sopenharmony_ci floatx80 z; 30768c2ecf20Sopenharmony_ci 30778c2ecf20Sopenharmony_ci aSig0 = extractFloatx80Frac( a ); 30788c2ecf20Sopenharmony_ci aExp = extractFloatx80Exp( a ); 30798c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 30808c2ecf20Sopenharmony_ci bSig = extractFloatx80Frac( b ); 30818c2ecf20Sopenharmony_ci bExp = extractFloatx80Exp( b ); 30828c2ecf20Sopenharmony_ci bSign = extractFloatx80Sign( b ); 30838c2ecf20Sopenharmony_ci if ( aExp == 0x7FFF ) { 30848c2ecf20Sopenharmony_ci if ( (bits64) ( aSig0<<1 ) 30858c2ecf20Sopenharmony_ci || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { 30868c2ecf20Sopenharmony_ci return propagateFloatx80NaN( a, b ); 30878c2ecf20Sopenharmony_ci } 30888c2ecf20Sopenharmony_ci goto invalid; 30898c2ecf20Sopenharmony_ci } 30908c2ecf20Sopenharmony_ci if ( bExp == 0x7FFF ) { 30918c2ecf20Sopenharmony_ci if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); 30928c2ecf20Sopenharmony_ci return a; 30938c2ecf20Sopenharmony_ci } 30948c2ecf20Sopenharmony_ci if ( bExp == 0 ) { 30958c2ecf20Sopenharmony_ci if ( bSig == 0 ) { 30968c2ecf20Sopenharmony_ci invalid: 30978c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 30988c2ecf20Sopenharmony_ci z.low = floatx80_default_nan_low; 30998c2ecf20Sopenharmony_ci z.high = floatx80_default_nan_high; 31008c2ecf20Sopenharmony_ci z.__padding = 0; 31018c2ecf20Sopenharmony_ci return z; 31028c2ecf20Sopenharmony_ci } 31038c2ecf20Sopenharmony_ci normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); 31048c2ecf20Sopenharmony_ci } 31058c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 31068c2ecf20Sopenharmony_ci if ( (bits64) ( aSig0<<1 ) == 0 ) return a; 31078c2ecf20Sopenharmony_ci normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); 31088c2ecf20Sopenharmony_ci } 31098c2ecf20Sopenharmony_ci bSig |= LIT64( 0x8000000000000000 ); 31108c2ecf20Sopenharmony_ci zSign = aSign; 31118c2ecf20Sopenharmony_ci expDiff = aExp - bExp; 31128c2ecf20Sopenharmony_ci aSig1 = 0; 31138c2ecf20Sopenharmony_ci if ( expDiff < 0 ) { 31148c2ecf20Sopenharmony_ci if ( expDiff < -1 ) return a; 31158c2ecf20Sopenharmony_ci shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); 31168c2ecf20Sopenharmony_ci expDiff = 0; 31178c2ecf20Sopenharmony_ci } 31188c2ecf20Sopenharmony_ci q = ( bSig <= aSig0 ); 31198c2ecf20Sopenharmony_ci if ( q ) aSig0 -= bSig; 31208c2ecf20Sopenharmony_ci expDiff -= 64; 31218c2ecf20Sopenharmony_ci while ( 0 < expDiff ) { 31228c2ecf20Sopenharmony_ci q = estimateDiv128To64( aSig0, aSig1, bSig ); 31238c2ecf20Sopenharmony_ci q = ( 2 < q ) ? q - 2 : 0; 31248c2ecf20Sopenharmony_ci mul64To128( bSig, q, &term0, &term1 ); 31258c2ecf20Sopenharmony_ci sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); 31268c2ecf20Sopenharmony_ci shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); 31278c2ecf20Sopenharmony_ci expDiff -= 62; 31288c2ecf20Sopenharmony_ci } 31298c2ecf20Sopenharmony_ci expDiff += 64; 31308c2ecf20Sopenharmony_ci if ( 0 < expDiff ) { 31318c2ecf20Sopenharmony_ci q = estimateDiv128To64( aSig0, aSig1, bSig ); 31328c2ecf20Sopenharmony_ci q = ( 2 < q ) ? q - 2 : 0; 31338c2ecf20Sopenharmony_ci q >>= 64 - expDiff; 31348c2ecf20Sopenharmony_ci mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); 31358c2ecf20Sopenharmony_ci sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); 31368c2ecf20Sopenharmony_ci shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); 31378c2ecf20Sopenharmony_ci while ( le128( term0, term1, aSig0, aSig1 ) ) { 31388c2ecf20Sopenharmony_ci ++q; 31398c2ecf20Sopenharmony_ci sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); 31408c2ecf20Sopenharmony_ci } 31418c2ecf20Sopenharmony_ci } 31428c2ecf20Sopenharmony_ci else { 31438c2ecf20Sopenharmony_ci term1 = 0; 31448c2ecf20Sopenharmony_ci term0 = bSig; 31458c2ecf20Sopenharmony_ci } 31468c2ecf20Sopenharmony_ci sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); 31478c2ecf20Sopenharmony_ci if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) 31488c2ecf20Sopenharmony_ci || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) 31498c2ecf20Sopenharmony_ci && ( q & 1 ) ) 31508c2ecf20Sopenharmony_ci ) { 31518c2ecf20Sopenharmony_ci aSig0 = alternateASig0; 31528c2ecf20Sopenharmony_ci aSig1 = alternateASig1; 31538c2ecf20Sopenharmony_ci zSign = ! zSign; 31548c2ecf20Sopenharmony_ci } 31558c2ecf20Sopenharmony_ci 31568c2ecf20Sopenharmony_ci return 31578c2ecf20Sopenharmony_ci normalizeRoundAndPackFloatx80( 31588c2ecf20Sopenharmony_ci roundData, zSign, bExp + expDiff, aSig0, aSig1 ); 31598c2ecf20Sopenharmony_ci 31608c2ecf20Sopenharmony_ci} 31618c2ecf20Sopenharmony_ci 31628c2ecf20Sopenharmony_ci/* 31638c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 31648c2ecf20Sopenharmony_ciReturns the square root of the extended double-precision floating-point 31658c2ecf20Sopenharmony_civalue `a'. The operation is performed according to the IEC/IEEE Standard 31668c2ecf20Sopenharmony_cifor Binary Floating-point Arithmetic. 31678c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 31688c2ecf20Sopenharmony_ci*/ 31698c2ecf20Sopenharmony_cifloatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a ) 31708c2ecf20Sopenharmony_ci{ 31718c2ecf20Sopenharmony_ci flag aSign; 31728c2ecf20Sopenharmony_ci int32 aExp, zExp; 31738c2ecf20Sopenharmony_ci bits64 aSig0, aSig1, zSig0, zSig1; 31748c2ecf20Sopenharmony_ci bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; 31758c2ecf20Sopenharmony_ci bits64 shiftedRem0, shiftedRem1; 31768c2ecf20Sopenharmony_ci floatx80 z; 31778c2ecf20Sopenharmony_ci 31788c2ecf20Sopenharmony_ci aSig0 = extractFloatx80Frac( a ); 31798c2ecf20Sopenharmony_ci aExp = extractFloatx80Exp( a ); 31808c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 31818c2ecf20Sopenharmony_ci if ( aExp == 0x7FFF ) { 31828c2ecf20Sopenharmony_ci if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); 31838c2ecf20Sopenharmony_ci if ( ! aSign ) return a; 31848c2ecf20Sopenharmony_ci goto invalid; 31858c2ecf20Sopenharmony_ci } 31868c2ecf20Sopenharmony_ci if ( aSign ) { 31878c2ecf20Sopenharmony_ci if ( ( aExp | aSig0 ) == 0 ) return a; 31888c2ecf20Sopenharmony_ci invalid: 31898c2ecf20Sopenharmony_ci roundData->exception |= float_flag_invalid; 31908c2ecf20Sopenharmony_ci z.low = floatx80_default_nan_low; 31918c2ecf20Sopenharmony_ci z.high = floatx80_default_nan_high; 31928c2ecf20Sopenharmony_ci z.__padding = 0; 31938c2ecf20Sopenharmony_ci return z; 31948c2ecf20Sopenharmony_ci } 31958c2ecf20Sopenharmony_ci if ( aExp == 0 ) { 31968c2ecf20Sopenharmony_ci if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); 31978c2ecf20Sopenharmony_ci normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); 31988c2ecf20Sopenharmony_ci } 31998c2ecf20Sopenharmony_ci zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; 32008c2ecf20Sopenharmony_ci zSig0 = estimateSqrt32( aExp, aSig0>>32 ); 32018c2ecf20Sopenharmony_ci zSig0 <<= 31; 32028c2ecf20Sopenharmony_ci aSig1 = 0; 32038c2ecf20Sopenharmony_ci shift128Right( aSig0, 0, ( aExp & 1 ) + 2, &aSig0, &aSig1 ); 32048c2ecf20Sopenharmony_ci zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0 ) + zSig0 + 4; 32058c2ecf20Sopenharmony_ci if ( 0 <= (sbits64) zSig0 ) zSig0 = LIT64( 0xFFFFFFFFFFFFFFFF ); 32068c2ecf20Sopenharmony_ci shortShift128Left( aSig0, aSig1, 2, &aSig0, &aSig1 ); 32078c2ecf20Sopenharmony_ci mul64To128( zSig0, zSig0, &term0, &term1 ); 32088c2ecf20Sopenharmony_ci sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); 32098c2ecf20Sopenharmony_ci while ( (sbits64) rem0 < 0 ) { 32108c2ecf20Sopenharmony_ci --zSig0; 32118c2ecf20Sopenharmony_ci shortShift128Left( 0, zSig0, 1, &term0, &term1 ); 32128c2ecf20Sopenharmony_ci term1 |= 1; 32138c2ecf20Sopenharmony_ci add128( rem0, rem1, term0, term1, &rem0, &rem1 ); 32148c2ecf20Sopenharmony_ci } 32158c2ecf20Sopenharmony_ci shortShift128Left( rem0, rem1, 63, &shiftedRem0, &shiftedRem1 ); 32168c2ecf20Sopenharmony_ci zSig1 = estimateDiv128To64( shiftedRem0, shiftedRem1, zSig0 ); 32178c2ecf20Sopenharmony_ci if ( (bits64) ( zSig1<<1 ) <= 10 ) { 32188c2ecf20Sopenharmony_ci if ( zSig1 == 0 ) zSig1 = 1; 32198c2ecf20Sopenharmony_ci mul64To128( zSig0, zSig1, &term1, &term2 ); 32208c2ecf20Sopenharmony_ci shortShift128Left( term1, term2, 1, &term1, &term2 ); 32218c2ecf20Sopenharmony_ci sub128( rem1, 0, term1, term2, &rem1, &rem2 ); 32228c2ecf20Sopenharmony_ci mul64To128( zSig1, zSig1, &term2, &term3 ); 32238c2ecf20Sopenharmony_ci sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); 32248c2ecf20Sopenharmony_ci while ( (sbits64) rem1 < 0 ) { 32258c2ecf20Sopenharmony_ci --zSig1; 32268c2ecf20Sopenharmony_ci shortShift192Left( 0, zSig0, zSig1, 1, &term1, &term2, &term3 ); 32278c2ecf20Sopenharmony_ci term3 |= 1; 32288c2ecf20Sopenharmony_ci add192( 32298c2ecf20Sopenharmony_ci rem1, rem2, rem3, term1, term2, term3, &rem1, &rem2, &rem3 ); 32308c2ecf20Sopenharmony_ci } 32318c2ecf20Sopenharmony_ci zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); 32328c2ecf20Sopenharmony_ci } 32338c2ecf20Sopenharmony_ci return 32348c2ecf20Sopenharmony_ci roundAndPackFloatx80( 32358c2ecf20Sopenharmony_ci roundData, 0, zExp, zSig0, zSig1 ); 32368c2ecf20Sopenharmony_ci 32378c2ecf20Sopenharmony_ci} 32388c2ecf20Sopenharmony_ci 32398c2ecf20Sopenharmony_ci/* 32408c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 32418c2ecf20Sopenharmony_ciReturns 1 if the extended double-precision floating-point value `a' is 32428c2ecf20Sopenharmony_ciequal to the corresponding value `b', and 0 otherwise. The comparison is 32438c2ecf20Sopenharmony_ciperformed according to the IEC/IEEE Standard for Binary Floating-point 32448c2ecf20Sopenharmony_ciArithmetic. 32458c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 32468c2ecf20Sopenharmony_ci*/ 32478c2ecf20Sopenharmony_ciflag floatx80_eq( floatx80 a, floatx80 b ) 32488c2ecf20Sopenharmony_ci{ 32498c2ecf20Sopenharmony_ci 32508c2ecf20Sopenharmony_ci if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) 32518c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( a )<<1 ) ) 32528c2ecf20Sopenharmony_ci || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 32538c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 32548c2ecf20Sopenharmony_ci ) { 32558c2ecf20Sopenharmony_ci if ( floatx80_is_signaling_nan( a ) 32568c2ecf20Sopenharmony_ci || floatx80_is_signaling_nan( b ) ) { 32578c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 32588c2ecf20Sopenharmony_ci } 32598c2ecf20Sopenharmony_ci return 0; 32608c2ecf20Sopenharmony_ci } 32618c2ecf20Sopenharmony_ci return 32628c2ecf20Sopenharmony_ci ( a.low == b.low ) 32638c2ecf20Sopenharmony_ci && ( ( a.high == b.high ) 32648c2ecf20Sopenharmony_ci || ( ( a.low == 0 ) 32658c2ecf20Sopenharmony_ci && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) 32668c2ecf20Sopenharmony_ci ); 32678c2ecf20Sopenharmony_ci 32688c2ecf20Sopenharmony_ci} 32698c2ecf20Sopenharmony_ci 32708c2ecf20Sopenharmony_ci/* 32718c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 32728c2ecf20Sopenharmony_ciReturns 1 if the extended double-precision floating-point value `a' is 32738c2ecf20Sopenharmony_ciless than or equal to the corresponding value `b', and 0 otherwise. The 32748c2ecf20Sopenharmony_cicomparison is performed according to the IEC/IEEE Standard for Binary 32758c2ecf20Sopenharmony_ciFloating-point Arithmetic. 32768c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 32778c2ecf20Sopenharmony_ci*/ 32788c2ecf20Sopenharmony_ciflag floatx80_le( floatx80 a, floatx80 b ) 32798c2ecf20Sopenharmony_ci{ 32808c2ecf20Sopenharmony_ci flag aSign, bSign; 32818c2ecf20Sopenharmony_ci 32828c2ecf20Sopenharmony_ci if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) 32838c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( a )<<1 ) ) 32848c2ecf20Sopenharmony_ci || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 32858c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 32868c2ecf20Sopenharmony_ci ) { 32878c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 32888c2ecf20Sopenharmony_ci return 0; 32898c2ecf20Sopenharmony_ci } 32908c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 32918c2ecf20Sopenharmony_ci bSign = extractFloatx80Sign( b ); 32928c2ecf20Sopenharmony_ci if ( aSign != bSign ) { 32938c2ecf20Sopenharmony_ci return 32948c2ecf20Sopenharmony_ci aSign 32958c2ecf20Sopenharmony_ci || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) 32968c2ecf20Sopenharmony_ci == 0 ); 32978c2ecf20Sopenharmony_ci } 32988c2ecf20Sopenharmony_ci return 32998c2ecf20Sopenharmony_ci aSign ? le128( b.high, b.low, a.high, a.low ) 33008c2ecf20Sopenharmony_ci : le128( a.high, a.low, b.high, b.low ); 33018c2ecf20Sopenharmony_ci 33028c2ecf20Sopenharmony_ci} 33038c2ecf20Sopenharmony_ci 33048c2ecf20Sopenharmony_ci/* 33058c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 33068c2ecf20Sopenharmony_ciReturns 1 if the extended double-precision floating-point value `a' is 33078c2ecf20Sopenharmony_ciless than the corresponding value `b', and 0 otherwise. The comparison 33088c2ecf20Sopenharmony_ciis performed according to the IEC/IEEE Standard for Binary Floating-point 33098c2ecf20Sopenharmony_ciArithmetic. 33108c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 33118c2ecf20Sopenharmony_ci*/ 33128c2ecf20Sopenharmony_ciflag floatx80_lt( floatx80 a, floatx80 b ) 33138c2ecf20Sopenharmony_ci{ 33148c2ecf20Sopenharmony_ci flag aSign, bSign; 33158c2ecf20Sopenharmony_ci 33168c2ecf20Sopenharmony_ci if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) 33178c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( a )<<1 ) ) 33188c2ecf20Sopenharmony_ci || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 33198c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 33208c2ecf20Sopenharmony_ci ) { 33218c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 33228c2ecf20Sopenharmony_ci return 0; 33238c2ecf20Sopenharmony_ci } 33248c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 33258c2ecf20Sopenharmony_ci bSign = extractFloatx80Sign( b ); 33268c2ecf20Sopenharmony_ci if ( aSign != bSign ) { 33278c2ecf20Sopenharmony_ci return 33288c2ecf20Sopenharmony_ci aSign 33298c2ecf20Sopenharmony_ci && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) 33308c2ecf20Sopenharmony_ci != 0 ); 33318c2ecf20Sopenharmony_ci } 33328c2ecf20Sopenharmony_ci return 33338c2ecf20Sopenharmony_ci aSign ? lt128( b.high, b.low, a.high, a.low ) 33348c2ecf20Sopenharmony_ci : lt128( a.high, a.low, b.high, b.low ); 33358c2ecf20Sopenharmony_ci 33368c2ecf20Sopenharmony_ci} 33378c2ecf20Sopenharmony_ci 33388c2ecf20Sopenharmony_ci/* 33398c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 33408c2ecf20Sopenharmony_ciReturns 1 if the extended double-precision floating-point value `a' is equal 33418c2ecf20Sopenharmony_cito the corresponding value `b', and 0 otherwise. The invalid exception is 33428c2ecf20Sopenharmony_ciraised if either operand is a NaN. Otherwise, the comparison is performed 33438c2ecf20Sopenharmony_ciaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic. 33448c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 33458c2ecf20Sopenharmony_ci*/ 33468c2ecf20Sopenharmony_ciflag floatx80_eq_signaling( floatx80 a, floatx80 b ) 33478c2ecf20Sopenharmony_ci{ 33488c2ecf20Sopenharmony_ci 33498c2ecf20Sopenharmony_ci if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) 33508c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( a )<<1 ) ) 33518c2ecf20Sopenharmony_ci || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 33528c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 33538c2ecf20Sopenharmony_ci ) { 33548c2ecf20Sopenharmony_ci float_raise( float_flag_invalid ); 33558c2ecf20Sopenharmony_ci return 0; 33568c2ecf20Sopenharmony_ci } 33578c2ecf20Sopenharmony_ci return 33588c2ecf20Sopenharmony_ci ( a.low == b.low ) 33598c2ecf20Sopenharmony_ci && ( ( a.high == b.high ) 33608c2ecf20Sopenharmony_ci || ( ( a.low == 0 ) 33618c2ecf20Sopenharmony_ci && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) 33628c2ecf20Sopenharmony_ci ); 33638c2ecf20Sopenharmony_ci 33648c2ecf20Sopenharmony_ci} 33658c2ecf20Sopenharmony_ci 33668c2ecf20Sopenharmony_ci/* 33678c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 33688c2ecf20Sopenharmony_ciReturns 1 if the extended double-precision floating-point value `a' is less 33698c2ecf20Sopenharmony_cithan or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs 33708c2ecf20Sopenharmony_cido not cause an exception. Otherwise, the comparison is performed according 33718c2ecf20Sopenharmony_cito the IEC/IEEE Standard for Binary Floating-point Arithmetic. 33728c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 33738c2ecf20Sopenharmony_ci*/ 33748c2ecf20Sopenharmony_ciflag floatx80_le_quiet( floatx80 a, floatx80 b ) 33758c2ecf20Sopenharmony_ci{ 33768c2ecf20Sopenharmony_ci flag aSign, bSign; 33778c2ecf20Sopenharmony_ci 33788c2ecf20Sopenharmony_ci if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) 33798c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( a )<<1 ) ) 33808c2ecf20Sopenharmony_ci || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 33818c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 33828c2ecf20Sopenharmony_ci ) { 33838c2ecf20Sopenharmony_ci /* Do nothing, even if NaN as we're quiet */ 33848c2ecf20Sopenharmony_ci return 0; 33858c2ecf20Sopenharmony_ci } 33868c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 33878c2ecf20Sopenharmony_ci bSign = extractFloatx80Sign( b ); 33888c2ecf20Sopenharmony_ci if ( aSign != bSign ) { 33898c2ecf20Sopenharmony_ci return 33908c2ecf20Sopenharmony_ci aSign 33918c2ecf20Sopenharmony_ci || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) 33928c2ecf20Sopenharmony_ci == 0 ); 33938c2ecf20Sopenharmony_ci } 33948c2ecf20Sopenharmony_ci return 33958c2ecf20Sopenharmony_ci aSign ? le128( b.high, b.low, a.high, a.low ) 33968c2ecf20Sopenharmony_ci : le128( a.high, a.low, b.high, b.low ); 33978c2ecf20Sopenharmony_ci 33988c2ecf20Sopenharmony_ci} 33998c2ecf20Sopenharmony_ci 34008c2ecf20Sopenharmony_ci/* 34018c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 34028c2ecf20Sopenharmony_ciReturns 1 if the extended double-precision floating-point value `a' is less 34038c2ecf20Sopenharmony_cithan the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause 34048c2ecf20Sopenharmony_cian exception. Otherwise, the comparison is performed according to the 34058c2ecf20Sopenharmony_ciIEC/IEEE Standard for Binary Floating-point Arithmetic. 34068c2ecf20Sopenharmony_ci------------------------------------------------------------------------------- 34078c2ecf20Sopenharmony_ci*/ 34088c2ecf20Sopenharmony_ciflag floatx80_lt_quiet( floatx80 a, floatx80 b ) 34098c2ecf20Sopenharmony_ci{ 34108c2ecf20Sopenharmony_ci flag aSign, bSign; 34118c2ecf20Sopenharmony_ci 34128c2ecf20Sopenharmony_ci if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) 34138c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( a )<<1 ) ) 34148c2ecf20Sopenharmony_ci || ( ( extractFloatx80Exp( b ) == 0x7FFF ) 34158c2ecf20Sopenharmony_ci && (bits64) ( extractFloatx80Frac( b )<<1 ) ) 34168c2ecf20Sopenharmony_ci ) { 34178c2ecf20Sopenharmony_ci /* Do nothing, even if NaN as we're quiet */ 34188c2ecf20Sopenharmony_ci return 0; 34198c2ecf20Sopenharmony_ci } 34208c2ecf20Sopenharmony_ci aSign = extractFloatx80Sign( a ); 34218c2ecf20Sopenharmony_ci bSign = extractFloatx80Sign( b ); 34228c2ecf20Sopenharmony_ci if ( aSign != bSign ) { 34238c2ecf20Sopenharmony_ci return 34248c2ecf20Sopenharmony_ci aSign 34258c2ecf20Sopenharmony_ci && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) 34268c2ecf20Sopenharmony_ci != 0 ); 34278c2ecf20Sopenharmony_ci } 34288c2ecf20Sopenharmony_ci return 34298c2ecf20Sopenharmony_ci aSign ? lt128( b.high, b.low, a.high, a.low ) 34308c2ecf20Sopenharmony_ci : lt128( a.high, a.low, b.high, b.low ); 34318c2ecf20Sopenharmony_ci 34328c2ecf20Sopenharmony_ci} 34338c2ecf20Sopenharmony_ci 34348c2ecf20Sopenharmony_ci#endif 34358c2ecf20Sopenharmony_ci 3436