/* * PROJECT: ReactOS CRT library * LICENSE: MIT (https://spdx.org/licenses/MIT) * PURPOSE: Integer to float conversion (__i64tod/u64tod/i64tos/u64tos) * COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com> */ #ifdef _USE_64_BITS_ typedef double FLOAT_TYPE; typedef unsigned long long FINT_TYPE; #define FRACTION_LEN 52 #define EXPONENT_LEN 11 #define SHIFT_OFFSET EXPONENT_LEN #else typedef float FLOAT_TYPE; typedef unsigned int FINT_TYPE; #define FRACTION_LEN 23 #define EXPONENT_LEN 8 #define SHIFT_OFFSET (EXPONENT_LEN + 32) #endif #ifdef _USE_SIGNED_ typedef long long INT64SU; #else typedef unsigned long long INT64SU; #endif typedef union _FLOAT_RESULT { FLOAT_TYPE value; FINT_TYPE raw; } FLOAT_RESULT; #define SIGN_MASK 0x8000000000000000ULL #define EXPONENT_ZERO ((1 << (EXPONENT_LEN - 1)) - 1) #define NEGATE(x) (~(x) + 1) FLOAT_TYPE __64tof(INT64SU value) { FLOAT_RESULT result; FINT_TYPE exponent = EXPONENT_ZERO + FRACTION_LEN; int count = 0; unsigned long long mask = SIGN_MASK; if (value == 0) return (FLOAT_TYPE)0; #ifdef _USE_SIGNED_ if (value & SIGN_MASK) { value = NEGATE(value); /* set Sign bit using exponent */ exponent |= 1 << EXPONENT_LEN; } #endif for (; count < 64; count++) { if (value & mask) break; mask = mask >> 1; } count -= SHIFT_OFFSET; /* exponent is FRACTION_LEN - count */ exponent -= count; result.raw = exponent << FRACTION_LEN; mask--; value = value & mask; if (value == 0) return result.value; if (count == 0) { result.raw |= value; } else if (count < 0) { count = NEGATE(count) - 1; value = value >> count; mask = value & 1; result.raw |= value >> 1; /* round up if left most bit of lost data is 1 */ if (mask) result.raw++; } else { result.raw |= value << count; } return result.value; }