Reactos
at master 275 lines 14 kB view raw
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 41__declspec(noinline) 42long cast_float_to_long(float f) 43{ 44 return (long)f; 45} 46 47__declspec(noinline) 48unsigned long cast_float_to_ulong(float f) 49{ 50 return (unsigned long)f; 51} 52 53__declspec(noinline) 54long cast_double_to_long(double d) 55{ 56 return (long)d; 57} 58 59__declspec(noinline) 60unsigned long cast_double_to_ulong(double d) 61{ 62 return (unsigned long)d; 63} 64 65__declspec(noinline) 66long long cast_float_to_longlong(float f) 67{ 68 return (long long)f; 69} 70 71__declspec(noinline) 72unsigned long long cast_float_to_ulonglong(float f) 73{ 74 return (unsigned long long)f; 75} 76 77__declspec(noinline) 78long long cast_double_to_longlong(double d) 79{ 80 return (long long)d; 81} 82 83__declspec(noinline) 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}