diff --git a/include/boost/decimal/detail/concepts.hpp b/include/boost/decimal/detail/concepts.hpp new file mode 100644 index 000000000..1c9cab5c2 --- /dev/null +++ b/include/boost/decimal/detail/concepts.hpp @@ -0,0 +1,380 @@ +// Copyright 2022 - 2023 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_DECIMAL_DETAIL_CONCEPTS +#define BOOST_DECIMAL_DETAIL_CONCEPTS + +#if (__cplusplus >= 202002L || _MSVC_LANG >= 202002L) && !defined(BOOST_MATH_DISABLE_CONCEPTS) + +#if __has_include() + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost::decimal::concepts { + +namespace detail { + +template +struct op_valid_impl +{ + template + static constexpr auto test(int) -> decltype(std::declval()(std::declval(), std::declval()), + void(), std::true_type()); + + template + static constexpr auto test(...) -> std::false_type; + + using type = decltype(test(0)); +}; + +template +using op_valid_t = typename op_valid_impl::type; + +template +inline constexpr bool op_valid_v = op_valid_t::value; + +// Detector for class member functions +struct nonesuch +{ + nonesuch(const nonesuch&) = delete; + ~nonesuch() = delete; + void operator=(const nonesuch&) = delete; +}; + +template typename Op, typename... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template typename Op, typename... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template typename Op, typename... Args> +using is_detected = typename detector::value_t; + +template typename Op, typename... Args> +using detected_t = typename detector::type; + +#define BOOST_DECIMAL_HAS_MEMBER_FUNCTION(member) \ +template \ +using has_##member##_t = decltype(std::declval().member()); \ + \ +template \ +inline constexpr bool has_##member##_v = is_detected::value; + +BOOST_DECIMAL_HAS_MEMBER_FUNCTION(begin) +BOOST_DECIMAL_HAS_MEMBER_FUNCTION(end) +BOOST_DECIMAL_HAS_MEMBER_FUNCTION(real) +BOOST_DECIMAL_HAS_MEMBER_FUNCTION(imag) + +} // Namespace detail + +template +concept integral = std::is_integral_v; + +template +concept signed_integral = integral && std::is_signed_v; + +template +concept unsigned_integral = integral && std::is_unsigned_v; + +template +concept real = std::is_floating_point_v; + +template +concept complex = std::is_same_v> + || std::is_same_v> + #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS + || std::is_same_v> + #endif + ; + +template +concept real_or_complex = real || complex; + +template +concept arithmetic = std::is_arithmetic_v; + +template +concept numerical = arithmetic || real_or_complex; + +template +concept signed_arithmetic = arithmetic && std::is_signed_v; + +template +concept unsigned_arithmetic = arithmetic && std::is_unsigned_v; + +template +concept arbitrary_unsigned_arithmetic_type = unsigned_arithmetic || + (detail::op_valid_v> && + detail::op_valid_v> && + detail::op_valid_v> && + detail::op_valid_v> && + detail::op_valid_v> && + detail::op_valid_v> && + detail::op_valid_v> && + detail::op_valid_v> && + detail::op_valid_v> && + detail::op_valid_v>); + +template +concept arbitrary_signed_arithmetic_type = signed_arithmetic || + (arbitrary_unsigned_arithmetic_type && + (detail::op_valid_v> || + std::numeric_limits::is_signed)); + +template +concept arbitrary_arithmetic_type = arbitrary_unsigned_arithmetic_type || + arbitrary_signed_arithmetic_type; + +template +concept arbitrary_unsigned_integer_type = arbitrary_unsigned_arithmetic_type && + std::numeric_limits::is_integer; + +template +concept arbitrary_signed_integer_type = arbitrary_signed_arithmetic_type && + std::numeric_limits::is_integer; + +template +concept arbitrary_integer_type = arbitrary_unsigned_integer_type || + arbitrary_signed_integer_type; + +template +concept arbitrary_real_type = arbitrary_arithmetic_type && + !std::numeric_limits::is_integer; + +template +concept arbitrary_complex_type = complex || + (detail::has_real_v && + detail::has_imag_v); + +template +concept arbitrary_real_or_complex_type = arbitrary_real_type || + arbitrary_complex_type; + +template +concept arbitrary_numerical_type = arbitrary_real_or_complex_type || + arbitrary_arithmetic_type; + +template +concept derived_from = std::is_base_of_v && + std::is_convertible_v; + +template +concept forward_iterator = derived_from::iterator_category, std::forward_iterator_tag>; + +template +concept bidirectional_iterator = derived_from::iterator_category, std::bidirectional_iterator_tag>; + +template +concept random_access_iterator = derived_from::iterator_category, std::random_access_iterator_tag>; + +template +concept output_iterator = derived_from::iterator_category, std::input_iterator_tag> && + derived_from::iterator_category, std::output_iterator_tag>; + +template +concept is_container = detail::has_begin_v && + detail::has_end_v; + +template +concept random_access_container = is_container && + boost::decimal::concepts::random_access_iterator; + +template +concept decimal_floating_point_type = detail::is_decimal_floating_point_v; + +} // boost::decimal::concepts + +#define BOOST_DECIMAL_INTEGRAL boost::decimal::concepts::integral +#define BOOST_DECIMAL_SIGNED_INTEGRAL boost::decimal::concepts::signed_integral +#define BOOST_DECIMAL_UNSIGNED_INTEGRAL boost::decimal::concepts::unsigned_integral +#define BOOST_DECIMAL_REAL boost::decimal::concepts::real +#define BOOST_DECIMAL_COMPLEX boost::decimal::concepts::complex +#define BOOST_DECIMAL_REAL_OR_COMPLEX boost::decimal::concepts::real_or_complex +#define BOOST_DECIMAL_ARITHMETIC boost::decimal::concepts::arithmetic +#define BOOST_DECIMAL_NUMERICAL boost::decimal::concepts::numerical +#define BOOST_DECIMAL_SIGNED_ARITHMETIC boost::decimal::concepts::signed_arithmetic +#define BOOST_DECIMAL_UNSIGNED_ARITHMETIC boost::decimal::concepts::unsigned_arithmetic +#define BOOST_DECIMAL_ARBITRARY_UNSIGNED_ARITHMETIC boost::decimal::concepts::arbitrary_unsigned_arithmetic_type +#define BOOST_DECIMAL_ARBITRARY_SIGNED_ARITHMETIC boost::decimal::concepts::arbitrary_signed_arithmetic_type +#define BOOST_DECIMAL_ARBITRARY_ARITHMETIC boost::decimal::concepts::arbitrary_arithmetic_type +#define BOOST_DECIMAL_ARBITRARY_UNSIGNED_INTEGER boost::decimal::concepts::arbitrary_unsigned_integer_type +#define BOOST_DECIMAL_ARBITRARY_SIGNED_INTEGER boost::decimal::concepts::arbitrary_signed_integer_type +#define BOOST_DECIMAL_ARBITRARY_INTEGER boost::decimal::concepts::arbitrary_integer_type +#define BOOST_DECIMAL_ARBITRARY_REAL boost::decimal::concepts::arbitrary_real_type +#define BOOST_DECIMAL_ARBITRARY_COMPLEX boost::decimal::concepts::arbitrary_complex_type +#define BOOST_DECIMAL_ARBITRARY_REAL_OR_COMPLEX boost::decimal::concepts::arbitrary_real_or_complex_type +#define BOOST_DECIMAL_ARBITRARY_NUMERICAL boost::decimal::concepts::arbitrary_numerical_type +#define BOOST_DECIMAL_DECIMAL_FLOATING_TYPE boost::decimal::concepts::decimal_floating_point_type + +#define BOOST_DECIMAL_CONTAINER boost::decimal::concepts::is_container +#define BOOST_DECIMAL_RANDOM_ACCESS_CONTAINER boost::decimal::concepts::random_access_container + +#define BOOST_DECIMAL_FORWARD_ITER boost::decimal::concepts::forward_iterator +#define BOOST_DECIMAL_BIDIRECTIONAL_ITER boost::decimal::concepts::bidirectional_iterator +#define BOOST_DECIMAL_RANDOM_ACCESS_ITER boost::decimal::concepts::random_access_iterator +#define BOOST_DECIMAL_OUTPUT_ITER(I, T) boost::decimal::concepts::output_iterator +#define BOOST_DECIMAL_REQUIRES_ITER(X) requires X + +#define BOOST_DECIMAL_REQUIRES(X, T) requires X + +#ifdef BOOST_DECIMAL_EXEC_COMPATIBLE +#include + +namespace boost::decimal::concepts { + +template +concept execution_policy = std::is_execution_policy_v>; + +} // Namespace boost::decimal::concepts + +#define BOOST_DECIMAL_EXECUTION_POLICY boost::decimal::concepts::execution_policy + +#endif // Has + +#endif // Has +#endif // C++20 + +// If concepts are unavailable replace them with typename for compatibility + +#ifndef BOOST_DECIMAL_INTEGRAL +# define BOOST_DECIMAL_INTEGRAL typename +#endif + +#ifndef BOOST_DECIMAL_SIGNED_INTEGRAL +# define BOOST_DECIMAL_SIGNED_INTEGRAL typename +#endif + +#ifndef BOOST_DECIMAL_UNSIGNED_INTEGRAL +# define BOOST_DECIMAL_UNSIGNED_INTEGRAL typename +#endif + +#ifndef BOOST_DECIMAL_REAL +# define BOOST_DECIMAL_REAL typename +#endif + +#ifndef BOOST_DECIMAL_COMPLEX +# define BOOST_DECIMAL_COMPLEX typename +#endif + +#ifndef BOOST_DECIMAL_REAL_OR_COMPLEX +# define BOOST_DECIMAL_REAL_OR_COMPLEX typename +#endif + +#ifndef BOOST_DECIMAL_ARITHMETIC +# define BOOST_DECIMAL_ARITHMETIC typename +#endif + +#ifndef BOOST_DECIMAL_NUMERICAL +# define BOOST_DECIMAL_NUMERICAL typename +#endif + +#ifndef BOOST_DECIMAL_SIGNED_ARITHMETIC +# define BOOST_DECIMAL_SIGNED_ARITHMETIC typename +#endif + +#ifndef BOOST_DECIMAL_UNSIGNED_ARITHMETIC +# define BOOST_DECIMAL_UNSIGNED_ARITHMETIC typename +#endif + +#ifndef BOOST_DECIMAL_ARBITRARY_UNSIGNED_ARITHMETIC +# define BOOST_DECIMAL_ARBITRARY_UNSIGNED_ARITHMETIC typename +#endif + +#ifndef BOOST_DECIMAL_ARBITRARY_SIGNED_ARITHMETIC +# define BOOST_DECIMAL_ARBITRARY_SIGNED_ARITHMETIC typename +#endif + +#ifndef BOOST_DECIMAL_ARBITRARY_ARITHMETIC +# define BOOST_DECIMAL_ARBITRARY_ARITHMETIC typename +#endif + +#ifndef BOOST_DECIMAL_ARBITRARY_UNSIGNED_INTEGER +# define BOOST_DECIMAL_ARBITRARY_UNSIGNED_INTEGER typename +#endif + +#ifndef BOOST_DECIMAL_ARBITRARY_SIGNED_INTEGER +# define BOOST_DECIMAL_ARBITRARY_SIGNED_INTEGER typename +#endif + +#ifndef BOOST_DECIMAL_ARBITRARY_INTEGER +# define BOOST_DECIMAL_ARBITRARY_INTEGER typename +#endif + +#ifndef BOOST_DECIMAL_ARBITRARY_REAL +# define BOOST_DECIMAL_ARBITRARY_REAL typename +#endif + +#ifndef BOOST_DECIMAL_ARBITRARY_COMPLEX +# define BOOST_DECIMAL_ARBITRARY_COMPLEX typename +#endif + +#ifndef BOOST_DECIMAL_ARBITRARY_REAL_OR_COMPLEX +# define BOOST_DECIMAL_ARBITRARY_REAL_OR_COMPLEX typename +#endif + +#ifndef BOOST_DECIMAL_ARBITRARY_NUMERICAL +# define BOOST_DECIMAL_ARBITRARY_NUMERICAL typename +#endif + +#ifndef BOOST_DECIMAL_POLICY +# define BOOST_DECIMAL_POLICY typename +#endif + +#ifndef BOOST_DECIMAL_FORWARD_ITER +# define BOOST_DECIMAL_FORWARD_ITER typename +#endif + +#ifndef BOOST_DECIMAL_BIDIRECTIONAL_ITER +# define BOOST_DECIMAL_BIDIRECTIONAL_ITER typename +#endif + +#ifndef BOOST_DECIMAL_RANDOM_ACCESS_ITER +# define BOOST_DECIMAL_RANDOM_ACCESS_ITER typename +#endif + +#ifndef BOOST_DECIMAL_DECIMAL_FLOATING_TYPE +# define BOOST_DECIMAL_DECIMAL_FLOATING_TYPE typename +#endif + +#ifndef BOOST_DECIMAL_OUTPUT_ITER +# define BOOST_DECIMAL_OUTPUT_ITER(I, T) +#endif + +#ifndef BOOST_DECIMAL_REQUIRES_ITER +# define BOOST_DECIMAL_REQUIRES_ITER(X) +#endif + +#ifndef BOOST_DECIMAL_CONTAINER +# define BOOST_DECIMAL_CONTAINER typename +#endif + +#ifndef BOOST_DECIMAL_RANDOM_ACCESS_CONTAINER +# define BOOST_DECIMAL_RANDOM_ACCESS_CONTAINER typename +#endif + +#ifndef BOOST_DECIMAL_EXECUTION_POLICY +# define BOOST_DECIMAL_EXECUTION_POLICY typename +#endif + +#ifndef BOOST_DECIMAL_REQUIRES +# define BOOST_DECIMAL_REQUIRES(X, T) +#endif + +#endif //BOOST_DECIMAL_DETAIL_CONCEPTS