xref: /llvm-project/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp (revision 6e6d266fb8cc1398e7d5a220a9332d88ce074464)
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 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10 
11 // <numeric>
12 
13 // template<class R, class T>
14 //   constexpr R saturate_cast(T x) noexcept;                     // freestanding
15 
16 #include <cassert>
17 #include <climits>
18 #include <concepts>
19 #include <limits>
20 #include <numeric>
21 
22 #include "test_macros.h"
23 #include <print>
24 
25 // Smaller to larger
26 static_assert(noexcept(std::saturate_cast<signed int>(std::numeric_limits<signed char>::max())));
27 static_assert(noexcept(std::saturate_cast<signed int>(std::numeric_limits<unsigned char>::max())));
28 
29 static_assert(noexcept(std::saturate_cast<unsigned int>(std::numeric_limits<signed char>::max())));
30 static_assert(noexcept(std::saturate_cast<unsigned int>(std::numeric_limits<unsigned char>::max())));
31 
32 // Same type
33 static_assert(noexcept(std::saturate_cast<signed long int>(std::numeric_limits<signed long int>::max())));
34 static_assert(noexcept(std::saturate_cast<unsigned long int>(std::numeric_limits<unsigned long int>::max())));
35 
36 // Larger to smaller
37 static_assert(noexcept(std::saturate_cast<signed char>(std::numeric_limits<signed int>::max())));
38 static_assert(noexcept(std::saturate_cast<signed char>(std::numeric_limits<unsigned int>::max())));
39 
40 static_assert(noexcept(std::saturate_cast<unsigned char>(std::numeric_limits<signed int>::max())));
41 static_assert(noexcept(std::saturate_cast<unsigned char>(std::numeric_limits<unsigned int>::max())));
42 
43 // Tests
44 
test()45 constexpr bool test() {
46   // clang-format off
47 
48 #ifndef TEST_HAS_NO_INT128
49   using SIntT = __int128_t;
50   using UIntT = __uint128_t;
51 #else
52   using SIntT = long long int;
53   using UIntT = unsigned long long int;
54 #endif
55 
56   // Constants the values of which depend on the context (platform)
57 
58   constexpr auto sBigMin = std::numeric_limits<SIntT>::min();
59   constexpr auto sZero   = SIntT{0};
60   constexpr auto sBigMax = std::numeric_limits<SIntT>::max();
61 
62   constexpr auto uZero   = UIntT{0};
63   constexpr auto uBigMax = std::numeric_limits<UIntT>::max();
64 
65   // Constants to avoid casting in place
66 
67   constexpr auto O_C  = static_cast<signed char>(0);
68   constexpr auto O_UC = static_cast<unsigned char>(0);
69 
70   constexpr auto O_S  = static_cast<signed short int>(0);
71   constexpr auto O_US = static_cast<unsigned short int>(0);
72 
73   // signed char
74 
75   // TODO(LLVM-20) remove [[maybe_unused]] and `{}` scope since all supported compilers support "Placeholder variables with no name",
76   // here and below...
77   { [[maybe_unused]] std::same_as<signed char> decltype(auto) _ = std::saturate_cast<signed char>(SCHAR_MAX); }
78   assert(std::saturate_cast<signed char>(SCHAR_MIN)  == SCHAR_MIN);
79   assert(std::saturate_cast<signed char>(      O_C)  ==       O_C);
80   assert(std::saturate_cast<signed char>(SCHAR_MAX)  == SCHAR_MAX);
81 
82   { [[maybe_unused]] std::same_as<signed char> decltype(auto) _ = std::saturate_cast<signed char>(UCHAR_MAX); }
83   assert(std::saturate_cast<signed char>(     O_UC)  ==       O_C);
84   assert(std::saturate_cast<signed char>(UCHAR_MAX)  == SCHAR_MAX);
85 
86   { [[maybe_unused]] std::same_as<signed char> decltype(auto) _ = std::saturate_cast<signed char>(sBigMax); }
87   assert(std::saturate_cast<signed char>(sBigMin)    == SCHAR_MIN); // saturated
88   assert(std::saturate_cast<signed char>(  sZero)    ==       O_C);
89   assert(std::saturate_cast<signed char>(sBigMax)    == SCHAR_MAX); // saturated
90 
91   { [[maybe_unused]] std::same_as<signed char> decltype(auto) _ = std::saturate_cast<signed char>(uBigMax); }
92   assert(std::saturate_cast<signed char>(  uZero)    ==       O_C);
93   assert(std::saturate_cast<signed char>(uBigMax)    == SCHAR_MAX); // saturated
94 
95   // short
96 
97   { [[maybe_unused]] std::same_as<signed short int> decltype(auto) _ = std::saturate_cast<signed short int>(SCHAR_MAX); }
98   assert(std::saturate_cast<signed short int>(SCHAR_MIN) == static_cast<signed short int>(SCHAR_MIN));
99   assert(std::saturate_cast<signed short int>(      O_C) == O_S);
100   assert(std::saturate_cast<signed short int>(SCHAR_MAX) == static_cast<signed short int>(SCHAR_MAX));
101 
102   { [[maybe_unused]] std::same_as<signed short int> decltype(auto) _ = std::saturate_cast<signed short int>(UCHAR_MAX); }
103   assert(std::saturate_cast<signed short int>(     O_UC) == O_S);
104   assert(std::saturate_cast<signed short int>(UCHAR_MAX) == static_cast<signed short int>(UCHAR_MAX));
105 
106   { [[maybe_unused]] std::same_as<signed short int> decltype(auto) _ = std::saturate_cast<signed short int>(SHRT_MAX); }
107   assert(std::saturate_cast<signed short int>( SHRT_MIN) == SHRT_MIN);
108   assert(std::saturate_cast<signed short int>(      O_S) == O_S);
109   assert(std::saturate_cast<signed short int>( SHRT_MAX) == SHRT_MAX);
110 
111   { [[maybe_unused]] std::same_as<signed short int> decltype(auto) _ = std::saturate_cast<signed short int>(USHRT_MAX); }
112   assert(std::saturate_cast<signed short int>(     O_US) == O_S);
113   assert(std::saturate_cast<signed short int>(USHRT_MAX) == SHRT_MAX); // saturated
114 
115   { [[maybe_unused]] std::same_as<signed short int> decltype(auto) _ = std::saturate_cast<signed short int>(sBigMax); }
116   assert(std::saturate_cast<signed short int>( sBigMin)   == SHRT_MIN); // saturated
117   assert(std::saturate_cast<signed short int>(   sZero)   == O_S);
118   assert(std::saturate_cast<signed short int>( sBigMax)   == SHRT_MAX); // saturated
119 
120   { [[maybe_unused]] std::same_as<signed short int> decltype(auto) _ = std::saturate_cast<signed short int>(uBigMax); }
121   assert(std::saturate_cast<signed short int>(   uZero)   == O_S);
122   assert(std::saturate_cast<signed short int>( uBigMax)   == SHRT_MAX); // saturated
123 
124   // int
125 
126   { [[maybe_unused]] std::same_as<signed int> decltype(auto) _ = std::saturate_cast<signed int>(SCHAR_MAX); }
127   assert(std::saturate_cast<signed int>(SCHAR_MIN) == static_cast<signed int>(SCHAR_MIN));
128   assert(std::saturate_cast<signed int>(      O_C) == 0);
129   assert(std::saturate_cast<signed int>(SCHAR_MAX) == static_cast<signed int>(SCHAR_MAX));
130 
131   { [[maybe_unused]] std::same_as<signed int> decltype(auto) _ = std::saturate_cast<signed int>(UCHAR_MAX); }
132   assert(std::saturate_cast<signed int>(     O_UC) == 0);
133   assert(std::saturate_cast<signed int>(UCHAR_MAX) == static_cast<signed int>(UCHAR_MAX));
134 
135   { [[maybe_unused]] std::same_as<signed int> decltype(auto) _ = std::saturate_cast<signed int>(INT_MAX); }
136   assert(std::saturate_cast<signed int>(  INT_MIN) == INT_MIN);
137   assert(std::saturate_cast<signed int>(        0) == 0);
138   assert(std::saturate_cast<signed int>(  INT_MAX) == INT_MAX);
139 
140   { [[maybe_unused]] std::same_as<signed int> decltype(auto) _ = std::saturate_cast<signed int>(UINT_MAX); }
141   assert(std::saturate_cast<signed int>(       0)  == 0);
142   assert(std::saturate_cast<signed int>(UINT_MAX)  == INT_MAX); // saturated
143 
144   { [[maybe_unused]] std::same_as<signed int> decltype(auto) _ = std::saturate_cast<signed int>(sBigMax); }
145   assert(std::saturate_cast<signed int>( sBigMin)  == INT_MIN); // saturated
146   assert(std::saturate_cast<signed int>(   sZero)  == 0);
147   assert(std::saturate_cast<signed int>( sBigMax)  == INT_MAX); // saturated
148 
149   { [[maybe_unused]] std::same_as<signed int> decltype(auto) _ = std::saturate_cast<signed int>(uBigMax); }
150   assert(std::saturate_cast<signed int>( uZero)    == 0);
151   assert(std::saturate_cast<signed int>( uBigMax)  == INT_MAX); // saturated
152 
153   // long
154 
155   { [[maybe_unused]] std::same_as<signed long int> decltype(auto) _ = std::saturate_cast<signed long int>(SCHAR_MAX); }
156   assert(std::saturate_cast<signed long int>(SCHAR_MIN) == static_cast<signed long int>(SCHAR_MIN));
157   assert(std::saturate_cast<signed long int>(      O_C) == 0L);
158   assert(std::saturate_cast<signed long int>(SCHAR_MAX) == static_cast<signed long int>(SCHAR_MAX));
159 
160   { [[maybe_unused]] std::same_as<signed long int> decltype(auto) _ = std::saturate_cast<signed long int>(UCHAR_MAX); }
161   assert(std::saturate_cast<signed long int>(     O_UC) == 0L);
162   assert(std::saturate_cast<signed long int>(UCHAR_MAX) == static_cast<signed long int>(UCHAR_MAX));
163 
164   { [[maybe_unused]] std::same_as<signed long int> decltype(auto) _ = std::saturate_cast<signed long int>(LONG_MAX); }
165   assert(std::saturate_cast<signed long int>( LONG_MIN) == LONG_MIN);
166   assert(std::saturate_cast<signed long int>(       0L) == 0L);
167   assert(std::saturate_cast<signed long int>( LONG_MAX) == LONG_MAX);
168 
169   { [[maybe_unused]] std::same_as<signed long int> decltype(auto) _ = std::saturate_cast<signed long int>(ULONG_MAX); }
170   assert(std::saturate_cast<signed long int>(      0UL) == 0L);
171   assert(std::saturate_cast<signed long int>(ULONG_MAX) == LONG_MAX); // saturated
172 
173   { [[maybe_unused]] std::same_as<signed long int> decltype(auto) _ = std::saturate_cast<signed long int>(sBigMax); }
174   assert(std::saturate_cast<signed long int>(  sBigMin) == LONG_MIN); // saturated
175   assert(std::saturate_cast<signed long int>(    sZero) == 0L);
176   assert(std::saturate_cast<signed long int>(  sBigMax) == LONG_MAX); // saturated
177 
178   { [[maybe_unused]] std::same_as<signed long int> decltype(auto) _ = std::saturate_cast<signed long int>(uBigMax); }
179   assert(std::saturate_cast<signed long int>(    uZero) == 0L);
180   assert(std::saturate_cast<signed long int>(  uBigMax) == LONG_MAX); // saturated
181 
182   // long long
183 
184   { [[maybe_unused]] std::same_as<signed long long int> decltype(auto) _ = std::saturate_cast<signed long long int>(SCHAR_MAX); }
185   assert(std::saturate_cast<signed long long int>(SCHAR_MIN) == static_cast<signed long long int>(SCHAR_MIN));
186   assert(std::saturate_cast<signed long long int>(      0LL) == 0LL);
187   assert(std::saturate_cast<signed long long int>(SCHAR_MAX) == static_cast<signed long long int>(SCHAR_MAX));
188 
189   { [[maybe_unused]]   std::same_as<signed long long int> decltype(auto) _ = std::saturate_cast<signed long long int>(UCHAR_MAX); }
190   assert(std::saturate_cast<signed long long int>(     O_UC) == 0LL);
191   assert(std::saturate_cast<signed long long int>(UCHAR_MAX) == static_cast<signed long long int>(UCHAR_MAX));
192 
193   { [[maybe_unused]] std::same_as<signed long long int> decltype(auto) _ = std::saturate_cast<signed long long int>(LLONG_MIN); }
194   assert(std::saturate_cast<signed long long int>(LLONG_MIN) == LLONG_MIN);
195   assert(std::saturate_cast<signed long long int>(      0LL) == 0LL);
196   assert(std::saturate_cast<signed long long int>(LLONG_MAX) == LLONG_MAX);
197 
198   { [[maybe_unused]] std::same_as<signed long long int> decltype(auto) _ = std::saturate_cast<signed long long int>(ULLONG_MAX); }
199   assert(std::saturate_cast<signed long long int>(      0ULL) == 0LL);
200   assert(std::saturate_cast<signed long long int>(ULLONG_MAX) == LLONG_MAX); // saturated
201 
202 #ifndef TEST_HAS_NO_INT128
203   { [[maybe_unused]] std::same_as<signed long long int> decltype(auto) _ = std::saturate_cast<signed long long int>(sBigMax); }
204   assert(std::saturate_cast<signed long long int>(   sBigMin) == LLONG_MIN); // (128-bit) saturated
205   assert(std::saturate_cast<signed long long int>(     sZero) == 0LL);
206   assert(std::saturate_cast<signed long long int>(   sBigMax) == LLONG_MAX); // (128-bit) saturated
207 
208   { [[maybe_unused]] std::same_as<signed long long int> decltype(auto) _ = std::saturate_cast<signed long long int>(uBigMax); }
209   assert(std::saturate_cast<signed long long int>(     uZero) == 0LL);
210   assert(std::saturate_cast<signed long long int>(   uBigMax) == LLONG_MAX); // (128-bit) saturated
211 
212   { [[maybe_unused]] std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(SCHAR_MAX); }
213   assert(std::saturate_cast<__int128_t>(SCHAR_MIN) == static_cast<__int128_t>(SCHAR_MIN));
214   assert(std::saturate_cast<__int128_t>(      O_C) == sZero);
215   assert(std::saturate_cast<__int128_t>(SCHAR_MAX) == static_cast<__int128_t>(SCHAR_MAX));
216 
217   { [[maybe_unused]] std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(UCHAR_MAX); }
218   assert(std::saturate_cast<__int128_t>(     O_UC) == sZero);
219   assert(std::saturate_cast<__int128_t>(UCHAR_MAX) == static_cast<__int128_t>(UCHAR_MAX));
220 
221   { [[maybe_unused]] std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(sBigMax); }
222   assert(std::saturate_cast<__int128_t>(  sBigMin) == sBigMin);
223   assert(std::saturate_cast<__int128_t>(    sZero) == sZero);
224   assert(std::saturate_cast<__int128_t>(  sBigMax) == sBigMax);
225 
226   { [[maybe_unused]] std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(uBigMax); }
227   assert(std::saturate_cast<__int128_t>(    uZero) == sZero);
228   assert(std::saturate_cast<__int128_t>(  uBigMax) == sBigMax); // saturated
229 #endif
230 
231   // unsigned char
232 
233   { [[maybe_unused]] std::same_as<unsigned char> decltype(auto) _ = std::saturate_cast<unsigned char>(SCHAR_MAX); }
234   assert(std::saturate_cast<unsigned char>(SCHAR_MIN) == O_UC);
235   assert(std::saturate_cast<unsigned char>(      O_C) == O_UC);
236   assert(std::saturate_cast<unsigned char>(SCHAR_MAX) == static_cast<unsigned char>(SCHAR_MAX));
237 
238   { [[maybe_unused]] std::same_as<unsigned char> decltype(auto) _ = std::saturate_cast<unsigned char>(UCHAR_MAX); }
239   assert(std::saturate_cast<unsigned char>(     O_UC) == O_UC);
240   assert(std::saturate_cast<unsigned char>(UCHAR_MAX) == UCHAR_MAX);
241 
242   { [[maybe_unused]] std::same_as<unsigned char> decltype(auto) _ = std::saturate_cast<unsigned char>(sBigMax); }
243   assert(std::saturate_cast<unsigned char>(  sBigMin) == O_UC);      // saturated
244   assert(std::saturate_cast<unsigned char>(    sZero) == O_UC);
245   assert(std::saturate_cast<unsigned char>(  sBigMax) == UCHAR_MAX); // saturated
246 
247   { [[maybe_unused]] std::same_as<unsigned char> decltype(auto) _ = std::saturate_cast<unsigned char>(uBigMax); }
248   assert(std::saturate_cast<unsigned char>(    uZero) == O_UC);
249   assert(std::saturate_cast<unsigned char>(  uBigMax) == UCHAR_MAX); // saturated
250 
251   // unsigned short
252 
253   { [[maybe_unused]] std::same_as<unsigned short int> decltype(auto) _ = std::saturate_cast<unsigned short int>(SCHAR_MAX); }
254   assert(std::saturate_cast<unsigned short int>(SCHAR_MIN) == O_US);
255   assert(std::saturate_cast<unsigned short int>(      O_C) == O_US);
256   assert(std::saturate_cast<unsigned short int>(SCHAR_MAX) == static_cast<unsigned short int>(SCHAR_MAX));
257 
258   { [[maybe_unused]] std::same_as<unsigned short int> decltype(auto) _ = std::saturate_cast<unsigned short int>(UCHAR_MAX); }
259   assert(std::saturate_cast<unsigned short int>(     O_UC) == O_US);
260   assert(std::saturate_cast<unsigned short int>(UCHAR_MAX) == static_cast<unsigned short int>(UCHAR_MAX));
261 
262   { [[maybe_unused]] std::same_as<unsigned short int> decltype(auto) _ = std::saturate_cast<unsigned short int>(SCHAR_MIN); }
263   assert(std::saturate_cast<unsigned short int>( SHRT_MIN) == O_US);
264   assert(std::saturate_cast<unsigned short int>(      O_S) == O_US);
265   assert(std::saturate_cast<unsigned short int>( SHRT_MAX) == static_cast<unsigned short int>(SHRT_MAX));
266 
267   { [[maybe_unused]] std::same_as<unsigned short int> decltype(auto) _ = std::saturate_cast<unsigned short int>(UCHAR_MAX); }
268   assert(std::saturate_cast<unsigned short int>(     O_US) == O_US);
269   assert(std::saturate_cast<unsigned short int>(USHRT_MAX) == USHRT_MAX);
270 
271   { [[maybe_unused]] std::same_as<unsigned short int> decltype(auto) _ = std::saturate_cast<unsigned short int>(sBigMax); }
272   assert(std::saturate_cast<unsigned short int>(  sBigMin) == O_US);      // saturated
273   assert(std::saturate_cast<unsigned short int>(    sZero) == O_US);
274   assert(std::saturate_cast<unsigned short int>(  sBigMax) == USHRT_MAX); // saturated
275 
276   { [[maybe_unused]] std::same_as<unsigned short int> decltype(auto) _ = std::saturate_cast<unsigned short int>(uBigMax); }
277   assert(std::saturate_cast<unsigned short int>(    uZero) == O_US);
278   assert(std::saturate_cast<unsigned short int>(  uBigMax) == USHRT_MAX); // saturated
279 
280   // unsigned int
281 
282   { [[maybe_unused]] std::same_as<unsigned int> decltype(auto) _ = std::saturate_cast<unsigned int>(SCHAR_MAX); }
283   assert(std::saturate_cast<unsigned int>(SCHAR_MIN) == O_US);
284   assert(std::saturate_cast<unsigned int>(     O_UC) == 0U);
285   assert(std::saturate_cast<unsigned int>(SCHAR_MAX) == static_cast<unsigned int>(SCHAR_MAX));
286 
287   { [[maybe_unused]] std::same_as<unsigned int> decltype(auto) _ = std::saturate_cast<unsigned int>(UCHAR_MAX); }
288   assert(std::saturate_cast<unsigned int>(     O_UC) == 0U);
289   assert(std::saturate_cast<unsigned int>(UCHAR_MAX) == static_cast<unsigned int>(UCHAR_MAX));
290 
291   { [[maybe_unused]] std::same_as<unsigned int> decltype(auto) _ = std::saturate_cast<unsigned int>(INT_MAX); }
292   assert(std::saturate_cast<unsigned int>(  INT_MIN) == 0U);
293   assert(std::saturate_cast<unsigned int>(        0) == 0U);
294   assert(std::saturate_cast<unsigned int>(  INT_MAX) == static_cast<unsigned int>(INT_MAX));
295 
296   { [[maybe_unused]] std::same_as<unsigned int> decltype(auto) _ = std::saturate_cast<unsigned int>(UINT_MAX); }
297   assert(std::saturate_cast<unsigned int>(       0U) == 0U);
298   assert(std::saturate_cast<unsigned int>( UINT_MAX) == UINT_MAX);
299 
300   { [[maybe_unused]] std::same_as<unsigned int> decltype(auto) _ = std::saturate_cast<unsigned int>(sBigMax); }
301   assert(std::saturate_cast<unsigned int>(  sBigMin) == 0U);       // saturated
302   assert(std::saturate_cast<unsigned int>(    sZero) == 0U);
303   assert(std::saturate_cast<unsigned int>(  sBigMax) == UINT_MAX); // saturated
304 
305   { [[maybe_unused]] std::same_as<unsigned int> decltype(auto) _ = std::saturate_cast<unsigned int>(uBigMax); }
306   assert(std::saturate_cast<unsigned int>(    uZero) == 0U);
307   assert(std::saturate_cast<unsigned int>(  uBigMax) == UINT_MAX);  // saturated
308 
309   // unsigned long
310 
311   { [[maybe_unused]] std::same_as<unsigned long int> decltype(auto) _ = std::saturate_cast<unsigned long int>(SCHAR_MAX); }
312   assert(std::saturate_cast<unsigned long int>(SCHAR_MIN) == 0UL);
313   assert(std::saturate_cast<unsigned long int>(      O_C) == 0UL);
314   assert(std::saturate_cast<unsigned long int>(SCHAR_MAX) == static_cast<unsigned long int>(SCHAR_MAX));
315 
316   { [[maybe_unused]] std::same_as<unsigned long int> decltype(auto) _ = std::saturate_cast<unsigned long int>(UCHAR_MAX); }
317   assert(std::saturate_cast<unsigned long int>(     O_UC) == 0UL);
318   assert(std::saturate_cast<unsigned long int>(UCHAR_MAX) == static_cast<unsigned long int>(UCHAR_MAX));
319 
320   { [[maybe_unused]] std::same_as<unsigned long int> decltype(auto) _ = std::saturate_cast<unsigned long int>(LONG_MAX); }
321   assert(std::saturate_cast<unsigned long int>( LONG_MIN) == 0UL);
322   assert(std::saturate_cast<unsigned long int>(       0L) == 0UL);
323   assert(std::saturate_cast<unsigned long int>( LONG_MAX) == static_cast<unsigned long int>(LONG_MAX));
324 
325   { [[maybe_unused]] std::same_as<unsigned long int> decltype(auto) _ = std::saturate_cast<unsigned long int>(ULONG_MAX); }
326   assert(std::saturate_cast<unsigned long int>(      0UL) == 0UL);
327   assert(std::saturate_cast<unsigned long int>(ULONG_MAX) == ULONG_MAX);
328 
329   { [[maybe_unused]] std::same_as<unsigned long int> decltype(auto) _ = std::saturate_cast<unsigned long int>(sBigMax); }
330   assert(std::saturate_cast<unsigned long int>(  sBigMin) == 0UL);       // saturated
331   assert(std::saturate_cast<unsigned long int>(    sZero) == 0UL);
332   assert(std::saturate_cast<unsigned long int>(  sBigMax) == (sizeof(UIntT) > sizeof(unsigned long int) ? ULONG_MAX : LONG_MAX)); // saturated depending on underlying types
333 
334   { [[maybe_unused]] std::same_as<unsigned long int> decltype(auto) _ = std::saturate_cast<unsigned long int>(uBigMax); }
335   assert(std::saturate_cast<unsigned long int>(    uZero) == 0UL);
336   assert(std::saturate_cast<unsigned long int>(  uBigMax) == ULONG_MAX); // saturated
337 
338   // unsigned long long
339 
340   { [[maybe_unused]] std::same_as<unsigned long long int> decltype(auto) _ = std::saturate_cast<unsigned long long int>(SCHAR_MAX); }
341   assert(std::saturate_cast<unsigned long long int>( SCHAR_MIN) == 0ULL);
342   assert(std::saturate_cast<unsigned long long int>(       O_C) == 0ULL);
343   assert(std::saturate_cast<unsigned long long int>( SCHAR_MAX) == static_cast<unsigned long long int>(SCHAR_MAX));
344 
345   { [[maybe_unused]] std::same_as<unsigned long long  int> decltype(auto) _ = std::saturate_cast<unsigned long long int>(UCHAR_MAX); }
346   assert(std::saturate_cast<unsigned long long int>(      O_UC) == 0ULL);
347   assert(std::saturate_cast<unsigned long long int>( UCHAR_MAX) == static_cast<unsigned long long int>(UCHAR_MAX));
348 
349   { [[maybe_unused]] std::same_as<unsigned long long int> decltype(auto) _ = std::saturate_cast<unsigned long long int>(LLONG_MAX); }
350   assert(std::saturate_cast<unsigned long long int>( LLONG_MIN) == 0ULL);
351   assert(std::saturate_cast<unsigned long long int>(       0LL) == 0ULL);
352   assert(std::saturate_cast<unsigned long long int>( LLONG_MAX) == static_cast<unsigned long long int>(LLONG_MAX));
353 
354   { [[maybe_unused]] std::same_as<unsigned long long int> decltype(auto) _ = std::saturate_cast<unsigned long long int>(ULLONG_MAX); }
355   assert(std::saturate_cast<unsigned long long int>(      0ULL) == 0ULL);
356   assert(std::saturate_cast<unsigned long long int>(ULLONG_MAX) == ULLONG_MAX);
357 
358 #ifndef TEST_HAS_NO_INT128
359   { [[maybe_unused]] std::same_as<unsigned long long int> decltype(auto) _ = std::saturate_cast<unsigned long long int>(sBigMax); }
360   assert(std::saturate_cast<unsigned long long int>(   sBigMin) == 0ULL);       // (128-bit) saturated
361   assert(std::saturate_cast<unsigned long long int>(     sZero) == 0ULL);
362   assert(std::saturate_cast<unsigned long long int>(   sBigMax) == ULLONG_MAX); // (128-bit) saturated
363 
364   { [[maybe_unused]] std::same_as<unsigned long long int> decltype(auto) _ = std::saturate_cast<unsigned long long int>(uBigMax); }
365   assert(std::saturate_cast<unsigned long long int>(     uZero) == 0ULL);
366   assert(std::saturate_cast<unsigned long long int>(   uBigMax) == ULLONG_MAX); // (128-bit) saturated
367 
368   { [[maybe_unused]] std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(SCHAR_MIN); }
369   assert(std::saturate_cast<__uint128_t>(SCHAR_MIN) == uZero);
370   assert(std::saturate_cast<__uint128_t>(      O_C) == uZero);
371   assert(std::saturate_cast<__uint128_t>(SCHAR_MAX) == static_cast<__uint128_t>(SCHAR_MAX));
372 
373   { [[maybe_unused]] std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(UCHAR_MAX); }
374   assert(std::saturate_cast<__uint128_t>(     O_UC) == uZero);
375   assert(std::saturate_cast<__uint128_t>(UCHAR_MAX) == static_cast<__uint128_t>(UCHAR_MAX));
376 
377   { [[maybe_unused]] std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(sBigMax); }
378   assert(std::saturate_cast<__uint128_t>(  sBigMin) == uZero); // saturated
379   assert(std::saturate_cast<__uint128_t>(    sZero) == uZero);
380   assert(std::saturate_cast<__uint128_t>(  sBigMax) == static_cast<__uint128_t>(sBigMax));
381 
382   { [[maybe_unused]] std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(uBigMax); }
383   assert(std::saturate_cast<__uint128_t>(    uZero) == uZero);
384   assert(std::saturate_cast<__uint128_t>(  uBigMax) == uBigMax);
385 #endif
386 
387   // clang-format on
388 
389   return true;
390 }
391 
main(int,char **)392 int main(int, char**) {
393   test();
394   static_assert(test());
395 
396   return 0;
397 }
398