2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00

Add arbitrary arithmetic concepts

[ci skip]
This commit is contained in:
Matt Borland
2022-10-17 10:39:40 -07:00
parent c495bf73ed
commit a4cd40ff4d
2 changed files with 97 additions and 8 deletions

View File

@@ -20,7 +20,7 @@ namespace boost::math::ccmath {
namespace detail {
template <BOOST_MATH_ARITHMETIC T>
template <BOOST_MATH_ARBITRARY_SIGNED_ARITHMETIC T>
inline constexpr T abs_impl(T x) noexcept
{
return boost::math::ccmath::isnan(x) ? std::numeric_limits<T>::quiet_NaN() :
@@ -33,7 +33,7 @@ inline constexpr T abs_impl(T x) noexcept
} // Namespace detail
template <typename T, std::enable_if_t<!std::is_unsigned_v<T>, 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<X> is true and if X
// cannot be converted to int by integral promotion (7.3.7), the program is ill-formed.
template <typename T, std::enable_if_t<std::is_unsigned_v<T>, 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<T, int>)

View File

@@ -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(<concepts>)
#include <concepts>
#include <utility>
#include <algorithm>
#include <concepts>
#include <functional>
#include <type_traits>
#include <limits>
#include <boost/math/tools/config.hpp>
#include <boost/math/concepts/real_type_concept.hpp>
namespace boost::math::concepts {
template <typename X, typename Y, typename Op>
struct op_valid_impl
{
template <typename U, typename L, typename R>
static constexpr auto test(int) -> decltype(std::declval<U>()(std::declval<L>(), std::declval<R>()),
void(), std::true_type());
template <typename U, typename L, typename R>
static constexpr auto test(...) -> std::false_type;
using type = decltype(test<Op, X, Y>(0));
};
template <typename X, typename Y, typename Op>
using op_valid = typename op_valid_impl<X, Y, Op>::type;
template <typename X, typename Y, typename Op>
inline constexpr bool op_valid_v = op_valid<X, Y, Op>::value;
template <typename T>
concept Integral = std::is_integral_v<T>
#ifdef __SIZEOF_INT128__
@@ -66,15 +90,56 @@ concept Unsigned_arithmetic = Arithmetic<T> && (std::is_unsigned_v<T>
#endif
);
template <typename T>
concept Arbitrary_unsigned_arithmetic_type = Unsigned_arithmetic<T> ||
(op_valid_v<T, T, std::equal_to<>> &&
op_valid_v<T, T, std::not_equal_to<>> &&
op_valid_v<T, T, std::greater<>> &&
op_valid_v<T, T, std::less<>> &&
op_valid_v<T, T, std::greater_equal<>> &&
op_valid_v<T, T, std::less_equal<>> &&
op_valid_v<T, T, std::plus<>> &&
op_valid_v<T, T, std::minus<>> &&
op_valid_v<T, T, std::multiplies<>> &&
op_valid_v<T, T, std::divides<>> &&
op_valid_v<T, T, std::modulus<>>);
template <typename T>
concept Arbitrary_signed_arithmetic_type = Signed_arithmetic<T> ||
(Arbitrary_unsigned_arithmetic_type<T> &&
op_valid_v<T, T, std::negate<>>);
template <typename T>
concept Arbitrary_arithmetic_type = Arbitrary_unsigned_arithmetic_type<T> ||
Arbitrary_signed_arithmetic_type<T>;
template <typename T>
concept Aribitrary_unsigned_integer_type = Arbitrary_unsigned_arithmetic_type<T> &&
std::numeric_limits<T>::is_integer;
template <typename T>
concept Aribitrary_signed_integer_type = Arbitrary_signed_arithmetic_type<T> &&
std::numeric_limits<T>::is_integer;
template <typename T>
concept Aribitrary_integer_type = Aribitrary_unsigned_integer_type<T> ||
Aribitrary_signed_integer_type<T>;
}
#define BOOST_MATH_INTEGRAL boost::math::concepts::Integral<T>
#define BOOST_MATH_SIGNED_INTEGRAL boost::math::concepts::Signed_integral<T>
#define BOOST_MATH_UNSIGNED_INTEGRAL boost::math::concepts::Unsigned_integral<T>
#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<T>
#endif
@@ -108,6 +173,30 @@ concept Unsigned_arithmetic = Arithmetic<T> && (std::is_unsigned_v<T>
# 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