diff --git a/include/boost/math/ccmath/abs.hpp b/include/boost/math/ccmath/abs.hpp index cd1e16d1f..bec9d1c49 100644 --- a/include/boost/math/ccmath/abs.hpp +++ b/include/boost/math/ccmath/abs.hpp @@ -20,7 +20,7 @@ namespace boost::math::ccmath { namespace detail { -template +template inline constexpr T abs_impl(T x) noexcept { return boost::math::ccmath::isnan(x) ? std::numeric_limits::quiet_NaN() : @@ -33,7 +33,7 @@ inline constexpr T abs_impl(T x) noexcept } // Namespace detail template , bool> = true> - BOOST_MATH_REQUIRES(BOOST_MATH_SIGNED_ARITHMETIC, T) + BOOST_MATH_REQUIRES(BOOST_MATH_ARBITRARY_SIGNED_ARITHMETIC, T) inline constexpr T abs(T x) noexcept { if(BOOST_MATH_IS_CONSTANT_EVALUATED(x)) @@ -50,7 +50,7 @@ inline constexpr T abs(T x) noexcept // If abs() is called with an argument of type X for which is_unsigned_v is true and if X // cannot be converted to int by integral promotion (7.3.7), the program is ill-formed. template , bool> = true> - BOOST_MATH_REQUIRES(BOOST_MATH_UNSIGNED_ARITHMETIC, T) + BOOST_MATH_REQUIRES(BOOST_MATH_ARBITRARY_UNSIGNED_ARITHMETIC, T) inline constexpr T abs(T x) noexcept { if constexpr (std::is_convertible_v) diff --git a/include/boost/math/concepts/concepts.hpp b/include/boost/math/concepts/concepts.hpp index 20ac3ce0b..b379eabec 100644 --- a/include/boost/math/concepts/concepts.hpp +++ b/include/boost/math/concepts/concepts.hpp @@ -6,15 +6,39 @@ #ifndef BOOST_MATH_CONCEPTS_CONCEPTS_HPP #define BOOST_MATH_CONCEPTS_CONCEPTS_HPP -#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L +#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::math::concepts { +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 = typename op_valid_impl::type; + +template +inline constexpr bool op_valid_v = op_valid::value; + template concept Integral = std::is_integral_v #ifdef __SIZEOF_INT128__ @@ -66,15 +90,56 @@ concept Unsigned_arithmetic = Arithmetic && (std::is_unsigned_v #endif ); +template +concept Arbitrary_unsigned_arithmetic_type = Unsigned_arithmetic || + (op_valid_v> && + op_valid_v> && + op_valid_v> && + op_valid_v> && + op_valid_v> && + op_valid_v> && + op_valid_v> && + op_valid_v> && + op_valid_v> && + op_valid_v> && + op_valid_v>); + +template +concept Arbitrary_signed_arithmetic_type = Signed_arithmetic || + (Arbitrary_unsigned_arithmetic_type && + op_valid_v>); + +template +concept Arbitrary_arithmetic_type = Arbitrary_unsigned_arithmetic_type || + Arbitrary_signed_arithmetic_type; + +template +concept Aribitrary_unsigned_integer_type = Arbitrary_unsigned_arithmetic_type && + std::numeric_limits::is_integer; + +template +concept Aribitrary_signed_integer_type = Arbitrary_signed_arithmetic_type && + std::numeric_limits::is_integer; + +template +concept Aribitrary_integer_type = Aribitrary_unsigned_integer_type || + Aribitrary_signed_integer_type; + } -#define BOOST_MATH_INTEGRAL boost::math::concepts::Integral -#define BOOST_MATH_SIGNED_INTEGRAL boost::math::concepts::Signed_integral -#define BOOST_MATH_UNSIGNED_INTEGRAL boost::math::concepts::Unsigned_integral +#define BOOST_MATH_INTEGRAL boost::math::concepts::Integral +#define BOOST_MATH_SIGNED_INTEGRAL boost::math::concepts::Signed_integral +#define BOOST_MATH_UNSIGNED_INTEGRAL boost::math::concepts::Unsigned_integral #define BOOST_MATH_REAL boost::math::concepts::Real #define BOOST_MATH_ARITHMETIC boost::math::concepts::Arithmetic #define BOOST_MATH_SIGNED_ARITHMETIC boost::math::concepts::Signed_arithmetic #define BOOST_MATH_UNSIGNED_ARITHMETIC boost::math::concepts::Unsigned_arithmetic +#define BOOST_MATH_ARBITRARY_UNSIGNED_ARITHMETIC boost::math::concepts::Arbitrary_unsigned_arithmetic_type +#define BOOST_MATH_ARBITRARY_SIGNED_ARITHMETIC boost::math::concepts::Arbitrary_signed_arithmetic_type +#define BOOST_MATH_ARBITRARY_ARITHMETIC boost::math::concepts::Arbitrary_arithmetic_type +#define BOOST_MATH_ARBITRARY_UNSIGNED_INTEGER boost::math::concepts::Aribitrary_unsigned_integer_type +#define BOOST_MATH_ARBITRARY_SIGNED_INTEGER boost::math::concepts::Aribitrary_signed_integer_type +#define BOOST_MATH_ARBITRARY_INTEGER boost::math::concepts::Aribitrary_integer_type #define BOOST_MATH_REQUIRES(X, T) requires X #endif @@ -108,6 +173,30 @@ concept Unsigned_arithmetic = Arithmetic && (std::is_unsigned_v # define BOOST_MATH_UNSIGNED_ARITHMETIC typename #endif +#ifndef BOOST_MATH_ARBITRARY_UNSIGNED_ARITHMETIC +# define BOOST_MATH_ARBITRARY_UNSIGNED_ARITHMETIC typename +#endif + +#ifndef BOOST_MATH_ARBITRARY_SIGNED_ARITHMETIC +# define BOOST_MATH_ARBITRARY_SIGNED_ARITHMETIC typename +#endif + +#ifndef BOOST_MATH_ARBITRARY_ARITHMETIC +# define BOOST_MATH_ARBITRARY_ARITHMETIC typename +#endif + +#ifndef BOOST_MATH_ARBITRARY_UNSIGNED_INTEGER +# define BOOST_MATH_ARBITRARY_UNSIGNED_INTEGER typename +#endif + +#ifndef BOOST_MATH_ARBITRARY_SIGNED_INTEGER +# define BOOST_MATH_ARBITRARY_SIGNED_INTEGER typename +#endif + +#ifndef BOOST_MATH_ARBITRARY_INTEGER +# define BOOST_MATH_ARBITRARY_INTEGER typename +#endif + #ifndef BOOST_MATH_REQUIRES # define BOOST_MATH_REQUIRES(X, T) #endif