Unconditionally include stdlib.h.
[libfirm] / ir / tv / fltcalc.c
index d580cc6..ba377b1 100644 (file)
@@ -25,9 +25,7 @@
  * @version  $Id$
  */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #include "fltcalc.h"
 #include "strcalc.h"
@@ -44,9 +42,7 @@
 #ifdef HAVE_STRING_H
 # include <string.h>
 #endif
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
+#include <stdlib.h>
 #include <stdio.h>
 #include <assert.h>
 
@@ -182,6 +178,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 +395,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 +436,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 +476,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 +552,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 +563,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 +575,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 +639,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 +653,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 +668,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 +676,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 +1152,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 +1165,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 +1183,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 +1333,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;
 
@@ -1416,11 +1430,10 @@ 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");
@@ -1439,8 +1452,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");
@@ -1471,7 +1483,7 @@ unsigned char fc_sub_bits(const fp_value *value, unsigned num_bits, unsigned byt
        /* this is used to cache the packed version of the value */
        static char *packed_value = NULL;
 
-       if (packed_value == NULL) packed_value = xmalloc(value_size);
+       if (packed_value == NULL) packed_value = XMALLOCN(char, value_size);
 
        if (value != NULL)
                pack(value, packed_value);