/* * PROJECT: ReactOS CRT library * LICENSE: MIT (https://spdx.org/licenses/MIT) * PURPOSE: Float to integer conversion (__dtoi64/dtou64/stoi64/stou64) * 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 #else typedef float FLOAT_TYPE; typedef unsigned int FINT_TYPE; #define FRACTION_LEN 23 #define EXPONENT_LEN 8 #endif typedef #ifndef _USE_SIGNED_ unsigned #endif long long FTO64_RESULT; #define SIGN_MASK (((FINT_TYPE)1) << (FRACTION_LEN + EXPONENT_LEN)) #define FRACTION_ONE (((FINT_TYPE)1) << FRACTION_LEN) #define FRACTION_MASK ((FRACTION_ONE) - 1) #define EXPONENT_MASK ((1 << EXPONENT_LEN) - 1) #define EXPONENT_ZERO ((1 << (EXPONENT_LEN - 1)) - 1) #ifdef _USE_SIGNED_ #define EXPONENT_MAX 62 #define INTNAN 0x8000000000000000ULL #else #define EXPONENT_MAX 63 #define INTNAN 0xFFFFFFFFFFFFFFFFULL #endif #define EXPONENT_INFINITY EXPONENT_MASK #define NEGATE(x) (~(x) + 1) FTO64_RESULT __fto64(FLOAT_TYPE value) { union { FLOAT_TYPE val_float; FINT_TYPE val_int; } u; int exponent; FTO64_RESULT fraction; u.val_float = value; exponent = (int)(u.val_int >> FRACTION_LEN); exponent &= EXPONENT_MASK; /* infinity and other NaNs */ if (exponent == EXPONENT_INFINITY) return INTNAN; /* subnormals and signed zeros */ if (exponent == 0) return 0; exponent -= EXPONENT_ZERO; /* number is less then one */ if (exponent < 0) return 0; /* number is too big */ if (exponent > EXPONENT_MAX) return INTNAN; #ifndef _USE_SIGNED_ if (u.val_int & SIGN_MASK) return INTNAN; #endif fraction = u.val_int & FRACTION_MASK; fraction |= FRACTION_ONE; exponent -= FRACTION_LEN; if (exponent != 0) { if (exponent < 0) fraction = fraction >> NEGATE(exponent); else fraction = fraction << exponent; } #ifdef _USE_SIGNED_ if (u.val_int & SIGN_MASK) fraction = NEGATE(fraction); #endif return fraction; }