tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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