Home | History | Annotate | Download | only in using_double_on_avr
      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