diff options
| author | kr.angelov <kr.angelov@gmail.com> | 2012-01-20 13:41:10 +0000 |
|---|---|---|
| committer | kr.angelov <kr.angelov@gmail.com> | 2012-01-20 13:41:10 +0000 |
| commit | 2eee382a62a909d5a3f2f5eda94f30fe68fd5335 (patch) | |
| tree | b0b0d513535895f244214aebf6358e172b8dce6d /src/runtime/c/gu/bits.c | |
| parent | b9728357126f8b9a6311cca17d9f0dcc2a7bfb9b (diff) | |
initial import of the C runtime
Diffstat (limited to 'src/runtime/c/gu/bits.c')
| -rw-r--r-- | src/runtime/c/gu/bits.c | 53 |
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; +} |
