aboutsummaryrefslogtreecommitdiff
path: root/source/slowfloat.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/slowfloat.c')
-rw-r--r--source/slowfloat.c102
1 files changed, 97 insertions, 5 deletions
diff --git a/source/slowfloat.c b/source/slowfloat.c
index 8ecf41f..5af10aa 100644
--- a/source/slowfloat.c
+++ b/source/slowfloat.c
@@ -1,12 +1,12 @@
/*============================================================================
-This C source file is part of TestFloat, Release 3b, a package of programs for
+This C source file is part of TestFloat, Release 3c, a package of programs for
testing the correctness of floating-point arithmetic complying with the IEEE
Standard for Floating-Point, by John R. Hauser.
-Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
-California. All rights reserved.
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -53,7 +53,9 @@ uint_fast8_t slow_extF80_roundingPrecision;
union ui16_f16 { uint16_t ui; float16_t f; };
#endif
union ui32_f32 { uint32_t ui; float32_t f; };
+#ifdef FLOAT64
union ui64_f64 { uint64_t ui; float64_t f; };
+#endif
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
@@ -108,6 +110,11 @@ void
case softfloat_round_near_maxMag:
if ( roundBits < UINT64_C( 0x100000000000 ) ) goto noIncrement;
break;
+#ifdef FLOAT_ROUND_ODD
+ case softfloat_round_odd:
+ sigX64 |= UINT64_C( 0x200000000000 );
+ goto noIncrement;
+#endif
}
sigX64 += UINT64_C( 0x200000000000 );
if ( sigX64 == UINT64_C( 0x0100000000000000 ) ) {
@@ -156,6 +163,11 @@ void
case softfloat_round_near_maxMag:
if ( roundBits < 0x80000000 ) goto noIncrement;
break;
+#ifdef FLOAT_ROUND_ODD
+ case softfloat_round_odd:
+ sigX64 |= UINT64_C( 0x100000000 );
+ goto noIncrement;
+#endif
}
sigX64 += UINT64_C( 0x100000000 );
if ( sigX64 == UINT64_C( 0x0100000000000000 ) ) {
@@ -199,6 +211,11 @@ void
case softfloat_round_near_maxMag:
if ( roundBits < 4 ) goto noIncrement;
break;
+#ifdef FLOAT_ROUND_ODD
+ case softfloat_round_odd:
+ sigX64 |= 8;
+ goto noIncrement;
+#endif
}
sigX64 += 8;
if ( sigX64 == UINT64_C( 0x0100000000000000 ) ) {
@@ -246,8 +263,13 @@ void
case softfloat_round_near_maxMag:
if ( roundBits < UINT64_C( 0x0080000000000000 ) ) goto noIncrement;
break;
+#ifdef FLOAT_ROUND_ODD
+ case softfloat_round_odd:
+ sigX0 |= UINT64_C( 0x100000000000000 );
+ goto noIncrement;
+#endif
}
- sigX0 += UINT64_C( 0x0100000000000000 );
+ sigX0 += UINT64_C( 0x100000000000000 );
sigX64 = xPtr->sig.v64 + ! sigX0;
if ( sigX64 == UINT64_C( 0x0100000000000000 ) ) {
++xPtr->exp;
@@ -291,6 +313,11 @@ void
case softfloat_round_near_maxMag:
if ( roundBits < 0x40 ) goto noIncrement;
break;
+#ifdef FLOAT_ROUND_ODD
+ case softfloat_round_odd:
+ sigX0 |= 0x80;
+ goto noIncrement;
+#endif
}
sigX0 += 0x80;
sigX64 = xPtr->sig.v64 + ! sigX0;
@@ -346,6 +373,9 @@ uint_fast32_t
return (xPtr->isInf && xPtr->sign) ? 0 : 0xFFFFFFFF;
}
if ( xPtr->isZero ) return 0;
+ if ( roundingMode == softfloat_round_odd ) {
+ roundingMode = softfloat_round_minMag;
+ }
savedExceptionFlags = slowfloat_exceptionFlags;
x = *xPtr;
shiftDist = 52 - x.exp;
@@ -412,6 +442,9 @@ uint_fast64_t
(xPtr->isInf && xPtr->sign) ? 0 : UINT64_C( 0xFFFFFFFFFFFFFFFF );
}
if ( xPtr->isZero ) return 0;
+ if ( roundingMode == softfloat_round_odd ) {
+ roundingMode = softfloat_round_minMag;
+ }
savedExceptionFlags = slowfloat_exceptionFlags;
x = *xPtr;
shiftDist = 112 - x.exp;
@@ -479,6 +512,9 @@ int_fast32_t
return (xPtr->isInf && xPtr->sign) ? -0x7FFFFFFF - 1 : 0x7FFFFFFF;
}
if ( xPtr->isZero ) return 0;
+ if ( roundingMode == softfloat_round_odd ) {
+ roundingMode = softfloat_round_minMag;
+ }
savedExceptionFlags = slowfloat_exceptionFlags;
x = *xPtr;
shiftDist = 52 - x.exp;
@@ -552,6 +588,9 @@ int_fast64_t
: INT64_C( 0x7FFFFFFFFFFFFFFF );
}
if ( xPtr->isZero ) return 0;
+ if ( roundingMode == softfloat_round_odd ) {
+ roundingMode = softfloat_round_minMag;
+ }
savedExceptionFlags = slowfloat_exceptionFlags;
x = *xPtr;
shiftDist = 112 - x.exp;
@@ -672,6 +711,7 @@ static float16_t floatXToF16( const struct floatX *xPtr )
break;
case softfloat_round_minMag:
case softfloat_round_max:
+ case softfloat_round_odd:
uiZ = 0xFBFF;
break;
}
@@ -684,6 +724,7 @@ static float16_t floatXToF16( const struct floatX *xPtr )
break;
case softfloat_round_minMag:
case softfloat_round_min:
+ case softfloat_round_odd:
uiZ = 0x7BFF;
break;
}
@@ -806,6 +847,7 @@ static float32_t floatXToF32( const struct floatX *xPtr )
break;
case softfloat_round_minMag:
case softfloat_round_max:
+ case softfloat_round_odd:
uiZ = 0xFF7FFFFF;
break;
}
@@ -818,6 +860,7 @@ static float32_t floatXToF32( const struct floatX *xPtr )
break;
case softfloat_round_minMag:
case softfloat_round_min:
+ case softfloat_round_odd:
uiZ = 0x7F7FFFFF;
break;
}
@@ -849,6 +892,8 @@ static float32_t floatXToF32( const struct floatX *xPtr )
}
+#ifdef FLOAT64
+
static void f64ToFloatX( float64_t a, struct floatX *xPtr )
{
union ui64_f64 uA;
@@ -939,6 +984,7 @@ static float64_t floatXToF64( const struct floatX *xPtr )
break;
case softfloat_round_minMag:
case softfloat_round_max:
+ case softfloat_round_odd:
uiZ = UINT64_C( 0xFFEFFFFFFFFFFFFF );
break;
}
@@ -951,6 +997,7 @@ static float64_t floatXToF64( const struct floatX *xPtr )
break;
case softfloat_round_minMag:
case softfloat_round_min:
+ case softfloat_round_odd:
uiZ = UINT64_C( 0x7FEFFFFFFFFFFFFF );
break;
}
@@ -982,6 +1029,8 @@ static float64_t floatXToF64( const struct floatX *xPtr )
}
+#endif
+
#ifdef EXTFLOAT80
static void extF80MToFloatX( const extFloat80_t *aPtr, struct floatX *xPtr )
@@ -1088,6 +1137,7 @@ static void floatXToExtF80M( const struct floatX *xPtr, extFloat80_t *zPtr )
break;
case softfloat_round_minMag:
case softfloat_round_max:
+ case softfloat_round_odd:
switch ( slow_extF80_roundingPrecision ) {
case 32:
uiZ0 = UINT64_C( 0xFFFFFF0000000000 );
@@ -1113,6 +1163,7 @@ static void floatXToExtF80M( const struct floatX *xPtr, extFloat80_t *zPtr )
break;
case softfloat_round_minMag:
case softfloat_round_min:
+ case softfloat_round_odd:
switch ( slow_extF80_roundingPrecision ) {
case 32:
uiZ0 = UINT64_C( 0xFFFFFF0000000000 );
@@ -1262,6 +1313,7 @@ static void floatXToF128M( const struct floatX *xPtr, float128_t *zPtr )
break;
case softfloat_round_minMag:
case softfloat_round_max:
+ case softfloat_round_odd:
uiZPtr->v64 = UINT64_C( 0xFFFEFFFFFFFFFFFF );
uiZPtr->v0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
break;
@@ -1276,6 +1328,7 @@ static void floatXToF128M( const struct floatX *xPtr, float128_t *zPtr )
break;
case softfloat_round_minMag:
case softfloat_round_min:
+ case softfloat_round_odd:
uiZPtr->v64 = UINT64_C( 0x7FFEFFFFFFFFFFFF );
uiZPtr->v0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
break;
@@ -1302,7 +1355,7 @@ static void floatXToF128M( const struct floatX *xPtr, float128_t *zPtr )
uiZ64 = (uint_fast64_t) exp<<48;
if ( x.sign ) uiZ64 |= UINT64_C( 0x8000000000000000 );
x.sig = shortShiftRightJam128( x.sig, 7 );
- uiZPtr->v64 = uiZ64 | x.sig.v64 & UINT64_C( 0x0000FFFFFFFFFFFF );
+ uiZPtr->v64 = uiZ64 | (x.sig.v64 & UINT64_C( 0x0000FFFFFFFFFFFF ));
uiZPtr->v0 = x.sig.v0;
}
@@ -1325,6 +1378,9 @@ void
struct uint128 sig;
if ( xPtr->isNaN || xPtr->isInf ) return;
+ if ( roundingMode == softfloat_round_odd ) {
+ roundingMode = softfloat_round_minMag;
+ }
exp = xPtr->exp;
shiftDist = 112 - exp;
if ( shiftDist <= 0 ) return;
@@ -2010,6 +2066,8 @@ float32_t slow_ui32_to_f32( uint32_t a )
}
+#ifdef FLOAT64
+
float64_t slow_ui32_to_f64( uint32_t a )
{
struct floatX x;
@@ -2019,6 +2077,8 @@ float64_t slow_ui32_to_f64( uint32_t a )
}
+#endif
+
#ifdef EXTFLOAT80
void slow_ui32_to_extF80M( uint32_t a, extFloat80_t *zPtr )
@@ -2067,6 +2127,8 @@ float32_t slow_ui64_to_f32( uint64_t a )
}
+#ifdef FLOAT64
+
float64_t slow_ui64_to_f64( uint64_t a )
{
struct floatX x;
@@ -2076,6 +2138,8 @@ float64_t slow_ui64_to_f64( uint64_t a )
}
+#endif
+
#ifdef EXTFLOAT80
void slow_ui64_to_extF80M( uint64_t a, extFloat80_t *zPtr )
@@ -2124,6 +2188,8 @@ float32_t slow_i32_to_f32( int32_t a )
}
+#ifdef FLOAT64
+
float64_t slow_i32_to_f64( int32_t a )
{
struct floatX x;
@@ -2133,6 +2199,8 @@ float64_t slow_i32_to_f64( int32_t a )
}
+#endif
+
#ifdef EXTFLOAT80
void slow_i32_to_extF80M( int32_t a, extFloat80_t *zPtr )
@@ -2181,6 +2249,8 @@ float32_t slow_i64_to_f32( int64_t a )
}
+#ifdef FLOAT64
+
float64_t slow_i64_to_f64( int64_t a )
{
struct floatX x;
@@ -2190,6 +2260,8 @@ float64_t slow_i64_to_f64( int64_t a )
}
+#endif
+
#ifdef EXTFLOAT80
void slow_i64_to_extF80M( int64_t a, extFloat80_t *zPtr )
@@ -2303,6 +2375,8 @@ float32_t slow_f16_to_f32( float16_t a )
}
+#ifdef FLOAT64
+
float64_t slow_f16_to_f64( float16_t a )
{
struct floatX x;
@@ -2312,6 +2386,8 @@ float64_t slow_f16_to_f64( float16_t a )
}
+#endif
+
#ifdef EXTFLOAT80
void slow_f16_to_extF80M( float16_t a, extFloat80_t *zPtr )
@@ -2589,6 +2665,8 @@ float16_t slow_f32_to_f16( float32_t a )
#endif
+#ifdef FLOAT64
+
float64_t slow_f32_to_f64( float32_t a )
{
struct floatX x;
@@ -2598,6 +2676,8 @@ float64_t slow_f32_to_f64( float32_t a )
}
+#endif
+
#ifdef EXTFLOAT80
void slow_f32_to_extF80M( float32_t a, extFloat80_t *zPtr )
@@ -2784,6 +2864,8 @@ bool slow_f32_lt_quiet( float32_t a, float32_t b )
}
+#ifdef FLOAT64
+
uint_fast32_t
slow_f64_to_ui32( float64_t a, uint_fast8_t roundingMode, bool exact )
{
@@ -3067,6 +3149,8 @@ bool slow_f64_lt_quiet( float64_t a, float64_t b )
}
+#endif
+
#ifdef EXTFLOAT80
uint_fast32_t
@@ -3175,6 +3259,8 @@ float32_t slow_extF80M_to_f32( const extFloat80_t *aPtr )
}
+#ifdef FLOAT64
+
float64_t slow_extF80M_to_f64( const extFloat80_t *aPtr )
{
struct floatX x;
@@ -3184,6 +3270,8 @@ float64_t slow_extF80M_to_f64( const extFloat80_t *aPtr )
}
+#endif
+
#ifdef FLOAT128
void slow_extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *zPtr )
@@ -3466,6 +3554,8 @@ float32_t slow_f128M_to_f32( const float128_t *aPtr )
}
+#ifdef FLOAT64
+
float64_t slow_f128M_to_f64( const float128_t *aPtr )
{
struct floatX x;
@@ -3475,6 +3565,8 @@ float64_t slow_f128M_to_f64( const float128_t *aPtr )
}
+#endif
+
#ifdef EXTFLOAT80
void slow_f128M_to_extF80M( const float128_t *aPtr, extFloat80_t *zPtr )