1//===----------------------------------------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9// REQUIRES: std-at-least-c++26
10
11// The test uses "Placeholder variables with no name"
12// UNSUPPORTED: apple-clang-15, apple-clang-16
13
14// <numeric>
15
16// template<class T>
17// constexpr T add_sat(T x, T y) noexcept; // freestanding
18
19#include <cassert>
20#include <concepts>
21#include <limits>
22#include <numeric>
23
24#include "test_macros.h"
25
26template <typename IntegerT>
27constexpr bool test_signed() {
28 constexpr auto minVal = std::numeric_limits<IntegerT>::min();
29 constexpr auto maxVal = std::numeric_limits<IntegerT>::max();
30
31 std::same_as<IntegerT> decltype(auto) _ = std::add_sat(minVal, maxVal);
32
33 static_assert(noexcept(std::add_sat(minVal, maxVal)));
34
35 // clang-format off
36
37 // Limit values (-1, 0, 1, min, max)
38
39 assert(std::add_sat(IntegerT{-1}, IntegerT{-1}) == IntegerT{-2});
40 assert(std::add_sat(IntegerT{-1}, IntegerT{ 0}) == IntegerT{-1});
41 assert(std::add_sat(IntegerT{-1}, IntegerT{ 1}) == IntegerT{ 0});
42 assert(std::add_sat(IntegerT{-1}, minVal) == minVal); // saturated
43 assert(std::add_sat(IntegerT{-1}, maxVal) == IntegerT{-1} + maxVal);
44
45 assert(std::add_sat(IntegerT{ 0}, IntegerT{-1}) == IntegerT{-1});
46 assert(std::add_sat(IntegerT{ 0}, IntegerT{ 0}) == IntegerT{ 0});
47 assert(std::add_sat(IntegerT{ 0}, IntegerT{ 1}) == IntegerT{ 1});
48 assert(std::add_sat(IntegerT{ 0}, minVal) == minVal);
49 assert(std::add_sat(IntegerT{ 0}, maxVal) == maxVal);
50
51 assert(std::add_sat(IntegerT{ 1}, IntegerT{-1}) == IntegerT{ 0});
52 assert(std::add_sat(IntegerT{ 1}, IntegerT{ 0}) == IntegerT{ 1});
53 assert(std::add_sat(IntegerT{ 1}, IntegerT{ 1}) == IntegerT{ 2});
54 assert(std::add_sat(IntegerT{ 1}, minVal) == IntegerT{ 1} + minVal);
55 assert(std::add_sat(IntegerT{ 1}, maxVal) == maxVal); // saturated
56
57 assert(std::add_sat( minVal, IntegerT{-1}) == minVal); // saturated
58 assert(std::add_sat( minVal, IntegerT{ 0}) == minVal);
59 assert(std::add_sat( minVal, IntegerT{ 1}) == minVal + IntegerT{ 1});
60 assert(std::add_sat( minVal, minVal) == minVal); // saturated
61 assert(std::add_sat( minVal, maxVal) == IntegerT{-1});
62
63 assert(std::add_sat( maxVal, IntegerT{-1}) == maxVal + IntegerT{-1});
64 assert(std::add_sat( maxVal, IntegerT{ 0}) == maxVal);
65 assert(std::add_sat( maxVal, IntegerT{ 1}) == maxVal); // saturated
66 assert(std::add_sat( maxVal, minVal) == IntegerT{-1});
67 assert(std::add_sat( maxVal, maxVal) == maxVal); // saturated
68
69 // No saturation (no limit values)
70
71 assert(std::add_sat(IntegerT{-27}, IntegerT{28})== IntegerT{ 1});
72 assert(std::add_sat(IntegerT{ 27}, IntegerT{28})== IntegerT{55});
73 {
74 constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27};
75 constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28};
76 assert(std::add_sat(x, y) == maxVal);
77 }
78
79 // Saturation (no limit values)
80
81 {
82 constexpr IntegerT x = minVal / IntegerT{2} + IntegerT{-27};
83 constexpr IntegerT y = minVal / IntegerT{2} + IntegerT{-28};
84 assert(std::add_sat(x, y) == minVal); // saturated
85 }
86 {
87 constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27};
88 constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28};
89 assert(std::add_sat(x, y) == maxVal); // saturated
90 }
91
92 // clang-format on
93
94 return true;
95}
96
97template <typename IntegerT>
98constexpr bool test_unsigned() {
99 constexpr auto minVal = std::numeric_limits<IntegerT>::min();
100 constexpr auto maxVal = std::numeric_limits<IntegerT>::max();
101
102 std::same_as<IntegerT> decltype(auto) _ = std::add_sat(minVal, maxVal);
103
104 static_assert(noexcept(std::add_sat(minVal, maxVal)));
105
106 // clang-format off
107
108 // Litmit values (0, 1, min, max)
109
110 assert(std::add_sat(IntegerT{0}, IntegerT{0}) == IntegerT{0});
111 assert(std::add_sat(IntegerT{0}, IntegerT{1}) == IntegerT{1});
112 assert(std::add_sat(IntegerT{0}, minVal) == IntegerT{0});
113 assert(std::add_sat(IntegerT{0}, maxVal) == maxVal);
114 assert(std::add_sat(IntegerT{1}, IntegerT{0}) == IntegerT{1});
115 assert(std::add_sat(IntegerT{1}, IntegerT{1}) == IntegerT{2});
116 assert(std::add_sat(IntegerT{1}, minVal) == IntegerT{1});
117 assert(std::add_sat(IntegerT{1}, maxVal) == maxVal); // saturated
118 assert(std::add_sat( minVal, IntegerT{0}) == IntegerT{0});
119 assert(std::add_sat( minVal, IntegerT{1}) == IntegerT{1});
120 assert(std::add_sat( minVal, minVal) == minVal);
121 assert(std::add_sat( minVal, maxVal) == maxVal);
122 assert(std::add_sat( maxVal, IntegerT{0}) == maxVal);
123 assert(std::add_sat( maxVal, IntegerT{1}) == maxVal); // saturated
124 assert(std::add_sat( maxVal, minVal) == maxVal);
125 assert(std::add_sat( maxVal, maxVal) == maxVal); // saturated
126
127 // No saturation (no limit values)
128
129 assert(std::add_sat(IntegerT{27}, IntegerT{28}) == IntegerT{55});
130
131 // Saturation (no limit values)
132
133 {
134 constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27};
135 constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28};
136 assert(std::add_sat( x, y) == maxVal); // saturated
137 assert(std::add_sat( x, maxVal) == maxVal); // saturated
138 assert(std::add_sat(maxVal, y) == maxVal); // saturated
139 }
140
141 // clang-format on
142
143 return true;
144}
145
146constexpr bool test() {
147 // Signed
148 test_signed<signed char>();
149 test_signed<short int>();
150 test_signed<int>();
151 test_signed<long int>();
152 test_signed<long long int>();
153#ifndef TEST_HAS_NO_INT128
154 test_signed<__int128_t>();
155#endif
156 // Unsigned
157 test_unsigned<unsigned char>();
158 test_unsigned<unsigned short int>();
159 test_unsigned<unsigned int>();
160 test_unsigned<unsigned long int>();
161 test_unsigned<unsigned long long int>();
162#ifndef TEST_HAS_NO_INT128
163 test_unsigned<__uint128_t>();
164#endif
165
166 return true;
167}
168
169int main(int, char**) {
170 test();
171 static_assert(test());
172
173 return 0;
174}
175

source code of libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.pass.cpp