X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftv%2Ffltcalc.c;h=d1ba43fc22361a04cadc8e9888cf7f4d409a77b0;hb=ead91aed10122a0137167cc5930d2b4c9e292995;hp=7d20bab5b5b2b2f71e45eee69df2c6dc90a8b726;hpb=354ec538057abddc8b757c5b0ba8e3c15115438b;p=libfirm diff --git a/ir/tv/fltcalc.c b/ir/tv/fltcalc.c index 7d20bab5b..d1ba43fc2 100644 --- a/ir/tv/fltcalc.c +++ b/ir/tv/fltcalc.c @@ -182,6 +182,8 @@ static void *pack(const fp_value *int_float, void *packed) { default: break; } + assert(int_float->desc.explicit_one <= 1); + /* pack sign: move it to the left after exponent AND mantissa */ sc_val_from_ulong(int_float->sign, temp); @@ -397,16 +399,19 @@ static int normalize(const fp_value *in_val, fp_value *out_val, int sticky) { } /** - * Operations involving NaN's must return NaN + * Operations involving NaN's must return NaN. + * They are NOT exact. */ #define handle_NAN(a, b, result) \ do { \ if (a->desc.clss == NAN) { \ if (a != result) memcpy(result, a, calc_buffer_size); \ + fc_exact = 0; \ return; \ } \ if (b->desc.clss == NAN) { \ if (b != result) memcpy(result, b, calc_buffer_size); \ + fc_exact = 0; \ return; \ } \ }while (0) @@ -435,6 +440,7 @@ static void _fadd(const fp_value *a, const fp_value *b, fp_value *result) { /* produce NaN on inf - inf */ if (sign && (a->desc.clss == INF) && (b->desc.clss == INF)) { + fc_exact = 0; fc_get_qnan(&a->desc, result); return; } @@ -474,12 +480,14 @@ static void _fadd(const fp_value *a, const fp_value *b, fp_value *result) { if (a->desc.clss == ZERO || b->desc.clss == INF) { if (b != result) memcpy(result, b, calc_buffer_size); + fc_exact = b->desc.clss == NORMAL; result->sign = res_sign; return; } if (b->desc.clss == ZERO || a->desc.clss == INF) { if (a != result) memcpy(result, a, calc_buffer_size); + fc_exact = a->desc.clss == NORMAL; result->sign = res_sign; return; } @@ -548,9 +556,10 @@ static void _fmul(const fp_value *a, const fp_value *b, fp_value *result) { /* produce NaN on 0 * inf */ if (a->desc.clss == ZERO) { - if (b->desc.clss == INF) + if (b->desc.clss == INF) { fc_get_qnan(&a->desc, result); - else { + fc_exact = 0; + } else { if (a != result) memcpy(result, a, calc_buffer_size); result->sign = res_sign; @@ -558,9 +567,10 @@ static void _fmul(const fp_value *a, const fp_value *b, fp_value *result) { return; } if (b->desc.clss == ZERO) { - if (a->desc.clss == INF) + if (a->desc.clss == INF) { fc_get_qnan(&a->desc, result); - else { + fc_exact = 0; + } else { if (b != result) memcpy(result, b, calc_buffer_size); result->sign = res_sign; @@ -569,12 +579,14 @@ static void _fmul(const fp_value *a, const fp_value *b, fp_value *result) { } if (a->desc.clss == INF) { + fc_exact = 0; if (a != result) memcpy(result, a, calc_buffer_size); result->sign = res_sign; return; } if (b->desc.clss == INF) { + fc_exact = 0; if (b != result) memcpy(result, b, calc_buffer_size); result->sign = res_sign; @@ -631,10 +643,11 @@ static void _fdiv(const fp_value *a, const fp_value *b, fp_value *result) { /* produce NAN on 0/0 and inf/inf */ if (a->desc.clss == ZERO) { - if (b->desc.clss == ZERO) + if (b->desc.clss == ZERO) { /* 0/0 -> NaN */ fc_get_qnan(&a->desc, result); - else { + fc_exact = 0; + } else { /* 0/x -> a */ if (a != result) memcpy(result, a, calc_buffer_size); @@ -644,10 +657,11 @@ static void _fdiv(const fp_value *a, const fp_value *b, fp_value *result) { } if (b->desc.clss == INF) { - if (a->desc.clss == INF) + fc_exact = 0; + if (a->desc.clss == INF) { /* inf/inf -> NaN */ fc_get_qnan(&a->desc, result); - else { + } else { /* x/inf -> 0 */ sc_val_from_ulong(0, NULL); _save_result(_exp(result)); @@ -658,6 +672,7 @@ static void _fdiv(const fp_value *a, const fp_value *b, fp_value *result) { } if (a->desc.clss == INF) { + fc_exact = 0; /* inf/x -> inf */ if (a != result) memcpy(result, a, calc_buffer_size); @@ -665,6 +680,7 @@ static void _fdiv(const fp_value *a, const fp_value *b, fp_value *result) { return; } if (b->desc.clss == ZERO) { + fc_exact = 0; /* division by zero */ if (result->sign) fc_get_minusinf(&a->desc, result); @@ -1140,6 +1156,7 @@ LLDBL fc_val_to_ieee754(const fp_value *val) { value_t buildval; ieee_descriptor_t desc; + unsigned mantissa_size; #ifdef HAVE_LONG_DOUBLE desc.exponent_size = 15; @@ -1152,6 +1169,7 @@ LLDBL fc_val_to_ieee754(const fp_value *val) { desc.explicit_one = 0; desc.clss = NORMAL; #endif + mantissa_size = desc.mantissa_size + desc.explicit_one; temp = alloca(calc_buffer_size); value = fc_cast(val, &desc, temp); @@ -1169,10 +1187,10 @@ LLDBL fc_val_to_ieee754(const fp_value *val) { mantissa1 = 0; for (byte_offset = 0; byte_offset < 4; byte_offset++) - mantissa1 |= sc_sub_bits(_mant(value), desc.mantissa_size, byte_offset) << (byte_offset<<3); + mantissa1 |= sc_sub_bits(_mant(value), mantissa_size, byte_offset) << (byte_offset << 3); for (; (byte_offset<<3) < desc.mantissa_size; byte_offset++) - mantissa0 |= sc_sub_bits(_mant(value), desc.mantissa_size, byte_offset) << ((byte_offset-4)<<3); + mantissa0 |= sc_sub_bits(_mant(value), mantissa_size, byte_offset) << ((byte_offset - 4) << 3); #ifdef HAVE_LONG_DOUBLE buildval.val.high = sign << 15; @@ -1319,7 +1337,7 @@ fp_value *fc_get_plusinf(const ieee_descriptor_t *desc, fp_value *result) { result->desc.exponent_size = desc->exponent_size; result->desc.mantissa_size = desc->mantissa_size; result->desc.explicit_one = desc->explicit_one; - result->desc.clss = NORMAL; + result->desc.clss = INF; result->sign = 0; @@ -1408,6 +1426,7 @@ int fc_is_subnormal(const fp_value *a) { char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) { char *mul_1; + LLDBL flt_val; mul_1 = alloca(calc_buffer_size); @@ -1415,22 +1434,21 @@ char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) { case FC_DEC: switch ((value_class_t)val->desc.clss) { case INF: - if (buflen >= 8 + val->sign) sprintf(buf, "%sINFINITY", val->sign ? "-":""); - else snprintf(buf, buflen, "%sINF", val->sign ? "-":NULL); + snprintf(buf, buflen, "%cINF", val->sign ? '-' : '+'); break; case NAN: - snprintf(buf, buflen, "NAN"); + snprintf(buf, buflen, "NaN"); break; case ZERO: snprintf(buf, buflen, "0.0"); break; default: - /* XXX to be implemented */ + flt_val = fc_val_to_ieee754(val); #ifdef HAVE_LONG_DOUBLE /* XXX 30 is arbitrary */ - snprintf(buf, buflen, "%.30LE", fc_val_to_ieee754(val)); + snprintf(buf, buflen, "%.30LE", flt_val); #else - snprintf(buf, buflen, "%.18E", fc_val_to_ieee754(val)); + snprintf(buf, buflen, "%.18E", flt_val); #endif } break; @@ -1438,8 +1456,7 @@ char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) { case FC_HEX: switch ((value_class_t)val->desc.clss) { case INF: - if (buflen >= 8+val->sign) sprintf(buf, "%sINFINITY", val->sign?"-":""); - else snprintf(buf, buflen, "%sINF", val->sign?"-":NULL); + snprintf(buf, buflen, "%cINF", val->sign ? '-' : '+'); break; case NAN: snprintf(buf, buflen, "NAN"); @@ -1448,10 +1465,11 @@ char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) { snprintf(buf, buflen, "0.0"); break; default: + flt_val = fc_val_to_ieee754(val); #ifdef HAVE_LONG_DOUBLE - snprintf(buf, buflen, "%LA", fc_val_to_ieee754(val)); + snprintf(buf, buflen, "%LA", flt_val); #else - snprintf(buf, buflen, "%A", fc_val_to_ieee754(val)); + snprintf(buf, buflen, "%A", flt_val); #endif } break;