Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  base_test.cc   Sprache: C

 
// Copyright 2019 Google LLC
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "hwy/base.h"

#include <limits>

#undef HWY_TARGET_INCLUDE
#define HWY_TARGET_INCLUDE "base_test.cc"
#include "hwy/foreach_target.h"  // IWYU pragma: keep
#include "hwy/highway.h"
#include "hwy/tests/test_util-inl.h"

HWY_BEFORE_NAMESPACE();
namespace hwy {
namespace HWY_NAMESPACE {

HWY_NOINLINE void TestAllLimits() {
  HWY_ASSERT_EQ(uint8_t{0}, LimitsMin<uint8_t>());
  HWY_ASSERT_EQ(uint16_t{0}, LimitsMin<uint16_t>());
  HWY_ASSERT_EQ(uint32_t{0}, LimitsMin<uint32_t>());
  HWY_ASSERT_EQ(uint64_t{0}, LimitsMin<uint64_t>());

  HWY_ASSERT_EQ(int8_t{-128}, LimitsMin<int8_t>());
  HWY_ASSERT_EQ(int16_t{-32768}, LimitsMin<int16_t>());
  HWY_ASSERT_EQ(static_cast<int32_t>(0x80000000u), LimitsMin<int32_t>());
  HWY_ASSERT_EQ(static_cast<int64_t>(0x8000000000000000ull),
                LimitsMin<int64_t>());

  HWY_ASSERT_EQ(uint8_t{0xFF}, LimitsMax<uint8_t>());
  HWY_ASSERT_EQ(uint16_t{0xFFFF}, LimitsMax<uint16_t>());
  HWY_ASSERT_EQ(uint32_t{0xFFFFFFFFu}, LimitsMax<uint32_t>());
  HWY_ASSERT_EQ(uint64_t{0xFFFFFFFFFFFFFFFFull}, LimitsMax<uint64_t>());

  HWY_ASSERT_EQ(int8_t{0x7F}, LimitsMax<int8_t>());
  HWY_ASSERT_EQ(int16_t{0x7FFF}, LimitsMax<int16_t>());
  HWY_ASSERT_EQ(int32_t{0x7FFFFFFFu}, LimitsMax<int32_t>());
  HWY_ASSERT_EQ(int64_t{0x7FFFFFFFFFFFFFFFull}, LimitsMax<int64_t>());

  HWY_ASSERT(LimitsMin<signed char>() == LimitsMin<int8_t>());
  HWY_ASSERT(LimitsMin<short>() <= LimitsMin<int16_t>());  // NOLINT
  HWY_ASSERT(LimitsMin<int>() <= LimitsMin<int16_t>());
  HWY_ASSERT(LimitsMin<long>() <= LimitsMin<int32_t>());       // NOLINT
  HWY_ASSERT(LimitsMin<long long>() <= LimitsMin<int64_t>());  // NOLINT

  HWY_ASSERT(LimitsMax<signed char>() == LimitsMax<int8_t>());
  HWY_ASSERT(LimitsMax<short>() >= LimitsMax<int16_t>());  // NOLINT
  HWY_ASSERT(LimitsMax<int>() >= LimitsMax<int16_t>());
  HWY_ASSERT(LimitsMax<long>() >= LimitsMax<int32_t>());       // NOLINT
  HWY_ASSERT(LimitsMax<long long>() >= LimitsMax<int64_t>());  // NOLINT

  HWY_ASSERT_EQ(static_cast<unsigned char>(0), LimitsMin<unsigned char>());
  HWY_ASSERT_EQ(static_cast<unsigned short>(0), LimitsMin<unsigned short>());
  HWY_ASSERT_EQ(0u, LimitsMin<unsigned>());
  HWY_ASSERT_EQ(0ul, LimitsMin<unsigned long>());        // NOLINT
  HWY_ASSERT_EQ(0ull, LimitsMin<unsigned long long>());  // NOLINT

  HWY_ASSERT(LimitsMax<unsigned char>() == LimitsMax<uint8_t>());
  HWY_ASSERT(LimitsMax<unsigned short>() >= LimitsMax<uint16_t>());  // NOLINT
  HWY_ASSERT(LimitsMax<unsigned>() >= LimitsMax<uint16_t>());
  HWY_ASSERT(LimitsMax<unsigned long>() >= LimitsMax<uint32_t>());  // NOLINT
  // NOLINTNEXTLINE
  HWY_ASSERT(LimitsMax<unsigned long long>() >= LimitsMax<uint64_t>());

  HWY_ASSERT(LimitsMin<char>() == 0 ||
             LimitsMin<char>() == LimitsMin<int8_t>());
  HWY_ASSERT(LimitsMax<char>() == LimitsMax<int8_t>() ||
             LimitsMax<char>() == LimitsMax<uint8_t>());

  HWY_ASSERT_EQ(size_t{0}, LimitsMin<size_t>());
  HWY_ASSERT(LimitsMin<ptrdiff_t>() < ptrdiff_t{0});
  HWY_ASSERT(LimitsMin<intptr_t>() < intptr_t{0});
  HWY_ASSERT_EQ(uintptr_t{0}, LimitsMin<uintptr_t>());
  HWY_ASSERT(LimitsMin<wchar_t>() <= wchar_t{0});

  HWY_ASSERT(LimitsMax<size_t>() > size_t{0});
  HWY_ASSERT(LimitsMax<ptrdiff_t>() > ptrdiff_t{0});
  HWY_ASSERT(LimitsMax<intptr_t>() > intptr_t{0});
  HWY_ASSERT(LimitsMax<uintptr_t>() > uintptr_t{0});
  HWY_ASSERT(LimitsMax<wchar_t>() > wchar_t{0});
}

struct TestLowestHighest {
  template <class T>
  HWY_NOINLINE void operator()(T /*unused*/) const {
    // numeric_limits<T>::lowest is only guaranteed to be what we expect (-max)
    // for built-in floating-point types.
    if (!IsSpecialFloat<T>()) {
      HWY_ASSERT_EQ(std::numeric_limits<T>::lowest(), LowestValue<T>());
      HWY_ASSERT_EQ(std::numeric_limits<T>::max(), HighestValue<T>());
    }
  }
};

HWY_NOINLINE void TestAllLowestHighest() { ForAllTypes(TestLowestHighest()); }
struct TestIsUnsigned {
  template <class T>
  HWY_NOINLINE void operator()(T /*unused*/) const {
    static_assert(!IsFloat<T>(), "Expected !IsFloat");
    static_assert(!IsSigned<T>(), "Expected !IsSigned");
    static_assert(IsInteger<T>(), "Expected IsInteger");
  }
};

struct TestIsSigned {
  template <class T>
  HWY_NOINLINE void operator()(T /*unused*/) const {
    static_assert(!IsFloat<T>(), "Expected !IsFloat");
    static_assert(IsSigned<T>(), "Expected IsSigned");
    static_assert(IsInteger<T>(), "Expected IsInteger");
  }
};

struct TestIsFloat {
  template <class T>
  HWY_NOINLINE void operator()(T /*unused*/) const {
    static_assert(IsFloat<T>(), "Expected IsFloat");
    static_assert(!IsInteger<T>(), "Expected !IsInteger");
    static_assert(IsSigned<T>(), "Floats are also considered signed");
  }
};

HWY_NOINLINE void TestAllType() {
  const TestIsUnsigned is_unsigned_test;
  const TestIsSigned is_signed_test;

  ForUnsignedTypes(is_unsigned_test);
  ForSignedTypes(is_signed_test);
  ForFloatTypes(TestIsFloat());

  is_unsigned_test(static_cast<unsigned char>(0));
  is_unsigned_test(static_cast<unsigned short>(0));
  is_unsigned_test(0u);
  is_unsigned_test(0ul);
  is_unsigned_test(0ull);
  is_unsigned_test(size_t{0});
  is_unsigned_test(uintptr_t{0});

  is_signed_test(static_cast<signed char>(0));
  is_signed_test(static_cast<signed short>(0));
  is_signed_test(0);
  is_signed_test(0L);
  is_signed_test(0LL);
  is_signed_test(ptrdiff_t{0});
  is_signed_test(intptr_t{0});

  static_assert(!IsFloat<char>(), "Expected !IsFloat()");
  static_assert(!IsFloat<wchar_t>(), "Expected !IsFloat()");
  static_assert(IsInteger<char>(), "Expected IsInteger()");
  static_assert(IsInteger<wchar_t>(), "Expected IsInteger()");

  static_assert(sizeof(MakeUnsigned<hwy::uint128_t>) == 16, "");
  static_assert(sizeof(MakeWide<uint64_t>) == 16, "Expected uint128_t");
  static_assert(sizeof(MakeNarrow<hwy::uint128_t>) == 8, "Expected uint64_t");
}

struct TestIsSame {
  template <class T>
  HWY_NOINLINE void operator()(T /*unused*/) const {
    static_assert(IsSame<T, T>(), "T == T");
    static_assert(!IsSame<MakeSigned<T>, MakeUnsigned<T>>(), "S != U");
    static_assert(!IsSame<MakeUnsigned<T>, MakeSigned<T>>(), "U != S");
  }
};

HWY_NOINLINE void TestAllIsSame() { ForAllTypes(TestIsSame()); }

HWY_NOINLINE void TestAllBitScan() {
  HWY_ASSERT_EQ(size_t{0}, Num0BitsAboveMS1Bit_Nonzero32(0x80000000u));
  HWY_ASSERT_EQ(size_t{0}, Num0BitsAboveMS1Bit_Nonzero32(0xFFFFFFFFu));
  HWY_ASSERT_EQ(size_t{1}, Num0BitsAboveMS1Bit_Nonzero32(0x40000000u));
  HWY_ASSERT_EQ(size_t{1}, Num0BitsAboveMS1Bit_Nonzero32(0x40108210u));
  HWY_ASSERT_EQ(size_t{30}, Num0BitsAboveMS1Bit_Nonzero32(2u));
  HWY_ASSERT_EQ(size_t{30}, Num0BitsAboveMS1Bit_Nonzero32(3u));
  HWY_ASSERT_EQ(size_t{31}, Num0BitsAboveMS1Bit_Nonzero32(1u));

  HWY_ASSERT_EQ(size_t{0},
                Num0BitsAboveMS1Bit_Nonzero64(0x8000000000000000ull));
  HWY_ASSERT_EQ(size_t{0},
                Num0BitsAboveMS1Bit_Nonzero64(0xFFFFFFFFFFFFFFFFull));
  HWY_ASSERT_EQ(size_t{1},
                Num0BitsAboveMS1Bit_Nonzero64(0x4000000000000000ull));
  HWY_ASSERT_EQ(size_t{1},
                Num0BitsAboveMS1Bit_Nonzero64(0x4010821004200011ull));
  HWY_ASSERT_EQ(size_t{62}, Num0BitsAboveMS1Bit_Nonzero64(2ull));
  HWY_ASSERT_EQ(size_t{62}, Num0BitsAboveMS1Bit_Nonzero64(3ull));
  HWY_ASSERT_EQ(size_t{63}, Num0BitsAboveMS1Bit_Nonzero64(1ull));

  HWY_ASSERT_EQ(size_t{0}, Num0BitsBelowLS1Bit_Nonzero32(1u));
  HWY_ASSERT_EQ(size_t{1}, Num0BitsBelowLS1Bit_Nonzero32(2u));
  HWY_ASSERT_EQ(size_t{30}, Num0BitsBelowLS1Bit_Nonzero32(0xC0000000u));
  HWY_ASSERT_EQ(size_t{31}, Num0BitsBelowLS1Bit_Nonzero32(0x80000000u));

  HWY_ASSERT_EQ(size_t{0}, Num0BitsBelowLS1Bit_Nonzero64(1ull));
  HWY_ASSERT_EQ(size_t{1}, Num0BitsBelowLS1Bit_Nonzero64(2ull));
  HWY_ASSERT_EQ(size_t{62},
                Num0BitsBelowLS1Bit_Nonzero64(0xC000000000000000ull));
  HWY_ASSERT_EQ(size_t{63},
                Num0BitsBelowLS1Bit_Nonzero64(0x8000000000000000ull));
}

HWY_NOINLINE void TestAllPopCount() {
  HWY_ASSERT_EQ(size_t{0}, PopCount(0u));
  HWY_ASSERT_EQ(size_t{1}, PopCount(1u));
  HWY_ASSERT_EQ(size_t{1}, PopCount(2u));
  HWY_ASSERT_EQ(size_t{2}, PopCount(3u));
  HWY_ASSERT_EQ(size_t{1}, PopCount(0x80000000u));
  HWY_ASSERT_EQ(size_t{31}, PopCount(0x7FFFFFFFu));
  HWY_ASSERT_EQ(size_t{32}, PopCount(0xFFFFFFFFu));

  HWY_ASSERT_EQ(size_t{1}, PopCount(0x80000000ull));
  HWY_ASSERT_EQ(size_t{31}, PopCount(0x7FFFFFFFull));
  HWY_ASSERT_EQ(size_t{32}, PopCount(0xFFFFFFFFull));
  HWY_ASSERT_EQ(size_t{33}, PopCount(0x10FFFFFFFFull));
  HWY_ASSERT_EQ(size_t{63}, PopCount(0xFFFEFFFFFFFFFFFFull));
  HWY_ASSERT_EQ(size_t{64}, PopCount(0xFFFFFFFFFFFFFFFFull));
}

template <class T>
static HWY_INLINE T TestEndianGetIntegerVal(T val) {
  static_assert(!IsFloat<T>() && !IsSpecialFloat<T>(),
                "T must not be a floating-point type");
  using TU = MakeUnsigned<T>;
  static_assert(sizeof(T) == sizeof(TU),
                "sizeof(T) == sizeof(TU) must be true");

  uint8_t result_bytes[sizeof(T)];
  const TU val_u = static_cast<TU>(val);

  for (size_t i = 0; i < sizeof(T); i++) {
#if HWY_IS_BIG_ENDIAN
    const size_t shift_amt = (sizeof(T) - 1 - i) * 8;
#else
    const size_t shift_amt = i * 8;
#endif
    result_bytes[i] = static_cast<uint8_t>((val_u >> shift_amt) & 0xFF);
  }

  T result;
  CopyBytes<sizeof(T)>(result_bytes, &result);
  return result;
}

template <class T, class... Bytes>
static HWY_INLINE T TestEndianCreateValueFromBytes(Bytes&&... bytes) {
  static_assert(sizeof(T) > 0, "sizeof(T) > 0 must be true");
  static_assert(sizeof...(Bytes) == sizeof(T),
                "sizeof...(Bytes) == sizeof(T) must be true");

  const uint8_t src_bytes[sizeof(T)]{static_cast<uint8_t>(bytes)...};

  T result;
  CopyBytes<sizeof(T)>(src_bytes, &result);
  return result;
}

#define HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(val) \
  HWY_ASSERT_EQ(val, TestEndianGetIntegerVal(val))

HWY_NOINLINE void TestAllEndian() {
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int8_t{0x01});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint8_t{0x01});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int16_t{0x0102});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint16_t{0x0102});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int32_t{0x01020304});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint32_t{0x01020304});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int64_t{0x0102030405060708});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint64_t{0x0102030405060708});

  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int16_t{0x0201});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint16_t{0x0201});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int32_t{0x04030201});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint32_t{0x04030201});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int64_t{0x0807060504030201});
  HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint64_t{0x0807060504030201});

  HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? int16_t{0x0102} : int16_t{0x0201},
                TestEndianCreateValueFromBytes<int16_t>(0x01, 0x02));
  HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? uint16_t{0x0102} : uint16_t{0x0201},
                TestEndianCreateValueFromBytes<uint16_t>(0x01, 0x02));
  HWY_ASSERT_EQ(
      HWY_IS_BIG_ENDIAN ? int32_t{0x01020304} : int32_t{0x04030201},
      TestEndianCreateValueFromBytes<int32_t>(0x01, 0x02, 0x03, 0x04));
  HWY_ASSERT_EQ(
      HWY_IS_BIG_ENDIAN ? uint32_t{0x01020304} : uint32_t{0x04030201},
      TestEndianCreateValueFromBytes<uint32_t>(0x01, 0x02, 0x03, 0x04));
  HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? int64_t{0x0102030405060708}
                                  : int64_t{0x0807060504030201},
                TestEndianCreateValueFromBytes<int64_t>(
                    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08));
  HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? uint64_t{0x0102030405060708}
                                  : uint64_t{0x0807060504030201},
                TestEndianCreateValueFromBytes<uint64_t>(
                    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08));

  HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? int16_t{-0x5EFE} : int16_t{0x02A1},
                TestEndianCreateValueFromBytes<int16_t>(0xA1, 0x02));
  HWY_ASSERT_EQ(
      HWY_IS_BIG_ENDIAN ? int32_t{-0x5E4D3CFC} : int32_t{0x04C3B2A1},
      TestEndianCreateValueFromBytes<int32_t>(0xA1, 0xB2, 0xC3, 0x04));
  HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN ? int64_t{-0x6E5D4C3B2A1908F8}
                                  : int64_t{0x08F7E6D5C4B3A291},
                TestEndianCreateValueFromBytes<int64_t>(
                    0x91, 0xA2, 0xB3, 0xC4, 0xD5, 0xE6, 0xF7, 0x08));

  HWY_ASSERT_EQ(HWY_IS_LITTLE_ENDIAN ? int16_t{-0x5DFF} : int16_t{0x01A2},
                TestEndianCreateValueFromBytes<int16_t>(0x01, 0xA2));
  HWY_ASSERT_EQ(
      HWY_IS_LITTLE_ENDIAN ? int32_t{-0x3B4C5DFF} : int32_t{0x01A2B3C4},
      TestEndianCreateValueFromBytes<int32_t>(0x01, 0xA2, 0xB3, 0xC4));
  HWY_ASSERT_EQ(HWY_IS_LITTLE_ENDIAN ? int64_t{-0x0718293A4B5C6DFF}
                                     : int64_t{0x0192A3B4C5D6E7F8},
                TestEndianCreateValueFromBytes<int64_t>(
                    0x01, 0x92, 0xA3, 0xB4, 0xC5, 0xD6, 0xE7, 0xF8));

