ReactOS 0.4.16-dev-1537-g4e425b5
floatconv.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS API tests
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Test for floating point conversion
5 * COPYRIGHT: Copyright 2024 Timo Kreuzer <timo.kreuzer@reactos.org>
6 */
7
8#include <apitest.h>
9
10/* Note: There are 2 behaviors for float to unsigned integer conversion:
11 * 1. The old behavior, which exists only on x86 and CL versions up to somewhere
12 * between 19.40.33811 and 19.41.33923:
13 * - If a negative float is cast to an unsigned integer, the result is ULONG_MAX
14 * for uint32 and ULLONG_MAX for uint64.
15 * - If a float is cast to an unsigned long and the value is larger than ULONG_MAX,
16 * the result is ULONG_MAX.
17 * 2. The new behavior (all x64 and x86 versions after the ones mentioned above):
18 * - If a negative float is cast to an unsigned integer, the result is the same as
19 first casting to the signed type, then casting to the unsigned type.
20 * - If a float is cast to an unsigned integer and the value is too large for the type,
21 * the result is 0 for uint32 and 0x8000000000000000 for uint64.
22 * In the old version, the float to unsigned conversion was inlined and used _ftoul2 and
23 * a comparison against 0x43e0000000000000 (9223372036854775808.0) to check for overflow.
24 * In the new version, the float to unsigned conversion is done by a call to _ftoul2_legacy,
25 * which checks for overflow by comparing against 0x5f800000 (18446744073709551616.0) and
26 * then forwards the call to either _ftol2 or _ftoul2.
27 */
28
29#if defined(_M_IX86) && defined(__VS_PROJECT__) && (_MSC_FULL_VER < 194133923)
30#define OLD_BEHAVIOR
31#endif
32
33#ifdef OLD_BEHAVIOR
34#define ULONG_OVERFLOW ULONG_MAX
35#define ULONGLONG_OVERFLOW ULLONG_MAX
36#else
37#define ULONG_OVERFLOW 0ul
38#define ULONGLONG_OVERFLOW 0x8000000000000000ull
39#endif
40
42long cast_float_to_long(float f)
43{
44 return (long)f;
45}
46
48unsigned long cast_float_to_ulong(float f)
49{
50 return (unsigned long)f;
51}
52
54long cast_double_to_long(double d)
55{
56 return (long)d;
57}
58
60unsigned long cast_double_to_ulong(double d)
61{
62 return (unsigned long)d;
63}
64
66long long cast_float_to_longlong(float f)
67{
68 return (long long)f;
69}
70
72unsigned long long cast_float_to_ulonglong(float f)
73{
74 return (unsigned long long)f;
75}
76
78long long cast_double_to_longlong(double d)
79{
80 return (long long)d;
81}
82
84unsigned long long cast_double_to_ulonglong(double d)
85{
86 return (unsigned long long)d;
87}
88
89void Test_float(void)
90{
91 // float to long cast
92 ok_eq_long(cast_float_to_long(0.0f), 0l);
93 ok_eq_long(cast_float_to_long(1.0f), 1l);
94 ok_eq_long(cast_float_to_long(-1.0f), -1l);
95 ok_eq_long(cast_float_to_long(0.5f), 0l);
96 ok_eq_long(cast_float_to_long(-0.5f), 0l);
97 ok_eq_long(cast_float_to_long(0.999999f), 0l);
98 ok_eq_long(cast_float_to_long(-0.999999f), 0l);
99 ok_eq_long(cast_float_to_long(2147483500.0f), 2147483520l);
100 ok_eq_long(cast_float_to_long(2147483583.999f), 2147483520l);
101 ok_eq_long(cast_float_to_long(-2147483583.999f), -2147483520l);
102 ok_eq_long(cast_float_to_long(2147483584.0f), LONG_MIN); // -2147483648
103 ok_eq_long(cast_float_to_long(2147483648.0f), LONG_MIN); // -2147483648
104 ok_eq_long(cast_float_to_long(-2147483648.0f), LONG_MIN); // -2147483648
105 ok_eq_long(cast_float_to_long(10000000000.0f), LONG_MIN);
106 ok_eq_long(cast_float_to_long(-10000000000.0f), LONG_MIN);
107
108 // float to unsigned long cast (positive values)
109 ok_eq_ulong(cast_float_to_ulong(0.0f), 0ul);
110 ok_eq_ulong(cast_float_to_ulong(1.0f), 1ul);
111 ok_eq_ulong(cast_float_to_ulong(0.5f), 0ul);
112 ok_eq_ulong(cast_float_to_ulong(0.999999f), 0ul);
113 ok_eq_ulong(cast_float_to_ulong(2147483648.0f), 2147483648ul); // 0x80000000
114 ok_eq_ulong(cast_float_to_ulong(4294967150.0f), 4294967040ul); // 0xFFFFFF00
115 ok_eq_ulong(cast_float_to_ulong(4294967294.0f), ULONG_OVERFLOW);
116
117 // float to unsigned long cast (negative values)
118 ok_eq_ulong(cast_float_to_ulong(-0.0f), 0ul);
119 ok_eq_ulong(cast_float_to_ulong(-0.5f), 0ul);
120 ok_eq_ulong(cast_float_to_ulong(-1.0f), ULONG_MAX);
121#ifdef OLD_BEHAVIOR
122 ok_eq_ulong(cast_float_to_ulong(-10.0f), ULONG_MAX);
123 ok_eq_ulong(cast_float_to_ulong(-1147483648.0f), ULONG_MAX);
124 ok_eq_ulong(cast_float_to_ulong(-2147483648.0f), ULONG_MAX);
125#else
126 ok_eq_ulong(cast_float_to_ulong(-10.0f), (unsigned long)-10);
127 ok_eq_ulong(cast_float_to_ulong(-1147483648.0f), (unsigned long)-1147483648ll);
128 ok_eq_ulong(cast_float_to_ulong(-2147483648.0f), (unsigned long)-2147483648ll);
129#endif
130
131 // float to long long cast
132 ok_eq_longlong(cast_float_to_longlong(0.0f), 0ll);
133 ok_eq_longlong(cast_float_to_longlong(1.0f), 1ll);
134 ok_eq_longlong(cast_float_to_longlong(-1.0f), -1ll);
135 ok_eq_longlong(cast_float_to_longlong(0.5f), 0ll);
136 ok_eq_longlong(cast_float_to_longlong(-0.5f), 0ll);
137 ok_eq_longlong(cast_float_to_longlong(0.999999f), 0ll);
138 ok_eq_longlong(cast_float_to_longlong(-0.999999f), 0ll);
139 ok_eq_longlong(cast_float_to_longlong(9223371761976868863.9999f), 9223371487098961920ll);
140 ok_eq_longlong(cast_float_to_longlong(9223371761976868864.0f), LLONG_MIN);
141 ok_eq_longlong(cast_float_to_longlong(-9223371761976868863.9999f), -9223371487098961920ll);
142 ok_eq_longlong(cast_float_to_longlong(-9223371761976868864.0f), LLONG_MIN);
143 ok_eq_longlong(cast_float_to_longlong(100000000000000000000.0f), LLONG_MIN);
144 ok_eq_longlong(cast_float_to_longlong(-100000000000000000000.0f), LLONG_MIN);
145
146 // float to unsigned long long cast (positive values)
147 ok_eq_ulonglong(cast_float_to_ulonglong(0.0f), 0ull);
148 ok_eq_ulonglong(cast_float_to_ulonglong(1.0f), 1ull);
149 ok_eq_ulonglong(cast_float_to_ulonglong(0.5f), 0ull);
150 ok_eq_ulonglong(cast_float_to_ulonglong(0.999999f), 0ull);
151 ok_eq_ulonglong(cast_float_to_ulonglong(9223371487098961920.0f), 9223371487098961920ull); // 0x7FFFFF8000000000
152 ok_eq_ulonglong(cast_float_to_ulonglong(9223372036854775808.0f), 9223372036854775808ull); // 0x8000000000000000
153 ok_eq_ulonglong(cast_float_to_ulonglong(18446743523953737727.9f), 18446742974197923840ull); // 0xFFFFFF0000000000
154#ifndef __GNUC__ // GCC inlines the conversion, we cannot fix this
155 ok_eq_ulonglong(cast_float_to_ulonglong(18446743523953737728.0f), ULONGLONG_OVERFLOW); // 0x8000000000000000 / 0xFFFFFFFFFFFFFFFF
156 ok_eq_ulonglong(cast_float_to_ulonglong(20000000000000000000.0f), ULONGLONG_OVERFLOW); // 0x8000000000000000 / 0xFFFFFFFFFFFFFFFF
157#endif
158
159 // float to unsigned long long cast (negative values)
160 ok_eq_ulonglong(cast_float_to_ulonglong(-0.0f), 0ull);
161 ok_eq_ulonglong(cast_float_to_ulonglong(-0.5f), 0ull);
162 ok_eq_ulonglong(cast_float_to_ulonglong(-1.0f), 18446744073709551615ull);
163#ifdef OLD_BEHAVIOR
164 ok_eq_ulonglong(cast_float_to_ulonglong(-10.0f), ULLONG_MAX);
165 ok_eq_ulonglong(cast_float_to_ulonglong(-1147483648.0f), ULLONG_MAX);
166 ok_eq_ulonglong(cast_float_to_ulonglong(-2147483648.0f), ULLONG_MAX);
167 ok_eq_ulonglong(cast_float_to_ulonglong(-9223371761976868863.9f), ULLONG_MAX);
168 ok_eq_ulonglong(cast_float_to_ulonglong(-9223371761976868864.0f), ULLONG_MAX);
169 ok_eq_ulonglong(cast_float_to_ulonglong(-9223372036854775808.0f), ULLONG_MAX);
170#else
171 ok_eq_ulonglong(cast_float_to_ulonglong(-10.0f), (unsigned long long)-10);
172 ok_eq_ulonglong(cast_float_to_ulonglong(-1147483648.0f), (unsigned long long)-1147483648ll);
173 ok_eq_ulonglong(cast_float_to_ulonglong(-2147483648.0f), (unsigned long long)-2147483648ll);
174 ok_eq_ulonglong(cast_float_to_ulonglong(-9223371761976868863.9f), (unsigned long long)-9223371487098961920);
175 ok_eq_ulonglong(cast_float_to_ulonglong(-9223371761976868864.0f), (unsigned long long)(-9223372036854775807ll - 1)); // 0x8000000000000000 / ULONGLONG_OVERFLOW
176 ok_eq_ulonglong(cast_float_to_ulonglong(-9223372036854775808.0f), (unsigned long long)(-9223372036854775807ll - 1)); // 0x8000000000000000 / ULONGLONG_OVERFLOW
177#endif
178 ok_eq_ulonglong(cast_float_to_ulonglong(-100000000000000000000.0f), ULONGLONG_OVERFLOW);
179}
180
181void Test_double(void)
182{
183 // double to long cast
184 ok_eq_long(cast_double_to_long(0.0), 0l);
185 ok_eq_long(cast_double_to_long(1.0), 1l);
186 ok_eq_long(cast_double_to_long(-1.0), -1l);
187 ok_eq_long(cast_double_to_long(0.5), 0l);
188 ok_eq_long(cast_double_to_long(-0.5), 0l);
189 ok_eq_long(cast_double_to_long(0.999999999), 0l);
190 ok_eq_long(cast_double_to_long(-0.999999999), 0l);
191 ok_eq_long(cast_double_to_long(2147483647.99999), 2147483647l);
192 ok_eq_long(cast_double_to_long(-2147483647.99999), -2147483647l);
193 ok_eq_long(cast_double_to_long(2147483648.0), LONG_MIN); // -2147483648
194 ok_eq_long(cast_double_to_long(-2147483648.0), LONG_MIN); // -2147483648
195 ok_eq_long(cast_double_to_long(10000000000.0), LONG_MIN);
196 ok_eq_long(cast_double_to_long(-10000000000.0), LONG_MIN);
197
198 // double to unsigned long cast (positive values)
199 ok_eq_ulong(cast_double_to_ulong(0.0), 0ul);
200 ok_eq_ulong(cast_double_to_ulong(1.0), 1ul);
201 ok_eq_ulong(cast_double_to_ulong(0.5), 0ul);
202 ok_eq_ulong(cast_double_to_ulong(0.999999999), 0ul);
203 ok_eq_ulong(cast_double_to_ulong(2147483648.0), 2147483648ul); // 0x80000000
204 ok_eq_ulong(cast_double_to_ulong(4294967295.0), 4294967295ul); // 0xFFFFFFFF
205 ok_eq_ulong(cast_double_to_ulong(4294967296.0), ULONG_OVERFLOW);
206
207 // double to unsigned long cast (negative values)
208 ok_eq_ulong(cast_double_to_ulong(-0.0), 0ul);
209 ok_eq_ulong(cast_double_to_ulong(-0.5), 0ul);
210 ok_eq_ulong(cast_double_to_ulong(-1.0), ULONG_MAX);
211#ifdef OLD_BEHAVIOR
212 ok_eq_ulong(cast_double_to_ulong(-10.0), ULONG_MAX);
213 ok_eq_ulong(cast_double_to_ulong(-1147483648.0), ULONG_MAX);
214 ok_eq_ulong(cast_double_to_ulong(-2147483648.0), ULONG_MAX);
215#else
216 ok_eq_ulong(cast_double_to_ulong(-10.0), (unsigned long)-10);
217 ok_eq_ulong(cast_double_to_ulong(-1147483648.0), (unsigned long)-1147483648ll);
218 ok_eq_ulong(cast_double_to_ulong(-2147483648.0), (unsigned long)-2147483648ll);
219#endif
220
221 // double to long long cast
222 ok_eq_longlong(cast_double_to_longlong(0.0), 0ll);
223 ok_eq_longlong(cast_double_to_longlong(1.0), 1ll);
224 ok_eq_longlong(cast_double_to_longlong(-1.0), -1ll);
225 ok_eq_longlong(cast_double_to_longlong(0.5), 0ll);
226 ok_eq_longlong(cast_double_to_longlong(-0.5), 0ll);
227 ok_eq_longlong(cast_double_to_longlong(0.999999), 0ll);
228 ok_eq_longlong(cast_double_to_longlong(-0.999999), 0ll);
229 ok_eq_longlong(cast_double_to_longlong(9223372036854775295.9), 9223372036854774784ll);
230 ok_eq_longlong(cast_double_to_longlong(9223372036854775296.0), LLONG_MIN);
231 ok_eq_longlong(cast_double_to_longlong(-9223372036854775295.9), -9223372036854774784ll);
232 ok_eq_longlong(cast_double_to_longlong(-9223372036854775296.0), LLONG_MIN);
233 ok_eq_longlong(cast_double_to_longlong(100000000000000000000.0), LLONG_MIN);
234 ok_eq_longlong(cast_double_to_longlong(-100000000000000000000.0), LLONG_MIN);
235
236 // double to unsigned long long cast (positive values)
237 ok_eq_ulonglong(cast_double_to_ulonglong(0.0), 0ull);
238 ok_eq_ulonglong(cast_double_to_ulonglong(1.0), 1ull);
239 ok_eq_ulonglong(cast_double_to_ulonglong(0.5), 0ull);
240 ok_eq_ulonglong(cast_double_to_ulonglong(0.999999), 0ull);
241 ok_eq_ulonglong(cast_double_to_ulonglong(9223372036854774784.0), 9223372036854774784ull); // 0x7FFFFFFFFFFFFC00
242 ok_eq_ulonglong(cast_double_to_ulonglong(9223372036854775808.0), 9223372036854775808ull); // 0x8000000000000000
243 ok_eq_ulonglong(cast_double_to_ulonglong(18446744073709550591.9), 18446744073709549568ull); // 0xFFFFFFFFFFFFF800
244#ifndef __GNUC__ // GCC inlines the conversion, we cannot fix this
245 ok_eq_ulonglong(cast_double_to_ulonglong(18446744073709550592.0), ULONGLONG_OVERFLOW); // 0x8000000000000000 / 0xFFFFFFFFFFFFFFFF
246 ok_eq_ulonglong(cast_double_to_ulonglong(18446744073709551616.0), ULONGLONG_OVERFLOW); // 0x8000000000000000 / 0xFFFFFFFFFFFFFFFF
247 ok_eq_ulonglong(cast_double_to_ulonglong(20000000000000000000.0), ULONGLONG_OVERFLOW); // 0x8000000000000000 / 0xFFFFFFFFFFFFFFFF
248#endif
249
250 // float to unsigned long long cast (negative values)
251 ok_eq_ulonglong(cast_double_to_ulonglong(-0.0), 0ull);
252 ok_eq_ulonglong(cast_double_to_ulonglong(-0.5), 0ull);
253 ok_eq_ulonglong(cast_double_to_ulonglong(-1.0), 18446744073709551615ull);
254#ifdef OLD_BEHAVIOR
255 ok_eq_ulonglong(cast_double_to_ulonglong(-10.0), ULLONG_MAX);
256 ok_eq_ulonglong(cast_double_to_ulonglong(-1147483648.0), ULLONG_MAX);
257 ok_eq_ulonglong(cast_double_to_ulonglong(-2147483648.0), ULLONG_MAX);
258 ok_eq_ulonglong(cast_double_to_ulonglong(-9223371761976868863.9), ULLONG_MAX);
259 ok_eq_ulonglong(cast_double_to_ulonglong(-9223371761976868864.0), ULLONG_MAX);
260 ok_eq_ulonglong(cast_double_to_ulonglong(-9223372036854775808.0), ULLONG_MAX);
261#else
262 ok_eq_ulonglong(cast_double_to_ulonglong(-10.0), (unsigned long long)-10);
263 ok_eq_ulonglong(cast_double_to_ulonglong(-1147483648.0), (unsigned long long)-1147483648ll);
264 ok_eq_ulonglong(cast_double_to_ulonglong(-2147483648.0), (unsigned long long)-2147483648ll);
265 ok_eq_ulonglong(cast_double_to_ulonglong(-9223372036854775000.0), (unsigned long long)-9223372036854774784ll);
266 ok_eq_ulonglong(cast_double_to_ulonglong(-9223372036854775808.0), (unsigned long long)(-9223372036854775807ll - 1));
267#endif
268 ok_eq_ulonglong(cast_double_to_ulonglong(-100000000000000000000.0), ULONGLONG_OVERFLOW);
269}
270
271START_TEST(floatconv)
272{
273 Test_float();
274 Test_double();
275}
#define ok_eq_ulong(value, expected)
Definition: apitest.h:48
#define ok_eq_longlong(value, expected)
Definition: apitest.h:49
#define ok_eq_long(value, expected)
Definition: apitest.h:47
#define ok_eq_ulonglong(value, expected)
Definition: apitest.h:50
#define START_TEST(x)
Definition: atltest.h:75
w ll
Definition: byte_order.h:167
r l[0]
Definition: byte_order.h:168
#define noinline
Definition: types.h:64
#define ULONG_OVERFLOW
Definition: floatconv.c:37
void Test_float(void)
Definition: floatconv.c:89
#define ULONGLONG_OVERFLOW
Definition: floatconv.c:38
void Test_double(void)
Definition: floatconv.c:181
void __declspec(noinline) __cdecl _free_base(void *const block)
Definition: free_base.cpp:98
GLfloat f
Definition: glext.h:7540
#define ULLONG_MAX
Definition: limits.h:47
#define LLONG_MIN
Definition: limits.h:46
#define ULONG_MAX
Definition: intsafe.h:155
#define LONG_MIN
Definition: intsafe.h:125
#define d
Definition: ke_i.h:81
#define f
Definition: ke_i.h:83