/* Conversion routines for platforms that do not support 'double' directly. */ #include "double_conversion.h" #include <math.h> typedef union { float f; uint32_t i; } conversion_t; /* Note: IEE 754 standard specifies float formats as follows: * Single precision: sign, 8-bit exp, 23-bit frac. * Double precision: sign, 11-bit exp, 52-bit frac. */ uint64_t float_to_double(float value) { conversion_t in; in.f = value; uint8_t sign; int16_t exponent; uint64_t mantissa; /* Decompose input value */ sign = (in.i >> 31) & 1; exponent = ((in.i >> 23) & 0xFF) - 127; mantissa = in.i & 0x7FFFFF; if (exponent == 128) { /* Special value (NaN etc.) */ exponent = 1024; } else if (exponent == -127) { if (!mantissa) { /* Zero */ exponent = -1023; } else { /* Denormalized */ mantissa <<= 1; while (!(mantissa & 0x800000)) { mantissa <<= 1; exponent--; } mantissa &= 0x7FFFFF; } } /* Combine fields */ mantissa <<= 29; mantissa |= (uint64_t)(exponent + 1023) << 52; mantissa |= (uint64_t)sign << 63; return mantissa; } float double_to_float(uint64_t value) { uint8_t sign; int16_t exponent; uint32_t mantissa; conversion_t out; /* Decompose input value */ sign = (value >> 63) & 1; exponent = ((value >> 52) & 0x7FF) - 1023; mantissa = (value >> 28) & 0xFFFFFF; /* Highest 24 bits */ /* Figure if value is in range representable by floats. */ if (exponent == 1024) { /* Special value */ exponent = 128; } else if (exponent > 127) { /* Too large */ if (sign) return -INFINITY; else return INFINITY; } else if (exponent < -150) { /* Too small */ if (sign) return -0.0f; else return 0.0f; } else if (exponent < -126) { /* Denormalized */ mantissa |= 0x1000000; mantissa >>= (-126 - exponent); exponent = -127; } /* Round off mantissa */ mantissa = (mantissa + 1) >> 1; /* Check if mantissa went over 2.0 */ if (mantissa & 0x800000) { exponent += 1; mantissa &= 0x7FFFFF; mantissa >>= 1; } /* Combine fields */ out.i = mantissa; out.i |= (uint32_t)(exponent + 127) << 23; out.i |= (uint32_t)sign << 31; return out.f; }