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
14 // constexpr T add_sat(T x, T y) noexcept; // freestanding
21 #include "test_macros.h"
23 template <typename IntegerT
>
24 constexpr bool test_signed() {
25 constexpr auto minVal
= std::numeric_limits
<IntegerT
>::min();
26 constexpr auto maxVal
= std::numeric_limits
<IntegerT
>::max();
28 // TODO(LLVM-20) remove [[maybe_unused]] since all supported compilers support "Placeholder variables with no name"
29 [[maybe_unused
]] std::same_as
<IntegerT
> decltype(auto) _
= std::add_sat(minVal
, maxVal
);
31 static_assert(noexcept(std::add_sat(minVal
, maxVal
)));
35 // Limit values (-1, 0, 1, min, max)
37 assert(std::add_sat(IntegerT
{-1}, IntegerT
{-1}) == IntegerT
{-2});
38 assert(std::add_sat(IntegerT
{-1}, IntegerT
{ 0}) == IntegerT
{-1});
39 assert(std::add_sat(IntegerT
{-1}, IntegerT
{ 1}) == IntegerT
{ 0});
40 assert(std::add_sat(IntegerT
{-1}, minVal
) == minVal
); // saturated
41 assert(std::add_sat(IntegerT
{-1}, maxVal
) == IntegerT
{-1} + maxVal
);
43 assert(std::add_sat(IntegerT
{ 0}, IntegerT
{-1}) == IntegerT
{-1});
44 assert(std::add_sat(IntegerT
{ 0}, IntegerT
{ 0}) == IntegerT
{ 0});
45 assert(std::add_sat(IntegerT
{ 0}, IntegerT
{ 1}) == IntegerT
{ 1});
46 assert(std::add_sat(IntegerT
{ 0}, minVal
) == minVal
);
47 assert(std::add_sat(IntegerT
{ 0}, maxVal
) == maxVal
);
49 assert(std::add_sat(IntegerT
{ 1}, IntegerT
{-1}) == IntegerT
{ 0});
50 assert(std::add_sat(IntegerT
{ 1}, IntegerT
{ 0}) == IntegerT
{ 1});
51 assert(std::add_sat(IntegerT
{ 1}, IntegerT
{ 1}) == IntegerT
{ 2});
52 assert(std::add_sat(IntegerT
{ 1}, minVal
) == IntegerT
{ 1} + minVal
);
53 assert(std::add_sat(IntegerT
{ 1}, maxVal
) == maxVal
); // saturated
55 assert(std::add_sat( minVal
, IntegerT
{-1}) == minVal
); // saturated
56 assert(std::add_sat( minVal
, IntegerT
{ 0}) == minVal
);
57 assert(std::add_sat( minVal
, IntegerT
{ 1}) == minVal
+ IntegerT
{ 1});
58 assert(std::add_sat( minVal
, minVal
) == minVal
); // saturated
59 assert(std::add_sat( minVal
, maxVal
) == IntegerT
{-1});
61 assert(std::add_sat( maxVal
, IntegerT
{-1}) == maxVal
+ IntegerT
{-1});
62 assert(std::add_sat( maxVal
, IntegerT
{ 0}) == maxVal
);
63 assert(std::add_sat( maxVal
, IntegerT
{ 1}) == maxVal
); // saturated
64 assert(std::add_sat( maxVal
, minVal
) == IntegerT
{-1});
65 assert(std::add_sat( maxVal
, maxVal
) == maxVal
); // saturated
67 // No saturation (no limit values)
69 assert(std::add_sat(IntegerT
{-27}, IntegerT
{28})== IntegerT
{ 1});
70 assert(std::add_sat(IntegerT
{ 27}, IntegerT
{28})== IntegerT
{55});
72 constexpr IntegerT x
= maxVal
/ IntegerT
{2} + IntegerT
{27};
73 constexpr IntegerT y
= maxVal
/ IntegerT
{2} + IntegerT
{28};
74 assert(std::add_sat(x
, y
) == maxVal
);
77 // Saturation (no limit values)
80 constexpr IntegerT x
= minVal
/ IntegerT
{2} + IntegerT
{-27};
81 constexpr IntegerT y
= minVal
/ IntegerT
{2} + IntegerT
{-28};
82 assert(std::add_sat(x
, y
) == minVal
); // saturated
85 constexpr IntegerT x
= maxVal
/ IntegerT
{2} + IntegerT
{27};
86 constexpr IntegerT y
= maxVal
/ IntegerT
{2} + IntegerT
{28};
87 assert(std::add_sat(x
, y
) == maxVal
); // saturated
95 template <typename IntegerT
>
96 constexpr bool test_unsigned() {
97 constexpr auto minVal
= std::numeric_limits
<IntegerT
>::min();
98 constexpr auto maxVal
= std::numeric_limits
<IntegerT
>::max();
100 // TODO(LLVM-20) remove [[maybe_unused]] since all supported compilers support "Placeholder variables with no name"
101 [[maybe_unused
]] std::same_as
<IntegerT
> decltype(auto) _
= std::add_sat(minVal
, maxVal
);
103 static_assert(noexcept(std::add_sat(minVal
, maxVal
)));
107 // Litmit values (0, 1, min, max)
109 assert(std::add_sat(IntegerT
{0}, IntegerT
{0}) == IntegerT
{0});
110 assert(std::add_sat(IntegerT
{0}, IntegerT
{1}) == IntegerT
{1});
111 assert(std::add_sat(IntegerT
{0}, minVal
) == IntegerT
{0});
112 assert(std::add_sat(IntegerT
{0}, maxVal
) == maxVal
);
113 assert(std::add_sat(IntegerT
{1}, IntegerT
{0}) == IntegerT
{1});
114 assert(std::add_sat(IntegerT
{1}, IntegerT
{1}) == IntegerT
{2});
115 assert(std::add_sat(IntegerT
{1}, minVal
) == IntegerT
{1});
116 assert(std::add_sat(IntegerT
{1}, maxVal
) == maxVal
); // saturated
117 assert(std::add_sat( minVal
, IntegerT
{0}) == IntegerT
{0});
118 assert(std::add_sat( minVal
, IntegerT
{1}) == IntegerT
{1});
119 assert(std::add_sat( minVal
, minVal
) == minVal
);
120 assert(std::add_sat( minVal
, maxVal
) == maxVal
);
121 assert(std::add_sat( maxVal
, IntegerT
{0}) == maxVal
);
122 assert(std::add_sat( maxVal
, IntegerT
{1}) == maxVal
); // saturated
123 assert(std::add_sat( maxVal
, minVal
) == maxVal
);
124 assert(std::add_sat( maxVal
, maxVal
) == maxVal
); // saturated
126 // No saturation (no limit values)
128 assert(std::add_sat(IntegerT
{27}, IntegerT
{28}) == IntegerT
{55});
130 // Saturation (no limit values)
133 constexpr IntegerT x
= maxVal
/ IntegerT
{2} + IntegerT
{27};
134 constexpr IntegerT y
= maxVal
/ IntegerT
{2} + IntegerT
{28};
135 assert(std::add_sat( x
, y
) == maxVal
); // saturated
136 assert(std::add_sat( x
, maxVal
) == maxVal
); // saturated
137 assert(std::add_sat(maxVal
, y
) == maxVal
); // saturated
145 constexpr bool test() {
147 test_signed
<signed char>();
148 test_signed
<short int>();
150 test_signed
<long int>();
151 test_signed
<long long int>();
152 #ifndef TEST_HAS_NO_INT128
153 test_signed
<__int128_t
>();
156 test_unsigned
<unsigned char>();
157 test_unsigned
<unsigned short int>();
158 test_unsigned
<unsigned int>();
159 test_unsigned
<unsigned long int>();
160 test_unsigned
<unsigned long long int>();
161 #ifndef TEST_HAS_NO_INT128
162 test_unsigned
<__uint128_t
>();
168 int main(int, char**) {
170 static_assert(test());