huaiyu wei / ennoTest2
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers double_conversion.c Source File

double_conversion.c

00001 /* Conversion routines for platforms that do not support 'double' directly. */
00002 
00003 #include "double_conversion.h"
00004 #include <math.h>
00005 
00006 typedef union {
00007     float f;
00008     uint32_t i;
00009 } conversion_t;
00010 
00011 /* Note: IEE 754 standard specifies float formats as follows:
00012  * Single precision: sign,  8-bit exp, 23-bit frac.
00013  * Double precision: sign, 11-bit exp, 52-bit frac.
00014  */
00015 
00016 uint64_t float_to_double(float value)
00017 {
00018     conversion_t in;
00019     in.f = value;
00020     uint8_t sign;
00021     int16_t exponent;
00022     uint64_t mantissa;
00023 
00024     /* Decompose input value */
00025     sign = (in.i >> 31) & 1;
00026     exponent = ((in.i >> 23) & 0xFF) - 127;
00027     mantissa = in.i & 0x7FFFFF;
00028 
00029     if (exponent == 128)
00030     {
00031         /* Special value (NaN etc.) */
00032         exponent = 1024;
00033     }
00034     else if (exponent == -127)
00035     {
00036         if (!mantissa)
00037         {
00038             /* Zero */
00039             exponent = -1023;
00040         }
00041         else
00042         {
00043             /* Denormalized */
00044             mantissa <<= 1;
00045             while (!(mantissa & 0x800000))
00046             {
00047                 mantissa <<= 1;
00048                 exponent--;
00049             }
00050             mantissa &= 0x7FFFFF;
00051         }
00052     }
00053 
00054     /* Combine fields */
00055     mantissa <<= 29;
00056     mantissa |= (uint64_t)(exponent + 1023) << 52;
00057     mantissa |= (uint64_t)sign << 63;
00058 
00059     return mantissa;
00060 }
00061 
00062 float double_to_float(uint64_t value)
00063 {
00064     uint8_t sign;
00065     int16_t exponent;
00066     uint32_t mantissa;
00067     conversion_t out;
00068 
00069     /* Decompose input value */
00070     sign = (value >> 63) & 1;
00071     exponent = ((value >> 52) & 0x7FF) - 1023;
00072     mantissa = (value >> 28) & 0xFFFFFF; /* Highest 24 bits */
00073 
00074     /* Figure if value is in range representable by floats. */
00075     if (exponent == 1024)
00076     {
00077         /* Special value */
00078         exponent = 128;
00079     }
00080     else if (exponent > 127)
00081     {
00082         /* Too large */
00083         if (sign)
00084             return -INFINITY;
00085         else
00086             return INFINITY;
00087     }
00088     else if (exponent < -150)
00089     {
00090         /* Too small */
00091         if (sign)
00092             return -0.0f;
00093         else
00094             return 0.0f;
00095     }
00096     else if (exponent < -126)
00097     {
00098         /* Denormalized */
00099         mantissa |= 0x1000000;
00100         mantissa >>= (-126 - exponent);
00101         exponent = -127;
00102     }
00103 
00104     /* Round off mantissa */
00105     mantissa = (mantissa + 1) >> 1;
00106 
00107     /* Check if mantissa went over 2.0 */
00108     if (mantissa & 0x800000)
00109     {
00110         exponent += 1;
00111         mantissa &= 0x7FFFFF;
00112         mantissa >>= 1;
00113     }
00114 
00115     /* Combine fields */
00116     out.i = mantissa;
00117     out.i |= (uint32_t)(exponent + 127) << 23;
00118     out.i |= (uint32_t)sign << 31;
00119 
00120     return out.f;
00121 }
00122 
00123