Fix bugs in proto3 mode encoding of submessages (#256)
[apps/agl-service-can-low-level.git] / examples / using_double_on_avr / double_conversion.c
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