| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // UNSUPPORTED: c++03, c++11, c++14, c++17 |
| |
| // <utility> |
| |
| // cmp_equal, cmp_not_equal, cmp_less, cmp_less_equal, cmp_greater, |
| // cmp_greater_equal, in_range applied to _BitInt(N). Widths span the int, |
| // long long, and __int128 size boundaries for same-sign, mixed-sign, and |
| // in_range checks. |
| |
| #include <cassert> |
| #include <limits> |
| #include <utility> |
| |
| #include "test_macros.h" |
| |
| #if TEST_HAS_BITINT |
| |
| template <class T, class U> |
| constexpr bool test_same_sign() { |
| // Same signedness: trivial equality/ordering. |
| static_assert(std::cmp_equal(T(0), U(0))); |
| static_assert(std::cmp_equal(T(42), U(42))); |
| static_assert(!std::cmp_equal(T(0), U(1))); |
| static_assert(std::cmp_less(T(0), U(1))); |
| static_assert(!std::cmp_less(T(1), U(0))); |
| static_assert(std::cmp_less_equal(T(1), U(1))); |
| static_assert(std::cmp_greater_equal(T(1), U(1))); |
| static_assert(std::cmp_not_equal(T(0), U(1))); |
| return true; |
| } |
| |
| template <class S, class U> |
| constexpr bool test_mixed_sign() { |
| // Signed vs unsigned of the SAME width: negative signed values must |
| // compare less than any unsigned value, regardless of the promotion |
| // branch chosen. |
| constexpr auto s_min = std::numeric_limits<S>::min(); |
| constexpr auto u_max = std::numeric_limits<U>::max(); |
| |
| static_assert(std::cmp_less(S(-1), U(0))); |
| static_assert(!std::cmp_equal(S(-1), U(-1))); // U(-1) wraps to u_max |
| static_assert(std::cmp_less(s_min, U(0))); |
| static_assert(std::cmp_greater(u_max, S(0))); |
| static_assert(std::cmp_greater(u_max, s_min)); |
| static_assert(std::cmp_less_equal(S(-1), U(0))); |
| static_assert(std::cmp_greater_equal(U(0), S(-1))); |
| |
| // Equal-value mixed-sign: a non-negative signed value must compare |
| // equal to the corresponding unsigned value. |
| static_assert(std::cmp_equal(S(7), U(7))); |
| static_assert(std::cmp_equal(U(7), S(7))); |
| return true; |
| } |
| |
| template <class S, class U> |
| constexpr bool test_in_range() { |
| // in_range relies on numeric_limits<_Tp>::min/max, which requires |
| // the digits10 fix (#193002) to be correct for odd _BitInt widths. |
| |
| // Signed target: value in range. |
| static_assert(std::in_range<S>(S(0))); |
| static_assert(std::in_range<S>(std::numeric_limits<S>::max())); |
| static_assert(std::in_range<S>(std::numeric_limits<S>::min())); |
| // Signed target: value out of range via a wider unsigned source. |
| static_assert(!std::in_range<S>(std::numeric_limits<U>::max())); |
| // Unsigned target: negative signed value is out of range. |
| static_assert(!std::in_range<U>(S(-1))); |
| // Unsigned target: zero is in range. |
| static_assert(std::in_range<U>(S(0))); |
| static_assert(std::in_range<U>(std::numeric_limits<U>::max())); |
| return true; |
| } |
| |
| constexpr bool test() { |
| // sizeof <= sizeof(int). |
| test_same_sign<_BitInt(7), _BitInt(7)>(); |
| test_same_sign<unsigned _BitInt(7), unsigned _BitInt(7)>(); |
| test_same_sign<_BitInt(13), _BitInt(13)>(); |
| test_mixed_sign<_BitInt(7), unsigned _BitInt(7)>(); |
| test_mixed_sign<_BitInt(13), unsigned _BitInt(13)>(); |
| test_in_range<_BitInt(7), unsigned _BitInt(7)>(); |
| test_in_range<_BitInt(13), unsigned _BitInt(13)>(); |
| |
| // signed _BitInt(32) fits in int; unsigned _BitInt(32) does not. |
| test_same_sign<_BitInt(32), _BitInt(32)>(); |
| test_same_sign<unsigned _BitInt(32), unsigned _BitInt(32)>(); |
| test_mixed_sign<_BitInt(32), unsigned _BitInt(32)>(); |
| test_in_range<_BitInt(32), unsigned _BitInt(32)>(); |
| |
| // sizeof <= sizeof(long long). |
| test_same_sign<_BitInt(33), _BitInt(33)>(); |
| test_same_sign<_BitInt(63), _BitInt(63)>(); |
| test_same_sign<unsigned _BitInt(63), unsigned _BitInt(63)>(); |
| test_mixed_sign<_BitInt(33), unsigned _BitInt(33)>(); |
| test_mixed_sign<_BitInt(63), unsigned _BitInt(63)>(); |
| test_in_range<_BitInt(33), unsigned _BitInt(33)>(); |
| test_in_range<_BitInt(63), unsigned _BitInt(63)>(); |
| |
| // signed _BitInt(64) fits in long long; unsigned _BitInt(64) does not. |
| test_same_sign<_BitInt(64), _BitInt(64)>(); |
| test_same_sign<unsigned _BitInt(64), unsigned _BitInt(64)>(); |
| test_mixed_sign<_BitInt(64), unsigned _BitInt(64)>(); |
| test_in_range<_BitInt(64), unsigned _BitInt(64)>(); |
| |
| # if __BITINT_MAXWIDTH__ >= 128 |
| // sizeof > sizeof(long long). |
| test_same_sign<_BitInt(65), _BitInt(65)>(); |
| test_same_sign<_BitInt(128), _BitInt(128)>(); |
| test_same_sign<unsigned _BitInt(128), unsigned _BitInt(128)>(); |
| test_mixed_sign<_BitInt(65), unsigned _BitInt(65)>(); |
| test_mixed_sign<_BitInt(128), unsigned _BitInt(128)>(); |
| test_in_range<_BitInt(65), unsigned _BitInt(65)>(); |
| test_in_range<_BitInt(128), unsigned _BitInt(128)>(); |
| # endif |
| |
| # if __BITINT_MAXWIDTH__ >= 200 |
| // Beyond __int128: widths with no builtin integer mapping. |
| test_same_sign<_BitInt(200), _BitInt(200)>(); |
| test_same_sign<unsigned _BitInt(200), unsigned _BitInt(200)>(); |
| test_mixed_sign<_BitInt(200), unsigned _BitInt(200)>(); |
| test_in_range<_BitInt(200), unsigned _BitInt(200)>(); |
| # endif |
| |
| // Cross-width: narrow signed _BitInt vs wide unsigned builtin. |
| // Negative source must be reported as less than any non-negative target. |
| static_assert(std::cmp_less(_BitInt(7)(-1), 0ull)); |
| static_assert(std::cmp_less(_BitInt(13)(-1), 0u)); |
| static_assert(std::cmp_less(_BitInt(63)(-1), 0ull)); |
| // Cross-type round-trip equality. |
| static_assert(std::cmp_equal(_BitInt(13)(42), 42)); |
| static_assert(std::cmp_equal(42, _BitInt(13)(42))); |
| static_assert(std::cmp_equal(static_cast<unsigned _BitInt(13)>(42), 42u)); |
| |
| return true; |
| } |
| |
| #endif // TEST_HAS_BITINT |
| |
| int main(int, char**) { |
| #if TEST_HAS_BITINT |
| test(); |
| static_assert(test()); |
| #endif |
| return 0; |
| } |