@ -1293,19 +1293,23 @@ float32 float64_to_float32(float64 a, float_status *s)
* Arithmetic .
*/
static FloatParts round_to_int ( FloatParts a , int rounding_mode , float_status * s )
static FloatParts round_to_int ( FloatParts a , int rmode ,
int scale , float_status * s )
{
if ( is_nan ( a . cls ) ) {
switch ( a . cls ) {
case float_class_qnan :
case float_class_snan :
return return_nan ( a , s ) ;
}
switch ( a . cls ) {
case float_class_zero :
case float_class_inf :
case float_class_qnan :
/* already "integral" */
break ;
case float_class_normal :
scale = MIN ( MAX ( scale , - 0x10000 ) , 0x10000 ) ;
a . exp + = scale ;
if ( a . exp > = DECOMPOSED_BINARY_POINT ) {
/* already integral */
break ;
@ -1314,7 +1318,7 @@ static FloatParts round_to_int(FloatParts a, int rounding_mode, float_status *s)
bool one ;
/* all fractional */
s - > float_exception_flags | = float_flag_inexact ;
switch ( rounding_ mode ) {
switch ( rmode ) {
case float_round_nearest_even :
one = a . exp = = - 1 & & a . frac > DECOMPOSED_IMPLICIT_BIT ;
break ;
@ -1347,7 +1351,7 @@ static FloatParts round_to_int(FloatParts a, int rounding_mode, float_status *s)
uint64_t rnd_mask = rnd_even_mask > > 1 ;
uint64_t inc ;
switch ( rounding_ mode ) {
switch ( rmode ) {
case float_round_nearest_even :
inc = ( ( a . frac & rnd_even_mask ) ! = frac_lsbm1 ? frac_lsbm1 : 0 ) ;
break ;
@ -1387,28 +1391,28 @@ static FloatParts round_to_int(FloatParts a, int rounding_mode, float_status *s)
float16 float16_round_to_int ( float16 a , float_status * s )
{
FloatParts pa = float16_unpack_canonical ( a , s ) ;
FloatParts pr = round_to_int ( pa , s - > float_rounding_mode , s ) ;
FloatParts pr = round_to_int ( pa , s - > float_rounding_mode , 0 , s ) ;
return float16_round_pack_canonical ( pr , s ) ;
}
float32 float32_round_to_int ( float32 a , float_status * s )
{
FloatParts pa = float32_unpack_canonical ( a , s ) ;
FloatParts pr = round_to_int ( pa , s - > float_rounding_mode , s ) ;
FloatParts pr = round_to_int ( pa , s - > float_rounding_mode , 0 , s ) ;
return float32_round_pack_canonical ( pr , s ) ;
}
float64 float64_round_to_int ( float64 a , float_status * s )
{
FloatParts pa = float64_unpack_canonical ( a , s ) ;
FloatParts pr = round_to_int ( pa , s - > float_rounding_mode , s ) ;
FloatParts pr = round_to_int ( pa , s - > float_rounding_mode , 0 , s ) ;
return float64_round_pack_canonical ( pr , s ) ;
}
float64 float64_trunc_to_int ( float64 a , float_status * s )
{
FloatParts pa = float64_unpack_canonical ( a , s ) ;
FloatParts pr = round_to_int ( pa , float_round_to_zero , s ) ;
FloatParts pr = round_to_int ( pa , float_round_to_zero , 0 , s ) ;
return float64_round_pack_canonical ( pr , s ) ;
}
@ -1423,13 +1427,13 @@ float64 float64_trunc_to_int(float64 a, float_status *s)
* is returned .
*/
static int64_t round_to_int_and_pack ( FloatParts in , int rmode ,
static int64_t round_to_int_and_pack ( FloatParts in , int rmode , int scale ,
int64_t min , int64_t max ,
float_status * s )
{
uint64_t r ;
int orig_flags = get_float_exception_flags ( s ) ;
FloatParts p = round_to_int ( in , rmode , s ) ;
FloatParts p = round_to_int ( in , rmode , scale , s ) ;
switch ( p . cls ) {
case float_class_snan :
@ -1469,38 +1473,158 @@ static int64_t round_to_int_and_pack(FloatParts in, int rmode,
}
}
# define FLOAT_TO_INT(fsz, isz) \
int # # isz # # _t float # # fsz # # _to_int # # isz ( float # # fsz a , \
float_status * s ) \
{ \
FloatParts p = float # # fsz # # _unpack_canonical ( a , s ) ; \
return round_to_int_and_pack ( p , s - > float_rounding_mode , \
INT # # isz # # _MIN , INT # # isz # # _MAX , \
s ) ; \
} \
\
int # # isz # # _t float # # fsz # # _to_int # # isz # # _round_to_zero \
( float # # fsz a , float_status * s ) \
{ \
FloatParts p = float # # fsz # # _unpack_canonical ( a , s ) ; \
return round_to_int_and_pack ( p , float_round_to_zero , \
INT # # isz # # _MIN , INT # # isz # # _MAX , \
s ) ; \
int16_t float16_to_int16_scalbn ( float16 a , int rmode , int scale ,
float_status * s )
{
return round_to_int_and_pack ( float16_unpack_canonical ( a , s ) ,
rmode , scale , INT16_MIN , INT16_MAX , s ) ;
}
int32_t float16_to_int32_scalbn ( float16 a , int rmode , int scale ,
float_status * s )
{
return round_to_int_and_pack ( float16_unpack_canonical ( a , s ) ,
rmode , scale , INT32_MIN , INT32_MAX , s ) ;
}
int64_t float16_to_int64_scalbn ( float16 a , int rmode , int scale ,
float_status * s )
{
return round_to_int_and_pack ( float16_unpack_canonical ( a , s ) ,
rmode , scale , INT64_MIN , INT64_MAX , s ) ;
}
int16_t float32_to_int16_scalbn ( float32 a , int rmode , int scale ,
float_status * s )
{
return round_to_int_and_pack ( float32_unpack_canonical ( a , s ) ,
rmode , scale , INT16_MIN , INT16_MAX , s ) ;
}
int32_t float32_to_int32_scalbn ( float32 a , int rmode , int scale ,
float_status * s )
{
return round_to_int_and_pack ( float32_unpack_canonical ( a , s ) ,
rmode , scale , INT32_MIN , INT32_MAX , s ) ;
}
int64_t float32_to_int64_scalbn ( float32 a , int rmode , int scale ,
float_status * s )
{
return round_to_int_and_pack ( float32_unpack_canonical ( a , s ) ,
rmode , scale , INT64_MIN , INT64_MAX , s ) ;
}
int16_t float64_to_int16_scalbn ( float64 a , int rmode , int scale ,
float_status * s )
{
return round_to_int_and_pack ( float64_unpack_canonical ( a , s ) ,
rmode , scale , INT16_MIN , INT16_MAX , s ) ;
}
int32_t float64_to_int32_scalbn ( float64 a , int rmode , int scale ,
float_status * s )
{
return round_to_int_and_pack ( float64_unpack_canonical ( a , s ) ,
rmode , scale , INT32_MIN , INT32_MAX , s ) ;
}
int64_t float64_to_int64_scalbn ( float64 a , int rmode , int scale ,
float_status * s )
{
return round_to_int_and_pack ( float64_unpack_canonical ( a , s ) ,
rmode , scale , INT64_MIN , INT64_MAX , s ) ;
}
int16_t float16_to_int16 ( float16 a , float_status * s )
{
return float16_to_int16_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
int32_t float16_to_int32 ( float16 a , float_status * s )
{
return float16_to_int32_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
int64_t float16_to_int64 ( float16 a , float_status * s )
{
return float16_to_int64_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
int16_t float32_to_int16 ( float32 a , float_status * s )
{
return float32_to_int16_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
int32_t float32_to_int32 ( float32 a , float_status * s )
{
return float32_to_int32_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
int64_t float32_to_int64 ( float32 a , float_status * s )
{
return float32_to_int64_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
int16_t float64_to_int16 ( float64 a , float_status * s )
{
return float64_to_int16_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
int32_t float64_to_int32 ( float64 a , float_status * s )
{
return float64_to_int32_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
int64_t float64_to_int64 ( float64 a , float_status * s )
{
return float64_to_int64_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
int16_t float16_to_int16_round_to_zero ( float16 a , float_status * s )
{
return float16_to_int16_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
int32_t float16_to_int32_round_to_zero ( float16 a , float_status * s )
{
return float16_to_int32_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
int64_t float16_to_int64_round_to_zero ( float16 a , float_status * s )
{
return float16_to_int64_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
int16_t float32_to_int16_round_to_zero ( float32 a , float_status * s )
{
return float32_to_int16_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
int32_t float32_to_int32_round_to_zero ( float32 a , float_status * s )
{
return float32_to_int32_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
FLOAT_TO_INT ( 16 , 16 )
FLOAT_TO_INT ( 16 , 32 )
FLOAT_TO_INT ( 16 , 64 )
int64_t float32_to_int64_round_to_zero ( float32 a , float_status * s )
{
return float32_to_int64_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
FLOAT_TO_INT ( 32 , 16 )
FLOAT_TO_INT ( 32 , 32 )
FLOAT_TO_INT ( 32 , 64 )
int16_t float64_to_int16_round_to_zero ( float64 a , float_status * s )
{
return float64_to_int16_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
FLOAT_TO_INT ( 64 , 16 )
FLOAT_TO_INT ( 64 , 32 )
FLOAT_TO_INT ( 64 , 64 )
int32_t float64_to_int32_round_to_zero ( float64 a , float_status * s )
{
return float64_to_int32_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
# undef FLOAT_TO_INT
int64_t float64_to_int64_round_to_zero ( float64 a , float_status * s )
{
return float64_to_int64_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
/*
* Returns the result of converting the floating - point value ` a ' to
@ -1515,11 +1639,12 @@ FLOAT_TO_INT(64, 64)
* flag .
*/
static uint64_t round_to_uint_and_pack ( FloatParts in , int rmode , uint64_t max ,
float_status * s )
static uint64_t round_to_uint_and_pack ( FloatParts in , int rmode , int scale ,
uint64_t max , float_status * s )
{
int orig_flags = get_float_exception_flags ( s ) ;
FloatParts p = round_to_int ( in , rmode , s ) ;
FloatParts p = round_to_int ( in , rmode , scale , s ) ;
uint64_t r ;
switch ( p . cls ) {
case float_class_snan :
@ -1532,8 +1657,6 @@ static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, uint64_t max,
case float_class_zero :
return 0 ;
case float_class_normal :
{
uint64_t r ;
if ( p . sign ) {
s - > float_exception_flags = orig_flags | float_flag_invalid ;
return 0 ;
@ -1555,45 +1678,165 @@ static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, uint64_t max,
if ( r > max ) {
s - > float_exception_flags = orig_flags | float_flag_invalid ;
return max ;
} else {
return r ;
}
}
return r ;
default :
g_assert_not_reached ( ) ;
}
}
# define FLOAT_TO_UINT(fsz, isz) \
uint # # isz # # _t float # # fsz # # _to_uint # # isz ( float # # fsz a , \
float_status * s ) \
{ \
FloatParts p = float # # fsz # # _unpack_canonical ( a , s ) ; \
return round_to_uint_and_pack ( p , s - > float_rounding_mode , \
UINT # # isz # # _MAX , s ) ; \
} \
\
uint # # isz # # _t float # # fsz # # _to_uint # # isz # # _round_to_zero \
( float # # fsz a , float_status * s ) \
{ \
FloatParts p = float # # fsz # # _unpack_canonical ( a , s ) ; \
return round_to_uint_and_pack ( p , float_round_to_zero , \
UINT # # isz # # _MAX , s ) ; \
uint16_t float16_to_uint16_scalbn ( float16 a , int rmode , int scale ,
float_status * s )
{
return round_to_uint_and_pack ( float16_unpack_canonical ( a , s ) ,
rmode , scale , UINT16_MAX , s ) ;
}
uint32_t float16_to_uint32_scalbn ( float16 a , int rmode , int scale ,
float_status * s )
{
return round_to_uint_and_pack ( float16_unpack_canonical ( a , s ) ,
rmode , scale , UINT32_MAX , s ) ;
}
uint64_t float16_to_uint64_scalbn ( float16 a , int rmode , int scale ,
float_status * s )
{
return round_to_uint_and_pack ( float16_unpack_canonical ( a , s ) ,
rmode , scale , UINT64_MAX , s ) ;
}
uint16_t float32_to_uint16_scalbn ( float32 a , int rmode , int scale ,
float_status * s )
{
return round_to_uint_and_pack ( float32_unpack_canonical ( a , s ) ,
rmode , scale , UINT16_MAX , s ) ;
}
uint32_t float32_to_uint32_scalbn ( float32 a , int rmode , int scale ,
float_status * s )
{
return round_to_uint_and_pack ( float32_unpack_canonical ( a , s ) ,
rmode , scale , UINT32_MAX , s ) ;
}
uint64_t float32_to_uint64_scalbn ( float32 a , int rmode , int scale ,
float_status * s )
{
return round_to_uint_and_pack ( float32_unpack_canonical ( a , s ) ,
rmode , scale , UINT64_MAX , s ) ;
}
uint16_t float64_to_uint16_scalbn ( float64 a , int rmode , int scale ,
float_status * s )
{
return round_to_uint_and_pack ( float64_unpack_canonical ( a , s ) ,
rmode , scale , UINT16_MAX , s ) ;
}
uint32_t float64_to_uint32_scalbn ( float64 a , int rmode , int scale ,
float_status * s )
{
return round_to_uint_and_pack ( float64_unpack_canonical ( a , s ) ,
rmode , scale , UINT32_MAX , s ) ;
}
uint64_t float64_to_uint64_scalbn ( float64 a , int rmode , int scale ,
float_status * s )
{
return round_to_uint_and_pack ( float64_unpack_canonical ( a , s ) ,
rmode , scale , UINT64_MAX , s ) ;
}
uint16_t float16_to_uint16 ( float16 a , float_status * s )
{
return float16_to_uint16_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
uint32_t float16_to_uint32 ( float16 a , float_status * s )
{
return float16_to_uint32_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
uint64_t float16_to_uint64 ( float16 a , float_status * s )
{
return float16_to_uint64_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
FLOAT_TO_UINT ( 16 , 16 )
FLOAT_TO_UINT ( 16 , 32 )
FLOAT_TO_UINT ( 16 , 64 )
uint16_t float32_to_uint16 ( float32 a , float_status * s )
{
return float32_to_uint16_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
FLOAT_TO_UINT ( 32 , 16 )
FLOAT_TO_UINT ( 32 , 32 )
FLOAT_TO_UINT ( 32 , 64 )
uint32_t float32_to_uint32 ( float32 a , float_status * s )
{
return float32_to_uint32_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
FLOAT_TO_UINT ( 64 , 16 )
FLOAT_TO_UINT ( 64 , 32 )
FLOAT_TO_UINT ( 64 , 64 )
uint64_t float32_to_uint64 ( float32 a , float_status * s )
{
return float32_to_uint64_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
# undef FLOAT_TO_UINT
uint16_t float64_to_uint16 ( float64 a , float_status * s )
{
return float64_to_uint16_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
uint32_t float64_to_uint32 ( float64 a , float_status * s )
{
return float64_to_uint32_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
uint64_t float64_to_uint64 ( float64 a , float_status * s )
{
return float64_to_uint64_scalbn ( a , s - > float_rounding_mode , 0 , s ) ;
}
uint16_t float16_to_uint16_round_to_zero ( float16 a , float_status * s )
{
return float16_to_uint16_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
uint32_t float16_to_uint32_round_to_zero ( float16 a , float_status * s )
{
return float16_to_uint32_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
uint64_t float16_to_uint64_round_to_zero ( float16 a , float_status * s )
{
return float16_to_uint64_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
uint16_t float32_to_uint16_round_to_zero ( float32 a , float_status * s )
{
return float32_to_uint16_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
uint32_t float32_to_uint32_round_to_zero ( float32 a , float_status * s )
{
return float32_to_uint32_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
uint64_t float32_to_uint64_round_to_zero ( float32 a , float_status * s )
{
return float32_to_uint64_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
uint16_t float64_to_uint16_round_to_zero ( float64 a , float_status * s )
{
return float64_to_uint16_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
uint32_t float64_to_uint32_round_to_zero ( float64 a , float_status * s )
{
return float64_to_uint32_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
uint64_t float64_to_uint64_round_to_zero ( float64 a , float_status * s )
{
return float64_to_uint64_scalbn ( a , float_round_to_zero , 0 , s ) ;
}
/*
* Integer to float conversions