#if HWY_IS_BIG_ENDIAN
  HWY_ASSERT_EQ(1.0f,
                TestEndianCreateValueFromBytes<float>(0x3F, 0x80, 0x00, 0x00));
  HWY_ASSERT_EQ(15922433.0f,
                TestEndianCreateValueFromBytes<float>(0x4B, 0x72, 0xF5, 0x01));
  HWY_ASSERT_EQ(-12357485.0f,
                TestEndianCreateValueFromBytes<float>(0xCB, 0x3C, 0x8F, 0x6D));
#else
  HWY_ASSERT_EQ(1.0f,
                TestEndianCreateValueFromBytes<float>(0x00, 0x00, 0x80, 0x3F));
  HWY_ASSERT_EQ(15922433.0f,
                TestEndianCreateValueFromBytes<float>(0x01, 0xF5, 0x72, 0x4B));
  HWY_ASSERT_EQ(-12357485.0f,
                TestEndianCreateValueFromBytes<float>(0x6D, 0x8F, 0x3C, 0xCB));
#endif

#if HWY_HAVE_FLOAT64
#if HWY_IS_BIG_ENDIAN
  HWY_ASSERT_EQ(1.0, TestEndianCreateValueFromBytes<double>(
                         0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
  HWY_ASSERT_EQ(8707235690688195.0,
                TestEndianCreateValueFromBytes<double>(0x43, 0x3E, 0xEF, 0x2F,
                                                       0x4A, 0x51, 0xAE, 0xC3));
  HWY_ASSERT_EQ(-6815854340348452.0,
                TestEndianCreateValueFromBytes<double>(0xC3, 0x38, 0x36, 0xFB,
                                                       0xC0, 0xCC, 0x1A, 0x24));
#else
  HWY_ASSERT_EQ(1.0, TestEndianCreateValueFromBytes<double>(
                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F));
  HWY_ASSERT_EQ(8707235690688195.0,
                TestEndianCreateValueFromBytes<double>(0xC3, 0xAE, 0x51, 0x4A,
                                                       0x2F, 0xEF, 0x3E, 0x43));
  HWY_ASSERT_EQ(-6815854340348452.0,
                TestEndianCreateValueFromBytes<double>(0x24, 0x1A, 0xCC, 0xC0,
                                                       0xFB, 0x36, 0x38, 0xC3));
#endif  // HWY_IS_BIG_ENDIAN
#endif  // HWY_HAVE_FLOAT64

#if HWY_IS_BIG_ENDIAN
  HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(1.0f),
                BitCastScalar<bfloat16_t>(
                    TestEndianCreateValueFromBytes<uint16_t>(0x3F, 0x80)));
  HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(0.333984375f),
                BitCastScalar<bfloat16_t>(
                    TestEndianCreateValueFromBytes<uint16_t>(0x3E, 0xAB)));
  HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(167121905303526337111381770240.0f),
                BitCastScalar<bfloat16_t>(
                    TestEndianCreateValueFromBytes<uint16_t>(0x70, 0x07)));
