[llvm-commits] [test-suite] r116246 - /test-suite/trunk/SingleSource/Regression/C/uint64_to_float.c
Owen Anderson
resistor at mac.com
Mon Oct 11 14:53:49 PDT 2010
Author: resistor
Date: Mon Oct 11 16:53:49 2010
New Revision: 116246
URL: http://llvm.org/viewvc/llvm-project?rev=116246&view=rev
Log:
Copy compiler_rt's floatundisf into the this test completely in an attempt to get it working on Linux X86_64.
Modified:
test-suite/trunk/SingleSource/Regression/C/uint64_to_float.c
Modified: test-suite/trunk/SingleSource/Regression/C/uint64_to_float.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/SingleSource/Regression/C/uint64_to_float.c?rev=116246&r1=116245&r2=116246&view=diff
==============================================================================
--- test-suite/trunk/SingleSource/Regression/C/uint64_to_float.c (original)
+++ test-suite/trunk/SingleSource/Regression/C/uint64_to_float.c Mon Oct 11 16:53:49 2010
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdint.h>
#include <fenv.h>
+#include <float.h>
// tests uint64_t --> float conversions. Not an exhaustive test, but sufficent
// to identify all reasonable bugs in such routines that I have yet encountered.
@@ -14,16 +15,73 @@
// We test in all four basic rounding modes, to further flush out any
// double-rounding issues, or behavior at zero.
-extern float __floatundisf(uint64_t);
+typedef union
+{
+ uint32_t u;
+ float f;
+} float_bits;
+
+
+float
+floatundisf(uint64_t a)
+{
+ if (a == 0)
+ return 0.0F;
+ const unsigned N = sizeof(uint64_t) * 8;
+ int sd = N - __builtin_clzll(a); /* number of significant digits */
+ int e = sd - 1; /* 8 exponent */
+ if (sd > FLT_MANT_DIG)
+ {
+ /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
+ * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
+ * 12345678901234567890123456
+ * 1 = msb 1 bit
+ * P = bit FLT_MANT_DIG-1 bits to the right of 1
+ * Q = bit FLT_MANT_DIG bits to the right of 1
+ * R = "or" of all bits to the right of Q
+ */
+ switch (sd)
+ {
+ case FLT_MANT_DIG + 1:
+ a <<= 1;
+ break;
+ case FLT_MANT_DIG + 2:
+ break;
+ default:
+ a = (a >> (sd - (FLT_MANT_DIG+2))) |
+ ((a & ((uint64_t)(-1) >> ((N + FLT_MANT_DIG+2) - sd))) != 0);
+ };
+ /* finish: */
+ a |= (a & 4) != 0; /* Or P into R */
+ ++a; /* round - this step may add a significant bit */
+ a >>= 2; /* dump Q and R */
+ /* a is now rounded to FLT_MANT_DIG or FLT_MANT_DIG+1 bits */
+ if (a & ((uint64_t)1 << FLT_MANT_DIG))
+ {
+ a >>= 1;
+ ++e;
+ }
+ /* a is now rounded to FLT_MANT_DIG bits */
+ }
+ else
+ {
+ a <<= (FLT_MANT_DIG - sd);
+ /* a is now rounded to FLT_MANT_DIG bits */
+ }
+ float_bits fb;
+ fb.u = ((e + 127) << 23) | /* exponent */
+ ((int32_t)a & 0x007FFFFF); /* mantissa */
+ return fb.f;
+}
+
void test(uint64_t x) {
- union floatbits { uint32_t x; float f; };
- const union floatbits expected = { .f = __floatundisf(x) };
- const union floatbits observed = { .f = x };
+ const float_bits expected = { .f = floatundisf(x) };
+ const float_bits observed = { .f = x };
- if (expected.x != observed.x) {
+ if (expected.u != observed.u) {
printf("Error detected @ 0x%016llx\n", x);
- printf("\tExpected result: %a (0x%08x)\n", expected.f, expected.x);
- printf("\tObserved result: %a (0x%08x)\n", observed.f, observed.x);
+ printf("\tExpected result: %a (0x%08x)\n", expected.f, expected.u);
+ printf("\tObserved result: %a (0x%08x)\n", observed.f, observed.u);
}
}
More information about the llvm-commits
mailing list