xref: /reactos/sdk/lib/crt/math/arm/__64tof.h (revision 9393fc32)
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