#else
  HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(1.0f),
                BitCastScalar<bfloat16_t>(
                    TestEndianCreateValueFromBytes<uint16_t>(0x80, 0x3F)));
  HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(0.333984375f),
                BitCastScalar<bfloat16_t>(
                    TestEndianCreateValueFromBytes<uint16_t>(0xAB, 0x3E)));
  HWY_ASSERT_EQ(ConvertScalarTo<bfloat16_t>(167121905303526337111381770240.0f),
                BitCastScalar<bfloat16_t>(
                    TestEndianCreateValueFromBytes<uint16_t>(0x07, 0x70)));
#endif
}

struct TestSpecialFloat {
  template <class T>
  static constexpr bool EnableSpecialFloatArithOpTest() {
    return (hwy::IsSame<T, float16_t>() && HWY_HAVE_SCALAR_F16_OPERATORS) ||
           (hwy::IsSame<T, bfloat16_t>() && HWY_HAVE_SCALAR_BF16_OPERATORS);
  }

  template <class T>
  static constexpr HWY_INLINE T EnsureNotNativeSpecialFloat(T&& val) {
#if HWY_HAVE_SCALAR_F16_TYPE
    static_assert(!hwy::IsSame<RemoveCvRef<T>, float16_t::Native>(),
                  "The operator must not return a float16_t::Native");
#endif
#if HWY_HAVE_SCALAR_BF16_TYPE
    static_assert(!hwy::IsSame<RemoveCvRef<T>, bfloat16_t::Native>(),
                  "The operator must not return a bfloat16_t::Native");
#endif
    return static_cast<T&&>(val);
  }

