Skip to content

Commit 59655d4

Browse files
committed
Define concepts
1 parent 153d4ad commit 59655d4

File tree

1 file changed

+380
-0
lines changed

1 file changed

+380
-0
lines changed
Lines changed: 380 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
// Copyright 2022 - 2023 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#ifndef BOOST_DECIMAL_DETAIL_CONCEPTS
6+
#define BOOST_DECIMAL_DETAIL_CONCEPTS
7+
8+
#if (__cplusplus >= 202002L || _MSVC_LANG >= 202002L) && !defined(BOOST_MATH_DISABLE_CONCEPTS)
9+
10+
#if __has_include(<concepts>)
11+
12+
#include <utility>
13+
#include <algorithm>
14+
#include <concepts>
15+
#include <functional>
16+
#include <type_traits>
17+
#include <limits>
18+
#include <iterator>
19+
#include <complex>
20+
#include <boost/decimal/detail/type_traits.hpp>
21+
22+
namespace boost::decimal::concepts {
23+
24+
namespace detail {
25+
26+
template <typename X, typename Y, typename Op>
27+
struct op_valid_impl
28+
{
29+
template <typename U, typename L, typename R>
30+
static constexpr auto test(int) -> decltype(std::declval<U>()(std::declval<L>(), std::declval<R>()),
31+
void(), std::true_type());
32+
33+
template <typename U, typename L, typename R>
34+
static constexpr auto test(...) -> std::false_type;
35+
36+
using type = decltype(test<Op, X, Y>(0));
37+
};
38+
39+
template <typename X, typename Y, typename Op>
40+
using op_valid_t = typename op_valid_impl<X, Y, Op>::type;
41+
42+
template <typename X, typename Y, typename Op>
43+
inline constexpr bool op_valid_v = op_valid_t<X, Y, Op>::value;
44+
45+
// Detector for class member functions
46+
struct nonesuch
47+
{
48+
nonesuch(const nonesuch&) = delete;
49+
~nonesuch() = delete;
50+
void operator=(const nonesuch&) = delete;
51+
};
52+
53+
template <typename Default, typename AlwaysVoid, template<typename...> typename Op, typename... Args>
54+
struct detector
55+
{
56+
using value_t = std::false_type;
57+
using type = Default;
58+
};
59+
60+
template <typename Default, template<typename...> typename Op, typename... Args>
61+
struct detector<Default, std::void_t<Op<Args...>>, Op, Args...>
62+
{
63+
using value_t = std::true_type;
64+
using type = Op<Args...>;
65+
};
66+
67+
template <template<typename...> typename Op, typename... Args>
68+
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
69+
70+
template <template<typename...> typename Op, typename... Args>
71+
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
72+
73+
#define BOOST_DECIMAL_HAS_MEMBER_FUNCTION(member) \
74+
template <typename T> \
75+
using has_##member##_t = decltype(std::declval<T&>().member()); \
76+
\
77+
template <typename T> \
78+
inline constexpr bool has_##member##_v = is_detected<has_##member##_t, T>::value;
79+
80+
BOOST_DECIMAL_HAS_MEMBER_FUNCTION(begin)
81+
BOOST_DECIMAL_HAS_MEMBER_FUNCTION(end)
82+
BOOST_DECIMAL_HAS_MEMBER_FUNCTION(real)
83+
BOOST_DECIMAL_HAS_MEMBER_FUNCTION(imag)
84+
85+
} // Namespace detail
86+
87+
template <typename T>
88+
concept integral = std::is_integral_v<T>;
89+
90+
template <typename T>
91+
concept signed_integral = integral<T> && std::is_signed_v<T>;
92+
93+
template <typename T>
94+
concept unsigned_integral = integral<T> && std::is_unsigned_v<T>;
95+
96+
template <typename T>
97+
concept real = std::is_floating_point_v<T>;
98+
99+
template <typename T>
100+
concept complex = std::is_same_v<T, std::complex<float>>
101+
|| std::is_same_v<T, std::complex<double>>
102+
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
103+
|| std::is_same_v<T, std::complex<long double>>
104+
#endif
105+
;
106+
107+
template <typename T>
108+
concept real_or_complex = real<T> || complex<T>;
109+
110+
template <typename T>
111+
concept arithmetic = std::is_arithmetic_v<T>;
112+
113+
template <typename T>
114+
concept numerical = arithmetic<T> || real_or_complex<T>;
115+
116+
template <typename T>
117+
concept signed_arithmetic = arithmetic<T> && std::is_signed_v<T>;
118+
119+
template <typename T>
120+
concept unsigned_arithmetic = arithmetic<T> && std::is_unsigned_v<T>;
121+
122+
template <typename T>
123+
concept arbitrary_unsigned_arithmetic_type = unsigned_arithmetic<T> ||
124+
(detail::op_valid_v<T, T, std::equal_to<>> &&
125+
detail::op_valid_v<T, T, std::not_equal_to<>> &&
126+
detail::op_valid_v<T, T, std::greater<>> &&
127+
detail::op_valid_v<T, T, std::less<>> &&
128+
detail::op_valid_v<T, T, std::greater_equal<>> &&
129+
detail::op_valid_v<T, T, std::less_equal<>> &&
130+
detail::op_valid_v<T, T, std::plus<>> &&
131+
detail::op_valid_v<T, T, std::minus<>> &&
132+
detail::op_valid_v<T, T, std::multiplies<>> &&
133+
detail::op_valid_v<T, T, std::divides<>>);
134+
135+
template <typename T>
136+
concept arbitrary_signed_arithmetic_type = signed_arithmetic<T> ||
137+
(arbitrary_unsigned_arithmetic_type<T> &&
138+
(detail::op_valid_v<T, T, std::negate<>> ||
139+
std::numeric_limits<T>::is_signed));
140+
141+
template <typename T>
142+
concept arbitrary_arithmetic_type = arbitrary_unsigned_arithmetic_type<T> ||
143+
arbitrary_signed_arithmetic_type<T>;
144+
145+
template <typename T>
146+
concept arbitrary_unsigned_integer_type = arbitrary_unsigned_arithmetic_type<T> &&
147+
std::numeric_limits<T>::is_integer;
148+
149+
template <typename T>
150+
concept arbitrary_signed_integer_type = arbitrary_signed_arithmetic_type<T> &&
151+
std::numeric_limits<T>::is_integer;
152+
153+
template <typename T>
154+
concept arbitrary_integer_type = arbitrary_unsigned_integer_type<T> ||
155+
arbitrary_signed_integer_type<T>;
156+
157+
template <typename T>
158+
concept arbitrary_real_type = arbitrary_arithmetic_type<T> &&
159+
!std::numeric_limits<T>::is_integer;
160+
161+
template <typename T>
162+
concept arbitrary_complex_type = complex<T> ||
163+
(detail::has_real_v<T> &&
164+
detail::has_imag_v<T>);
165+
166+
template <typename T>
167+
concept arbitrary_real_or_complex_type = arbitrary_real_type<T> ||
168+
arbitrary_complex_type<T>;
169+
170+
template <typename T>
171+
concept arbitrary_numerical_type = arbitrary_real_or_complex_type<T> ||
172+
arbitrary_arithmetic_type<T>;
173+
174+
template <typename Derived, typename Base>
175+
concept derived_from = std::is_base_of_v<Base, Derived> &&
176+
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
177+
178+
template <typename T>
179+
concept forward_iterator = derived_from<typename std::iterator_traits<T>::iterator_category, std::forward_iterator_tag>;
180+
181+
template <typename T>
182+
concept bidirectional_iterator = derived_from<typename std::iterator_traits<T>::iterator_category, std::bidirectional_iterator_tag>;
183+
184+
template <typename T>
185+
concept random_access_iterator = derived_from<typename std::iterator_traits<T>::iterator_category, std::random_access_iterator_tag>;
186+
187+
template <typename I, typename T>
188+
concept output_iterator = derived_from<typename std::iterator_traits<I>::iterator_category, std::input_iterator_tag> &&
189+
derived_from<typename std::iterator_traits<T>::iterator_category, std::output_iterator_tag>;
190+
191+
template <typename T>
192+
concept is_container = detail::has_begin_v<T> &&
193+
detail::has_end_v<T>;
194+
195+
template <typename T>
196+
concept random_access_container = is_container<T> &&
197+
boost::decimal::concepts::random_access_iterator<typename T::iterator>;
198+
199+
template <typename T>
200+
concept decimal_floating_point_type = detail::is_decimal_floating_point_v<T>;
201+
202+
} // boost::decimal::concepts
203+
204+
#define BOOST_DECIMAL_INTEGRAL boost::decimal::concepts::integral
205+
#define BOOST_DECIMAL_SIGNED_INTEGRAL boost::decimal::concepts::signed_integral
206+
#define BOOST_DECIMAL_UNSIGNED_INTEGRAL boost::decimal::concepts::unsigned_integral
207+
#define BOOST_DECIMAL_REAL boost::decimal::concepts::real
208+
#define BOOST_DECIMAL_COMPLEX boost::decimal::concepts::complex
209+
#define BOOST_DECIMAL_REAL_OR_COMPLEX boost::decimal::concepts::real_or_complex
210+
#define BOOST_DECIMAL_ARITHMETIC boost::decimal::concepts::arithmetic
211+
#define BOOST_DECIMAL_NUMERICAL boost::decimal::concepts::numerical
212+
#define BOOST_DECIMAL_SIGNED_ARITHMETIC boost::decimal::concepts::signed_arithmetic
213+
#define BOOST_DECIMAL_UNSIGNED_ARITHMETIC boost::decimal::concepts::unsigned_arithmetic
214+
#define BOOST_DECIMAL_ARBITRARY_UNSIGNED_ARITHMETIC boost::decimal::concepts::arbitrary_unsigned_arithmetic_type
215+
#define BOOST_DECIMAL_ARBITRARY_SIGNED_ARITHMETIC boost::decimal::concepts::arbitrary_signed_arithmetic_type
216+
#define BOOST_DECIMAL_ARBITRARY_ARITHMETIC boost::decimal::concepts::arbitrary_arithmetic_type
217+
#define BOOST_DECIMAL_ARBITRARY_UNSIGNED_INTEGER boost::decimal::concepts::arbitrary_unsigned_integer_type
218+
#define BOOST_DECIMAL_ARBITRARY_SIGNED_INTEGER boost::decimal::concepts::arbitrary_signed_integer_type
219+
#define BOOST_DECIMAL_ARBITRARY_INTEGER boost::decimal::concepts::arbitrary_integer_type
220+
#define BOOST_DECIMAL_ARBITRARY_REAL boost::decimal::concepts::arbitrary_real_type
221+
#define BOOST_DECIMAL_ARBITRARY_COMPLEX boost::decimal::concepts::arbitrary_complex_type
222+
#define BOOST_DECIMAL_ARBITRARY_REAL_OR_COMPLEX boost::decimal::concepts::arbitrary_real_or_complex_type
223+
#define BOOST_DECIMAL_ARBITRARY_NUMERICAL boost::decimal::concepts::arbitrary_numerical_type
224+
#define BOOST_DECIMAL_DECIMAL_FLOATING_TYPE boost::decimal::concepts::decimal_floating_point_type
225+
226+
#define BOOST_DECIMAL_CONTAINER boost::decimal::concepts::is_container
227+
#define BOOST_DECIMAL_RANDOM_ACCESS_CONTAINER boost::decimal::concepts::random_access_container
228+
229+
#define BOOST_DECIMAL_FORWARD_ITER boost::decimal::concepts::forward_iterator
230+
#define BOOST_DECIMAL_BIDIRECTIONAL_ITER boost::decimal::concepts::bidirectional_iterator
231+
#define BOOST_DECIMAL_RANDOM_ACCESS_ITER boost::decimal::concepts::random_access_iterator
232+
#define BOOST_DECIMAL_OUTPUT_ITER(I, T) boost::decimal::concepts::output_iterator<I, T>
233+
#define BOOST_DECIMAL_REQUIRES_ITER(X) requires X
234+
235+
#define BOOST_DECIMAL_REQUIRES(X, T) requires X<T>
236+
237+
#ifdef BOOST_DECIMAL_EXEC_COMPATIBLE
238+
#include <execution>
239+
240+
namespace boost::decimal::concepts {
241+
242+
template <typename T>
243+
concept execution_policy = std::is_execution_policy_v<std::remove_cvref_t<T>>;
244+
245+
} // Namespace boost::decimal::concepts
246+
247+
#define BOOST_DECIMAL_EXECUTION_POLICY boost::decimal::concepts::execution_policy
248+
249+
#endif // Has <execution>
250+
251+
#endif // Has <concepts>
252+
#endif // C++20
253+
254+
// If concepts are unavailable replace them with typename for compatibility
255+
256+
#ifndef BOOST_DECIMAL_INTEGRAL
257+
# define BOOST_DECIMAL_INTEGRAL typename
258+
#endif
259+
260+
#ifndef BOOST_DECIMAL_SIGNED_INTEGRAL
261+
# define BOOST_DECIMAL_SIGNED_INTEGRAL typename
262+
#endif
263+
264+
#ifndef BOOST_DECIMAL_UNSIGNED_INTEGRAL
265+
# define BOOST_DECIMAL_UNSIGNED_INTEGRAL typename
266+
#endif
267+
268+
#ifndef BOOST_DECIMAL_REAL
269+
# define BOOST_DECIMAL_REAL typename
270+
#endif
271+
272+
#ifndef BOOST_DECIMAL_COMPLEX
273+
# define BOOST_DECIMAL_COMPLEX typename
274+
#endif
275+
276+
#ifndef BOOST_DECIMAL_REAL_OR_COMPLEX
277+
# define BOOST_DECIMAL_REAL_OR_COMPLEX typename
278+
#endif
279+
280+
#ifndef BOOST_DECIMAL_ARITHMETIC
281+
# define BOOST_DECIMAL_ARITHMETIC typename
282+
#endif
283+
284+
#ifndef BOOST_DECIMAL_NUMERICAL
285+
# define BOOST_DECIMAL_NUMERICAL typename
286+
#endif
287+
288+
#ifndef BOOST_DECIMAL_SIGNED_ARITHMETIC
289+
# define BOOST_DECIMAL_SIGNED_ARITHMETIC typename
290+
#endif
291+
292+
#ifndef BOOST_DECIMAL_UNSIGNED_ARITHMETIC
293+
# define BOOST_DECIMAL_UNSIGNED_ARITHMETIC typename
294+
#endif
295+
296+
#ifndef BOOST_DECIMAL_ARBITRARY_UNSIGNED_ARITHMETIC
297+
# define BOOST_DECIMAL_ARBITRARY_UNSIGNED_ARITHMETIC typename
298+
#endif
299+
300+
#ifndef BOOST_DECIMAL_ARBITRARY_SIGNED_ARITHMETIC
301+
# define BOOST_DECIMAL_ARBITRARY_SIGNED_ARITHMETIC typename
302+
#endif
303+
304+
#ifndef BOOST_DECIMAL_ARBITRARY_ARITHMETIC
305+
# define BOOST_DECIMAL_ARBITRARY_ARITHMETIC typename
306+
#endif
307+
308+
#ifndef BOOST_DECIMAL_ARBITRARY_UNSIGNED_INTEGER
309+
# define BOOST_DECIMAL_ARBITRARY_UNSIGNED_INTEGER typename
310+
#endif
311+
312+
#ifndef BOOST_DECIMAL_ARBITRARY_SIGNED_INTEGER
313+
# define BOOST_DECIMAL_ARBITRARY_SIGNED_INTEGER typename
314+
#endif
315+
316+
#ifndef BOOST_DECIMAL_ARBITRARY_INTEGER
317+
# define BOOST_DECIMAL_ARBITRARY_INTEGER typename
318+
#endif
319+
320+
#ifndef BOOST_DECIMAL_ARBITRARY_REAL
321+
# define BOOST_DECIMAL_ARBITRARY_REAL typename
322+
#endif
323+
324+
#ifndef BOOST_DECIMAL_ARBITRARY_COMPLEX
325+
# define BOOST_DECIMAL_ARBITRARY_COMPLEX typename
326+
#endif
327+
328+
#ifndef BOOST_DECIMAL_ARBITRARY_REAL_OR_COMPLEX
329+
# define BOOST_DECIMAL_ARBITRARY_REAL_OR_COMPLEX typename
330+
#endif
331+
332+
#ifndef BOOST_DECIMAL_ARBITRARY_NUMERICAL
333+
# define BOOST_DECIMAL_ARBITRARY_NUMERICAL typename
334+
#endif
335+
336+
#ifndef BOOST_DECIMAL_POLICY
337+
# define BOOST_DECIMAL_POLICY typename
338+
#endif
339+
340+
#ifndef BOOST_DECIMAL_FORWARD_ITER
341+
# define BOOST_DECIMAL_FORWARD_ITER typename
342+
#endif
343+
344+
#ifndef BOOST_DECIMAL_BIDIRECTIONAL_ITER
345+
# define BOOST_DECIMAL_BIDIRECTIONAL_ITER typename
346+
#endif
347+
348+
#ifndef BOOST_DECIMAL_RANDOM_ACCESS_ITER
349+
# define BOOST_DECIMAL_RANDOM_ACCESS_ITER typename
350+
#endif
351+
352+
#ifndef BOOST_DECIMAL_DECIMAL_FLOATING_TYPE
353+
# define BOOST_DECIMAL_DECIMAL_FLOATING_TYPE typename
354+
#endif
355+
356+
#ifndef BOOST_DECIMAL_OUTPUT_ITER
357+
# define BOOST_DECIMAL_OUTPUT_ITER(I, T)
358+
#endif
359+
360+
#ifndef BOOST_DECIMAL_REQUIRES_ITER
361+
# define BOOST_DECIMAL_REQUIRES_ITER(X)
362+
#endif
363+
364+
#ifndef BOOST_DECIMAL_CONTAINER
365+
# define BOOST_DECIMAL_CONTAINER typename
366+
#endif
367+
368+
#ifndef BOOST_DECIMAL_RANDOM_ACCESS_CONTAINER
369+
# define BOOST_DECIMAL_RANDOM_ACCESS_CONTAINER typename
370+
#endif
371+
372+
#ifndef BOOST_DECIMAL_EXECUTION_POLICY
373+
# define BOOST_DECIMAL_EXECUTION_POLICY typename
374+
#endif
375+
376+
#ifndef BOOST_DECIMAL_REQUIRES
377+
# define BOOST_DECIMAL_REQUIRES(X, T)
378+
#endif
379+
380+
#endif //BOOST_DECIMAL_DETAIL_CONCEPTS

0 commit comments

Comments
 (0)