1 /* 2 * PROJECT: ReactOS CRT library 3 * LICENSE: MIT (https://spdx.org/licenses/MIT) 4 * PURPOSE: Integer to float conversion (__i64tod/u64tod/i64tos/u64tos) 5 * COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com> 6 */ 7 8 #ifdef _USE_64_BITS_ 9 typedef double FLOAT_TYPE; 10 typedef unsigned long long FINT_TYPE; 11 #define FRACTION_LEN 52 12 #define EXPONENT_LEN 11 13 #define SHIFT_OFFSET EXPONENT_LEN 14 #else 15 typedef float FLOAT_TYPE; 16 typedef unsigned int FINT_TYPE; 17 #define FRACTION_LEN 23 18 #define EXPONENT_LEN 8 19 #define SHIFT_OFFSET (EXPONENT_LEN + 32) 20 #endif 21 22 #ifdef _USE_SIGNED_ 23 typedef long long INT64SU; 24 #else 25 typedef unsigned long long INT64SU; 26 #endif 27 28 typedef union _FLOAT_RESULT 29 { 30 FLOAT_TYPE value; 31 FINT_TYPE raw; 32 } FLOAT_RESULT; 33 34 #define SIGN_MASK 0x8000000000000000ULL 35 36 #define EXPONENT_ZERO ((1 << (EXPONENT_LEN - 1)) - 1) 37 38 #define NEGATE(x) (~(x) + 1) 39 40 FLOAT_TYPE 41 __64tof(INT64SU value) 42 { 43 FLOAT_RESULT result; 44 FINT_TYPE exponent = EXPONENT_ZERO + FRACTION_LEN; 45 int count = 0; 46 unsigned long long mask = SIGN_MASK; 47 48 if (value == 0) 49 return (FLOAT_TYPE)0; 50 51 #ifdef _USE_SIGNED_ 52 if (value & SIGN_MASK) 53 { 54 value = NEGATE(value); 55 /* set Sign bit using exponent */ 56 exponent |= 1 << EXPONENT_LEN; 57 } 58 #endif 59 60 for (; count < 64; count++) 61 { 62 if (value & mask) 63 break; 64 mask = mask >> 1; 65 } 66 67 count -= SHIFT_OFFSET; 68 /* exponent is FRACTION_LEN - count */ 69 exponent -= count; 70 result.raw = exponent << FRACTION_LEN; 71 72 mask--; 73 value = value & mask; 74 if (value == 0) 75 return result.value; 76 77 if (count == 0) 78 { 79 result.raw |= value; 80 } 81 else if (count < 0) 82 { 83 count = NEGATE(count) - 1; 84 value = value >> count; 85 mask = value & 1; 86 result.raw |= value >> 1; 87 88 /* round up if left most bit of lost data is 1 */ 89 if (mask) 90 result.raw++; 91 } 92 else 93 { 94 result.raw |= value << count; 95 } 96 97 return result.value; 98 } 99