summaryrefslogtreecommitdiff
path: root/src/runtime/c/gu/bits.c
diff options
context:
space:
mode:
authorkr.angelov <kr.angelov@gmail.com>2012-01-20 13:41:10 +0000
committerkr.angelov <kr.angelov@gmail.com>2012-01-20 13:41:10 +0000
commit2eee382a62a909d5a3f2f5eda94f30fe68fd5335 (patch)
treeb0b0d513535895f244214aebf6358e172b8dce6d /src/runtime/c/gu/bits.c
parentb9728357126f8b9a6311cca17d9f0dcc2a7bfb9b (diff)
initial import of the C runtime
Diffstat (limited to 'src/runtime/c/gu/bits.c')
-rw-r--r--src/runtime/c/gu/bits.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/runtime/c/gu/bits.c b/src/runtime/c/gu/bits.c
new file mode 100644
index 000000000..9126b0448
--- /dev/null
+++ b/src/runtime/c/gu/bits.c
@@ -0,0 +1,53 @@
+#include <gu/bits.h>
+
+#include <limits.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+unsigned gu_ceil2e(unsigned u)
+{
+ u--;
+ u |= u >> 1;
+ u |= u >> 2;
+ u |= u >> 4;
+ u |= u >> 8;
+#if UINT_MAX > UINT16_MAX
+ u |= u >> 16;
+#endif
+#if UINT_MAX > UINT32_MAX
+ u |= u >> 32;
+#endif
+ u++;
+ return u;
+}
+
+GU_DEFINE_TYPE(GuIntDecodeExn, abstract, _);
+
+double
+gu_decode_double(uint64_t u)
+{
+ bool sign = u >> 63;
+ unsigned rawexp = u >> 52 & 0x7ff;
+ uint64_t mantissa = u & 0xfffffffffffff;
+ double ret;
+
+ if (rawexp == 0x7ff) {
+ if (mantissa == 0) {
+ ret = INFINITY;
+ } else {
+ // At least glibc supports specifying the
+ // mantissa like this.
+ int len = snprintf(NULL, 0, "0x%" PRIx64, mantissa);
+ char buf[len + 1];
+ snprintf(buf, len + 1, "0x%" PRIx64, mantissa);
+ ret = nan(buf);
+ }
+ } else {
+ uint64_t m = rawexp ? 1ULL << 52 | mantissa : mantissa << 1;
+ ret = ldexp((double) m, rawexp - 1075);
+ }
+ return sign ? copysign(ret, -1.0) : ret;
+}