^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) ===============================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) This C source file is part of the SoftFloat IEC/IEEE Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) Arithmetic Package, Release 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) Written by John R. Hauser. This work was made possible in part by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) International Computer Science Institute, located at Suite 600, 1947 Center
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) Street, Berkeley, California 94704. Funding was partially provided by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) National Science Foundation under grant MIP-9311980. The original version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) of this code was written as part of a project to build a fixed-point vector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) processor in collaboration with the University of California at Berkeley,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) overseen by Profs. Nelson Morgan and John Wawrzynek. More information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) is available through the web page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) http://www.jhauser.us/arithmetic/SoftFloat-2b/SoftFloat-source.txt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) Derivative works are acceptable, even for commercial purposes, so long as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) (1) they include prominent notice that the work is derivative, and (2) they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) include prominent notice akin to these three paragraphs for those parts of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) this code that are retained.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) ===============================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <asm/div64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include "fpa11.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) //#include "milieu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) //#include "softfloat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) Primitive arithmetic functions, including multi-word arithmetic, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) division and square root approximations. (Can be specialized to target if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) desired.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include "softfloat-macros"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) Functions and definitions to determine: (1) whether tininess for underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) is detected before or after rounding by default, (2) what (if anything)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) happens when exceptions are raised, (3) how signaling NaNs are distinguished
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) are propagated from function inputs to output. These details are target-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) specific.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include "softfloat-specialize"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) and 7, and returns the properly rounded 32-bit integer corresponding to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) input. If `zSign' is nonzero, the input is negated before being converted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) to an integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) input is simply rounded to an integer, with the inexact exception raised if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) the input cannot be represented exactly as an integer. If the fixed-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) input is too large, however, the invalid exception is raised and the largest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) positive or negative integer is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static int32 roundAndPackInt32( struct roundingData *roundData, flag zSign, bits64 absZ )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int8 roundingMode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) flag roundNearestEven;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int8 roundIncrement, roundBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int32 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) roundingMode = roundData->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) roundNearestEven = ( roundingMode == float_round_nearest_even );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) roundIncrement = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if ( ! roundNearestEven ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if ( roundingMode == float_round_to_zero ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) roundIncrement = 0x7F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if ( zSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if ( roundingMode == float_round_up ) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if ( roundingMode == float_round_down ) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) roundBits = absZ & 0x7F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) absZ = ( absZ + roundIncrement )>>7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) z = absZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if ( zSign ) z = - z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return zSign ? 0x80000000 : 0x7FFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if ( roundBits ) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) Returns the fraction bits of the single-precision floating-point value `a'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) INLINE bits32 extractFloat32Frac( float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return a & 0x007FFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) Returns the exponent bits of the single-precision floating-point value `a'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) INLINE int16 extractFloat32Exp( float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return ( a>>23 ) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) Returns the sign bit of the single-precision floating-point value `a'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #if 0 /* in softfloat.h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) INLINE flag extractFloat32Sign( float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return a>>31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) Normalizes the subnormal single-precision floating-point value represented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) by the denormalized significand `aSig'. The normalized exponent and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) significand are stored at the locations pointed to by `zExpPtr' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) `zSigPtr', respectively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int8 shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) shiftCount = countLeadingZeros32( aSig ) - 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) *zSigPtr = aSig<<shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) *zExpPtr = 1 - shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) single-precision floating-point value, returning the result. After being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) shifted into the proper positions, the three fields are simply added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) together to form the result. This means that any integer portion of `zSig'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) will be added into the exponent. Since a properly normalized significand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) will have an integer portion equal to 1, the `zExp' input should be 1 less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) than the desired result exponent whenever `zSig' is a complete, normalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) significand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) float32 f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) __asm__("@ packFloat32 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) mov %0, %1, asl #31 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) orr %0, %2, asl #23 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) orr %0, %3"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) : /* no outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) : "g" (f), "g" (zSign), "g" (zExp), "g" (zSig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) : "cc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) Takes an abstract floating-point value having sign `zSign', exponent `zExp',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) and significand `zSig', and returns the proper single-precision floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) point value corresponding to the abstract input. Ordinarily, the abstract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) value is simply rounded and packed into the single-precision format, with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) the inexact exception raised if the abstract input cannot be represented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) exactly. If the abstract value is too large, however, the overflow and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) inexact exceptions are raised and an infinity or maximal finite value is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) returned. If the abstract value is too small, the input value is rounded to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) a subnormal number, and the underflow and inexact exceptions are raised if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) the abstract input cannot be represented exactly as a subnormal single-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) precision floating-point number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) The input significand `zSig' has its binary point between bits 30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) and 29, which is 7 bits to the left of the usual location. This shifted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) significand must be normalized or smaller. If `zSig' is not normalized,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) `zExp' must be 0; in that case, the result returned is a subnormal number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) and it must not require rounding. In the usual case that `zSig' is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) The handling of underflow and overflow follows the IEC/IEEE Standard for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static float32 roundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int8 roundingMode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) flag roundNearestEven;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int8 roundIncrement, roundBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) flag isTiny;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) roundingMode = roundData->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) roundNearestEven = ( roundingMode == float_round_nearest_even );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) roundIncrement = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if ( ! roundNearestEven ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if ( roundingMode == float_round_to_zero ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) roundIncrement = 0x7F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if ( zSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if ( roundingMode == float_round_up ) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if ( roundingMode == float_round_down ) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) roundBits = zSig & 0x7F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if ( 0xFD <= (bits16) zExp ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if ( ( 0xFD < zExp )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) || ( ( zExp == 0xFD )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) roundData->exception |= float_flag_overflow | float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if ( zExp < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) isTiny =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ( float_detect_tininess == float_tininess_before_rounding )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) || ( zExp < -1 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) || ( zSig + roundIncrement < 0x80000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) shift32RightJamming( zSig, - zExp, &zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) zExp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) roundBits = zSig & 0x7F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if ( roundBits ) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) zSig = ( zSig + roundIncrement )>>7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if ( zSig == 0 ) zExp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return packFloat32( zSign, zExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) Takes an abstract floating-point value having sign `zSign', exponent `zExp',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) and significand `zSig', and returns the proper single-precision floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) point value corresponding to the abstract input. This routine is just like
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) `roundAndPackFloat32' except that `zSig' does not have to be normalized in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) any way. In all cases, `zExp' must be 1 less than the ``true'' floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) point exponent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static float32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) normalizeRoundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) int8 shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) shiftCount = countLeadingZeros32( zSig ) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return roundAndPackFloat32( roundData, zSign, zExp - shiftCount, zSig<<shiftCount );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) Returns the fraction bits of the double-precision floating-point value `a'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) INLINE bits64 extractFloat64Frac( float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return a & LIT64( 0x000FFFFFFFFFFFFF );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) Returns the exponent bits of the double-precision floating-point value `a'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) INLINE int16 extractFloat64Exp( float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return ( a>>52 ) & 0x7FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) Returns the sign bit of the double-precision floating-point value `a'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) #if 0 /* in softfloat.h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) INLINE flag extractFloat64Sign( float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return a>>63;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) Normalizes the subnormal double-precision floating-point value represented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) by the denormalized significand `aSig'. The normalized exponent and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) significand are stored at the locations pointed to by `zExpPtr' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) `zSigPtr', respectively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int8 shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) shiftCount = countLeadingZeros64( aSig ) - 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) *zSigPtr = aSig<<shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) *zExpPtr = 1 - shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) double-precision floating-point value, returning the result. After being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) shifted into the proper positions, the three fields are simply added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) together to form the result. This means that any integer portion of `zSig'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) will be added into the exponent. Since a properly normalized significand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) will have an integer portion equal to 1, the `zExp' input should be 1 less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) than the desired result exponent whenever `zSig' is a complete, normalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) significand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) INLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<52 ) + zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) Takes an abstract floating-point value having sign `zSign', exponent `zExp',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) and significand `zSig', and returns the proper double-precision floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) point value corresponding to the abstract input. Ordinarily, the abstract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) value is simply rounded and packed into the double-precision format, with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) the inexact exception raised if the abstract input cannot be represented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) exactly. If the abstract value is too large, however, the overflow and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) inexact exceptions are raised and an infinity or maximal finite value is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) returned. If the abstract value is too small, the input value is rounded to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) a subnormal number, and the underflow and inexact exceptions are raised if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) the abstract input cannot be represented exactly as a subnormal double-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) precision floating-point number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) The input significand `zSig' has its binary point between bits 62
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) and 61, which is 10 bits to the left of the usual location. This shifted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) significand must be normalized or smaller. If `zSig' is not normalized,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) `zExp' must be 0; in that case, the result returned is a subnormal number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) and it must not require rounding. In the usual case that `zSig' is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) The handling of underflow and overflow follows the IEC/IEEE Standard for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static float64 roundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) int8 roundingMode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) flag roundNearestEven;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) int16 roundIncrement, roundBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) flag isTiny;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) roundingMode = roundData->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) roundNearestEven = ( roundingMode == float_round_nearest_even );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) roundIncrement = 0x200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if ( ! roundNearestEven ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if ( roundingMode == float_round_to_zero ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) roundIncrement = 0x3FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if ( zSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if ( roundingMode == float_round_up ) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if ( roundingMode == float_round_down ) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) roundBits = zSig & 0x3FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if ( 0x7FD <= (bits16) zExp ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if ( ( 0x7FD < zExp )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) || ( ( zExp == 0x7FD )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) && ( (sbits64) ( zSig + roundIncrement ) < 0 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) //register int lr = __builtin_return_address(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) //printk("roundAndPackFloat64 called from 0x%08x\n",lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) roundData->exception |= float_flag_overflow | float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if ( zExp < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) isTiny =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) ( float_detect_tininess == float_tininess_before_rounding )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) || ( zExp < -1 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) || ( zSig + roundIncrement < LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) shift64RightJamming( zSig, - zExp, &zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) zExp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) roundBits = zSig & 0x3FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if ( roundBits ) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) zSig = ( zSig + roundIncrement )>>10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if ( zSig == 0 ) zExp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return packFloat64( zSign, zExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) Takes an abstract floating-point value having sign `zSign', exponent `zExp',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) and significand `zSig', and returns the proper double-precision floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) point value corresponding to the abstract input. This routine is just like
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) `roundAndPackFloat64' except that `zSig' does not have to be normalized in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) any way. In all cases, `zExp' must be 1 less than the ``true'' floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) point exponent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) static float64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) normalizeRoundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int8 shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) shiftCount = countLeadingZeros64( zSig ) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return roundAndPackFloat64( roundData, zSign, zExp - shiftCount, zSig<<shiftCount );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) #ifdef FLOATX80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) Returns the fraction bits of the extended double-precision floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) value `a'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) INLINE bits64 extractFloatx80Frac( floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return a.low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) Returns the exponent bits of the extended double-precision floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) value `a'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) INLINE int32 extractFloatx80Exp( floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return a.high & 0x7FFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) Returns the sign bit of the extended double-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) `a'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) INLINE flag extractFloatx80Sign( floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return a.high>>15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) Normalizes the subnormal extended double-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) represented by the denormalized significand `aSig'. The normalized exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) and significand are stored at the locations pointed to by `zExpPtr' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) `zSigPtr', respectively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) int8 shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) shiftCount = countLeadingZeros64( aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) *zSigPtr = aSig<<shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) *zExpPtr = 1 - shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) extended double-precision floating-point value, returning the result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) floatx80 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) z.low = zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) z.high = ( ( (bits16) zSign )<<15 ) + zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) z.__padding = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) Takes an abstract floating-point value having sign `zSign', exponent `zExp',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) and extended significand formed by the concatenation of `zSig0' and `zSig1',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) and returns the proper extended double-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) corresponding to the abstract input. Ordinarily, the abstract value is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) rounded and packed into the extended double-precision format, with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) inexact exception raised if the abstract input cannot be represented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) exactly. If the abstract value is too large, however, the overflow and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) inexact exceptions are raised and an infinity or maximal finite value is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) returned. If the abstract value is too small, the input value is rounded to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) a subnormal number, and the underflow and inexact exceptions are raised if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) the abstract input cannot be represented exactly as a subnormal extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) double-precision floating-point number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) If `roundingPrecision' is 32 or 64, the result is rounded to the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) number of bits as single or double precision, respectively. Otherwise, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) result is rounded to the full precision of the extended double-precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) The input significand must be normalized or smaller. If the input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) significand is not normalized, `zExp' must be 0; in that case, the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) returned is a subnormal number, and it must not require rounding. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) handling of underflow and overflow follows the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static floatx80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) roundAndPackFloatx80(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) int8 roundingMode, roundingPrecision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) flag roundNearestEven, increment, isTiny;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) int64 roundIncrement, roundMask, roundBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) roundingMode = roundData->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) roundingPrecision = roundData->precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) roundNearestEven = ( roundingMode == float_round_nearest_even );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if ( roundingPrecision == 80 ) goto precision80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if ( roundingPrecision == 64 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) roundIncrement = LIT64( 0x0000000000000400 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) roundMask = LIT64( 0x00000000000007FF );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) else if ( roundingPrecision == 32 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) roundIncrement = LIT64( 0x0000008000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) roundMask = LIT64( 0x000000FFFFFFFFFF );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) goto precision80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) zSig0 |= ( zSig1 != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if ( ! roundNearestEven ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if ( roundingMode == float_round_to_zero ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) roundIncrement = roundMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if ( zSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if ( roundingMode == float_round_up ) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if ( roundingMode == float_round_down ) roundIncrement = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) roundBits = zSig0 & roundMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if ( ( 0x7FFE < zExp )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) goto overflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if ( zExp <= 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) isTiny =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ( float_detect_tininess == float_tininess_before_rounding )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) || ( zExp < 0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) || ( zSig0 <= zSig0 + roundIncrement );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) zExp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) roundBits = zSig0 & roundMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if ( roundBits ) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) zSig0 += roundIncrement;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if ( (sbits64) zSig0 < 0 ) zExp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) roundIncrement = roundMask + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) roundMask |= roundIncrement;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) zSig0 &= ~ roundMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return packFloatx80( zSign, zExp, zSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if ( roundBits ) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) zSig0 += roundIncrement;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if ( zSig0 < roundIncrement ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ++zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) zSig0 = LIT64( 0x8000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) roundIncrement = roundMask + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) roundMask |= roundIncrement;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) zSig0 &= ~ roundMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if ( zSig0 == 0 ) zExp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return packFloatx80( zSign, zExp, zSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) precision80:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) increment = ( (sbits64) zSig1 < 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if ( ! roundNearestEven ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if ( roundingMode == float_round_to_zero ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) increment = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if ( zSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) increment = ( roundingMode == float_round_down ) && zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) increment = ( roundingMode == float_round_up ) && zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if ( ( 0x7FFE < zExp )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) || ( ( zExp == 0x7FFE )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) && increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) roundMask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) overflow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) roundData->exception |= float_flag_overflow | float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if ( ( roundingMode == float_round_to_zero )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) || ( zSign && ( roundingMode == float_round_up ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) || ( ! zSign && ( roundingMode == float_round_down ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return packFloatx80( zSign, 0x7FFE, ~ roundMask );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if ( zExp <= 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) isTiny =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ( float_detect_tininess == float_tininess_before_rounding )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) || ( zExp < 0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) || ! increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) zExp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if ( isTiny && zSig1 ) roundData->exception |= float_flag_underflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if ( zSig1 ) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if ( roundNearestEven ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) increment = ( (sbits64) zSig1 < 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if ( zSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) increment = ( roundingMode == float_round_down ) && zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) increment = ( roundingMode == float_round_up ) && zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if ( increment ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) ++zSig0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) zSig0 &= ~ ( ( zSig1 + zSig1 == 0 ) & roundNearestEven );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if ( (sbits64) zSig0 < 0 ) zExp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return packFloatx80( zSign, zExp, zSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if ( zSig1 ) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if ( increment ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) ++zSig0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if ( zSig0 == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ++zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) zSig0 = LIT64( 0x8000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) zSig0 &= ~ ( ( zSig1 + zSig1 == 0 ) & roundNearestEven );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if ( zSig0 == 0 ) zExp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return packFloatx80( zSign, zExp, zSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) Takes an abstract floating-point value having sign `zSign', exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) and returns the proper extended double-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) corresponding to the abstract input. This routine is just like
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) `roundAndPackFloatx80' except that the input significand does not have to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) normalized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static floatx80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) normalizeRoundAndPackFloatx80(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) int8 shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if ( zSig0 == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) zSig0 = zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) zSig1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) zExp -= 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) shiftCount = countLeadingZeros64( zSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) zExp -= shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) roundAndPackFloatx80( roundData, zSign, zExp, zSig0, zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) Returns the result of converting the 32-bit two's complement integer `a' to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) the single-precision floating-point format. The conversion is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) float32 int32_to_float32(struct roundingData *roundData, int32 a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) flag zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if ( a == 0 ) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) zSign = ( a < 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return normalizeRoundAndPackFloat32( roundData, zSign, 0x9C, zSign ? - a : a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) Returns the result of converting the 32-bit two's complement integer `a' to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) the double-precision floating-point format. The conversion is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) float64 int32_to_float64( int32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) uint32 absA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) int8 shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) bits64 zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if ( a == 0 ) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) aSign = ( a < 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) absA = aSign ? - a : a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) shiftCount = countLeadingZeros32( absA ) + 21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) zSig = absA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return packFloat64( aSign, 0x432 - shiftCount, zSig<<shiftCount );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) #ifdef FLOATX80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) Returns the result of converting the 32-bit two's complement integer `a'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) to the extended double-precision floating-point format. The conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) is performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) floatx80 int32_to_floatx80( int32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) flag zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) uint32 absA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) int8 shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) bits64 zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if ( a == 0 ) return packFloatx80( 0, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) zSign = ( a < 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) absA = zSign ? - a : a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) shiftCount = countLeadingZeros32( absA ) + 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) zSig = absA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) return packFloatx80( zSign, 0x403E - shiftCount, zSig<<shiftCount );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) Returns the result of converting the single-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) `a' to the 32-bit two's complement integer format. The conversion is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) Arithmetic---which means in particular that the conversion is rounded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) according to the current rounding mode. If `a' is a NaN, the largest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) positive integer is returned. Otherwise, if the conversion overflows, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) largest integer with the same sign as `a' is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) int32 float32_to_int32( struct roundingData *roundData, float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) int16 aExp, shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) bits32 aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) bits64 zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) aSig = extractFloat32Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) aExp = extractFloat32Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if ( aExp ) aSig |= 0x00800000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) shiftCount = 0xAF - aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) zSig = aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) zSig <<= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if ( 0 < shiftCount ) shift64RightJamming( zSig, shiftCount, &zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return roundAndPackInt32( roundData, aSign, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) Returns the result of converting the single-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) `a' to the 32-bit two's complement integer format. The conversion is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) Arithmetic, except that the conversion is always rounded toward zero. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) `a' is a NaN, the largest positive integer is returned. Otherwise, if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) conversion overflows, the largest integer with the same sign as `a' is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) int32 float32_to_int32_round_to_zero( float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) int16 aExp, shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) bits32 aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) int32 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) aSig = extractFloat32Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) aExp = extractFloat32Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) shiftCount = aExp - 0x9E;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if ( 0 <= shiftCount ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if ( a == 0xCF000000 ) return 0x80000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return 0x80000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) else if ( aExp <= 0x7E ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if ( aExp | aSig ) float_raise( float_flag_inexact );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) aSig = ( aSig | 0x00800000 )<<8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) z = aSig>>( - shiftCount );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) float_raise( float_flag_inexact );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return aSign ? - z : z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) Returns the result of converting the single-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) `a' to the double-precision floating-point format. The conversion is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) float64 float32_to_float64( float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) int16 aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) bits32 aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) aSig = extractFloat32Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) aExp = extractFloat32Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if ( aExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return packFloat64( aSign, 0x7FF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if ( aSig == 0 ) return packFloat64( aSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) normalizeFloat32Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) --aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) #ifdef FLOATX80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) Returns the result of converting the single-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) `a' to the extended double-precision floating-point format. The conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) is performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) floatx80 float32_to_floatx80( float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) int16 aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) bits32 aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) aSig = extractFloat32Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) aExp = extractFloat32Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if ( aExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) normalizeFloat32Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) aSig |= 0x00800000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) Rounds the single-precision floating-point value `a' to an integer, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) returns the result as a single-precision floating-point value. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) operation is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) float32 float32_round_to_int( struct roundingData *roundData, float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) int16 aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) bits32 lastBitMask, roundBitsMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) int8 roundingMode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) float32 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) aExp = extractFloat32Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if ( 0x96 <= aExp ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return propagateFloat32NaN( a, a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) roundingMode = roundData->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if ( aExp <= 0x7E ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if ( (bits32) ( a<<1 ) == 0 ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) switch ( roundingMode ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) case float_round_nearest_even:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) return packFloat32( aSign, 0x7F, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) case float_round_down:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return aSign ? 0xBF800000 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) case float_round_up:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return aSign ? 0x80000000 : 0x3F800000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) return packFloat32( aSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) lastBitMask = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) lastBitMask <<= 0x96 - aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) roundBitsMask = lastBitMask - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) z = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if ( roundingMode == float_round_nearest_even ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) z += lastBitMask>>1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) else if ( roundingMode != float_round_to_zero ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) z += roundBitsMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) z &= ~ roundBitsMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if ( z != a ) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) Returns the result of adding the absolute values of the single-precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) floating-point values `a' and `b'. If `zSign' is true, the sum is negated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) before being returned. `zSign' is ignored if the result is a NaN. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) addition is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) static float32 addFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) int16 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) bits32 aSig, bSig, zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) int16 expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) aSig = extractFloat32Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) aExp = extractFloat32Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) bSig = extractFloat32Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) bExp = extractFloat32Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) expDiff = aExp - bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) aSig <<= 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) bSig <<= 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if ( 0 < expDiff ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if ( aExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if ( aSig ) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) --expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) bSig |= 0x20000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) shift32RightJamming( bSig, expDiff, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) zExp = aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) else if ( expDiff < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if ( bExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) if ( bSig ) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return packFloat32( zSign, 0xFF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) ++expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) aSig |= 0x20000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) shift32RightJamming( aSig, - expDiff, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) zExp = bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if ( aExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if ( aSig | bSig ) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) zSig = 0x40000000 + aSig + bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) zExp = aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) goto roundAndPack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) aSig |= 0x20000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) zSig = ( aSig + bSig )<<1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) --zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if ( (sbits32) zSig < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) zSig = aSig + bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) ++zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) roundAndPack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return roundAndPackFloat32( roundData, zSign, zExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) Returns the result of subtracting the absolute values of the single-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) precision floating-point values `a' and `b'. If `zSign' is true, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) difference is negated before being returned. `zSign' is ignored if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) result is a NaN. The subtraction is performed according to the IEC/IEEE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) static float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) int16 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) bits32 aSig, bSig, zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) int16 expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) aSig = extractFloat32Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) aExp = extractFloat32Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) bSig = extractFloat32Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) bExp = extractFloat32Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) expDiff = aExp - bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) aSig <<= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) bSig <<= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if ( 0 < expDiff ) goto aExpBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if ( expDiff < 0 ) goto bExpBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if ( aExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if ( aSig | bSig ) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) return float32_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) aExp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) bExp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if ( bSig < aSig ) goto aBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if ( aSig < bSig ) goto bBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return packFloat32( roundData->mode == float_round_down, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) bExpBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if ( bExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if ( bSig ) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) return packFloat32( zSign ^ 1, 0xFF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) ++expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) aSig |= 0x40000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) shift32RightJamming( aSig, - expDiff, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) bSig |= 0x40000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) bBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) zSig = bSig - aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) zExp = bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) zSign ^= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) goto normalizeRoundAndPack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) aExpBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if ( aExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if ( aSig ) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) --expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) bSig |= 0x40000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) shift32RightJamming( bSig, expDiff, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) aSig |= 0x40000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) aBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) zSig = aSig - bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) zExp = aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) normalizeRoundAndPack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) --zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return normalizeRoundAndPackFloat32( roundData, zSign, zExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) Returns the result of adding the single-precision floating-point values `a'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) and `b'. The operation is performed according to the IEC/IEEE Standard for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) float32 float32_add( struct roundingData *roundData, float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) bSign = extractFloat32Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if ( aSign == bSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return addFloat32Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return subFloat32Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) Returns the result of subtracting the single-precision floating-point values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) `a' and `b'. The operation is performed according to the IEC/IEEE Standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) float32 float32_sub( struct roundingData *roundData, float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) bSign = extractFloat32Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if ( aSign == bSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) return subFloat32Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return addFloat32Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) Returns the result of multiplying the single-precision floating-point values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) `a' and `b'. The operation is performed according to the IEC/IEEE Standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) float32 float32_mul( struct roundingData *roundData, float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) flag aSign, bSign, zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) int16 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) bits32 aSig, bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) bits64 zSig64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) bits32 zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) aSig = extractFloat32Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) aExp = extractFloat32Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) bSig = extractFloat32Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) bExp = extractFloat32Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) bSign = extractFloat32Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) zSign = aSign ^ bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if ( aExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if ( ( bExp | bSig ) == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) return float32_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) return packFloat32( zSign, 0xFF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if ( bExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if ( bSig ) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) if ( ( aExp | aSig ) == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) return float32_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) return packFloat32( zSign, 0xFF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) normalizeFloat32Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if ( bSig == 0 ) return packFloat32( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) normalizeFloat32Subnormal( bSig, &bExp, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) zExp = aExp + bExp - 0x7F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) aSig = ( aSig | 0x00800000 )<<7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) bSig = ( bSig | 0x00800000 )<<8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) zSig = zSig64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if ( 0 <= (sbits32) ( zSig<<1 ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) zSig <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) --zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) return roundAndPackFloat32( roundData, zSign, zExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) Returns the result of dividing the single-precision floating-point value `a'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) by the corresponding value `b'. The operation is performed according to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) float32 float32_div( struct roundingData *roundData, float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) flag aSign, bSign, zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) int16 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) bits32 aSig, bSig, zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) aSig = extractFloat32Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) aExp = extractFloat32Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) bSig = extractFloat32Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) bExp = extractFloat32Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) bSign = extractFloat32Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) zSign = aSign ^ bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if ( aExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) if ( aSig ) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) if ( bExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if ( bSig ) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) return float32_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) return packFloat32( zSign, 0xFF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if ( bExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if ( bSig ) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) return packFloat32( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) if ( bSig == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) if ( ( aExp | aSig ) == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) return float32_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) roundData->exception |= float_flag_divbyzero;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) return packFloat32( zSign, 0xFF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) normalizeFloat32Subnormal( bSig, &bExp, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) normalizeFloat32Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) zExp = aExp - bExp + 0x7D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) aSig = ( aSig | 0x00800000 )<<7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) bSig = ( bSig | 0x00800000 )<<8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if ( bSig <= ( aSig + aSig ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) aSig >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) ++zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) bits64 tmp = ( (bits64) aSig )<<32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) do_div( tmp, bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) zSig = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) if ( ( zSig & 0x3F ) == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) return roundAndPackFloat32( roundData, zSign, zExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) Returns the remainder of the single-precision floating-point value `a'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) with respect to the corresponding value `b'. The operation is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) float32 float32_rem( struct roundingData *roundData, float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) flag aSign, bSign, zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) int16 aExp, bExp, expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) bits32 aSig, bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) bits32 q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) bits64 aSig64, bSig64, q64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) bits32 alternateASig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) sbits32 sigMean;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) aSig = extractFloat32Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) aExp = extractFloat32Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) bSig = extractFloat32Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) bExp = extractFloat32Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) bSign = extractFloat32Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if ( aExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) return float32_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) if ( bExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) if ( bSig ) return propagateFloat32NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if ( bSig == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) return float32_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) normalizeFloat32Subnormal( bSig, &bExp, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) if ( aSig == 0 ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) normalizeFloat32Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) expDiff = aExp - bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) aSig |= 0x00800000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) bSig |= 0x00800000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if ( expDiff < 32 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) aSig <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) bSig <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if ( expDiff < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) if ( expDiff < -1 ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) aSig >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) q = ( bSig <= aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) if ( q ) aSig -= bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if ( 0 < expDiff ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) bits64 tmp = ( (bits64) aSig )<<32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) do_div( tmp, bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) q = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) q >>= 32 - expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) bSig >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) aSig >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) bSig >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) if ( bSig <= aSig ) aSig -= bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) aSig64 = ( (bits64) aSig )<<40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) bSig64 = ( (bits64) bSig )<<40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) expDiff -= 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) while ( 0 < expDiff ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) q64 = estimateDiv128To64( aSig64, 0, bSig64 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) q64 = ( 2 < q64 ) ? q64 - 2 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) aSig64 = - ( ( bSig * q64 )<<38 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) expDiff -= 62;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) expDiff += 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) q64 = estimateDiv128To64( aSig64, 0, bSig64 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) q64 = ( 2 < q64 ) ? q64 - 2 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) q = q64>>( 64 - expDiff );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) bSig <<= 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) alternateASig = aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) ++q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) aSig -= bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) } while ( 0 <= (sbits32) aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) sigMean = aSig + alternateASig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) aSig = alternateASig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) zSign = ( (sbits32) aSig < 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) if ( zSign ) aSig = - aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) return normalizeRoundAndPackFloat32( roundData, aSign ^ zSign, bExp, aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) Returns the square root of the single-precision floating-point value `a'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) The operation is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) float32 float32_sqrt( struct roundingData *roundData, float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) int16 aExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) bits32 aSig, zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) bits64 rem, term;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) aSig = extractFloat32Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) aExp = extractFloat32Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if ( aExp == 0xFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) if ( aSig ) return propagateFloat32NaN( a, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if ( ! aSign ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) return float32_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if ( aSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if ( ( aExp | aSig ) == 0 ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) return float32_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if ( aSig == 0 ) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) normalizeFloat32Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) aSig = ( aSig | 0x00800000 )<<8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) zSig = estimateSqrt32( aExp, aSig ) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) if ( ( zSig & 0x7F ) <= 5 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) if ( zSig < 2 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) zSig = 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) aSig >>= aExp & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) term = ( (bits64) zSig ) * zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) rem = ( ( (bits64) aSig )<<32 ) - term;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) while ( (sbits64) rem < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) --zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) rem += ( ( (bits64) zSig )<<1 ) | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) zSig |= ( rem != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) shift32RightJamming( zSig, 1, &zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) return roundAndPackFloat32( roundData, 0, zExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) Returns 1 if the single-precision floating-point value `a' is equal to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) corresponding value `b', and 0 otherwise. The comparison is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) flag float32_eq( float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) Returns 1 if the single-precision floating-point value `a' is less than or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) equal to the corresponding value `b', and 0 otherwise. The comparison is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) flag float32_le( float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) bSign = extractFloat32Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) return ( a == b ) || ( aSign ^ ( a < b ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) Returns 1 if the single-precision floating-point value `a' is less than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) the corresponding value `b', and 0 otherwise. The comparison is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) flag float32_lt( float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) bSign = extractFloat32Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) return ( a != b ) && ( aSign ^ ( a < b ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) Returns 1 if the single-precision floating-point value `a' is equal to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) corresponding value `b', and 0 otherwise. The invalid exception is raised
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) if either operand is a NaN. Otherwise, the comparison is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) flag float32_eq_signaling( float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) Returns 1 if the single-precision floating-point value `a' is less than or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) cause an exception. Otherwise, the comparison is performed according to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) flag float32_le_quiet( float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) //int16 aExp, bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) /* Do nothing, even if NaN as we're quiet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) bSign = extractFloat32Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) return ( a == b ) || ( aSign ^ ( a < b ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) Returns 1 if the single-precision floating-point value `a' is less than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) exception. Otherwise, the comparison is performed according to the IEC/IEEE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) flag float32_lt_quiet( float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) /* Do nothing, even if NaN as we're quiet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) aSign = extractFloat32Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) bSign = extractFloat32Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) return ( a != b ) && ( aSign ^ ( a < b ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) Returns the result of converting the double-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) `a' to the 32-bit two's complement integer format. The conversion is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) Arithmetic---which means in particular that the conversion is rounded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) according to the current rounding mode. If `a' is a NaN, the largest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) positive integer is returned. Otherwise, if the conversion overflows, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) largest integer with the same sign as `a' is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) int32 float64_to_int32( struct roundingData *roundData, float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) int16 aExp, shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) bits64 aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) shiftCount = 0x42C - aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) return roundAndPackInt32( roundData, aSign, aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) Returns the result of converting the double-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) `a' to the 32-bit two's complement integer format. The conversion is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) Arithmetic, except that the conversion is always rounded toward zero. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) `a' is a NaN, the largest positive integer is returned. Otherwise, if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) conversion overflows, the largest integer with the same sign as `a' is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) int32 float64_to_int32_round_to_zero( float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) int16 aExp, shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) bits64 aSig, savedASig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) int32 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) shiftCount = 0x433 - aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) if ( shiftCount < 21 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) else if ( 52 < shiftCount ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) if ( aExp || aSig ) float_raise( float_flag_inexact );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) aSig |= LIT64( 0x0010000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) savedASig = aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) aSig >>= shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) z = aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) if ( aSign ) z = - z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) if ( ( z < 0 ) ^ aSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) invalid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) return aSign ? 0x80000000 : 0x7FFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) if ( ( aSig<<shiftCount ) != savedASig ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) float_raise( float_flag_inexact );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) Returns the result of converting the double-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) `a' to the 32-bit two's complement unsigned integer format. The conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) is performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) Arithmetic---which means in particular that the conversion is rounded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) according to the current rounding mode. If `a' is a NaN, the largest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) positive integer is returned. Otherwise, if the conversion overflows, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) largest positive integer is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) int32 float64_to_uint32( struct roundingData *roundData, float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) int16 aExp, shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) bits64 aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) aSign = 0; //extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) //if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) shiftCount = 0x42C - aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) return roundAndPackInt32( roundData, aSign, aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) Returns the result of converting the double-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) `a' to the 32-bit two's complement integer format. The conversion is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) Arithmetic, except that the conversion is always rounded toward zero. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) `a' is a NaN, the largest positive integer is returned. Otherwise, if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) conversion overflows, the largest positive integer is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) int32 float64_to_uint32_round_to_zero( float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) int16 aExp, shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) bits64 aSig, savedASig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) int32 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) shiftCount = 0x433 - aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) if ( shiftCount < 21 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) else if ( 52 < shiftCount ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) if ( aExp || aSig ) float_raise( float_flag_inexact );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) aSig |= LIT64( 0x0010000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) savedASig = aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) aSig >>= shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) z = aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) if ( aSign ) z = - z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) if ( ( z < 0 ) ^ aSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) invalid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) return aSign ? 0x80000000 : 0x7FFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) if ( ( aSig<<shiftCount ) != savedASig ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) float_raise( float_flag_inexact );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) Returns the result of converting the double-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) `a' to the single-precision floating-point format. The conversion is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) float32 float64_to_float32( struct roundingData *roundData, float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) int16 aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) bits64 aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) bits32 zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) if ( aExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) return packFloat32( aSign, 0xFF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) shift64RightJamming( aSig, 22, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) zSig = aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) if ( aExp || zSig ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) zSig |= 0x40000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) aExp -= 0x381;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) return roundAndPackFloat32( roundData, aSign, aExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) #ifdef FLOATX80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) Returns the result of converting the double-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) `a' to the extended double-precision floating-point format. The conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) is performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) floatx80 float64_to_floatx80( float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) int16 aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) bits64 aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) if ( aExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) normalizeFloat64Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) packFloatx80(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) Rounds the double-precision floating-point value `a' to an integer, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) returns the result as a double-precision floating-point value. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) operation is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) float64 float64_round_to_int( struct roundingData *roundData, float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) int16 aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) bits64 lastBitMask, roundBitsMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) int8 roundingMode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) float64 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) if ( 0x433 <= aExp ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) return propagateFloat64NaN( a, a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) if ( aExp <= 0x3FE ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) if ( (bits64) ( a<<1 ) == 0 ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) switch ( roundData->mode ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) case float_round_nearest_even:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) return packFloat64( aSign, 0x3FF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) case float_round_down:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) return aSign ? LIT64( 0xBFF0000000000000 ) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) case float_round_up:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) return packFloat64( aSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) lastBitMask = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) lastBitMask <<= 0x433 - aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) roundBitsMask = lastBitMask - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) z = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) roundingMode = roundData->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) if ( roundingMode == float_round_nearest_even ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) z += lastBitMask>>1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) else if ( roundingMode != float_round_to_zero ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) z += roundBitsMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) z &= ~ roundBitsMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) if ( z != a ) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) Returns the result of adding the absolute values of the double-precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) floating-point values `a' and `b'. If `zSign' is true, the sum is negated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) before being returned. `zSign' is ignored if the result is a NaN. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) addition is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) static float64 addFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) int16 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) bits64 aSig, bSig, zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) int16 expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) bSig = extractFloat64Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) bExp = extractFloat64Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) expDiff = aExp - bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) aSig <<= 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) bSig <<= 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) if ( 0 < expDiff ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) if ( aExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) if ( aSig ) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) --expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) bSig |= LIT64( 0x2000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) shift64RightJamming( bSig, expDiff, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) zExp = aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) else if ( expDiff < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) if ( bExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) if ( bSig ) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) return packFloat64( zSign, 0x7FF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) ++expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) aSig |= LIT64( 0x2000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) shift64RightJamming( aSig, - expDiff, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) zExp = bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) if ( aExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) if ( aSig | bSig ) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) zSig = LIT64( 0x4000000000000000 ) + aSig + bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) zExp = aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) goto roundAndPack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) aSig |= LIT64( 0x2000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) zSig = ( aSig + bSig )<<1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) --zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) if ( (sbits64) zSig < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) zSig = aSig + bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) ++zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) roundAndPack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) return roundAndPackFloat64( roundData, zSign, zExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) Returns the result of subtracting the absolute values of the double-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) precision floating-point values `a' and `b'. If `zSign' is true, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) difference is negated before being returned. `zSign' is ignored if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) result is a NaN. The subtraction is performed according to the IEC/IEEE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) static float64 subFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) int16 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) bits64 aSig, bSig, zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) int16 expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) bSig = extractFloat64Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) bExp = extractFloat64Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) expDiff = aExp - bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) aSig <<= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) bSig <<= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) if ( 0 < expDiff ) goto aExpBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) if ( expDiff < 0 ) goto bExpBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) if ( aExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) if ( aSig | bSig ) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) return float64_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) aExp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) bExp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) if ( bSig < aSig ) goto aBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) if ( aSig < bSig ) goto bBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) return packFloat64( roundData->mode == float_round_down, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) bExpBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) if ( bExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) if ( bSig ) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) return packFloat64( zSign ^ 1, 0x7FF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) ++expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) aSig |= LIT64( 0x4000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) shift64RightJamming( aSig, - expDiff, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) bSig |= LIT64( 0x4000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) bBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) zSig = bSig - aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) zExp = bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) zSign ^= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) goto normalizeRoundAndPack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) aExpBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) if ( aExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) if ( aSig ) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) --expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) bSig |= LIT64( 0x4000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) shift64RightJamming( bSig, expDiff, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) aSig |= LIT64( 0x4000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) aBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) zSig = aSig - bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) zExp = aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) normalizeRoundAndPack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) --zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) return normalizeRoundAndPackFloat64( roundData, zSign, zExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) Returns the result of adding the double-precision floating-point values `a'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) and `b'. The operation is performed according to the IEC/IEEE Standard for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) float64 float64_add( struct roundingData *roundData, float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) bSign = extractFloat64Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) if ( aSign == bSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) return addFloat64Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) return subFloat64Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) Returns the result of subtracting the double-precision floating-point values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) `a' and `b'. The operation is performed according to the IEC/IEEE Standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) float64 float64_sub( struct roundingData *roundData, float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) bSign = extractFloat64Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) if ( aSign == bSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) return subFloat64Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) return addFloat64Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) Returns the result of multiplying the double-precision floating-point values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) `a' and `b'. The operation is performed according to the IEC/IEEE Standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) float64 float64_mul( struct roundingData *roundData, float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) flag aSign, bSign, zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) int16 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) bits64 aSig, bSig, zSig0, zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) bSig = extractFloat64Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) bExp = extractFloat64Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) bSign = extractFloat64Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) zSign = aSign ^ bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) if ( aExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) if ( ( bExp | bSig ) == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) return float64_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) return packFloat64( zSign, 0x7FF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) if ( bExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) if ( bSig ) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) if ( ( aExp | aSig ) == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) return float64_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) return packFloat64( zSign, 0x7FF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) normalizeFloat64Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) if ( bSig == 0 ) return packFloat64( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) normalizeFloat64Subnormal( bSig, &bExp, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) zExp = aExp + bExp - 0x3FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) mul64To128( aSig, bSig, &zSig0, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) zSig0 |= ( zSig1 != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) if ( 0 <= (sbits64) ( zSig0<<1 ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) zSig0 <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) --zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) return roundAndPackFloat64( roundData, zSign, zExp, zSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) Returns the result of dividing the double-precision floating-point value `a'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) by the corresponding value `b'. The operation is performed according to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) float64 float64_div( struct roundingData *roundData, float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) flag aSign, bSign, zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) int16 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) bits64 aSig, bSig, zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) bits64 rem0, rem1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) bits64 term0, term1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) bSig = extractFloat64Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) bExp = extractFloat64Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) bSign = extractFloat64Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) zSign = aSign ^ bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) if ( aExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) if ( aSig ) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) if ( bExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) if ( bSig ) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) return float64_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) return packFloat64( zSign, 0x7FF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) if ( bExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) if ( bSig ) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) return packFloat64( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) if ( bSig == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) if ( ( aExp | aSig ) == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) return float64_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) roundData->exception |= float_flag_divbyzero;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) return packFloat64( zSign, 0x7FF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) normalizeFloat64Subnormal( bSig, &bExp, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) normalizeFloat64Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) zExp = aExp - bExp + 0x3FD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) if ( bSig <= ( aSig + aSig ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) aSig >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) ++zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) zSig = estimateDiv128To64( aSig, 0, bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) if ( ( zSig & 0x1FF ) <= 2 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) mul64To128( bSig, zSig, &term0, &term1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) sub128( aSig, 0, term0, term1, &rem0, &rem1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) while ( (sbits64) rem0 < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) --zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) zSig |= ( rem1 != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) return roundAndPackFloat64( roundData, zSign, zExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) Returns the remainder of the double-precision floating-point value `a'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) with respect to the corresponding value `b'. The operation is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) float64 float64_rem( struct roundingData *roundData, float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) flag aSign, bSign, zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) int16 aExp, bExp, expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) bits64 aSig, bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) bits64 q, alternateASig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) sbits64 sigMean;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) bSig = extractFloat64Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) bExp = extractFloat64Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) bSign = extractFloat64Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) if ( aExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) return float64_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) if ( bExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) if ( bSig ) return propagateFloat64NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) if ( bSig == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) return float64_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) normalizeFloat64Subnormal( bSig, &bExp, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) if ( aSig == 0 ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) normalizeFloat64Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) expDiff = aExp - bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) if ( expDiff < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) if ( expDiff < -1 ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) aSig >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) q = ( bSig <= aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) if ( q ) aSig -= bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) expDiff -= 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) while ( 0 < expDiff ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) q = estimateDiv128To64( aSig, 0, bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) q = ( 2 < q ) ? q - 2 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) aSig = - ( ( bSig>>2 ) * q );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) expDiff -= 62;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) expDiff += 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) if ( 0 < expDiff ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) q = estimateDiv128To64( aSig, 0, bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) q = ( 2 < q ) ? q - 2 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) q >>= 64 - expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) bSig >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) aSig >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) bSig >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) alternateASig = aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) ++q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) aSig -= bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) } while ( 0 <= (sbits64) aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) sigMean = aSig + alternateASig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) aSig = alternateASig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) zSign = ( (sbits64) aSig < 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) if ( zSign ) aSig = - aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) return normalizeRoundAndPackFloat64( roundData, aSign ^ zSign, bExp, aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) Returns the square root of the double-precision floating-point value `a'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) The operation is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) float64 float64_sqrt( struct roundingData *roundData, float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) int16 aExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) bits64 aSig, zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) bits64 rem0, rem1, term0, term1; //, shiftedRem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) //float64 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) aSig = extractFloat64Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) aExp = extractFloat64Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) if ( aExp == 0x7FF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) if ( aSig ) return propagateFloat64NaN( a, a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) if ( ! aSign ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) return float64_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) if ( aSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) if ( ( aExp | aSig ) == 0 ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) return float64_default_nan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) if ( aSig == 0 ) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) normalizeFloat64Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) aSig |= LIT64( 0x0010000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) zSig = estimateSqrt32( aExp, aSig>>21 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) zSig <<= 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) aSig <<= 9 - ( aExp & 1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) zSig = estimateDiv128To64( aSig, 0, zSig ) + zSig + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) if ( ( zSig & 0x3FF ) <= 5 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) if ( zSig < 2 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) zSig = LIT64( 0xFFFFFFFFFFFFFFFF );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) aSig <<= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) mul64To128( zSig, zSig, &term0, &term1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) sub128( aSig, 0, term0, term1, &rem0, &rem1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) while ( (sbits64) rem0 < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) --zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) shortShift128Left( 0, zSig, 1, &term0, &term1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) term1 |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) add128( rem0, rem1, term0, term1, &rem0, &rem1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) zSig |= ( ( rem0 | rem1 ) != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) shift64RightJamming( zSig, 1, &zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) return roundAndPackFloat64( roundData, 0, zExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) Returns 1 if the double-precision floating-point value `a' is equal to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) corresponding value `b', and 0 otherwise. The comparison is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) flag float64_eq( float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) Returns 1 if the double-precision floating-point value `a' is less than or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) equal to the corresponding value `b', and 0 otherwise. The comparison is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) flag float64_le( float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) bSign = extractFloat64Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) return ( a == b ) || ( aSign ^ ( a < b ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) Returns 1 if the double-precision floating-point value `a' is less than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) the corresponding value `b', and 0 otherwise. The comparison is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) flag float64_lt( float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) bSign = extractFloat64Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) return ( a != b ) && ( aSign ^ ( a < b ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) Returns 1 if the double-precision floating-point value `a' is equal to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) corresponding value `b', and 0 otherwise. The invalid exception is raised
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) if either operand is a NaN. Otherwise, the comparison is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) flag float64_eq_signaling( float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) Returns 1 if the double-precision floating-point value `a' is less than or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) cause an exception. Otherwise, the comparison is performed according to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) flag float64_le_quiet( float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) //int16 aExp, bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) /* Do nothing, even if NaN as we're quiet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) bSign = extractFloat64Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) return ( a == b ) || ( aSign ^ ( a < b ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) Returns 1 if the double-precision floating-point value `a' is less than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) exception. Otherwise, the comparison is performed according to the IEC/IEEE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) flag float64_lt_quiet( float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) /* Do nothing, even if NaN as we're quiet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) aSign = extractFloat64Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) bSign = extractFloat64Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) return ( a != b ) && ( aSign ^ ( a < b ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) #ifdef FLOATX80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) Returns the result of converting the extended double-precision floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) point value `a' to the 32-bit two's complement integer format. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) conversion is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) Floating-point Arithmetic---which means in particular that the conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) is rounded according to the current rounding mode. If `a' is a NaN, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) largest positive integer is returned. Otherwise, if the conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) overflows, the largest integer with the same sign as `a' is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) int32 floatx80_to_int32( struct roundingData *roundData, floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) int32 aExp, shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) bits64 aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) aSig = extractFloatx80Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) aExp = extractFloatx80Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) shiftCount = 0x4037 - aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) if ( shiftCount <= 0 ) shiftCount = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) shift64RightJamming( aSig, shiftCount, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) return roundAndPackInt32( roundData, aSign, aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) Returns the result of converting the extended double-precision floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) point value `a' to the 32-bit two's complement integer format. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) conversion is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) Floating-point Arithmetic, except that the conversion is always rounded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) toward zero. If `a' is a NaN, the largest positive integer is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) Otherwise, if the conversion overflows, the largest integer with the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) sign as `a' is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) int32 floatx80_to_int32_round_to_zero( floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) int32 aExp, shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) bits64 aSig, savedASig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) int32 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) aSig = extractFloatx80Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) aExp = extractFloatx80Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) shiftCount = 0x403E - aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) if ( shiftCount < 32 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) else if ( 63 < shiftCount ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) if ( aExp || aSig ) float_raise( float_flag_inexact );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) savedASig = aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) aSig >>= shiftCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) z = aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) if ( aSign ) z = - z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) if ( ( z < 0 ) ^ aSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) invalid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) return aSign ? 0x80000000 : 0x7FFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) if ( ( aSig<<shiftCount ) != savedASig ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) float_raise( float_flag_inexact );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) Returns the result of converting the extended double-precision floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) point value `a' to the single-precision floating-point format. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) conversion is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) float32 floatx80_to_float32( struct roundingData *roundData, floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) int32 aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) bits64 aSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) aSig = extractFloatx80Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) aExp = extractFloatx80Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) if ( aExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) if ( (bits64) ( aSig<<1 ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) return commonNaNToFloat32( floatx80ToCommonNaN( a ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) return packFloat32( aSign, 0xFF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) shift64RightJamming( aSig, 33, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) if ( aExp || aSig ) aExp -= 0x3F81;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) return roundAndPackFloat32( roundData, aSign, aExp, aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) Returns the result of converting the extended double-precision floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) point value `a' to the double-precision floating-point format. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) conversion is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) float64 floatx80_to_float64( struct roundingData *roundData, floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) int32 aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) bits64 aSig, zSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) aSig = extractFloatx80Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) aExp = extractFloatx80Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) if ( aExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) if ( (bits64) ( aSig<<1 ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) return commonNaNToFloat64( floatx80ToCommonNaN( a ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) return packFloat64( aSign, 0x7FF, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) shift64RightJamming( aSig, 1, &zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) if ( aExp || aSig ) aExp -= 0x3C01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) return roundAndPackFloat64( roundData, aSign, aExp, zSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) Rounds the extended double-precision floating-point value `a' to an integer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) and returns the result as an extended quadruple-precision floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) value. The operation is performed according to the IEC/IEEE Standard for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) floatx80 floatx80_round_to_int( struct roundingData *roundData, floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) int32 aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) bits64 lastBitMask, roundBitsMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) int8 roundingMode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) floatx80 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) aExp = extractFloatx80Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) if ( 0x403E <= aExp ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) return propagateFloatx80NaN( a, a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) if ( aExp <= 0x3FFE ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) if ( ( aExp == 0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) switch ( roundData->mode ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) case float_round_nearest_even:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) case float_round_down:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) aSign ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) : packFloatx80( 0, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) case float_round_up:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) aSign ? packFloatx80( 1, 0, 0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) return packFloatx80( aSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) lastBitMask = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) lastBitMask <<= 0x403E - aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) roundBitsMask = lastBitMask - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) z = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) roundingMode = roundData->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) if ( roundingMode == float_round_nearest_even ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) z.low += lastBitMask>>1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) else if ( roundingMode != float_round_to_zero ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) z.low += roundBitsMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) z.low &= ~ roundBitsMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) if ( z.low == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) ++z.high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) z.low = LIT64( 0x8000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) if ( z.low != a.low ) roundData->exception |= float_flag_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) Returns the result of adding the absolute values of the extended double-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) precision floating-point values `a' and `b'. If `zSign' is true, the sum is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) negated before being returned. `zSign' is ignored if the result is a NaN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) The addition is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) static floatx80 addFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) int32 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) bits64 aSig, bSig, zSig0, zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) int32 expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) aSig = extractFloatx80Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) aExp = extractFloatx80Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) bSig = extractFloatx80Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) bExp = extractFloatx80Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) expDiff = aExp - bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) if ( 0 < expDiff ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) if ( aExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) if ( bExp == 0 ) --expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) zExp = aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) else if ( expDiff < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) if ( bExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) if ( aExp == 0 ) ++expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) zExp = bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) if ( aExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) zSig1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) zSig0 = aSig + bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) goto roundAndPack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) zExp = aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) goto shiftRight1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) zSig0 = aSig + bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) if ( (sbits64) zSig0 < 0 ) goto roundAndPack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) shiftRight1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) zSig0 |= LIT64( 0x8000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) ++zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) roundAndPack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) roundAndPackFloatx80(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) roundData, zSign, zExp, zSig0, zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) Returns the result of subtracting the absolute values of the extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) double-precision floating-point values `a' and `b'. If `zSign' is true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) the difference is negated before being returned. `zSign' is ignored if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) result is a NaN. The subtraction is performed according to the IEC/IEEE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) int32 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) bits64 aSig, bSig, zSig0, zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) int32 expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) floatx80 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) aSig = extractFloatx80Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) aExp = extractFloatx80Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) bSig = extractFloatx80Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) bExp = extractFloatx80Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) expDiff = aExp - bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) if ( 0 < expDiff ) goto aExpBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) if ( expDiff < 0 ) goto bExpBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) if ( aExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) z.low = floatx80_default_nan_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) z.high = floatx80_default_nan_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) z.__padding = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) aExp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) bExp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) zSig1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) if ( bSig < aSig ) goto aBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) if ( aSig < bSig ) goto bBigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) return packFloatx80( roundData->mode == float_round_down, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) bExpBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) if ( bExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) if ( aExp == 0 ) ++expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) bBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) zExp = bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) zSign ^= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) goto normalizeRoundAndPack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) aExpBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) if ( aExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) if ( bExp == 0 ) --expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) aBigger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) zExp = aExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) normalizeRoundAndPack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) normalizeRoundAndPackFloatx80(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) roundData, zSign, zExp, zSig0, zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) Returns the result of adding the extended double-precision floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) values `a' and `b'. The operation is performed according to the IEC/IEEE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) floatx80 floatx80_add( struct roundingData *roundData, floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) bSign = extractFloatx80Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) if ( aSign == bSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) return addFloatx80Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) return subFloatx80Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) Returns the result of subtracting the extended double-precision floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) point values `a' and `b'. The operation is performed according to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) floatx80 floatx80_sub( struct roundingData *roundData, floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) bSign = extractFloatx80Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) if ( aSign == bSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) return subFloatx80Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) return addFloatx80Sigs( roundData, a, b, aSign );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) Returns the result of multiplying the extended double-precision floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) point values `a' and `b'. The operation is performed according to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) flag aSign, bSign, zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) int32 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) bits64 aSig, bSig, zSig0, zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) floatx80 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) aSig = extractFloatx80Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) aExp = extractFloatx80Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) bSig = extractFloatx80Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) bExp = extractFloatx80Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) bSign = extractFloatx80Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) zSign = aSign ^ bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) if ( aExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) if ( (bits64) ( aSig<<1 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) if ( ( bExp | bSig ) == 0 ) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) if ( bExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) if ( ( aExp | aSig ) == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) invalid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) z.low = floatx80_default_nan_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) z.high = floatx80_default_nan_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) z.__padding = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) zExp = aExp + bExp - 0x3FFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) mul64To128( aSig, bSig, &zSig0, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) if ( 0 < (sbits64) zSig0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) --zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) roundAndPackFloatx80(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) roundData, zSign, zExp, zSig0, zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) Returns the result of dividing the extended double-precision floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) value `a' by the corresponding value `b'. The operation is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) flag aSign, bSign, zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) int32 aExp, bExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) bits64 aSig, bSig, zSig0, zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) bits64 rem0, rem1, rem2, term0, term1, term2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) floatx80 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) aSig = extractFloatx80Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) aExp = extractFloatx80Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) bSig = extractFloatx80Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) bExp = extractFloatx80Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) bSign = extractFloatx80Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) zSign = aSign ^ bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) if ( aExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) if ( bExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) if ( bExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) return packFloatx80( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) if ( bSig == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) if ( ( aExp | aSig ) == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) invalid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) z.low = floatx80_default_nan_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) z.high = floatx80_default_nan_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) z.__padding = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) roundData->exception |= float_flag_divbyzero;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) zExp = aExp - bExp + 0x3FFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) rem1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) if ( bSig <= aSig ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) shift128Right( aSig, 0, 1, &aSig, &rem1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) ++zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) zSig0 = estimateDiv128To64( aSig, rem1, bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) mul64To128( bSig, zSig0, &term0, &term1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) sub128( aSig, rem1, term0, term1, &rem0, &rem1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) while ( (sbits64) rem0 < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) --zSig0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) zSig1 = estimateDiv128To64( rem1, 0, bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) if ( (bits64) ( zSig1<<1 ) <= 8 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) mul64To128( bSig, zSig1, &term1, &term2 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) sub128( rem1, 0, term1, term2, &rem1, &rem2 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) while ( (sbits64) rem1 < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) --zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) add128( rem1, rem2, 0, bSig, &rem1, &rem2 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) zSig1 |= ( ( rem1 | rem2 ) != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) roundAndPackFloatx80(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) roundData, zSign, zExp, zSig0, zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) Returns the remainder of the extended double-precision floating-point value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) `a' with respect to the corresponding value `b'. The operation is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) flag aSign, bSign, zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) int32 aExp, bExp, expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) bits64 aSig0, aSig1, bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) bits64 q, term0, term1, alternateASig0, alternateASig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) floatx80 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) aSig0 = extractFloatx80Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) aExp = extractFloatx80Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) bSig = extractFloatx80Frac( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) bExp = extractFloatx80Exp( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) bSign = extractFloatx80Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) if ( aExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) if ( (bits64) ( aSig0<<1 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) if ( bExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) if ( bExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) if ( bSig == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) invalid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) z.low = floatx80_default_nan_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) z.high = floatx80_default_nan_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) z.__padding = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) if ( (bits64) ( aSig0<<1 ) == 0 ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) bSig |= LIT64( 0x8000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) zSign = aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) expDiff = aExp - bExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) aSig1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) if ( expDiff < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) if ( expDiff < -1 ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) shift128Right( aSig0, 0, 1, &aSig0, &aSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) expDiff = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) q = ( bSig <= aSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) if ( q ) aSig0 -= bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) expDiff -= 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) while ( 0 < expDiff ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) q = estimateDiv128To64( aSig0, aSig1, bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) q = ( 2 < q ) ? q - 2 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) mul64To128( bSig, q, &term0, &term1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) expDiff -= 62;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) expDiff += 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) if ( 0 < expDiff ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) q = estimateDiv128To64( aSig0, aSig1, bSig );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) q = ( 2 < q ) ? q - 2 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) q >>= 64 - expDiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) while ( le128( term0, term1, aSig0, aSig1 ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) ++q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) term1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) term0 = bSig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) && ( q & 1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) aSig0 = alternateASig0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) aSig1 = alternateASig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) zSign = ! zSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) normalizeRoundAndPackFloatx80(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) roundData, zSign, bExp + expDiff, aSig0, aSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) Returns the square root of the extended double-precision floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) value `a'. The operation is performed according to the IEC/IEEE Standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) flag aSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) int32 aExp, zExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) bits64 aSig0, aSig1, zSig0, zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) bits64 shiftedRem0, shiftedRem1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) floatx80 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) aSig0 = extractFloatx80Frac( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) aExp = extractFloatx80Exp( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) if ( aExp == 0x7FFF ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) if ( ! aSign ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) goto invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) if ( aSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) if ( ( aExp | aSig0 ) == 0 ) return a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) invalid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) roundData->exception |= float_flag_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) z.low = floatx80_default_nan_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) z.high = floatx80_default_nan_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) z.__padding = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) if ( aExp == 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) zSig0 = estimateSqrt32( aExp, aSig0>>32 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) zSig0 <<= 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) aSig1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) shift128Right( aSig0, 0, ( aExp & 1 ) + 2, &aSig0, &aSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0 ) + zSig0 + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) if ( 0 <= (sbits64) zSig0 ) zSig0 = LIT64( 0xFFFFFFFFFFFFFFFF );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) shortShift128Left( aSig0, aSig1, 2, &aSig0, &aSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) mul64To128( zSig0, zSig0, &term0, &term1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) while ( (sbits64) rem0 < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) --zSig0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) shortShift128Left( 0, zSig0, 1, &term0, &term1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) term1 |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) add128( rem0, rem1, term0, term1, &rem0, &rem1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) shortShift128Left( rem0, rem1, 63, &shiftedRem0, &shiftedRem1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) zSig1 = estimateDiv128To64( shiftedRem0, shiftedRem1, zSig0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) if ( (bits64) ( zSig1<<1 ) <= 10 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) if ( zSig1 == 0 ) zSig1 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) mul64To128( zSig0, zSig1, &term1, &term2 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) shortShift128Left( term1, term2, 1, &term1, &term2 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) sub128( rem1, 0, term1, term2, &rem1, &rem2 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) mul64To128( zSig1, zSig1, &term2, &term3 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) while ( (sbits64) rem1 < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) --zSig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) shortShift192Left( 0, zSig0, zSig1, 1, &term1, &term2, &term3 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) term3 |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) add192(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) rem1, rem2, rem3, term1, term2, term3, &rem1, &rem2, &rem3 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) roundAndPackFloatx80(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) roundData, 0, zExp, zSig0, zSig1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) Returns 1 if the extended double-precision floating-point value `a' is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) equal to the corresponding value `b', and 0 otherwise. The comparison is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) flag floatx80_eq( floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) && (bits64) ( extractFloatx80Frac( a )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) || ( ( extractFloatx80Exp( b ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) && (bits64) ( extractFloatx80Frac( b )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) if ( floatx80_is_signaling_nan( a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) || floatx80_is_signaling_nan( b ) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) ( a.low == b.low )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) && ( ( a.high == b.high )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) || ( ( a.low == 0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) Returns 1 if the extended double-precision floating-point value `a' is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) less than or equal to the corresponding value `b', and 0 otherwise. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) comparison is performed according to the IEC/IEEE Standard for Binary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) flag floatx80_le( floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) && (bits64) ( extractFloatx80Frac( a )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) || ( ( extractFloatx80Exp( b ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) && (bits64) ( extractFloatx80Frac( b )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) bSign = extractFloatx80Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) if ( aSign != bSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) aSign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) aSign ? le128( b.high, b.low, a.high, a.low )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) : le128( a.high, a.low, b.high, b.low );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) Returns 1 if the extended double-precision floating-point value `a' is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) less than the corresponding value `b', and 0 otherwise. The comparison
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) is performed according to the IEC/IEEE Standard for Binary Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) flag floatx80_lt( floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) && (bits64) ( extractFloatx80Frac( a )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) || ( ( extractFloatx80Exp( b ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) && (bits64) ( extractFloatx80Frac( b )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) bSign = extractFloatx80Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) if ( aSign != bSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) aSign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) aSign ? lt128( b.high, b.low, a.high, a.low )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) : lt128( a.high, a.low, b.high, b.low );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) Returns 1 if the extended double-precision floating-point value `a' is equal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) to the corresponding value `b', and 0 otherwise. The invalid exception is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) raised if either operand is a NaN. Otherwise, the comparison is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) flag floatx80_eq_signaling( floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) && (bits64) ( extractFloatx80Frac( a )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) || ( ( extractFloatx80Exp( b ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) && (bits64) ( extractFloatx80Frac( b )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) ( a.low == b.low )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) && ( ( a.high == b.high )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) || ( ( a.low == 0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) Returns 1 if the extended double-precision floating-point value `a' is less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) do not cause an exception. Otherwise, the comparison is performed according
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) flag floatx80_le_quiet( floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) && (bits64) ( extractFloatx80Frac( a )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) || ( ( extractFloatx80Exp( b ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) && (bits64) ( extractFloatx80Frac( b )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) /* Do nothing, even if NaN as we're quiet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) bSign = extractFloatx80Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) if ( aSign != bSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) aSign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) == 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) aSign ? le128( b.high, b.low, a.high, a.low )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) : le128( a.high, a.low, b.high, b.low );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) Returns 1 if the extended double-precision floating-point value `a' is less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) an exception. Otherwise, the comparison is performed according to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) IEC/IEEE Standard for Binary Floating-point Arithmetic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) flag floatx80_lt_quiet( floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) flag aSign, bSign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) && (bits64) ( extractFloatx80Frac( a )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) || ( ( extractFloatx80Exp( b ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) && (bits64) ( extractFloatx80Frac( b )<<1 ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) /* Do nothing, even if NaN as we're quiet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) aSign = extractFloatx80Sign( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) bSign = extractFloatx80Sign( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) if ( aSign != bSign ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) aSign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) != 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) aSign ? lt128( b.high, b.low, a.high, a.low )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) : lt128( a.high, a.low, b.high, b.low );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435)