1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10 // The test uses "Placeholder variables with no name"
15 // constexpr T sub_sat(T x, T y) noexcept; // freestanding
22 #include "test_macros.h"
24 template <typename IntegerT
>
25 constexpr bool test_signed() {
26 constexpr auto minVal
= std::numeric_limits
<IntegerT
>::min();
27 constexpr auto maxVal
= std::numeric_limits
<IntegerT
>::max();
29 // TODO(LLVM-20) remove [[maybe_unused]] since all supported compilers support "Placeholder variables with no name"
30 [[maybe_unused
]] std::same_as
<IntegerT
> decltype(auto) _
= std::sub_sat(minVal
, maxVal
);
32 static_assert(noexcept(std::sub_sat(minVal
, maxVal
)));
36 // Limit values (-1, 0, 1, min, max)
38 assert(std::sub_sat(IntegerT
{-1}, IntegerT
{-1}) == IntegerT
{ 0});
39 assert(std::sub_sat(IntegerT
{-1}, IntegerT
{ 0}) == IntegerT
{-1});
40 assert(std::sub_sat(IntegerT
{-1}, IntegerT
{ 1}) == IntegerT
{-2});
41 assert(std::sub_sat(IntegerT
{-1}, minVal
) == IntegerT
{-1} - minVal
);
42 assert(std::sub_sat(IntegerT
{-1}, maxVal
) == IntegerT
{-1} - maxVal
);
44 assert(std::sub_sat(IntegerT
{ 0}, IntegerT
{-1}) == IntegerT
{ 1});
45 assert(std::sub_sat(IntegerT
{ 0}, IntegerT
{ 0}) == IntegerT
{ 0});
46 assert(std::sub_sat(IntegerT
{ 0}, IntegerT
{ 1}) == IntegerT
{-1});
47 assert(std::sub_sat(IntegerT
{ 0}, minVal
) == maxVal
); // saturated
48 assert(std::sub_sat(IntegerT
{ 0}, maxVal
) == -maxVal
);
50 assert(std::sub_sat( minVal
, IntegerT
{-1}) == minVal
- IntegerT
{-1});
51 assert(std::sub_sat( minVal
, IntegerT
{ 0}) == minVal
);
52 assert(std::sub_sat( minVal
, IntegerT
{ 1}) == minVal
); // saturated
53 assert(std::sub_sat( minVal
, minVal
) == IntegerT
{0});
54 assert(std::sub_sat( minVal
, maxVal
) == minVal
); // saturated
56 assert(std::sub_sat( maxVal
, IntegerT
{-1}) == maxVal
); // saturated
57 assert(std::sub_sat( maxVal
, IntegerT
{ 0}) == maxVal
);
58 assert(std::sub_sat( maxVal
, IntegerT
{ 1}) == maxVal
- IntegerT
{ 1});
59 assert(std::sub_sat( maxVal
, minVal
) == maxVal
); // saturated
60 assert(std::sub_sat( maxVal
, maxVal
) == IntegerT
{0});
62 // No saturation (no limit values)
64 assert(std::sub_sat(IntegerT
{ 27}, IntegerT
{-28}) == 55);
65 assert(std::sub_sat(IntegerT
{ 27}, IntegerT
{ 28}) == -1);
66 assert(std::sub_sat(IntegerT
{-27}, IntegerT
{ 28}) == -55);
67 assert(std::sub_sat(IntegerT
{-27}, IntegerT
{-28}) == 1);
69 // Saturation (no limit values)
72 constexpr IntegerT lesserVal
= minVal
/ IntegerT
{2} + IntegerT
{27};
73 constexpr IntegerT biggerVal
= maxVal
/ IntegerT
{2} + IntegerT
{28};
74 assert(std::sub_sat(lesserVal
, biggerVal
) == minVal
); // saturated
77 constexpr IntegerT biggerVal
= maxVal
/ IntegerT
{2} + IntegerT
{28};
78 constexpr IntegerT lesserVal
= minVal
/ IntegerT
{2} + IntegerT
{27};
79 assert(std::sub_sat(biggerVal
, lesserVal
) == maxVal
); // saturated
87 template <typename IntegerT
>
88 constexpr bool test_unsigned() {
89 constexpr auto minVal
= std::numeric_limits
<IntegerT
>::min();
90 constexpr auto maxVal
= std::numeric_limits
<IntegerT
>::max();
92 // TODO(LLVM-20) remove [[maybe_unused]] since all supported compilers support "Placeholder variables with no name"
93 [[maybe_unused
]] std::same_as
<IntegerT
> decltype(auto) _
= std::sub_sat(minVal
, maxVal
);
95 static_assert(noexcept(std::sub_sat(minVal
, maxVal
)));
99 // Limit values (0, 1, min, max)
101 assert(std::sub_sat(IntegerT
{0}, IntegerT
{0}) == IntegerT
{0});
102 assert(std::sub_sat(IntegerT
{0}, IntegerT
{1}) == minVal
); // saturated
103 assert(std::sub_sat(IntegerT
{0}, minVal
) == minVal
);
104 assert(std::sub_sat(IntegerT
{0}, maxVal
) == minVal
); // saturated
106 assert(std::sub_sat(IntegerT
{1}, IntegerT
{0}) == IntegerT
{1});
107 assert(std::sub_sat(IntegerT
{1}, IntegerT
{1}) == IntegerT
{0});
108 assert(std::sub_sat(IntegerT
{1}, minVal
) == IntegerT
{1});
109 assert(std::sub_sat(IntegerT
{1}, maxVal
) == minVal
); // saturated
111 assert(std::sub_sat( minVal
, IntegerT
{0}) == IntegerT
{0});
112 assert(std::sub_sat( minVal
, IntegerT
{1}) == minVal
);
113 assert(std::sub_sat( minVal
, maxVal
) == minVal
);
114 assert(std::sub_sat( minVal
, maxVal
) == minVal
);
116 assert(std::sub_sat( maxVal
, IntegerT
{0}) == maxVal
);
117 assert(std::sub_sat( maxVal
, IntegerT
{1}) == maxVal
- IntegerT
{1});
118 assert(std::sub_sat( maxVal
, minVal
) == maxVal
);
119 assert(std::sub_sat( maxVal
, maxVal
) == IntegerT
{0});
121 // Saturation (no limit values)
124 constexpr IntegerT lesserVal
= minVal
/ IntegerT
{2} + IntegerT
{27};
125 constexpr IntegerT biggerVal
= maxVal
/ IntegerT
{2} + IntegerT
{28};
126 assert(std::sub_sat(lesserVal
, biggerVal
) == minVal
); // saturated
134 constexpr bool test() {
136 test_signed
<signed char>();
137 test_signed
<short int>();
139 test_signed
<long int>();
140 test_signed
<long long int>();
141 #ifndef TEST_HAS_NO_INT128
142 test_signed
<__int128_t
>();
145 test_unsigned
<unsigned char>();
146 test_unsigned
<unsigned short int>();
147 test_unsigned
<unsigned int>();
148 test_unsigned
<unsigned long int>();
149 test_unsigned
<unsigned long long int>();
150 #ifndef TEST_HAS_NO_INT128
151 test_unsigned
<__uint128_t
>();
157 int main(int, char**) {
159 static_assert(test());