[ORC-RT][LoongArch] Add initial support for loongarch64 in ELFNixPlatform (#123575)
[llvm-project.git] / libcxx / test / std / numerics / numeric.ops / numeric.ops.sat / sub_sat.pass.cpp
blobd7bdf2c0271acf3f85e26b7a3ba86c96349de83b
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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10 // The test uses "Placeholder variables with no name"
12 // <numeric>
14 // template<class T>
15 // constexpr T sub_sat(T x, T y) noexcept; // freestanding
17 #include <cassert>
18 #include <concepts>
19 #include <limits>
20 #include <numeric>
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)));
34 // clang-format off
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
82 // clang-format on
84 return true;
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)));
97 // clang-format off
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
129 // clang-format on
131 return true;
134 constexpr bool test() {
135 // Signed
136 test_signed<signed char>();
137 test_signed<short int>();
138 test_signed<int>();
139 test_signed<long int>();
140 test_signed<long long int>();
141 #ifndef TEST_HAS_NO_INT128
142 test_signed<__int128_t>();
143 #endif
144 // Unsigned
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>();
152 #endif
154 return true;
157 int main(int, char**) {
158 test();
159 static_assert(test());
161 return 0;