Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add arbitrary arithmetic concepts
[ci skip]
  • Loading branch information
mborland committed Oct 17, 2022
commit a4cd40ff4db6afc602dde96242f182df272f69cd
6 changes: 3 additions & 3 deletions include/boost/math/ccmath/abs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() :
Expand All @@ -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))
Expand All @@ -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>)
Expand Down
99 changes: 94 additions & 5 deletions include/boost/math/concepts/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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__
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down