base_test.cc (40342B)
1 // Copyright 2019 Google LLC 2 // SPDX-License-Identifier: Apache-2.0 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #include "hwy/base.h" 17 18 #include <limits> 19 20 #include "hwy/nanobenchmark.h" 21 22 #undef HWY_TARGET_INCLUDE 23 #define HWY_TARGET_INCLUDE "base_test.cc" 24 #include "hwy/foreach_target.h" // IWYU pragma: keep 25 #include "hwy/highway.h" 26 #include "hwy/tests/test_util-inl.h" 27 28 HWY_BEFORE_NAMESPACE(); 29 namespace hwy { 30 namespace HWY_NAMESPACE { 31 namespace { 32 33 HWY_NOINLINE void TestUnreachable() { 34 if (!hwy::Unpredictable1()) { 35 HWY_UNREACHABLE; 36 } 37 } 38 39 HWY_NOINLINE void TestAllLimits() { 40 HWY_ASSERT_EQ(uint8_t{0}, LimitsMin<uint8_t>()); 41 HWY_ASSERT_EQ(uint16_t{0}, LimitsMin<uint16_t>()); 42 HWY_ASSERT_EQ(uint32_t{0}, LimitsMin<uint32_t>()); 43 HWY_ASSERT_EQ(uint64_t{0}, LimitsMin<uint64_t>()); 44 45 HWY_ASSERT_EQ(int8_t{-128}, LimitsMin<int8_t>()); 46 HWY_ASSERT_EQ(int16_t{-32768}, LimitsMin<int16_t>()); 47 HWY_ASSERT_EQ(static_cast<int32_t>(0x80000000u), LimitsMin<int32_t>()); 48 HWY_ASSERT_EQ(static_cast<int64_t>(0x8000000000000000ull), 49 LimitsMin<int64_t>()); 50 51 HWY_ASSERT_EQ(uint8_t{0xFF}, LimitsMax<uint8_t>()); 52 HWY_ASSERT_EQ(uint16_t{0xFFFF}, LimitsMax<uint16_t>()); 53 HWY_ASSERT_EQ(uint32_t{0xFFFFFFFFu}, LimitsMax<uint32_t>()); 54 HWY_ASSERT_EQ(uint64_t{0xFFFFFFFFFFFFFFFFull}, LimitsMax<uint64_t>()); 55 56 HWY_ASSERT_EQ(int8_t{0x7F}, LimitsMax<int8_t>()); 57 HWY_ASSERT_EQ(int16_t{0x7FFF}, LimitsMax<int16_t>()); 58 HWY_ASSERT_EQ(int32_t{0x7FFFFFFFu}, LimitsMax<int32_t>()); 59 HWY_ASSERT_EQ(int64_t{0x7FFFFFFFFFFFFFFFull}, LimitsMax<int64_t>()); 60 61 HWY_ASSERT(LimitsMin<signed char>() == LimitsMin<int8_t>()); 62 HWY_ASSERT(LimitsMin<short>() <= LimitsMin<int16_t>()); // NOLINT 63 HWY_ASSERT(LimitsMin<int>() <= LimitsMin<int16_t>()); 64 HWY_ASSERT(LimitsMin<long>() <= LimitsMin<int32_t>()); // NOLINT 65 HWY_ASSERT(LimitsMin<long long>() <= LimitsMin<int64_t>()); // NOLINT 66 67 HWY_ASSERT(LimitsMax<signed char>() == LimitsMax<int8_t>()); 68 HWY_ASSERT(LimitsMax<short>() >= LimitsMax<int16_t>()); // NOLINT 69 HWY_ASSERT(LimitsMax<int>() >= LimitsMax<int16_t>()); 70 HWY_ASSERT(LimitsMax<long>() >= LimitsMax<int32_t>()); // NOLINT 71 HWY_ASSERT(LimitsMax<long long>() >= LimitsMax<int64_t>()); // NOLINT 72 73 HWY_ASSERT_EQ(static_cast<unsigned char>(0), LimitsMin<unsigned char>()); 74 HWY_ASSERT_EQ(static_cast<unsigned short>(0), LimitsMin<unsigned short>()); 75 HWY_ASSERT_EQ(0u, LimitsMin<unsigned>()); 76 HWY_ASSERT_EQ(0ul, LimitsMin<unsigned long>()); // NOLINT 77 HWY_ASSERT_EQ(0ull, LimitsMin<unsigned long long>()); // NOLINT 78 79 HWY_ASSERT(LimitsMax<unsigned char>() == LimitsMax<uint8_t>()); 80 HWY_ASSERT(LimitsMax<unsigned short>() >= LimitsMax<uint16_t>()); // NOLINT 81 HWY_ASSERT(LimitsMax<unsigned>() >= LimitsMax<uint16_t>()); 82 HWY_ASSERT(LimitsMax<unsigned long>() >= LimitsMax<uint32_t>()); // NOLINT 83 // NOLINTNEXTLINE 84 HWY_ASSERT(LimitsMax<unsigned long long>() >= LimitsMax<uint64_t>()); 85 86 HWY_ASSERT(LimitsMin<char>() == 0 || 87 LimitsMin<char>() == LimitsMin<int8_t>()); 88 HWY_ASSERT(LimitsMax<char>() == LimitsMax<int8_t>() || 89 LimitsMax<char>() == LimitsMax<uint8_t>()); 90 91 HWY_ASSERT_EQ(size_t{0}, LimitsMin<size_t>()); 92 HWY_ASSERT(LimitsMin<ptrdiff_t>() < ptrdiff_t{0}); 93 HWY_ASSERT(LimitsMin<intptr_t>() < intptr_t{0}); 94 HWY_ASSERT_EQ(uintptr_t{0}, LimitsMin<uintptr_t>()); 95 HWY_ASSERT(LimitsMin<wchar_t>() <= wchar_t{0}); 96 97 HWY_ASSERT(LimitsMax<size_t>() > size_t{0}); 98 HWY_ASSERT(LimitsMax<ptrdiff_t>() > ptrdiff_t{0}); 99 HWY_ASSERT(LimitsMax<intptr_t>() > intptr_t{0}); 100 HWY_ASSERT(LimitsMax<uintptr_t>() > uintptr_t{0}); 101 HWY_ASSERT(LimitsMax<wchar_t>() > wchar_t{0}); 102 } 103 104 struct TestLowestHighest { 105 template <class T> 106 HWY_NOINLINE void operator()(T /*unused*/) const { 107 // numeric_limits<T>::lowest is only guaranteed to be what we expect (-max) 108 // for built-in floating-point types. 109 if (!IsSpecialFloat<T>()) { 110 HWY_ASSERT_EQ(std::numeric_limits<T>::lowest(), LowestValue<T>()); 111 HWY_ASSERT_EQ(std::numeric_limits<T>::max(), HighestValue<T>()); 112 113 if (IsFloat<T>()) { 114 HWY_ASSERT(ScalarSignBit(NegativeInfOrLowestValue<T>())); 115 HWY_ASSERT(!ScalarIsFinite(NegativeInfOrLowestValue<T>())); 116 HWY_ASSERT(!ScalarSignBit(PositiveInfOrHighestValue<T>())); 117 HWY_ASSERT(!ScalarIsFinite(PositiveInfOrHighestValue<T>())); 118 HWY_ASSERT(NegativeInfOrLowestValue<T>() < 119 std::numeric_limits<T>::lowest()); 120 HWY_ASSERT(PositiveInfOrHighestValue<T>() > 121 std::numeric_limits<T>::max()); 122 } else { 123 HWY_ASSERT_EQ(std::numeric_limits<T>::lowest(), 124 NegativeInfOrLowestValue<T>()); 125 HWY_ASSERT_EQ(std::numeric_limits<T>::max(), 126 PositiveInfOrHighestValue<T>()); 127 } 128 } 129 } 130 }; 131 132 HWY_NOINLINE void TestAllLowestHighest() { ForAllTypes(TestLowestHighest()); } 133 struct TestIsUnsigned { 134 template <class T> 135 HWY_NOINLINE void operator()(T /*unused*/) const { 136 static_assert(!IsFloat<T>(), "Expected !IsFloat"); 137 static_assert(!IsSigned<T>(), "Expected !IsSigned"); 138 static_assert(IsUnsigned<T>(), "Expected IsUnsigned"); 139 static_assert(IsInteger<T>(), "Expected IsInteger"); 140 } 141 }; 142 143 struct TestIsSigned { 144 template <class T> 145 HWY_NOINLINE void operator()(T /*unused*/) const { 146 static_assert(!IsFloat<T>(), "Expected !IsFloat"); 147 static_assert(IsSigned<T>(), "Expected IsSigned"); 148 static_assert(!IsUnsigned<T>(), "Expected !IsUnsigned"); 149 static_assert(IsInteger<T>(), "Expected IsInteger"); 150 } 151 }; 152 153 struct TestIsFloat { 154 template <class T> 155 HWY_NOINLINE void operator()(T /*unused*/) const { 156 static_assert(IsFloat<T>(), "Expected IsFloat"); 157 static_assert(IsSigned<T>(), "Floats are also considered signed"); 158 static_assert(!IsUnsigned<T>(), "Expected !IsUnsigned"); 159 static_assert(!IsInteger<T>(), "Expected !IsInteger"); 160 } 161 }; 162 163 HWY_NOINLINE void TestAllType() { 164 const TestIsUnsigned is_unsigned_test; 165 const TestIsSigned is_signed_test; 166 167 ForUnsignedTypes(is_unsigned_test); 168 ForSignedTypes(is_signed_test); 169 ForFloatTypes(TestIsFloat()); 170 171 is_unsigned_test(static_cast<unsigned char>(0)); 172 is_unsigned_test(static_cast<unsigned short>(0)); 173 is_unsigned_test(0u); 174 is_unsigned_test(0ul); 175 is_unsigned_test(0ull); 176 is_unsigned_test(size_t{0}); 177 is_unsigned_test(uintptr_t{0}); 178 179 is_signed_test(static_cast<signed char>(0)); 180 is_signed_test(static_cast<signed short>(0)); 181 is_signed_test(0); 182 is_signed_test(0L); 183 is_signed_test(0LL); 184 is_signed_test(ptrdiff_t{0}); 185 is_signed_test(intptr_t{0}); 186 187 static_assert(!IsFloat<char>(), "Expected !IsFloat<char>()"); 188 static_assert(!IsFloat<wchar_t>(), "Expected !IsFloat<wchar_t>()"); 189 static_assert(IsInteger<char>(), "Expected IsInteger<char>()"); 190 static_assert(IsInteger<wchar_t>(), "Expected IsInteger<wchar_t>()"); 191 192 static_assert(sizeof(MakeUnsigned<hwy::uint128_t>) == 16, ""); 193 static_assert(sizeof(MakeWide<uint64_t>) == 16, "Expected uint128_t"); 194 static_assert(sizeof(MakeNarrow<hwy::uint128_t>) == 8, "Expected uint64_t"); 195 } 196 197 struct TestIsSame { 198 template <class T> 199 HWY_NOINLINE void operator()(T /*unused*/) const { 200 static_assert(IsSame<T, T>(), "T == T"); 201 static_assert(!IsSame<MakeSigned<T>, MakeUnsigned<T>>(), "S != U"); 202 static_assert(!IsSame<MakeUnsigned<T>, MakeSigned<T>>(), "U != S"); 203 } 204 }; 205 206 HWY_NOINLINE void TestAllIsSame() { ForAllTypes(TestIsSame()); } 207 208 HWY_NOINLINE void TestAllBitScan() { 209 HWY_ASSERT_EQ(size_t{0}, Num0BitsAboveMS1Bit_Nonzero32(0x80000000u)); 210 HWY_ASSERT_EQ(size_t{0}, Num0BitsAboveMS1Bit_Nonzero32(0xFFFFFFFFu)); 211 HWY_ASSERT_EQ(size_t{1}, Num0BitsAboveMS1Bit_Nonzero32(0x40000000u)); 212 HWY_ASSERT_EQ(size_t{1}, Num0BitsAboveMS1Bit_Nonzero32(0x40108210u)); 213 HWY_ASSERT_EQ(size_t{30}, Num0BitsAboveMS1Bit_Nonzero32(2u)); 214 HWY_ASSERT_EQ(size_t{30}, Num0BitsAboveMS1Bit_Nonzero32(3u)); 215 HWY_ASSERT_EQ(size_t{31}, Num0BitsAboveMS1Bit_Nonzero32(1u)); 216 217 HWY_ASSERT_EQ(size_t{0}, 218 Num0BitsAboveMS1Bit_Nonzero64(0x8000000000000000ull)); 219 HWY_ASSERT_EQ(size_t{0}, 220 Num0BitsAboveMS1Bit_Nonzero64(0xFFFFFFFFFFFFFFFFull)); 221 HWY_ASSERT_EQ(size_t{1}, 222 Num0BitsAboveMS1Bit_Nonzero64(0x4000000000000000ull)); 223 HWY_ASSERT_EQ(size_t{1}, 224 Num0BitsAboveMS1Bit_Nonzero64(0x4010821004200011ull)); 225 HWY_ASSERT_EQ(size_t{62}, Num0BitsAboveMS1Bit_Nonzero64(2ull)); 226 HWY_ASSERT_EQ(size_t{62}, Num0BitsAboveMS1Bit_Nonzero64(3ull)); 227 HWY_ASSERT_EQ(size_t{63}, Num0BitsAboveMS1Bit_Nonzero64(1ull)); 228 229 HWY_ASSERT_EQ(size_t{0}, Num0BitsBelowLS1Bit_Nonzero32(1u)); 230 HWY_ASSERT_EQ(size_t{1}, Num0BitsBelowLS1Bit_Nonzero32(2u)); 231 HWY_ASSERT_EQ(size_t{30}, Num0BitsBelowLS1Bit_Nonzero32(0xC0000000u)); 232 HWY_ASSERT_EQ(size_t{31}, Num0BitsBelowLS1Bit_Nonzero32(0x80000000u)); 233 234 HWY_ASSERT_EQ(size_t{0}, Num0BitsBelowLS1Bit_Nonzero64(1ull)); 235 HWY_ASSERT_EQ(size_t{1}, Num0BitsBelowLS1Bit_Nonzero64(2ull)); 236 HWY_ASSERT_EQ(size_t{62}, 237 Num0BitsBelowLS1Bit_Nonzero64(0xC000000000000000ull)); 238 HWY_ASSERT_EQ(size_t{63}, 239 Num0BitsBelowLS1Bit_Nonzero64(0x8000000000000000ull)); 240 } 241 242 HWY_NOINLINE void TestAllPopCount() { 243 HWY_ASSERT_EQ(size_t{0}, PopCount(0u)); 244 HWY_ASSERT_EQ(size_t{1}, PopCount(1u)); 245 HWY_ASSERT_EQ(size_t{1}, PopCount(2u)); 246 HWY_ASSERT_EQ(size_t{2}, PopCount(3u)); 247 HWY_ASSERT_EQ(size_t{1}, PopCount(0x80000000u)); 248 HWY_ASSERT_EQ(size_t{31}, PopCount(0x7FFFFFFFu)); 249 HWY_ASSERT_EQ(size_t{32}, PopCount(0xFFFFFFFFu)); 250 251 HWY_ASSERT_EQ(size_t{1}, PopCount(0x80000000ull)); 252 HWY_ASSERT_EQ(size_t{31}, PopCount(0x7FFFFFFFull)); 253 HWY_ASSERT_EQ(size_t{32}, PopCount(0xFFFFFFFFull)); 254 HWY_ASSERT_EQ(size_t{33}, PopCount(0x10FFFFFFFFull)); 255 HWY_ASSERT_EQ(size_t{63}, PopCount(0xFFFEFFFFFFFFFFFFull)); 256 HWY_ASSERT_EQ(size_t{64}, PopCount(0xFFFFFFFFFFFFFFFFull)); 257 } 258 259 // Exhaustive test for small/large dividends and divisors 260 HWY_NOINLINE void TestAllDivisor() { 261 // Small d, small n 262 for (uint32_t d = 1; d < 256; ++d) { 263 const Divisor divisor(d); 264 for (uint32_t n = 0; n < 256; ++n) { 265 HWY_ASSERT(divisor.Divide(n) == n / d); 266 HWY_ASSERT(divisor.Remainder(n) == n % d); 267 } 268 } 269 270 // Large d, small n 271 for (uint32_t d = 0xFFFFFF00u; d != 0; ++d) { 272 const Divisor divisor(d); 273 for (uint32_t n = 0; n < 256; ++n) { 274 HWY_ASSERT(divisor.Divide(n) == n / d); 275 HWY_ASSERT(divisor.Remainder(n) == n % d); 276 } 277 } 278 279 // Small d, large n 280 for (uint32_t d = 1; d < 256; ++d) { 281 const Divisor divisor(d); 282 for (uint32_t n = 0xFFFFFF00u; n != 0; ++n) { 283 HWY_ASSERT(divisor.Divide(n) == n / d); 284 HWY_ASSERT(divisor.Remainder(n) == n % d); 285 } 286 } 287 288 // Large d, large n 289 for (uint32_t d = 0xFFFFFF00u; d != 0; ++d) { 290 const Divisor divisor(d); 291 for (uint32_t n = 0xFFFFFF00u; n != 0; ++n) { 292 HWY_ASSERT(divisor.Divide(n) == n / d); 293 HWY_ASSERT(divisor.Remainder(n) == n % d); 294 } 295 } 296 } 297 298 HWY_NOINLINE void TestAllDivisor64() { 299 // Small d, small n 300 for (uint64_t d = 1; d < 256; ++d) { 301 const Divisor64 divisor(d); 302 for (uint64_t n = 0; n < 256; ++n) { 303 HWY_ASSERT(divisor.Divide(n) == n / d); 304 HWY_ASSERT(divisor.Remainder(n) == n % d); 305 } 306 } 307 308 // Large d, small n 309 for (uint64_t d = 0xFFFFFFFFFFFFFF00ULL; d != 0; ++d) { 310 const Divisor64 divisor(d); 311 for (uint64_t n = 0; n < 256; ++n) { 312 HWY_ASSERT(divisor.Divide(n) == n / d); 313 HWY_ASSERT(divisor.Remainder(n) == n % d); 314 } 315 } 316 317 // Small d, large n 318 for (uint64_t d = 1; d < 256; ++d) { 319 const Divisor64 divisor(d); 320 for (uint64_t n = 0xFFFFFFFFFFFFFF00ULL; n != 0; ++n) { 321 HWY_ASSERT(divisor.Divide(n) == n / d); 322 HWY_ASSERT(divisor.Remainder(n) == n % d); 323 } 324 } 325 326 // Large d, large n 327 for (uint64_t d = 0xFFFFFFFFFFFFFF00ULL; d != 0; ++d) { 328 const Divisor64 divisor(d); 329 for (uint64_t n = 0xFFFFFFFFFFFFFF00ULL; n != 0; ++n) { 330 HWY_ASSERT(divisor.Divide(n) == n / d); 331 HWY_ASSERT(divisor.Remainder(n) == n % d); 332 } 333 } 334 } 335 336 struct TestScalarShr { 337 template <class T> 338 HWY_NOINLINE void operator()(T /*unused*/) const { 339 using TU = MakeUnsigned<T>; 340 constexpr T kMsb = static_cast<T>(1ULL << (sizeof(T) * 8 - 1)); 341 constexpr int kSizeInBits = static_cast<int>(sizeof(T) * 8); 342 343 constexpr T kVal1 = static_cast<T>(0x776B0405296C183BULL & LimitsMax<TU>()); 344 constexpr T kVal2 = static_cast<T>(kVal1 | kMsb); 345 346 for (int i = 0; i < kSizeInBits; i++) { 347 T expected1; 348 T expected2; 349 350 const TU expected1_bits = static_cast<TU>(static_cast<TU>(kVal1) >> i); 351 const TU expected2_bits = static_cast<TU>( 352 (static_cast<TU>(kVal2) >> i) | 353 ((IsSigned<T>() && i > 0) 354 ? (~((static_cast<TU>(1) << (kSizeInBits - i)) - 1)) 355 : 0)); 356 357 CopySameSize(&expected1_bits, &expected1); 358 CopySameSize(&expected2_bits, &expected2); 359 360 HWY_ASSERT_EQ(expected1, ScalarShr(kVal1, i)); 361 HWY_ASSERT_EQ(expected2, ScalarShr(kVal2, i)); 362 } 363 } 364 }; 365 366 HWY_NOINLINE void TestAllScalarShr() { ForIntegerTypes(TestScalarShr()); } 367 368 template <class T> 369 static HWY_INLINE void AssertMul128Result(T expected_hi, T expected_lo, T a, 370 T b, const char* file, 371 const int line) { 372 RemoveCvRef<T> actual_hi; 373 const RemoveCvRef<T> actual_lo = Mul128(a, b, &actual_hi); 374 hwy::AssertEqual(expected_lo, actual_lo, hwy::TargetName(HWY_TARGET), file, 375 line); 376 hwy::AssertEqual(expected_hi, actual_hi, hwy::TargetName(HWY_TARGET), file, 377 line); 378 } 379 380 HWY_NOINLINE void TestAllMul128() { 381 AssertMul128Result(static_cast<int64_t>(0), static_cast<int64_t>(0), 382 static_cast<int64_t>(0), static_cast<int64_t>(0), __FILE__, 383 __LINE__); 384 AssertMul128Result(static_cast<int64_t>(0), static_cast<int64_t>(0), 385 static_cast<int64_t>(0), static_cast<int64_t>(1), __FILE__, 386 __LINE__); 387 AssertMul128Result(static_cast<int64_t>(0), static_cast<int64_t>(0), 388 static_cast<int64_t>(0), static_cast<int64_t>(-1), 389 __FILE__, __LINE__); 390 AssertMul128Result(static_cast<int64_t>(0), static_cast<int64_t>(0), 391 static_cast<int64_t>(1), static_cast<int64_t>(0), __FILE__, 392 __LINE__); 393 AssertMul128Result(static_cast<int64_t>(0), static_cast<int64_t>(0), 394 static_cast<int64_t>(-1), static_cast<int64_t>(0), 395 __FILE__, __LINE__); 396 397 AssertMul128Result(static_cast<int64_t>(0), static_cast<int64_t>(1), 398 static_cast<int64_t>(1), static_cast<int64_t>(1), __FILE__, 399 __LINE__); 400 AssertMul128Result(static_cast<int64_t>(-1), static_cast<int64_t>(-1), 401 static_cast<int64_t>(-1), static_cast<int64_t>(1), 402 __FILE__, __LINE__); 403 AssertMul128Result(static_cast<int64_t>(-1), static_cast<int64_t>(-1), 404 static_cast<int64_t>(1), static_cast<int64_t>(-1), 405 __FILE__, __LINE__); 406 AssertMul128Result(static_cast<int64_t>(0), static_cast<int64_t>(1), 407 static_cast<int64_t>(-1), static_cast<int64_t>(-1), 408 __FILE__, __LINE__); 409 410 AssertMul128Result(static_cast<uint64_t>(0), static_cast<uint64_t>(0), 411 static_cast<uint64_t>(0), static_cast<uint64_t>(0), 412 __FILE__, __LINE__); 413 AssertMul128Result(static_cast<uint64_t>(0), static_cast<uint64_t>(0), 414 static_cast<uint64_t>(0), static_cast<uint64_t>(1), 415 __FILE__, __LINE__); 416 AssertMul128Result(static_cast<uint64_t>(0), static_cast<uint64_t>(0), 417 static_cast<uint64_t>(1), static_cast<uint64_t>(0), 418 __FILE__, __LINE__); 419 AssertMul128Result(static_cast<uint64_t>(0), static_cast<uint64_t>(1), 420 static_cast<uint64_t>(1), static_cast<uint64_t>(1), 421 __FILE__, __LINE__); 422 423 AssertMul128Result(static_cast<int64_t>(0x24E331A77C96011DULL), 424 static_cast<int64_t>(0x3C5385F8E294E438ULL), 425 static_cast<int64_t>(0x4F87AE233A08DD18ULL), 426 static_cast<int64_t>(0x76BCCD32975A49CDULL), __FILE__, 427 __LINE__); 428 AssertMul128Result(static_cast<int64_t>(0xFD1F5A95DF919291ULL), 429 static_cast<int64_t>(0x3C5385F8E294E438ULL), 430 static_cast<int64_t>(0x4F87AE233A08DD18ULL), 431 static_cast<int64_t>(0xF6BCCD32975A49CDULL), __FILE__, 432 __LINE__); 433 AssertMul128Result(static_cast<int64_t>(0xE984CB0E30E8DC36ULL), 434 static_cast<int64_t>(0xBC5385F8E294E438ULL), 435 static_cast<int64_t>(0xCF87AE233A08DD18ULL), 436 static_cast<int64_t>(0x76BCCD32975A49CDULL), __FILE__, 437 __LINE__); 438 AssertMul128Result(static_cast<int64_t>(0x01C0F3FC93E46DAAULL), 439 static_cast<int64_t>(0xBC5385F8E294E438ULL), 440 static_cast<int64_t>(0xCF87AE233A08DD18ULL), 441 static_cast<int64_t>(0xF6BCCD32975A49CDULL), __FILE__, 442 __LINE__); 443 444 AssertMul128Result(static_cast<uint64_t>(0x24E331A77C96011DULL), 445 static_cast<uint64_t>(0x3C5385F8E294E438ULL), 446 static_cast<uint64_t>(0x4F87AE233A08DD18ULL), 447 static_cast<uint64_t>(0x76BCCD32975A49CDULL), __FILE__, 448 __LINE__); 449 AssertMul128Result(static_cast<uint64_t>(0x4CA708B9199A6FA9ULL), 450 static_cast<uint64_t>(0x3C5385F8E294E438ULL), 451 static_cast<uint64_t>(0x4F87AE233A08DD18ULL), 452 static_cast<uint64_t>(0xF6BCCD32975A49CDULL), __FILE__, 453 __LINE__); 454 AssertMul128Result(static_cast<uint64_t>(0x60419840C8432603ULL), 455 static_cast<uint64_t>(0xBC5385F8E294E438ULL), 456 static_cast<uint64_t>(0xCF87AE233A08DD18ULL), 457 static_cast<uint64_t>(0x76BCCD32975A49CDULL), __FILE__, 458 __LINE__); 459 AssertMul128Result(static_cast<uint64_t>(0xC8056F526547948FULL), 460 static_cast<uint64_t>(0xBC5385F8E294E438ULL), 461 static_cast<uint64_t>(0xCF87AE233A08DD18ULL), 462 static_cast<uint64_t>(0xF6BCCD32975A49CDULL), __FILE__, 463 __LINE__); 464 } 465 466 template <class T> 467 static HWY_INLINE T TestEndianGetIntegerVal(T val) { 468 static_assert(!IsFloat<T>() && !IsSpecialFloat<T>(), 469 "T must not be a floating-point type"); 470 using TU = MakeUnsigned<T>; 471 static_assert(sizeof(T) == sizeof(TU), 472 "sizeof(T) == sizeof(TU) must be true"); 473 474 uint8_t result_bytes[sizeof(T)]; 475 const TU val_u = static_cast<TU>(val); 476 477 for (size_t i = 0; i < sizeof(T); i++) { 478 #if HWY_IS_BIG_ENDIAN 479 const size_t shift_amt = (sizeof(T) - 1 - i) * 8; 480 #else 481 const size_t shift_amt = i * 8; 482 #endif 483 result_bytes[i] = static_cast<uint8_t>((val_u >> shift_amt) & 0xFF); 484 } 485 486 T result; 487 CopyBytes<sizeof(T)>(result_bytes, &result); 488 return result; 489 } 490 491 template <class T, class... Bytes> 492 static HWY_INLINE T TestEndianCreateValueFromBytes(Bytes&&... bytes) { 493 static_assert(sizeof(T) > 0, "sizeof(T) > 0 must be true"); 494 static_assert(sizeof...(Bytes) == sizeof(T), 495 "sizeof...(Bytes) == sizeof(T) must be true"); 496 497 const uint8_t src_bytes[sizeof(T)]{static_cast<uint8_t>(bytes)...}; 498 499 T result; 500 CopyBytes<sizeof(T)>(src_bytes, &result); 501 return result; 502 } 503 504 #define HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(val) \ 505 HWY_ASSERT_EQ(val, TestEndianGetIntegerVal(val)) 506 507 HWY_NOINLINE void TestAllEndian() { 508 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int8_t{0x01}); 509 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint8_t{0x01}); 510 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int16_t{0x0102}); 511 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint16_t{0x0102}); 512 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int32_t{0x01020304}); 513 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint32_t{0x01020304}); 514 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int64_t{0x0102030405060708}); 515 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint64_t{0x0102030405060708}); 516 517 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int16_t{0x0201}); 518 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint16_t{0x0201}); 519 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int32_t{0x04030201}); 520 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint32_t{0x04030201}); 521 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int64_t{0x0807060504030201}); 522 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint64_t{0x0807060504030201}); 523 524 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? int16_t{0x0102} : int16_t{0x0201}, 525 TestEndianCreateValueFromBytes<int16_t>(0x01, 0x02)); 526 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? uint16_t{0x0102} : uint16_t{0x0201}, 527 TestEndianCreateValueFromBytes<uint16_t>(0x01, 0x02)); 528 HWY_ASSERT_EQ( 529 HWY_IS_BIG_ENDIAN ? int32_t{0x01020304} : int32_t{0x04030201}, 530 TestEndianCreateValueFromBytes<int32_t>(0x01, 0x02, 0x03, 0x04)); 531 HWY_ASSERT_EQ( 532 HWY_IS_BIG_ENDIAN ? uint32_t{0x01020304} : uint32_t{0x04030201}, 533 TestEndianCreateValueFromBytes<uint32_t>(0x01, 0x02, 0x03, 0x04)); 534 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? int64_t{0x0102030405060708} 535 : int64_t{0x0807060504030201}, 536 TestEndianCreateValueFromBytes<int64_t>( 537 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08)); 538 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? uint64_t{0x0102030405060708} 539 : uint64_t{0x0807060504030201}, 540 TestEndianCreateValueFromBytes<uint64_t>( 541 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08)); 542 543 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? int16_t{-0x5EFE} : int16_t{0x02A1}, 544 TestEndianCreateValueFromBytes<int16_t>(0xA1, 0x02)); 545 HWY_ASSERT_EQ( 546 HWY_IS_BIG_ENDIAN ? int32_t{-0x5E4D3CFC} : int32_t{0x04C3B2A1}, 547 TestEndianCreateValueFromBytes<int32_t>(0xA1, 0xB2, 0xC3, 0x04)); 548 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? int64_t{-0x6E5D4C3B2A1908F8} 549 : int64_t{0x08F7E6D5C4B3A291}, 550 TestEndianCreateValueFromBytes<int64_t>( 551 0x91, 0xA2, 0xB3, 0xC4, 0xD5, 0xE6, 0xF7, 0x08)); 552 553 HWY_ASSERT_EQ(HWY_IS_LITTLE_ENDIAN ? int16_t{-0x5DFF} : int16_t{0x01A2}, 554 TestEndianCreateValueFromBytes<int16_t>(0x01, 0xA2)); 555 HWY_ASSERT_EQ( 556 HWY_IS_LITTLE_ENDIAN ? int32_t{-0x3B4C5DFF} : int32_t{0x01A2B3C4}, 557 TestEndianCreateValueFromBytes<int32_t>(0x01, 0xA2, 0xB3, 0xC4)); 558 HWY_ASSERT_EQ(HWY_IS_LITTLE_ENDIAN ? int64_t{-0x0718293A4B5C6DFF} 559 : int64_t{0x0192A3B4C5D6E7F8}, 560 TestEndianCreateValueFromBytes<int64_t>( 561 0x01, 0x92, 0xA3, 0xB4, 0xC5, 0xD6, 0xE7, 0xF8)); 562 563 #if HWY_IS_BIG_ENDIAN 564 HWY_ASSERT_EQ(1.0f, 565 TestEndianCreateValueFromBytes<float>(0x3F, 0x80, 0x00, 0x00)); 566 HWY_ASSERT_EQ(15922433.0f, 567 TestEndianCreateValueFromBytes<float>(0x4B, 0x72, 0xF5, 0x01)); 568 HWY_ASSERT_EQ(-12357485.0f, 569 TestEndianCreateValueFromBytes<float>(0xCB, 0x3C, 0x8F, 0x6D)); 570 #else 571 HWY_ASSERT_EQ(1.0f, 572 TestEndianCreateValueFromBytes<float>(0x00, 0x00, 0x80, 0x3F)); 573 HWY_ASSERT_EQ(15922433.0f, 574 TestEndianCreateValueFromBytes<float>(0x01, 0xF5, 0x72, 0x4B)); 575 HWY_ASSERT_EQ(-12357485.0f, 576 TestEndianCreateValueFromBytes<float>(0x6D, 0x8F, 0x3C, 0xCB)); 577 #endif 578 579 #if HWY_HAVE_FLOAT64 580 #if HWY_IS_BIG_ENDIAN 581 HWY_ASSERT_EQ(1.0, TestEndianCreateValueFromBytes<double>( 582 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); 583 HWY_ASSERT_EQ(8707235690688195.0, 584 TestEndianCreateValueFromBytes<double>(0x43, 0x3E, 0xEF, 0x2F, 585 0x4A, 0x51, 0xAE, 0xC3)); 586 HWY_ASSERT_EQ(-6815854340348452.0, 587 TestEndianCreateValueFromBytes<double>(0xC3, 0x38, 0x36, 0xFB, 588 0xC0, 0xCC, 0x1A, 0x24)); 589 #else 590 HWY_ASSERT_EQ(1.0, TestEndianCreateValueFromBytes<double>( 591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F)); 592 HWY_ASSERT_EQ(8707235690688195.0, 593 TestEndianCreateValueFromBytes<double>(0xC3, 0xAE, 0x51, 0x4A, 594 0x2F, 0xEF, 0x3E, 0x43)); 595 HWY_ASSERT_EQ(-6815854340348452.0, 596 TestEndianCreateValueFromBytes<double>(0x24, 0x1A, 0xCC, 0xC0, 597 0xFB, 0x36, 0x38, 0xC3)); 598 #endif // HWY_IS_BIG_ENDIAN 599 #endif // HWY_HAVE_FLOAT64 600 601 #if HWY_IS_BIG_ENDIAN 602 HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(1.0f), 603 BitCastScalar<bfloat16_t>( 604 TestEndianCreateValueFromBytes<uint16_t>(0x3F, 0x80))); 605 HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(0.333984375f), 606 BitCastScalar<bfloat16_t>( 607 TestEndianCreateValueFromBytes<uint16_t>(0x3E, 0xAB))); 608 HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(167121905303526337111381770240.0f), 609 BitCastScalar<bfloat16_t>( 610 TestEndianCreateValueFromBytes<uint16_t>(0x70, 0x07))); 611 #else 612 HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(1.0f), 613 BitCastScalar<bfloat16_t>( 614 TestEndianCreateValueFromBytes<uint16_t>(0x80, 0x3F))); 615 HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(0.333984375f), 616 BitCastScalar<bfloat16_t>( 617 TestEndianCreateValueFromBytes<uint16_t>(0xAB, 0x3E))); 618 HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(167121905303526337111381770240.0f), 619 BitCastScalar<bfloat16_t>( 620 TestEndianCreateValueFromBytes<uint16_t>(0x07, 0x70))); 621 #endif 622 } 623 624 struct TestSpecialFloat { 625 template <class T> 626 static constexpr bool EnableSpecialFloatArithOpTest() { 627 return (hwy::IsSame<T, float16_t>() && HWY_HAVE_SCALAR_F16_OPERATORS) || 628 (hwy::IsSame<T, bfloat16_t>() && HWY_HAVE_SCALAR_BF16_OPERATORS); 629 } 630 631 template <class T> 632 static constexpr HWY_INLINE T EnsureNotNativeSpecialFloat(T&& val) { 633 #if HWY_HAVE_SCALAR_F16_TYPE 634 static_assert(!hwy::IsSame<RemoveCvRef<T>, float16_t::Native>(), 635 "The operator must not return a float16_t::Native"); 636 #endif 637 #if HWY_HAVE_SCALAR_BF16_TYPE 638 static_assert(!hwy::IsSame<RemoveCvRef<T>, bfloat16_t::Native>(), 639 "The operator must not return a bfloat16_t::Native"); 640 #endif 641 return static_cast<T&&>(val); 642 } 643 644 template <class T> 645 static HWY_INLINE void AssertSpecialFloatOpResultInRange(float min_expected, 646 float max_expected, 647 T actual, 648 const char* filename, 649 const int line) { 650 if (!(actual >= min_expected && actual <= max_expected)) { 651 hwy::Abort( 652 filename, line, 653 "mismatch: value was expected to be between %g and %g, got %g\n", 654 static_cast<double>(min_expected), static_cast<double>(max_expected), 655 ConvertScalarTo<double>(actual)); 656 } 657 } 658 659 template <class T, 660 hwy::EnableIf<EnableSpecialFloatArithOpTest<T>()>* = nullptr> 661 static HWY_NOINLINE void TestSpecialFloatArithOperators(T /*unused*/) { 662 #if HWY_HAVE_SCALAR_F16_OPERATORS || HWY_HAVE_SCALAR_BF16_OPERATORS 663 AssertSpecialFloatOpResultInRange( 664 -0.008422852f, -0.008361816f, 665 EnsureNotNativeSpecialFloat(static_cast<T>(-0.008911133f) + 666 static_cast<T>(5.264282E-4f)), 667 __FILE__, __LINE__); 668 AssertSpecialFloatOpResultInRange( 669 0.44335937f, 0.4453125f, 670 EnsureNotNativeSpecialFloat(static_cast<T>(-0.0014266968f) + 671 0.4453125f), 672 __FILE__, __LINE__); 673 AssertSpecialFloatOpResultInRange( 674 39.25f, 39.5f, 675 EnsureNotNativeSpecialFloat(34.25f + static_cast<T>(5.0625f)), __FILE__, 676 __LINE__); 677 678 AssertSpecialFloatOpResultInRange( 679 7456.0f, 7488.0f, 680 EnsureNotNativeSpecialFloat(static_cast<T>(0.29101562f) - 681 static_cast<T>(-7456.0f)), 682 __FILE__, __LINE__); 683 AssertSpecialFloatOpResultInRange( 684 -2.21875f, -2.203125f, 685 EnsureNotNativeSpecialFloat(static_cast<T>(1.66893E-4f) - 2.21875f), 686 __FILE__, __LINE__); 687 AssertSpecialFloatOpResultInRange( 688 0.32421875f, 0.32617188f, 689 EnsureNotNativeSpecialFloat(0.35351562f - static_cast<T>(0.028198242f)), 690 __FILE__, __LINE__); 691 692 AssertSpecialFloatOpResultInRange( 693 -0.01135254f, -0.011291503f, 694 EnsureNotNativeSpecialFloat(static_cast<T>(2.109375f) * 695 static_cast<T>(-0.0053710938f)), 696 __FILE__, __LINE__); 697 AssertSpecialFloatOpResultInRange( 698 2.359375f, 2.375f, 699 EnsureNotNativeSpecialFloat(static_cast<T>(0.0019454956f) * 1216.0f), 700 __FILE__, __LINE__); 701 AssertSpecialFloatOpResultInRange( 702 -1.1014938E-4f, 3.453125f, 703 EnsureNotNativeSpecialFloat(-0.00038146973f * 704 static_cast<T>(-0.00037956237f)), 705 __FILE__, __LINE__); 706 707 AssertSpecialFloatOpResultInRange( 708 -27.875f, -27.75f, 709 EnsureNotNativeSpecialFloat(static_cast<T>(-56.5f) / 710 static_cast<T>(2.03125f)), 711 __FILE__, __LINE__); 712 AssertSpecialFloatOpResultInRange( 713 0.033203125f, 0.033447266f, 714 EnsureNotNativeSpecialFloat(static_cast<T>(470.0f) / 14080.0f), 715 __FILE__, __LINE__); 716 AssertSpecialFloatOpResultInRange( 717 0.51953125f, 0.5234375f, 718 EnsureNotNativeSpecialFloat(0.26367188f / static_cast<T>(0.50390625f)), 719 __FILE__, __LINE__); 720 721 T incr_assign_result_1 = static_cast<T>(1.373291E-4f); 722 EnsureNotNativeSpecialFloat(incr_assign_result_1 += 723 static_cast<T>(-20.375f)); 724 AssertSpecialFloatOpResultInRange(-20.375f, -20.25f, incr_assign_result_1, 725 __FILE__, __LINE__); 726 727 T incr_assign_result_2 = static_cast<T>(2.1457672E-4f); 728 EnsureNotNativeSpecialFloat(incr_assign_result_2 += static_cast<int8_t>(7)); 729 AssertSpecialFloatOpResultInRange(7.0f, 7.03125f, incr_assign_result_2, 730 __FILE__, __LINE__); 731 732 float incr_assign_result3 = -6.747985f; 733 incr_assign_result3 += static_cast<T>(4.15625f); 734 AssertSpecialFloatOpResultInRange(-2.59375f, -2.578125f, 735 incr_assign_result3, __FILE__, __LINE__); 736 737 float incr_assign_result4 = 6.71875; 738 incr_assign_result4 += static_cast<T>(2.359375); 739 AssertSpecialFloatOpResultInRange(9.0625, 9.125, incr_assign_result4, 740 __FILE__, __LINE__); 741 742 T decr_assign_result_1 = static_cast<T>(4.4059753E-4f); 743 EnsureNotNativeSpecialFloat(decr_assign_result_1 -= 744 static_cast<T>(6880.0f)); 745 AssertSpecialFloatOpResultInRange(-6880, -6848, decr_assign_result_1, 746 __FILE__, __LINE__); 747 748 T decr_assign_result_2 = static_cast<T>(85.5f); 749 EnsureNotNativeSpecialFloat(decr_assign_result_2 -= static_cast<int8_t>(5)); 750 AssertSpecialFloatOpResultInRange(80.5f, 80.5f, decr_assign_result_2, 751 __FILE__, __LINE__); 752 753 float decr_assign_result3 = 9.875f; 754 decr_assign_result3 -= static_cast<T>(1.5234375f); 755 AssertSpecialFloatOpResultInRange(8.3125f, 8.375f, decr_assign_result3, 756 __FILE__, __LINE__); 757 758 double decr_assign_result4 = 0.337890625; 759 decr_assign_result4 -= static_cast<T>(2.328125); 760 AssertSpecialFloatOpResultInRange(-1.9921875, -1.984375, 761 decr_assign_result4, __FILE__, __LINE__); 762 763 T mul_assign_result_1 = static_cast<T>(15680.0f); 764 EnsureNotNativeSpecialFloat(mul_assign_result_1 *= 765 static_cast<T>(0.001373291f)); 766 AssertSpecialFloatOpResultInRange(21.5f, 21.625f, mul_assign_result_1, 767 __FILE__, __LINE__); 768 769 T mul_assign_result_2 = static_cast<T>(2.609375f); 770 EnsureNotNativeSpecialFloat(mul_assign_result_2 *= static_cast<int8_t>(7)); 771 AssertSpecialFloatOpResultInRange(18.25, 18.375, mul_assign_result_2, 772 __FILE__, __LINE__); 773 774 float mul_assign_result3 = 4.125f; 775 mul_assign_result3 *= static_cast<T>(3.375f); 776 AssertSpecialFloatOpResultInRange(13.875f, 13.9375f, mul_assign_result3, 777 __FILE__, __LINE__); 778 779 double mul_assign_result4 = 7.9375; 780 mul_assign_result4 *= static_cast<T>(0.79296875); 781 AssertSpecialFloatOpResultInRange(6.28125, 6.3125, mul_assign_result4, 782 __FILE__, __LINE__); 783 784 T div_assign_result_1 = static_cast<T>(11584.0f); 785 EnsureNotNativeSpecialFloat(div_assign_result_1 /= static_cast<T>(9.5625f)); 786 AssertSpecialFloatOpResultInRange(1208.0f, 1216.0f, div_assign_result_1, 787 __FILE__, __LINE__); 788 789 T div_assign_result_2 = static_cast<T>(0.12109375f); 790 EnsureNotNativeSpecialFloat(div_assign_result_2 /= static_cast<int8_t>(3)); 791 AssertSpecialFloatOpResultInRange(0.040283203f, 0.040527344f, 792 div_assign_result_2, __FILE__, __LINE__); 793 794 float div_assign_result_3 = 0.21679688f; 795 div_assign_result_3 /= static_cast<T>(3.421875f); 796 AssertSpecialFloatOpResultInRange(0.06298828125f, 0.0634765625f, 797 div_assign_result_3, __FILE__, __LINE__); 798 799 double div_assign_result_4 = 5.34375; 800 div_assign_result_4 /= static_cast<T>(0.337890625); 801 AssertSpecialFloatOpResultInRange(15.8125, 15.875, div_assign_result_4, 802 __FILE__, __LINE__); 803 804 HWY_ASSERT_EQ(static_cast<T>(-1.0f), 805 EnsureNotNativeSpecialFloat(-static_cast<T>(1.0f))); 806 HWY_ASSERT_EQ(static_cast<T>(1.0f), 807 EnsureNotNativeSpecialFloat(+static_cast<T>(1.0f))); 808 809 T pre_incr_result_1 = static_cast<T>(1.0f); 810 T pre_incr_result_2 = EnsureNotNativeSpecialFloat(++pre_incr_result_1); 811 HWY_ASSERT_EQ(static_cast<T>(2.0f), pre_incr_result_1); 812 HWY_ASSERT_EQ(static_cast<T>(2.0f), pre_incr_result_2); 813 814 T post_incr_result_1 = static_cast<T>(5.0f); 815 T post_incr_result_2 = EnsureNotNativeSpecialFloat(post_incr_result_1++); 816 HWY_ASSERT_EQ(static_cast<T>(6.0f), post_incr_result_1); 817 HWY_ASSERT_EQ(static_cast<T>(5.0f), post_incr_result_2); 818 819 T pre_decr_result_1 = static_cast<T>(-2.0f); 820 T pre_decr_result_2 = EnsureNotNativeSpecialFloat(--pre_decr_result_1); 821 HWY_ASSERT_EQ(static_cast<T>(-3.0f), pre_decr_result_1); 822 HWY_ASSERT_EQ(static_cast<T>(-3.0f), pre_decr_result_2); 823 824 T post_decr_result_1 = static_cast<T>(-7.0f); 825 T post_decr_result_2 = EnsureNotNativeSpecialFloat(post_decr_result_1--); 826 HWY_ASSERT_EQ(static_cast<T>(-8.0f), post_decr_result_1); 827 HWY_ASSERT_EQ(static_cast<T>(-7.0f), post_decr_result_2); 828 829 HWY_ASSERT(static_cast<T>(1.0f) == 1.0f); 830 HWY_ASSERT(static_cast<T>(-2.40625f) != 0.0033416748f); 831 HWY_ASSERT(static_cast<T>(-3248.0f) < 0.0018997193f); 832 HWY_ASSERT(static_cast<T>(-27904.0f) <= -3.859375f); 833 HWY_ASSERT(static_cast<T>(1.078125f) > 0.010009765f); 834 HWY_ASSERT(static_cast<T>(45312.0f) >= 0.00024318695f); 835 836 HWY_ASSERT(2.0f == static_cast<T>(2.0f)); 837 HWY_ASSERT(-5.78125f != static_cast<T>(-15168.0f)); 838 HWY_ASSERT(-0.056884766f < static_cast<T>(0.000088214875f)); 839 HWY_ASSERT(0.00008392333f <= static_cast<T>(1384.0f)); 840 HWY_ASSERT(21888.0f > static_cast<T>(-2.578125f)); 841 HWY_ASSERT(0.087402344 >= static_cast<T>(-0.65625f)); 842 #endif // HWY_HAVE_SCALAR_F16_OPERATORS || HWY_HAVE_SCALAR_BF16_OPERATORS 843 } 844 845 template <class T, 846 hwy::EnableIf<!EnableSpecialFloatArithOpTest<T>()>* = nullptr> 847 static HWY_INLINE void TestSpecialFloatArithOperators(T /*unused*/) {} 848 849 template <class T> 850 HWY_NOINLINE void operator()(T /*unused*/) const { 851 static_assert(IsSpecialFloat<T>(), "IsSpecialFloat<T>() must be true"); 852 853 HWY_ASSERT_EQ(static_cast<uint32_t>(0x436B0000u), 854 BitCastScalar<uint32_t>(ConvertScalarTo<float>( 855 BitCastScalar<T>(static_cast<uint16_t>( 856 IsSame<T, hwy::float16_t>() ? 0x5B58u : 0x436Bu))))); 857 HWY_ASSERT_EQ(static_cast<uint32_t>(0xBB790000u), 858 BitCastScalar<uint32_t>(ConvertScalarTo<float>( 859 BitCastScalar<T>(static_cast<uint16_t>( 860 IsSame<T, hwy::float16_t>() ? 0x9BC8u : 0xBB79u))))); 861 862 HWY_ASSERT_EQ(static_cast<uint32_t>( 863 IsSame<T, hwy::float16_t>() ? 0xC0B86000u : 0xC5C30000u), 864 BitCastScalar<uint32_t>(ConvertScalarTo<float>( 865 BitCastScalar<T>(static_cast<uint16_t>(0xC5C3u))))); 866 HWY_ASSERT_EQ(static_cast<uint32_t>( 867 IsSame<T, hwy::float16_t>() ? 0x41D20000u : 0x4E900000u), 868 BitCastScalar<uint32_t>(ConvertScalarTo<float>( 869 BitCastScalar<T>(static_cast<uint16_t>(0x4E90u))))); 870 871 HWY_ASSERT_EQ(1696.0, ConvertScalarTo<double>(ConvertScalarTo<T>(1696.0f))); 872 HWY_ASSERT_EQ( 873 -0.00177001953125f, 874 ConvertScalarTo<float>(ConvertScalarTo<T>(-0.00177001953125f))); 875 876 HWY_ASSERT_EQ(0.49609375f, 877 ConvertScalarTo<float>(ConvertScalarTo<T>(0.49609375))); 878 HWY_ASSERT_EQ( 879 0.000553131103515625, 880 ConvertScalarTo<double>(ConvertScalarTo<T>(0.000553131103515625))); 881 882 HWY_ASSERT_EQ(ConvertScalarTo<T>(3.0f), ConvertScalarTo<T>(3)); 883 HWY_ASSERT_EQ(ConvertScalarTo<T>(-5.5f), ConvertScalarTo<T>(-5.5)); 884 HWY_ASSERT_EQ(ConvertScalarTo<T>(0.82421875f), 885 ConvertScalarTo<T>(BF16FromF32(0.82421875f))); 886 HWY_ASSERT_EQ(ConvertScalarTo<T>(-6.375f), 887 ConvertScalarTo<T>(F16FromF32(-6.375f))); 888 889 HWY_ASSERT(ConvertScalarTo<T>(-3.671875f) < 890 ConvertScalarTo<T>(0.0218505859375f)); 891 HWY_ASSERT(ConvertScalarTo<T>(-0.033447265625f) <= 892 ConvertScalarTo<T>(8.249282836914062E-5f)); 893 HWY_ASSERT(ConvertScalarTo<T>(23296.0f) > ConvertScalarTo<T>(192.0f)); 894 HWY_ASSERT(ConvertScalarTo<T>(41984.0f) >= ConvertScalarTo<T>(370.0f)); 895 896 TestSpecialFloatArithOperators(T()); 897 } 898 }; 899 900 HWY_NOINLINE void TestAllSpecialFloat() { 901 TestSpecialFloat test; 902 test(float16_t()); 903 test(bfloat16_t()); 904 } 905 906 } // namespace 907 // NOLINTNEXTLINE(google-readability-namespace-comments) 908 } // namespace HWY_NAMESPACE 909 } // namespace hwy 910 HWY_AFTER_NAMESPACE(); 911 912 #if HWY_ONCE 913 namespace hwy { 914 namespace { 915 HWY_BEFORE_TEST(BaseTest); 916 HWY_EXPORT_AND_TEST_P(BaseTest, TestUnreachable); 917 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllLimits); 918 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllLowestHighest); 919 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllType); 920 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllIsSame); 921 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllBitScan); 922 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllPopCount); 923 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllDivisor); 924 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllDivisor64); 925 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllScalarShr); 926 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllMul128); 927 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllEndian); 928 HWY_EXPORT_AND_TEST_P(BaseTest, TestAllSpecialFloat); 929 HWY_AFTER_TEST(); 930 } // namespace 931 } // namespace hwy 932 HWY_TEST_MAIN(); 933 #endif // HWY_ONCE