1 /* 2 * PROJECT: ReactOS CRT library 3 * LICENSE: MIT (https://spdx.org/licenses/MIT) 4 * PURPOSE: Float to integer conversion (__dtoi64/dtou64/stoi64/stou64) 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 #else 14 typedef float FLOAT_TYPE; 15 typedef unsigned int FINT_TYPE; 16 #define FRACTION_LEN 23 17 #define EXPONENT_LEN 8 18 #endif 19 20 typedef 21 #ifndef _USE_SIGNED_ 22 unsigned 23 #endif 24 long long FTO64_RESULT; 25 26 typedef union _FTO64_UNION 27 { 28 FLOAT_TYPE value; 29 FINT_TYPE raw; 30 } FTO64_UNION; 31 32 #define SIGN_MASK (((FINT_TYPE)1) << (FRACTION_LEN + EXPONENT_LEN)) 33 34 #define FRACTION_ONE (((FINT_TYPE)1) << FRACTION_LEN) 35 #define FRACTION_MASK ((FRACTION_ONE) - 1) 36 37 #define EXPONENT_MASK ((1 << EXPONENT_LEN) - 1) 38 #define EXPONENT_ZERO ((1 << (EXPONENT_LEN - 1)) - 1) 39 40 #ifdef _USE_SIGNED_ 41 #define EXPONENT_MAX 62 42 #define INTNAN 0x8000000000000000ULL 43 #else 44 #define EXPONENT_MAX 63 45 #define INTNAN 0xFFFFFFFFFFFFFFFFULL 46 #endif 47 48 #define EXPONENT_INFINITY EXPONENT_MASK 49 50 #define NEGATE(x) (~(x) + 1) 51 52 FTO64_RESULT 53 __fto64(FLOAT_TYPE fvalue) 54 { 55 FTO64_UNION u = { .value = fvalue }; 56 FINT_TYPE value = u.raw; 57 int exponent; 58 FTO64_RESULT fraction; 59 60 exponent = (int)(value >> FRACTION_LEN); 61 exponent &= EXPONENT_MASK; 62 63 /* infinity and other NaNs */ 64 if (exponent == EXPONENT_INFINITY) 65 return INTNAN; 66 67 /* subnormals and signed zeros */ 68 if (exponent == 0) 69 return 0; 70 71 exponent -= EXPONENT_ZERO; 72 73 /* number is less then one */ 74 if (exponent < 0) 75 return 0; 76 77 /* number is too big */ 78 if (exponent > EXPONENT_MAX) 79 return INTNAN; 80 81 #ifndef _USE_SIGNED_ 82 if (value & SIGN_MASK) 83 return INTNAN; 84 #endif 85 86 fraction = value & FRACTION_MASK; 87 fraction |= FRACTION_ONE; 88 89 exponent -= FRACTION_LEN; 90 if (exponent != 0) 91 { 92 if (exponent < 0) 93 fraction = fraction >> NEGATE(exponent); 94 else 95 fraction = fraction << exponent; 96 } 97 98 #ifdef _USE_SIGNED_ 99 if (value & SIGN_MASK) 100 fraction = NEGATE(fraction); 101 #endif 102 103 return fraction; 104 } 105