|
@@ -3154,6 +3154,60 @@ static int64_t float128_to_int64_scalbn(float128 a, FloatRoundMode rmode,
|
|
return parts_float_to_sint(&p, rmode, scale, INT64_MIN, INT64_MAX, s);
|
|
return parts_float_to_sint(&p, rmode, scale, INT64_MIN, INT64_MAX, s);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static Int128 float128_to_int128_scalbn(float128 a, FloatRoundMode rmode,
|
|
|
|
+ int scale, float_status *s)
|
|
|
|
+{
|
|
|
|
+ int flags = 0;
|
|
|
|
+ Int128 r;
|
|
|
|
+ FloatParts128 p;
|
|
|
|
+
|
|
|
|
+ float128_unpack_canonical(&p, a, s);
|
|
|
|
+
|
|
|
|
+ switch (p.cls) {
|
|
|
|
+ case float_class_snan:
|
|
|
|
+ flags |= float_flag_invalid_snan;
|
|
|
|
+ /* fall through */
|
|
|
|
+ case float_class_qnan:
|
|
|
|
+ flags |= float_flag_invalid;
|
|
|
|
+ r = UINT128_MAX;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case float_class_inf:
|
|
|
|
+ flags = float_flag_invalid | float_flag_invalid_cvti;
|
|
|
|
+ r = p.sign ? INT128_MIN : INT128_MAX;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case float_class_zero:
|
|
|
|
+ return int128_zero();
|
|
|
|
+
|
|
|
|
+ case float_class_normal:
|
|
|
|
+ if (parts_round_to_int_normal(&p, rmode, scale, 128 - 2)) {
|
|
|
|
+ flags = float_flag_inexact;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (p.exp < 127) {
|
|
|
|
+ int shift = 127 - p.exp;
|
|
|
|
+ r = int128_urshift(int128_make128(p.frac_lo, p.frac_hi), shift);
|
|
|
|
+ if (p.sign) {
|
|
|
|
+ r = int128_neg(r);
|
|
|
|
+ }
|
|
|
|
+ } else if (p.exp == 127 && p.sign && p.frac_lo == 0 &&
|
|
|
|
+ p.frac_hi == DECOMPOSED_IMPLICIT_BIT) {
|
|
|
|
+ r = INT128_MIN;
|
|
|
|
+ } else {
|
|
|
|
+ flags = float_flag_invalid | float_flag_invalid_cvti;
|
|
|
|
+ r = p.sign ? INT128_MIN : INT128_MAX;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ g_assert_not_reached();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ float_raise(flags, s);
|
|
|
|
+ return r;
|
|
|
|
+}
|
|
|
|
+
|
|
static int32_t floatx80_to_int32_scalbn(floatx80 a, FloatRoundMode rmode,
|
|
static int32_t floatx80_to_int32_scalbn(floatx80 a, FloatRoundMode rmode,
|
|
int scale, float_status *s)
|
|
int scale, float_status *s)
|
|
{
|
|
{
|
|
@@ -3236,6 +3290,11 @@ int64_t float128_to_int64(float128 a, float_status *s)
|
|
return float128_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
|
|
return float128_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+Int128 float128_to_int128(float128 a, float_status *s)
|
|
|
|
+{
|
|
|
|
+ return float128_to_int128_scalbn(a, s->float_rounding_mode, 0, s);
|
|
|
|
+}
|
|
|
|
+
|
|
int32_t floatx80_to_int32(floatx80 a, float_status *s)
|
|
int32_t floatx80_to_int32(floatx80 a, float_status *s)
|
|
{
|
|
{
|
|
return floatx80_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
|
|
return floatx80_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
|
|
@@ -3301,6 +3360,11 @@ int64_t float128_to_int64_round_to_zero(float128 a, float_status *s)
|
|
return float128_to_int64_scalbn(a, float_round_to_zero, 0, s);
|
|
return float128_to_int64_scalbn(a, float_round_to_zero, 0, s);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+Int128 float128_to_int128_round_to_zero(float128 a, float_status *s)
|
|
|
|
+{
|
|
|
|
+ return float128_to_int128_scalbn(a, float_round_to_zero, 0, s);
|
|
|
|
+}
|
|
|
|
+
|
|
int32_t floatx80_to_int32_round_to_zero(floatx80 a, float_status *s)
|
|
int32_t floatx80_to_int32_round_to_zero(floatx80 a, float_status *s)
|
|
{
|
|
{
|
|
return floatx80_to_int32_scalbn(a, float_round_to_zero, 0, s);
|
|
return floatx80_to_int32_scalbn(a, float_round_to_zero, 0, s);
|
|
@@ -3480,6 +3544,61 @@ static uint64_t float128_to_uint64_scalbn(float128 a, FloatRoundMode rmode,
|
|
return parts_float_to_uint(&p, rmode, scale, UINT64_MAX, s);
|
|
return parts_float_to_uint(&p, rmode, scale, UINT64_MAX, s);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static Int128 float128_to_uint128_scalbn(float128 a, FloatRoundMode rmode,
|
|
|
|
+ int scale, float_status *s)
|
|
|
|
+{
|
|
|
|
+ int flags = 0;
|
|
|
|
+ Int128 r;
|
|
|
|
+ FloatParts128 p;
|
|
|
|
+
|
|
|
|
+ float128_unpack_canonical(&p, a, s);
|
|
|
|
+
|
|
|
|
+ switch (p.cls) {
|
|
|
|
+ case float_class_snan:
|
|
|
|
+ flags |= float_flag_invalid_snan;
|
|
|
|
+ /* fall through */
|
|
|
|
+ case float_class_qnan:
|
|
|
|
+ flags |= float_flag_invalid;
|
|
|
|
+ r = UINT128_MAX;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case float_class_inf:
|
|
|
|
+ flags = float_flag_invalid | float_flag_invalid_cvti;
|
|
|
|
+ r = p.sign ? int128_zero() : UINT128_MAX;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case float_class_zero:
|
|
|
|
+ return int128_zero();
|
|
|
|
+
|
|
|
|
+ case float_class_normal:
|
|
|
|
+ if (parts_round_to_int_normal(&p, rmode, scale, 128 - 2)) {
|
|
|
|
+ flags = float_flag_inexact;
|
|
|
|
+ if (p.cls == float_class_zero) {
|
|
|
|
+ r = int128_zero();
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (p.sign) {
|
|
|
|
+ flags = float_flag_invalid | float_flag_invalid_cvti;
|
|
|
|
+ r = int128_zero();
|
|
|
|
+ } else if (p.exp <= 127) {
|
|
|
|
+ int shift = 127 - p.exp;
|
|
|
|
+ r = int128_urshift(int128_make128(p.frac_lo, p.frac_hi), shift);
|
|
|
|
+ } else {
|
|
|
|
+ flags = float_flag_invalid | float_flag_invalid_cvti;
|
|
|
|
+ r = UINT128_MAX;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ g_assert_not_reached();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ float_raise(flags, s);
|
|
|
|
+ return r;
|
|
|
|
+}
|
|
|
|
+
|
|
uint8_t float16_to_uint8(float16 a, float_status *s)
|
|
uint8_t float16_to_uint8(float16 a, float_status *s)
|
|
{
|
|
{
|
|
return float16_to_uint8_scalbn(a, s->float_rounding_mode, 0, s);
|
|
return float16_to_uint8_scalbn(a, s->float_rounding_mode, 0, s);
|
|
@@ -3540,6 +3659,11 @@ uint64_t float128_to_uint64(float128 a, float_status *s)
|
|
return float128_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
|
|
return float128_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+Int128 float128_to_uint128(float128 a, float_status *s)
|
|
|
|
+{
|
|
|
|
+ return float128_to_uint128_scalbn(a, s->float_rounding_mode, 0, s);
|
|
|
|
+}
|
|
|
|
+
|
|
uint16_t float16_to_uint16_round_to_zero(float16 a, float_status *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);
|
|
return float16_to_uint16_scalbn(a, float_round_to_zero, 0, s);
|
|
@@ -3595,6 +3719,11 @@ uint64_t float128_to_uint64_round_to_zero(float128 a, float_status *s)
|
|
return float128_to_uint64_scalbn(a, float_round_to_zero, 0, s);
|
|
return float128_to_uint64_scalbn(a, float_round_to_zero, 0, s);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+Int128 float128_to_uint128_round_to_zero(float128 a, float_status *s)
|
|
|
|
+{
|
|
|
|
+ return float128_to_uint128_scalbn(a, float_round_to_zero, 0, s);
|
|
|
|
+}
|
|
|
|
+
|
|
uint16_t bfloat16_to_uint16(bfloat16 a, float_status *s)
|
|
uint16_t bfloat16_to_uint16(bfloat16 a, float_status *s)
|
|
{
|
|
{
|
|
return bfloat16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
|
|
return bfloat16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
|
|
@@ -3780,6 +3909,35 @@ bfloat16 int16_to_bfloat16(int16_t a, float_status *status)
|
|
return int64_to_bfloat16_scalbn(a, 0, status);
|
|
return int64_to_bfloat16_scalbn(a, 0, status);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+float128 int128_to_float128(Int128 a, float_status *status)
|
|
|
|
+{
|
|
|
|
+ FloatParts128 p = { };
|
|
|
|
+ int shift;
|
|
|
|
+
|
|
|
|
+ if (int128_nz(a)) {
|
|
|
|
+ p.cls = float_class_normal;
|
|
|
|
+ if (!int128_nonneg(a)) {
|
|
|
|
+ p.sign = true;
|
|
|
|
+ a = int128_neg(a);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ shift = clz64(int128_gethi(a));
|
|
|
|
+ if (shift == 64) {
|
|
|
|
+ shift += clz64(int128_getlo(a));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ p.exp = 127 - shift;
|
|
|
|
+ a = int128_lshift(a, shift);
|
|
|
|
+
|
|
|
|
+ p.frac_hi = int128_gethi(a);
|
|
|
|
+ p.frac_lo = int128_getlo(a);
|
|
|
|
+ } else {
|
|
|
|
+ p.cls = float_class_zero;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return float128_round_pack_canonical(&p, status);
|
|
|
|
+}
|
|
|
|
+
|
|
float128 int64_to_float128(int64_t a, float_status *status)
|
|
float128 int64_to_float128(int64_t a, float_status *status)
|
|
{
|
|
{
|
|
FloatParts128 p;
|
|
FloatParts128 p;
|
|
@@ -3969,6 +4127,31 @@ float128 uint64_to_float128(uint64_t a, float_status *status)
|
|
return float128_round_pack_canonical(&p, status);
|
|
return float128_round_pack_canonical(&p, status);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+float128 uint128_to_float128(Int128 a, float_status *status)
|
|
|
|
+{
|
|
|
|
+ FloatParts128 p = { };
|
|
|
|
+ int shift;
|
|
|
|
+
|
|
|
|
+ if (int128_nz(a)) {
|
|
|
|
+ p.cls = float_class_normal;
|
|
|
|
+
|
|
|
|
+ shift = clz64(int128_gethi(a));
|
|
|
|
+ if (shift == 64) {
|
|
|
|
+ shift += clz64(int128_getlo(a));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ p.exp = 127 - shift;
|
|
|
|
+ a = int128_lshift(a, shift);
|
|
|
|
+
|
|
|
|
+ p.frac_hi = int128_gethi(a);
|
|
|
|
+ p.frac_lo = int128_getlo(a);
|
|
|
|
+ } else {
|
|
|
|
+ p.cls = float_class_zero;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return float128_round_pack_canonical(&p, status);
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Minimum and maximum
|
|
* Minimum and maximum
|
|
*/
|
|
*/
|