17ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* Conversion routines for platforms that do not support 'double' directly. */ 27ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 37ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include "double_conversion.h" 47ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <math.h> 57ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 67ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohentypedef union { 77ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen float f; 87ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint32_t i; 97ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} conversion_t; 107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* Note: IEE 754 standard specifies float formats as follows: 127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * Single precision: sign, 8-bit exp, 23-bit frac. 137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * Double precision: sign, 11-bit exp, 52-bit frac. 147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen */ 157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenuint64_t float_to_double(float value) 177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen conversion_t in; 197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen in.f = value; 207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint8_t sign; 217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen int16_t exponent; 227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint64_t mantissa; 237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 247ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Decompose input value */ 257ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen sign = (in.i >> 31) & 1; 267ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen exponent = ((in.i >> 23) & 0xFF) - 127; 277ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa = in.i & 0x7FFFFF; 287ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 297ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (exponent == 128) 307ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 317ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Special value (NaN etc.) */ 327ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen exponent = 1024; 337ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 347ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else if (exponent == -127) 357ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 367ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!mantissa) 377ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 387ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Zero */ 397ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen exponent = -1023; 407ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 417ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 427ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 437ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Denormalized */ 447ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa <<= 1; 457ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen while (!(mantissa & 0x800000)) 467ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 477ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa <<= 1; 487ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen exponent--; 497ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 507ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa &= 0x7FFFFF; 517ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 527ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 537ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 547ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Combine fields */ 557ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa <<= 29; 567ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa |= (uint64_t)(exponent + 1023) << 52; 577ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa |= (uint64_t)sign << 63; 587ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 597ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return mantissa; 607ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 617ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 627ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenfloat double_to_float(uint64_t value) 637ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 647ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint8_t sign; 657ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen int16_t exponent; 667ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint32_t mantissa; 677ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen conversion_t out; 687ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 697ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Decompose input value */ 707ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen sign = (value >> 63) & 1; 717ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen exponent = ((value >> 52) & 0x7FF) - 1023; 727ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa = (value >> 28) & 0xFFFFFF; /* Highest 24 bits */ 737ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 747ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Figure if value is in range representable by floats. */ 757ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (exponent == 1024) 767ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 777ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Special value */ 787ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen exponent = 128; 797ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 807ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else if (exponent > 127) 817ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 827ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Too large */ 837ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (sign) 847ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return -INFINITY; 857ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 867ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return INFINITY; 877ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 887ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else if (exponent < -150) 897ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 907ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Too small */ 917ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (sign) 927ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return -0.0f; 937ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 947ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return 0.0f; 957ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 967ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else if (exponent < -126) 977ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 987ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Denormalized */ 997ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa |= 0x1000000; 1007ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa >>= (-126 - exponent); 1017ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen exponent = -127; 1027ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1037ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1047ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Round off mantissa */ 1057ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa = (mantissa + 1) >> 1; 1067ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1077ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Check if mantissa went over 2.0 */ 1087ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (mantissa & 0x800000) 1097ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen exponent += 1; 1117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa &= 0x7FFFFF; 1127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen mantissa >>= 1; 1137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Combine fields */ 1167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen out.i = mantissa; 1177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen out.i |= (uint32_t)(exponent + 127) << 23; 1187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen out.i |= (uint32_t)sign << 31; 1197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return out.f; 1217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 1227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 124