  template <class T>
  static HWY_INLINE void AssertSpecialFloatOpResultInRange(float min_expected,
                                                           float max_expected,
                                                           T actual,
                                                           const char* filename,
                                                           const int line) {
    if (!(actual >= min_expected && actual <= max_expected)) {
      hwy::Abort(
          filename, line,
          "mismatch: value was expected to be between %g and %g, got %g\n",
          static_cast<double>(min_expected), static_cast<double>(max_expected),
          ConvertScalarTo<double>(actual));
    }
  }

  template <class T,
            hwy::EnableIf<EnableSpecialFloatArithOpTest<T>()>* = nullptr>
  static HWY_NOINLINE void TestSpecialFloatArithOperators(T /*unused*/) {
#if HWY_HAVE_SCALAR_F16_OPERATORS || HWY_HAVE_SCALAR_BF16_OPERATORS
    AssertSpecialFloatOpResultInRange(
        -0.008422852f, -0.008361816f,
        EnsureNotNativeSpecialFloat(static_cast<T>(-0.008911133f) +
                                    static_cast<T>(5.264282E-4f)),
        __FILE__, __LINE__);
    AssertSpecialFloatOpResultInRange(
        0.44335937f, 0.4453125f,
        EnsureNotNativeSpecialFloat(static_cast<T>(-0.0014266968f) +
                                    0.4453125f),
        __FILE__, __LINE__);
    AssertSpecialFloatOpResultInRange(
        39.25f, 39.5f,
        EnsureNotNativeSpecialFloat(34.25f + static_cast<T>(5.0625f)), __FILE__,
        __LINE__);

    AssertSpecialFloatOpResultInRange(
        7456.0f, 7488.0f,
        EnsureNotNativeSpecialFloat(static_cast<T>(0.29101562f) -
                                    static_cast<T>(-7456.0f)),
        __FILE__, __LINE__);
    AssertSpecialFloatOpResultInRange(
        -2.21875f, -2.203125f,
        EnsureNotNativeSpecialFloat(static_cast<T>(1.66893E-4f) - 2.21875f),
        __FILE__, __LINE__);
    AssertSpecialFloatOpResultInRange(
        0.32421875f, 0.32617188f,
        EnsureNotNativeSpecialFloat(0.35351562f - static_cast<T>(0.028198242f)),
        __FILE__, __LINE__);

    AssertSpecialFloatOpResultInRange(
        -0.01135254f, -0.011291503f,
        EnsureNotNativeSpecialFloat(static_cast<T>(2.109375f) *
                                    static_cast<T>(-0.0053710938f)),
        __FILE__, __LINE__);
    AssertSpecialFloatOpResultInRange(
        2.359375f, 2.375f,
        EnsureNotNativeSpecialFloat(static_cast<T>(0.0019454956f) * 1216.0f),
        __FILE__, __LINE__);
    AssertSpecialFloatOpResultInRange(
        -1.1014938E-4f, 3.453125f,
        EnsureNotNativeSpecialFloat(-0.00038146973f *
                                    static_cast<T>(-0.00037956237f)),
        __FILE__, __LINE__);

    AssertSpecialFloatOpResultInRange(
        -27.875f, -27.75f,
        EnsureNotNativeSpecialFloat(static_cast<T>(-56.5f) /
                                    static_cast<T>(2.03125f)),
        __FILE__, __LINE__);
    AssertSpecialFloatOpResultInRange(
        0.033203125f, 0.033447266f,
        EnsureNotNativeSpecialFloat(static_cast<T>(470.0f) / 14080.0f),
        __FILE__, __LINE__);
    AssertSpecialFloatOpResultInRange(
        0.51953125f, 0.5234375f,
        EnsureNotNativeSpecialFloat(0.26367188f / static_cast<T>(0.50390625f)),
        __FILE__, __LINE__);

    T incr_assign_result_1 = static_cast<T>(1.373291E-4f);
    EnsureNotNativeSpecialFloat(incr_assign_result_1 +=
                                static_cast<T>(-20.375f));
    AssertSpecialFloatOpResultInRange(-20.375f, -20.25f, incr_assign_result_1,
                                      __FILE__, __LINE__);

    T incr_assign_result_2 = static_cast<T>(2.1457672E-4f);
    EnsureNotNativeSpecialFloat(incr_assign_result_2 += static_cast<int8_t>(7));
    AssertSpecialFloatOpResultInRange(7.0f, 7.03125f, incr_assign_result_2,
                                      __FILE__, __LINE__);

    T decr_assign_result_1 = static_cast<T>(4.4059753E-4f);
    EnsureNotNativeSpecialFloat(decr_assign_result_1 -=
                                static_cast<T>(6880.0f));
    AssertSpecialFloatOpResultInRange(-6880, -6848, decr_assign_result_1,
                                      __FILE__, __LINE__);

    T decr_assign_result_2 = static_cast<T>(85.5f);
    EnsureNotNativeSpecialFloat(decr_assign_result_2 -= static_cast<int8_t>(5));
    AssertSpecialFloatOpResultInRange(80.5f, 80.5f, decr_assign_result_2,
                                      __FILE__, __LINE__);

    T mul_assign_result_1 = static_cast<T>(15680.0f);
    EnsureNotNativeSpecialFloat(mul_assign_result_1 *=
                                static_cast<T>(0.001373291f));
    AssertSpecialFloatOpResultInRange(21.5f, 21.625f, mul_assign_result_1,
                                      __FILE__, __LINE__);

    T mul_assign_result_2 = static_cast<T>(2.609375f);
    EnsureNotNativeSpecialFloat(mul_assign_result_2 *= static_cast<int8_t>(7));
    AssertSpecialFloatOpResultInRange(18.25, 18.375, mul_assign_result_2,
                                      __FILE__, __LINE__);

    T div_assign_result_1 = static_cast<T>(11584.0f);
    EnsureNotNativeSpecialFloat(div_assign_result_1 /= static_cast<T>(9.5625f));
    AssertSpecialFloatOpResultInRange(1208.0f, 1216.0f, div_assign_result_1,
                                      __FILE__, __LINE__);

    T div_assign_result_2 = static_cast<T>(0.12109375f);
    EnsureNotNativeSpecialFloat(div_assign_result_2 /= static_cast<int8_t>(3));
    AssertSpecialFloatOpResultInRange(0.040283203f, 0.040527344f,
                                      div_assign_result_2, __FILE__, __LINE__);

    HWY_ASSERT_EQ(static_cast<T>(-1.0f),
                  EnsureNotNativeSpecialFloat(-static_cast<T>(1.0f)));
    HWY_ASSERT_EQ(static_cast<T>(1.0f),
                  EnsureNotNativeSpecialFloat(+static_cast<T>(1.0f)));

    T pre_incr_result_1 = static_cast<T>(1.0f);
    T pre_incr_result_2 = EnsureNotNativeSpecialFloat(++pre_incr_result_1);
    HWY_ASSERT_EQ(static_cast<T>(2.0f), pre_incr_result_1);
    HWY_ASSERT_EQ(static_cast<T>(2.0f), pre_incr_result_2);

    T post_incr_result_1 = static_cast<T>(5.0f);
    T post_incr_result_2 = EnsureNotNativeSpecialFloat(post_incr_result_1++);
    HWY_ASSERT_EQ(static_cast<T>(6.0f), post_incr_result_1);
    HWY_ASSERT_EQ(static_cast<T>(5.0f), post_incr_result_2);

    T pre_decr_result_1 = static_cast<T>(-2.0f);
    T pre_decr_result_2 = EnsureNotNativeSpecialFloat(--pre_decr_result_1);
    HWY_ASSERT_EQ(static_cast<T>(-3.0f), pre_decr_result_1);
    HWY_ASSERT_EQ(static_cast<T>(-3.0f), pre_decr_result_2);

    T post_decr_result_1 = static_cast<T>(-7.0f);
    T post_decr_result_2 = EnsureNotNativeSpecialFloat(post_decr_result_1--);
    HWY_ASSERT_EQ(static_cast<T>(-8.0f), post_decr_result_1);
    HWY_ASSERT_EQ(static_cast<T>(-7.0f), post_decr_result_2);

    HWY_ASSERT(static_cast<T>(1.0f) == 1.0f);
    HWY_ASSERT(static_cast<T>(-2.40625f) != 0.0033416748f);
    HWY_ASSERT(static_cast<T>(-3248.0f) < 0.0018997193f);
    HWY_ASSERT(static_cast<T>(-27904.0f) <= -3.859375f);
    HWY_ASSERT(static_cast<T>(1.078125f) > 0.010009765f);
    HWY_ASSERT(static_cast<T>(45312.0f) >= 0.00024318695f);

    HWY_ASSERT(2.0f == static_cast<T>(2.0f));
    HWY_ASSERT(-5.78125f != static_cast<T>(-15168.0f));
    HWY_ASSERT(-0.056884766f < static_cast<T>(0.000088214875f));
    HWY_ASSERT(0.00008392333f <= static_cast<T>(1384.0f));
    HWY_ASSERT(21888.0f > static_cast<T>(-2.578125f));
    HWY_ASSERT(0.087402344 >= static_cast<T>(-0.65625f));
#endif  // HWY_HAVE_SCALAR_F16_OPERATORS || HWY_HAVE_SCALAR_BF16_OPERATORS
  }

