1/* Conversion routines for platforms that do not support 'double' directly. */
2
3#include "double_conversion.h"
4#include <math.h>
5
6typedef 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
16uint64_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
62float 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