diff --git a/ext/fputils/configure.in b/ext/fputils/configure.in index 59a21c18e..bb2291b6f 100644 --- a/ext/fputils/configure.in +++ b/ext/fputils/configure.in @@ -12,10 +12,14 @@ DX_INIT_DOXYGEN([libfputils]) AC_REQUIRE_AUX_FILE([tap-driver.sh]) AC_PROG_CC -AM_PROG_CC_C_O +AC_PROG_CC_C99 AC_PROG_LIBTOOL AC_PROG_AWK +if test "x$ac_cv_prog_cc_c99" = "xno"; then + AC_MSG_ERROR([Could not enable C99 support in compiler.]) +fi + AM_CFLAGS="-Wall -Werror" AM_CPPFLAGS="-I\$(abs_top_srcdir)/include" diff --git a/ext/fputils/fp80.c b/ext/fputils/fp80.c index 703b07ac9..8100a4d99 100644 --- a/ext/fputils/fp80.c +++ b/ext/fputils/fp80.c @@ -36,10 +36,8 @@ #include typedef union { - union { - uint64_t bits; - double value; - }; + uint64_t bits; + double value; } fp64_t; @@ -74,7 +72,7 @@ build_fp64(int sign, uint64_t frac, int exp) int fp80_sgn(fp80_t fp80) { - return (fp80.u.repr.se & FP80_SIGN_BIT) ? -1 : 1; + return (fp80.repr.se & FP80_SIGN_BIT) ? -1 : 1; } int @@ -105,9 +103,9 @@ fp80_isqnan(fp80_t fp80) int fp80_isqnani(fp80_t fp80) { - const uint64_t frac_low = fp80.u.repr.fi & (FP80_FRAC_MASK >> 1); + const uint64_t frac_low = fp80.repr.fi & (FP80_FRAC_MASK >> 1); - return fp80_isqnan(fp80) && (fp80.u.repr.se & FP80_SIGN_BIT) && !frac_low; + return fp80_isqnan(fp80) && (fp80.repr.se & FP80_SIGN_BIT) && !frac_low; } int @@ -133,7 +131,7 @@ fp80_isnan(fp80_t fp80) int fp80_iszero(fp80_t fp80) { - return fp80.u.repr.fi == 0 && FP80_EXP(fp80) == 0 ? fp80_sgn(fp80) : 0; + return fp80.repr.fi == 0 && FP80_EXP(fp80) == 0 ? fp80_sgn(fp80) : 0; } int @@ -169,10 +167,10 @@ fp80_classify(fp80_t fp80) double fp80_cvtd(fp80_t fp80) { - const int sign = fp80.u.repr.se & FP80_SIGN_BIT; + const int sign = fp80.repr.se & FP80_SIGN_BIT; if (!fp80_isspecial(fp80)) { - const uint64_t frac = fp80.u.repr.fi; + const uint64_t frac = fp80.repr.fi; const int unb_exp = FP80_EXP(fp80) - FP80_EXP_BIAS; const int fp64_exp = unb_exp + FP64_EXP_BIAS; const uint64_t fp64_frac = frac >> (FP80_FRAC_BITS - FP64_FRAC_BITS); @@ -242,6 +240,6 @@ void fp80_debug_dump(FILE *fout, fp80_t fp80) { fprintf(fout, "sgn: %i, int: %i, frac: 0x%llx, exp: 0x%x (%i)\n", - fp80_sgn(fp80), !!(fp80.u.repr.fi & FP80_INT_BIT), FP80_FRAC(fp80), + fp80_sgn(fp80), !!(fp80.repr.fi & FP80_INT_BIT), FP80_FRAC(fp80), FP80_EXP(fp80), FP80_EXP(fp80) - FP80_EXP_BIAS); } diff --git a/ext/fputils/fpbits.h b/ext/fputils/fpbits.h index 9fb934843..335a122d3 100644 --- a/ext/fputils/fpbits.h +++ b/ext/fputils/fpbits.h @@ -76,15 +76,15 @@ #define BUILD_FP80(sign, frac, exp) \ { \ - .u.repr.se = BUILD_FP80_SE(sign, exp), \ - .u.repr.fi = BUILD_FP80_FI(frac, exp) \ + .repr.se = BUILD_FP80_SE(sign, exp), \ + .repr.fi = BUILD_FP80_FI(frac, exp) \ } #define FP80_FRAC(fp80) \ - (fp80.u.repr.fi & FP80_FRAC_MASK) + (fp80.repr.fi & FP80_FRAC_MASK) #define FP80_EXP(fp80) \ - (fp80.u.repr.se & FP80_EXP_MASK) + (fp80.repr.se & FP80_EXP_MASK) #define FP64_FRAC(fp64) \ (fp64.bits & FP64_FRAC_MASK) diff --git a/ext/fputils/include/fputils/fp80.h b/ext/fputils/include/fputils/fp80.h index e584baab4..70acb6cb1 100644 --- a/ext/fputils/include/fputils/fp80.h +++ b/ext/fputils/include/fputils/fp80.h @@ -46,14 +46,12 @@ extern "C" { */ /** Internal representation of an 80-bit float. */ -typedef struct { - union { - char bits[10]; - struct { - uint64_t fi; - uint16_t se; - } repr; - } u; +typedef union { + char bits[10]; + struct { + uint64_t fi; + uint16_t se; + } repr; } fp80_t; /** Constant representing +inf */ diff --git a/ext/fputils/tests/fp80_cvtd.c b/ext/fputils/tests/fp80_cvtd.c index 425a5c44a..5a49d3426 100644 --- a/ext/fputils/tests/fp80_cvtd.c +++ b/ext/fputils/tests/fp80_cvtd.c @@ -35,6 +35,15 @@ #include #include +/* We provide our own version of isinf_sgn since the C99 standard + * doesn't guarantee that isinf() returns the sign of the infinity + * (most implementations do). */ +static inline int +isinf_sgn(double x) +{ + return isinf(x) ? (signbit(x) ? -1 : 1) : 0; +} + static void test_fp80_cvtd_class(const char *name, fp80_t fin, int class) { @@ -48,10 +57,10 @@ test_fp80_cvtd_class(const char *name, fp80_t fin, int class) } static void -test_fp80_cvtd_inf(const char *name, fp80_t fin, int inf_class) +test_fp80_cvtd_inf(const char *name, fp80_t fin, int expected_inf_class) { double d = fp80_cvtd(fin); - if (isinf(d) != inf_class) { + if (isinf_sgn(d) != expected_inf_class) { test_diag("wrong infinity type"); test_fail(name); } else {