1 // (C) Copyright John Maddock 2019.
2 // Use, modification and distribution are subject to the
3 // Boost Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #include <boost/config.hpp>
7 #include <boost/multiprecision/number.hpp>
8 #include <limits>
9
10 // clang-format off
11
12 template <class T, class U>
do_test_constexpr_add_subtract(T a,U b)13 BOOST_CXX14_CONSTEXPR T do_test_constexpr_add_subtract(T a, U b)
14 {
15 a = +b;
16 if constexpr(std::numeric_limits<U>::is_signed && std::numeric_limits<T>::is_signed)
17 b = -b;
18 a += b;
19 a += a;
20 a -= b;
21 a -= a;
22 ++a;
23 --a;
24 T bb(b);
25 a += bb++;
26 a += bb--;
27 a = a + b;
28 a += a - b;
29 if constexpr(std::numeric_limits<U>::is_signed && std::numeric_limits<T>::is_signed)
30 a -= b - -a;
31 a += b + a;
32 if constexpr(std::numeric_limits<T>::is_signed)
33 {
34 a = -a;
35 if constexpr(std::numeric_limits<U>::is_signed)
36 a -= b;
37 }
38 return a;
39 }
40
41 template <class T>
test_constexpr_add_subtract(T a)42 BOOST_CXX14_CONSTEXPR T test_constexpr_add_subtract(T a)
43 {
44 a += do_test_constexpr_add_subtract(a, a);
45 a += do_test_constexpr_add_subtract(a, static_cast<unsigned char>(2));
46 a += do_test_constexpr_add_subtract(a, static_cast<signed char>(2));
47 a += do_test_constexpr_add_subtract(a, static_cast<char>(2));
48 a += do_test_constexpr_add_subtract(a, static_cast<short>(2));
49 a += do_test_constexpr_add_subtract(a, static_cast<unsigned short>(2));
50 a += do_test_constexpr_add_subtract(a, static_cast<int>(2));
51 a += do_test_constexpr_add_subtract(a, static_cast<unsigned int>(2));
52 a += do_test_constexpr_add_subtract(a, static_cast<long>(2));
53 a += do_test_constexpr_add_subtract(a, static_cast<unsigned long>(2));
54 a += do_test_constexpr_add_subtract(a, static_cast<long long>(2));
55 a += do_test_constexpr_add_subtract(a, static_cast<unsigned long long>(2));
56 #ifdef BOOST_HAS_INT128
57 a += do_test_constexpr_add_subtract(a, static_cast<__int128>(2));
58 a += do_test_constexpr_add_subtract(a, static_cast<unsigned __int128>(2));
59 a -= do_test_constexpr_add_subtract(a, static_cast<__int128>(2));
60 a -= do_test_constexpr_add_subtract(a, static_cast<unsigned __int128>(2));
61 #endif
62
63 if constexpr (boost::multiprecision::number_category<T>::value == boost::multiprecision::number_kind_floating_point)
64 {
65 a += do_test_constexpr_add_subtract(a, static_cast<float>(2));
66 a += do_test_constexpr_add_subtract(a, static_cast<double>(2));
67 a += do_test_constexpr_add_subtract(a, static_cast<long double>(2));
68 #ifdef BOOST_HAS_FLOAT128
69 a += do_test_constexpr_add_subtract(a, static_cast<__float128>(2));
70 #endif
71 }
72
73 return a;
74 }
75
76 template <class T, class U>
do_test_constexpr_mul_divide(T a,U b)77 BOOST_CXX14_CONSTEXPR T do_test_constexpr_mul_divide(T a, U b)
78 {
79 a *= b;
80 a = a * b;
81 if constexpr(std::numeric_limits<T>::is_signed && std::numeric_limits<U>::is_signed)
82 {
83 a *= -b;
84 a = a * -b;
85 }
86 a /= b;
87 a = a / b;
88 if constexpr(std::numeric_limits<T>::is_signed && std::numeric_limits<U>::is_signed)
89 {
90 a /= -b;
91 a = a / -b;
92 }
93 if constexpr (boost::multiprecision::number_category<T>::value == boost::multiprecision::number_kind_integer && boost::multiprecision::number_category<U>::value == boost::multiprecision::number_kind_integer)
94 {
95 a %= b;
96 a = a % b;
97 }
98 return a;
99 }
100
101 template <class T>
test_constexpr_mul_divide(T a)102 BOOST_CXX14_CONSTEXPR T test_constexpr_mul_divide(T a)
103 {
104 a += do_test_constexpr_mul_divide(a, a);
105 a += do_test_constexpr_mul_divide(a, static_cast<unsigned char>(2));
106 a += do_test_constexpr_mul_divide(a, static_cast<signed char>(2));
107 a += do_test_constexpr_mul_divide(a, static_cast<char>(2));
108 a += do_test_constexpr_mul_divide(a, static_cast<short>(2));
109 a += do_test_constexpr_mul_divide(a, static_cast<unsigned short>(2));
110 a += do_test_constexpr_mul_divide(a, static_cast<int>(2));
111 a += do_test_constexpr_mul_divide(a, static_cast<unsigned int>(2));
112 a += do_test_constexpr_mul_divide(a, static_cast<long>(2));
113 a += do_test_constexpr_mul_divide(a, static_cast<unsigned long>(2));
114 a += do_test_constexpr_mul_divide(a, static_cast<long long>(2));
115 a += do_test_constexpr_mul_divide(a, static_cast<unsigned long long>(2));
116 #ifdef BOOST_HAS_INT128
117 a += do_test_constexpr_mul_divide(a, static_cast<__int128>(2));
118 a += do_test_constexpr_mul_divide(a, static_cast<unsigned __int128>(2));
119 a -= do_test_constexpr_mul_divide(a, static_cast<__int128>(2));
120 a -= do_test_constexpr_mul_divide(a, static_cast<unsigned __int128>(2));
121 #endif
122
123 if constexpr (boost::multiprecision::number_category<T>::value == boost::multiprecision::number_kind_floating_point)
124 {
125 a += do_test_constexpr_mul_divide(a, static_cast<float>(2));
126 a += do_test_constexpr_mul_divide(a, static_cast<double>(2));
127 a += do_test_constexpr_mul_divide(a, static_cast<long double>(2));
128 #ifdef BOOST_HAS_FLOAT128
129 a += do_test_constexpr_mul_divide(a, static_cast<__float128>(2));
130 #endif
131 }
132 return a;
133 }
134
135 template <class T, class U>
do_test_constexpr_bitwise(T a,U b)136 BOOST_CXX14_CONSTEXPR T do_test_constexpr_bitwise(T a, U b)
137 {
138 a |= b;
139 a &= b;
140 a <<= 2;
141 a ^= b;
142 a = a | b;
143 a = a & b;
144 a <<= 2;
145 a = a ^ b;
146 if constexpr (std::numeric_limits<T>::is_signed == false)
147 {
148 a = ~a;
149 a >>= std::numeric_limits<T>::digits - 3;
150 }
151
152 a <<= 5;
153 a = a << 2;
154 a >>= 5;
155 a = a >> 2;
156
157 return a;
158 }
159
160 template <class T>
test_constexpr_bitwise(T a)161 BOOST_CXX14_CONSTEXPR T test_constexpr_bitwise(T a)
162 {
163 a += do_test_constexpr_bitwise(a, a);
164 a += do_test_constexpr_bitwise(a, static_cast<unsigned char>(2));
165 a += do_test_constexpr_bitwise(a, static_cast<signed char>(2));
166 a += do_test_constexpr_bitwise(a, static_cast<char>(2));
167 a += do_test_constexpr_bitwise(a, static_cast<short>(2));
168 a += do_test_constexpr_bitwise(a, static_cast<unsigned short>(2));
169 a += do_test_constexpr_bitwise(a, static_cast<int>(2));
170 a += do_test_constexpr_bitwise(a, static_cast<unsigned int>(2));
171 a += do_test_constexpr_bitwise(a, static_cast<long>(2));
172 a += do_test_constexpr_bitwise(a, static_cast<unsigned long>(2));
173 a += do_test_constexpr_bitwise(a, static_cast<long long>(2));
174 a += do_test_constexpr_bitwise(a, static_cast<unsigned long long>(2));
175 #ifdef BOOST_HAS_INT128
176 a += do_test_constexpr_bitwise(a, static_cast<__int128>(2));
177 a += do_test_constexpr_bitwise(a, static_cast<unsigned __int128>(2));
178 #endif
179
180 return a;
181 }
182
183 template <class T, class U>
do_test_constexpr_logical(T a,U b)184 BOOST_CXX14_CONSTEXPR T do_test_constexpr_logical(T a, U b)
185 {
186 T result(0);
187 if(a || b)
188 ++result;
189 if(b || a)
190 ++result;
191 if(a && b)
192 ++result;
193 if(b && a)
194 ++result;
195 if(a)
196 ++result;
197 if(!a)
198 ++result;
199 return result;
200 }
201
202 template <class T>
test_constexpr_logical(T a)203 BOOST_CXX14_CONSTEXPR T test_constexpr_logical(T a)
204 {
205 a += do_test_constexpr_logical(a, a);
206 a += do_test_constexpr_logical(a, static_cast<unsigned char>(2));
207 a += do_test_constexpr_logical(a, static_cast<signed char>(2));
208 a += do_test_constexpr_logical(a, static_cast<char>(2));
209 a += do_test_constexpr_logical(a, static_cast<short>(2));
210 a += do_test_constexpr_logical(a, static_cast<unsigned short>(2));
211 a += do_test_constexpr_logical(a, static_cast<int>(2));
212 a += do_test_constexpr_logical(a, static_cast<unsigned int>(2));
213 a += do_test_constexpr_logical(a, static_cast<long>(2));
214 a += do_test_constexpr_logical(a, static_cast<unsigned long>(2));
215 a += do_test_constexpr_logical(a, static_cast<long long>(2));
216 a += do_test_constexpr_logical(a, static_cast<unsigned long long>(2));
217 #ifdef BOOST_HAS_INT128
218 a += do_test_constexpr_logical(a, static_cast<__int128>(2));
219 a += do_test_constexpr_logical(a, static_cast<unsigned __int128>(2));
220 a -= do_test_constexpr_logical(a, static_cast<__int128>(2));
221 a -= do_test_constexpr_logical(a, static_cast<unsigned __int128>(2));
222 #endif
223
224 return a;
225 }
226
227 template <class T, class U>
do_test_constexpr_compare(T a,U b)228 BOOST_CXX14_CONSTEXPR T do_test_constexpr_compare(T a, U b)
229 {
230 T result(0);
231 if(a == b)
232 ++result;
233 if(b == a)
234 ++result;
235 if(a != b)
236 ++result;
237 if(b != a)
238 ++result;
239 if(a < b)
240 ++result;
241 if(b < a)
242 ++result;
243 if(a <= b)
244 ++result;
245 if(b <= a)
246 ++result;
247 if(a > b)
248 ++result;
249 if(b > a)
250 ++result;
251 if(a >= b)
252 ++result;
253 if(b >= a)
254 ++result;
255
256 T u(b);
257 if(u == a)
258 ++result;
259
260 return result;
261 }
262
263 template <class T>
test_constexpr_compare(T a)264 BOOST_CXX14_CONSTEXPR T test_constexpr_compare(T a)
265 {
266 a += do_test_constexpr_compare(a, a);
267 a += do_test_constexpr_compare(a, static_cast<unsigned char>(2));
268 a += do_test_constexpr_compare(a, static_cast<signed char>(2));
269 a += do_test_constexpr_compare(a, static_cast<char>(2));
270 a += do_test_constexpr_compare(a, static_cast<short>(2));
271 a += do_test_constexpr_compare(a, static_cast<unsigned short>(2));
272 a += do_test_constexpr_compare(a, static_cast<int>(2));
273 a += do_test_constexpr_compare(a, static_cast<unsigned int>(2));
274 a += do_test_constexpr_compare(a, static_cast<long>(2));
275 a += do_test_constexpr_compare(a, static_cast<unsigned long>(2));
276 a += do_test_constexpr_compare(a, static_cast<long long>(2));
277 a += do_test_constexpr_compare(a, static_cast<unsigned long long>(2));
278 #ifdef BOOST_HAS_INT128
279 a += do_test_constexpr_compare(a, static_cast<__int128>(2));
280 a += do_test_constexpr_compare(a, static_cast<unsigned __int128>(2));
281 a -= do_test_constexpr_compare(a, static_cast<__int128>(2));
282 a -= do_test_constexpr_compare(a, static_cast<unsigned __int128>(2));
283 #endif
284
285 if constexpr (boost::multiprecision::number_category<T>::value == boost::multiprecision::number_kind_floating_point)
286 {
287 a += do_test_constexpr_compare(a, static_cast<float>(2));
288 a += do_test_constexpr_compare(a, static_cast<double>(2));
289 a += do_test_constexpr_compare(a, static_cast<long double>(2));
290 #ifdef BOOST_HAS_FLOAT128
291 a += do_test_constexpr_compare(a, static_cast<__float128>(2));
292 #endif
293 }
294 return a;
295 }
296
297 // clang-format on
298