  template <class T,
            hwy::EnableIf<!EnableSpecialFloatArithOpTest<T>()>* = nullptr>
  static HWY_INLINE void TestSpecialFloatArithOperators(T /*unused*/) {}

  template <class T>
  HWY_NOINLINE void operator()(T /*unused*/) const {
    static_assert(IsSpecialFloat<T>(), "IsSpecialFloat() must be true");

    HWY_ASSERT_EQ(static_cast<uint32_t>(0x436B0000u),
                  BitCastScalar<uint32_t>(ConvertScalarTo<float>(
                      BitCastScalar<T>(static_cast<uint16_t>(
                          IsSame<T, hwy::float16_t>() ? 0x5B58u : 0x436Bu)))));
    HWY_ASSERT_EQ(static_cast<uint32_t>(0xBB790000u),
                  BitCastScalar<uint32_t>(ConvertScalarTo<float>(
                      BitCastScalar<T>(static_cast<uint16_t>(
                          IsSame<T, hwy::float16_t>() ? 0x9BC8u : 0xBB79u)))));

    HWY_ASSERT_EQ(static_cast<uint32_t>(
                      IsSame<T, hwy::float16_t>() ? 0xC0B86000u : 0xC5C30000u),
                  BitCastScalar<uint32_t>(ConvertScalarTo<float>(
                      BitCastScalar<T>(static_cast<uint16_t>(0xC5C3u)))));
    HWY_ASSERT_EQ(static_cast<uint32_t>(
                      IsSame<T, hwy::float16_t>() ? 0x41D20000u : 0x4E900000u),
                  BitCastScalar<uint32_t>(ConvertScalarTo<float>(
                      BitCastScalar<T>(static_cast<uint16_t>(0x4E90u)))));

    HWY_ASSERT_EQ(1696.0, ConvertScalarTo<double>(ConvertScalarTo<T>(1696.0f)));
    HWY_ASSERT_EQ(
        -0.00177001953125f,
        ConvertScalarTo<float>(ConvertScalarTo<T>(-0.00177001953125f)));

    HWY_ASSERT_EQ(0.49609375f,
                  ConvertScalarTo<float>(ConvertScalarTo<T>(0.49609375)));
    HWY_ASSERT_EQ(
        0.000553131103515625,
        ConvertScalarTo<double>(ConvertScalarTo<T>(0.000553131103515625)));

    HWY_ASSERT_EQ(ConvertScalarTo<T>(3.0f), ConvertScalarTo<T>(3));
    HWY_ASSERT_EQ(ConvertScalarTo<T>(-5.5f), ConvertScalarTo<T>(-5.5));
    HWY_ASSERT_EQ(ConvertScalarTo<T>(0.82421875f),
                  ConvertScalarTo<T>(BF16FromF32(0.82421875f)));
    HWY_ASSERT_EQ(ConvertScalarTo<T>(-6.375f),
                  ConvertScalarTo<T>(F16FromF32(-6.375f)));

    HWY_ASSERT(ConvertScalarTo<T>(-3.671875f) <
               ConvertScalarTo<T>(0.0218505859375f));
    HWY_ASSERT(ConvertScalarTo<T>(-0.033447265625f) <=
               ConvertScalarTo<T>(8.249282836914062E-5f));
    HWY_ASSERT(ConvertScalarTo<T>(23296.0f) > ConvertScalarTo<T>(192.0f));
    HWY_ASSERT(ConvertScalarTo<T>(41984.0f) >= ConvertScalarTo<T>(370.0f));

    TestSpecialFloatArithOperators(T());
  }
};

