softfloat.c

来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 1,878 行 · 第 1/5 页

C
1,878
字号
         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {            float_raise( float_flag_invalid );        }        return 0;    }    return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );}/*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is less than orequal to the corresponding value `b', and 0 otherwise.  The comparison isperformed according to the IEC/IEEE Standard for Binary Floating-pointArithmetic.-------------------------------------------------------------------------------*/flag float32_le( float32 a, float32 b ){    flag aSign, bSign;    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        float_raise( float_flag_invalid );        return 0;    }    aSign = extractFloat32Sign( a );    bSign = extractFloat32Sign( b );    if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );    return ( a == b ) || ( aSign ^ ( a < b ) );}/*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is less thanthe corresponding value `b', and 0 otherwise.  The comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic.-------------------------------------------------------------------------------*/flag float32_lt( float32 a, float32 b ){    flag aSign, bSign;    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        float_raise( float_flag_invalid );        return 0;    }    aSign = extractFloat32Sign( a );    bSign = extractFloat32Sign( b );    if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );    return ( a != b ) && ( aSign ^ ( a < b ) );}/*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is equal to thecorresponding value `b', and 0 otherwise.  The invalid exception is raisedif either operand is a NaN.  Otherwise, the comparison is performedaccording to the IEC/IEEE Standard for Binary Floating-point Arithmetic.-------------------------------------------------------------------------------*/flag float32_eq_signaling( float32 a, float32 b ){    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        float_raise( float_flag_invalid );        return 0;    }    return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );}/*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is less than orequal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do notcause an exception.  Otherwise, the comparison is performed according to theIEC/IEEE Standard for Binary Floating-point Arithmetic.-------------------------------------------------------------------------------*/flag float32_le_quiet( float32 a, float32 b ){    flag aSign, bSign;    //int16 aExp, bExp;    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        /* Do nothing, even if NaN as we're quiet */        return 0;    }    aSign = extractFloat32Sign( a );    bSign = extractFloat32Sign( b );    if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );    return ( a == b ) || ( aSign ^ ( a < b ) );}/*-------------------------------------------------------------------------------Returns 1 if the single-precision floating-point value `a' is less thanthe corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause anexception.  Otherwise, the comparison is performed according to the IEC/IEEEStandard for Binary Floating-point Arithmetic.-------------------------------------------------------------------------------*/flag float32_lt_quiet( float32 a, float32 b ){    flag aSign, bSign;    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        /* Do nothing, even if NaN as we're quiet */        return 0;    }    aSign = extractFloat32Sign( a );    bSign = extractFloat32Sign( b );    if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );    return ( a != b ) && ( aSign ^ ( a < b ) );}/*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point value`a' to the 32-bit two's complement integer format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-pointArithmetic---which means in particular that the conversion is roundedaccording to the current rounding mode.  If `a' is a NaN, the largestpositive integer is returned.  Otherwise, if the conversion overflows, thelargest integer with the same sign as `a' is returned.-------------------------------------------------------------------------------*/int32 float64_to_int32( struct roundingData *roundData, float64 a ){    flag aSign;    int16 aExp, shiftCount;    bits64 aSig;    aSig = extractFloat64Frac( a );    aExp = extractFloat64Exp( a );    aSign = extractFloat64Sign( a );    if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;    if ( aExp ) aSig |= LIT64( 0x0010000000000000 );    shiftCount = 0x42C - aExp;    if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );    return roundAndPackInt32( roundData, aSign, aSig );}/*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point value`a' to the 32-bit two's complement integer format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-pointArithmetic, except that the conversion is always rounded toward zero.  If`a' is a NaN, the largest positive integer is returned.  Otherwise, if theconversion overflows, the largest integer with the same sign as `a' isreturned.-------------------------------------------------------------------------------*/int32 float64_to_int32_round_to_zero( float64 a ){    flag aSign;    int16 aExp, shiftCount;    bits64 aSig, savedASig;    int32 z;    aSig = extractFloat64Frac( a );    aExp = extractFloat64Exp( a );    aSign = extractFloat64Sign( a );    shiftCount = 0x433 - aExp;    if ( shiftCount < 21 ) {        if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;        goto invalid;    }    else if ( 52 < shiftCount ) {        if ( aExp || aSig ) float_raise( float_flag_inexact );        return 0;    }    aSig |= LIT64( 0x0010000000000000 );    savedASig = aSig;    aSig >>= shiftCount;    z = aSig;    if ( aSign ) z = - z;    if ( ( z < 0 ) ^ aSign ) { invalid:        float_raise( float_flag_invalid );        return aSign ? 0x80000000 : 0x7FFFFFFF;    }    if ( ( aSig<<shiftCount ) != savedASig ) {        float_raise( float_flag_inexact );    }    return z;}/*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point value`a' to the 32-bit two's complement unsigned integer format.  The conversionis performed according to the IEC/IEEE Standard for Binary Floating-pointArithmetic---which means in particular that the conversion is roundedaccording to the current rounding mode.  If `a' is a NaN, the largestpositive integer is returned.  Otherwise, if the conversion overflows, thelargest positive integer is returned.-------------------------------------------------------------------------------*/int32 float64_to_uint32( struct roundingData *roundData, float64 a ){    flag aSign;    int16 aExp, shiftCount;    bits64 aSig;    aSig = extractFloat64Frac( a );    aExp = extractFloat64Exp( a );    aSign = 0; //extractFloat64Sign( a );    //if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;    if ( aExp ) aSig |= LIT64( 0x0010000000000000 );    shiftCount = 0x42C - aExp;    if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );    return roundAndPackInt32( roundData, aSign, aSig );}/*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point value`a' to the 32-bit two's complement integer format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-pointArithmetic, except that the conversion is always rounded toward zero.  If`a' is a NaN, the largest positive integer is returned.  Otherwise, if theconversion overflows, the largest positive integer is returned.-------------------------------------------------------------------------------*/int32 float64_to_uint32_round_to_zero( float64 a ){    flag aSign;    int16 aExp, shiftCount;    bits64 aSig, savedASig;    int32 z;    aSig = extractFloat64Frac( a );    aExp = extractFloat64Exp( a );    aSign = extractFloat64Sign( a );    shiftCount = 0x433 - aExp;    if ( shiftCount < 21 ) {        if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;        goto invalid;    }    else if ( 52 < shiftCount ) {        if ( aExp || aSig ) float_raise( float_flag_inexact );        return 0;    }    aSig |= LIT64( 0x0010000000000000 );    savedASig = aSig;    aSig >>= shiftCount;    z = aSig;    if ( aSign ) z = - z;    if ( ( z < 0 ) ^ aSign ) { invalid:        float_raise( float_flag_invalid );        return aSign ? 0x80000000 : 0x7FFFFFFF;    }    if ( ( aSig<<shiftCount ) != savedASig ) {        float_raise( float_flag_inexact );    }    return z;}/*-------------------------------------------------------------------------------Returns the result of converting the double-precision floating-point value`a' to the single-precision floating-point format.  The conversion isperformed according to the IEC/IEEE Standard for Binary Floating-pointArithmetic.-------------------------------------------------------------------------------*/float32 float64_to_float32( struct roundingData *roundData, float64 a ){    flag aSign;    int16 aExp;    bits64 aSig;    bits32 zSig;    aSig = extractFloat64Frac( a );    aExp = extractFloat64Exp( a );    aSign = extractFloat64Sign( a );    if ( aExp == 0x7FF ) {        if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) );        return packFloat32( aSign, 0xFF, 0 );    }    shift64RightJamming( aSig, 22, &aSig );    zSig = aSig;    if ( aExp || zSig ) {        zSig |= 0x40000000;        aExp -= 0x381;    }    return roundAndPackFloat32( roundData, aSign, aExp, zSig );}/*-------------------------------------------------------------------------------Rounds the double-precision floating-point value `a' to an integer, andreturns the result as a double-precision floating-point value.  Theoperation is performed according to the IEC/IEEE Standard for BinaryFloating-point Arithmetic.-------------------------------------------------------------------------------*/float64 float64_round_to_int( struct roundingData *roundData, float64 a ){    flag aSign;    int16 aExp;    bits64 lastBitMask, roundBitsMask;    int8 roundingMode;    float64 z;    aExp = extractFloat64Exp( a );    if ( 0x433 <= aExp ) {        if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) {            return propagateFloat64NaN( a, a );        }        return a;    }    if ( aExp <= 0x3FE ) {        if ( (bits64) ( a<<1 ) == 0 ) return a;        roundData->exception |= float_flag_inexact;        aSign = extractFloat64Sign( a );        switch ( roundData->mode ) {         case float_round_nearest_even:            if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {                return packFloat64( aSign, 0x3FF, 0 );            }            break;         case float_round_down:            return aSign ? LIT64( 0xBFF0000000000000 ) : 0;         case float_round_up:            return            aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 );        }        return packFloat64( aSign, 0, 0 );    }    lastBitMask = 1;    lastBitMask <<= 0x433 - aExp;    roundBitsMask = lastBitMask - 1;    z = a;    roundingMode = roundData->mode;    if ( roundingMode == float_round_nearest_even ) {        z += lastBitMask>>1;        if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;    }    else if ( roundingMode != float_round_to_zero ) {        if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) {            z += roundBitsMask;        }    }    z &= ~ roundBitsMask;    if ( z != a ) roundData->exception |= float_flag_inexact;    return z;}/*-------------------------------------------------------------------------------Returns the result of adding the absolute values of the double-precision

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?