| /* 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; |
| } |
| |
| |