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