Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / multiprecision / test / constexpr_arithmetric_test.hpp
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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