HWY_NOINLINE void TestAllSpecialFloat() {
  TestSpecialFloat test;
  test(float16_t());
  test(bfloat16_t());
}

// NOLINTNEXTLINE(google-readability-namespace-comments)
}  // namespace HWY_NAMESPACE
}  // namespace hwy
HWY_AFTER_NAMESPACE();

#if HWY_ONCE

namespace hwy {
HWY_BEFORE_TEST(BaseTest);
HWY_EXPORT_AND_TEST_P(BaseTest, TestAllLimits);
HWY_EXPORT_AND_TEST_P(BaseTest, TestAllLowestHighest);
HWY_EXPORT_AND_TEST_P(BaseTest, TestAllType);
HWY_EXPORT_AND_TEST_P(BaseTest, TestAllIsSame);
HWY_EXPORT_AND_TEST_P(BaseTest, TestAllBitScan);
HWY_EXPORT_AND_TEST_P(BaseTest, TestAllPopCount);
HWY_EXPORT_AND_TEST_P(BaseTest, TestAllEndian);
HWY_EXPORT_AND_TEST_P(BaseTest, TestAllSpecialFloat);
}  // namespace hwy

#endif

Messung V0.5
C=93 H=96 G=94

¤ Dauer der Verarbeitung: 0.7 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge