1 /* Conversion routines for platforms that do not support 'double' directly. */ 2 3 #include "double_conversion.h" 4 #include <math.h> 5 6 typedef union { 7 float f; 8 uint32_t i; 9 } conversion_t; 10 11 /* Note: IEE 754 standard specifies float formats as follows: 12 * Single precision: sign, 8-bit exp, 23-bit frac. 13 * Double precision: sign, 11-bit exp, 52-bit frac. 14 */ 15 16 uint64_t float_to_double(float value) 17 { 18 conversion_t in; 19 in.f = value; 20 uint8_t sign; 21 int16_t exponent; 22 uint64_t mantissa; 23 24 /* Decompose input value */ 25 sign = (in.i >> 31) & 1; 26 exponent = ((in.i >> 23) & 0xFF) - 127; 27 mantissa = in.i & 0x7FFFFF; 28 29 if (exponent == 128) 30 { 31 /* Special value (NaN etc.) */ 32 exponent = 1024; 33 } 34 else if (exponent == -127) 35 { 36 if (!mantissa) 37 { 38 /* Zero */ 39 exponent = -1023; 40 } 41 else 42 { 43 /* Denormalized */ 44 mantissa <<= 1; 45 while (!(mantissa & 0x800000)) 46 { 47 mantissa <<= 1; 48 exponent--; 49 } 50 mantissa &= 0x7FFFFF; 51 } 52 } 53 54 /* Combine fields */ 55 mantissa <<= 29; 56 mantissa |= (uint64_t)(exponent + 1023) << 52; 57 mantissa |= (uint64_t)sign << 63; 58 59 return mantissa; 60 } 61 62 float double_to_float(uint64_t value) 63 { 64 uint8_t sign; 65 int16_t exponent; 66 uint32_t mantissa; 67 conversion_t out; 68 69 /* Decompose input value */ 70 sign = (value >> 63) & 1; 71 exponent = ((value >> 52) & 0x7FF) - 1023; 72 mantissa = (value >> 28) & 0xFFFFFF; /* Highest 24 bits */ 73 74 /* Figure if value is in range representable by floats. */ 75 if (exponent == 1024) 76 { 77 /* Special value */ 78 exponent = 128; 79 } 80 else if (exponent > 127) 81 { 82 /* Too large */ 83 if (sign) 84 return -INFINITY; 85 else 86 return INFINITY; 87 } 88 else if (exponent < -150) 89 { 90 /* Too small */ 91 if (sign) 92 return -0.0f; 93 else 94 return 0.0f; 95 } 96 else if (exponent < -126) 97 { 98 /* Denormalized */ 99 mantissa |= 0x1000000; 100 mantissa >>= (-126 - exponent); 101 exponent = -127; 102 } 103 104 /* Round off mantissa */ 105 mantissa = (mantissa + 1) >> 1; 106 107 /* Check if mantissa went over 2.0 */ 108 if (mantissa & 0x800000) 109 { 110 exponent += 1; 111 mantissa &= 0x7FFFFF; 112 mantissa >>= 1; 113 } 114 115 /* Combine fields */ 116 out.i = mantissa; 117 out.i |= (uint32_t)(exponent + 127) << 23; 118 out.i |= (uint32_t)sign << 31; 119 120 return out.f; 121 } 122 123 124