xref: /reactos/sdk/lib/crt/math/arm/__fto64.h (revision 81db5e1d)
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