This PR adds the code of Boost.Math as of version 1.89 into the third-party directory, as discussed in a recent RFC [1]. The goal is for this code to be used as a back-end for the C++17 Math Special Functions. As explained in third-paty/README.md, this code is cleared for usage inside libc++ for the Math Special functions, however the LLVM Foundation should be consulted before using this code anywhere else in the LLVM project, due to the fact that it is under the Boost Software License (as opposed to the usual LLVM license). See the RFC [1] for more details. [1]: https://discourse.llvm.org/t/rfc-libc-taking-a-dependency-on-boost-math-for-the-c-17-math-special-functions
424 lines
12 KiB
C++
424 lines
12 KiB
C++
// Copyright Peter Dimov 2015-2021.
|
|
// Copyright Matt Borland 2021.
|
|
// Use, modification and distribution are subject to the
|
|
// Boost Software License, Version 1.0. (See accompanying file
|
|
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
// Template metaprogramming classes and functions to replace MPL
|
|
// Source: http://www.pdimov.com/cpp2/simple_cxx11_metaprogramming.html
|
|
// Source: https://github.com/boostorg/mp11/
|
|
|
|
#ifndef BOOST_MATH_TOOLS_MP
|
|
#define BOOST_MATH_TOOLS_MP
|
|
|
|
#include <boost/math/tools/config.hpp>
|
|
#include <boost/math/tools/type_traits.hpp>
|
|
#include <boost/math/tools/cstdint.hpp>
|
|
|
|
namespace boost { namespace math { namespace tools { namespace meta_programming {
|
|
|
|
// Types:
|
|
// Typelist
|
|
template<typename... T>
|
|
struct mp_list {};
|
|
|
|
// Size_t
|
|
template<boost::math::size_t N>
|
|
using mp_size_t = boost::math::integral_constant<boost::math::size_t, N>;
|
|
|
|
// Boolean
|
|
template<bool B>
|
|
using mp_bool = boost::math::integral_constant<bool, B>;
|
|
|
|
// Identity
|
|
template<typename T>
|
|
struct mp_identity
|
|
{
|
|
using type = T;
|
|
};
|
|
|
|
// Turns struct into quoted metafunction
|
|
template<template<typename...> class F>
|
|
struct mp_quote_trait
|
|
{
|
|
template<typename... T>
|
|
using fn = typename F<T...>::type;
|
|
};
|
|
|
|
namespace detail {
|
|
// Size
|
|
template<typename L>
|
|
struct mp_size_impl {};
|
|
|
|
template<template<typename...> class L, typename... T> // Template template parameter must use class
|
|
struct mp_size_impl<L<T...>>
|
|
{
|
|
using type = boost::math::integral_constant<boost::math::size_t, sizeof...(T)>;
|
|
};
|
|
}
|
|
|
|
template<typename T>
|
|
using mp_size = typename detail::mp_size_impl<T>::type;
|
|
|
|
namespace detail {
|
|
// Front
|
|
template<typename L>
|
|
struct mp_front_impl {};
|
|
|
|
template<template<typename...> class L, typename T1, typename... T>
|
|
struct mp_front_impl<L<T1, T...>>
|
|
{
|
|
using type = T1;
|
|
};
|
|
}
|
|
|
|
template<typename T>
|
|
using mp_front = typename detail::mp_front_impl<T>::type;
|
|
|
|
namespace detail {
|
|
// At
|
|
// TODO - Use tree based lookup for larger typelists
|
|
// http://odinthenerd.blogspot.com/2017/04/tree-based-lookup-why-kvasirmpl-is.html
|
|
template<typename L, boost::math::size_t>
|
|
struct mp_at_c {};
|
|
|
|
template<template<typename...> class L, typename T0, typename... T>
|
|
struct mp_at_c<L<T0, T...>, 0>
|
|
{
|
|
using type = T0;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename... T>
|
|
struct mp_at_c<L<T0, T1, T...>, 1>
|
|
{
|
|
using type = T1;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename T2, typename... T>
|
|
struct mp_at_c<L<T0, T1, T2, T...>, 2>
|
|
{
|
|
using type = T2;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename... T>
|
|
struct mp_at_c<L<T0, T1, T2, T3, T...>, 3>
|
|
{
|
|
using type = T3;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename... T>
|
|
struct mp_at_c<L<T0, T1, T2, T3, T4, T...>, 4>
|
|
{
|
|
using type = T4;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename... T>
|
|
struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T...>, 5>
|
|
{
|
|
using type = T5;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
|
|
typename... T>
|
|
struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T...>, 6>
|
|
{
|
|
using type = T6;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
|
|
typename T7, typename... T>
|
|
struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T...>, 7>
|
|
{
|
|
using type = T7;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
|
|
typename T7, typename T8, typename... T>
|
|
struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T...>, 8>
|
|
{
|
|
using type = T8;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
|
|
typename T7, typename T8, typename T9, typename... T>
|
|
struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>, 9>
|
|
{
|
|
using type = T9;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
|
|
typename T7, typename T8, typename T9, typename T10, typename... T>
|
|
struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, 10>
|
|
{
|
|
using type = T10;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
|
|
typename T7, typename T8, typename T9, typename T10, typename T11, typename... T>
|
|
struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T...>, 11>
|
|
{
|
|
using type = T11;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
|
|
typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename... T>
|
|
struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T...>, 12>
|
|
{
|
|
using type = T12;
|
|
};
|
|
}
|
|
|
|
template<typename L, boost::math::size_t Index>
|
|
using mp_at_c = typename detail::mp_at_c<L, Index>::type;
|
|
|
|
template<typename L, typename Index>
|
|
using mp_at = typename detail::mp_at_c<L, Index::value>::type;
|
|
|
|
// Back
|
|
template<typename L>
|
|
using mp_back = mp_at_c<L, mp_size<L>::value - 1>;
|
|
|
|
namespace detail {
|
|
// Push back
|
|
template<typename L, typename... T>
|
|
struct mp_push_back_impl {};
|
|
|
|
template<template<typename...> class L, typename... U, typename... T>
|
|
struct mp_push_back_impl<L<U...>, T...>
|
|
{
|
|
using type = L<U..., T...>;
|
|
};
|
|
}
|
|
|
|
template<typename L, typename... T>
|
|
using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type;
|
|
|
|
namespace detail {
|
|
// Push front
|
|
template<typename L, typename... T>
|
|
struct mp_push_front_impl {};
|
|
|
|
template<template<typename...> class L, typename... U, typename... T>
|
|
struct mp_push_front_impl<L<U...>, T...>
|
|
{
|
|
using type = L<T..., U...>;
|
|
};
|
|
}
|
|
|
|
template<typename L, typename... T>
|
|
using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;
|
|
|
|
namespace detail{
|
|
// If
|
|
template<bool C, typename T, typename... E>
|
|
struct mp_if_c_impl{};
|
|
|
|
template<typename T, typename... E>
|
|
struct mp_if_c_impl<true, T, E...>
|
|
{
|
|
using type = T;
|
|
};
|
|
|
|
template<typename T, typename E>
|
|
struct mp_if_c_impl<false, T, E>
|
|
{
|
|
using type = E;
|
|
};
|
|
}
|
|
|
|
template<bool C, typename T, typename... E>
|
|
using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
|
|
|
|
template<typename C, typename T, typename... E>
|
|
using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;
|
|
|
|
namespace detail {
|
|
// Find if
|
|
template<typename L, template<typename...> class P>
|
|
struct mp_find_if_impl {};
|
|
|
|
template<template<typename...> class L, template<typename...> class P>
|
|
struct mp_find_if_impl<L<>, P>
|
|
{
|
|
using type = mp_size_t<0>;
|
|
};
|
|
|
|
template<typename L, template<typename...> class P>
|
|
struct mp_find_if_impl_2
|
|
{
|
|
using r = typename mp_find_if_impl<L, P>::type;
|
|
using type = mp_size_t<1 + r::value>;
|
|
};
|
|
|
|
template<template<typename...> class L, typename T1, typename... T, template<typename...> class P>
|
|
struct mp_find_if_impl<L<T1, T...>, P>
|
|
{
|
|
using type = typename mp_if<P<T1>, mp_identity<mp_size_t<0>>, mp_find_if_impl_2<mp_list<T...>, P>>::type;
|
|
};
|
|
}
|
|
|
|
template<typename L, template<typename...> class P>
|
|
using mp_find_if = typename detail::mp_find_if_impl<L, P>::type;
|
|
|
|
template<typename L, typename Q>
|
|
using mp_find_if_q = mp_find_if<L, Q::template fn>;
|
|
|
|
namespace detail {
|
|
// Append
|
|
template<typename... L>
|
|
struct mp_append_impl {};
|
|
|
|
template<>
|
|
struct mp_append_impl<>
|
|
{
|
|
using type = mp_list<>;
|
|
};
|
|
|
|
template<template<typename...> class L, typename... T>
|
|
struct mp_append_impl<L<T...>>
|
|
{
|
|
using type = L<T...>;
|
|
};
|
|
|
|
template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2>
|
|
struct mp_append_impl<L1<T1...>, L2<T2...>>
|
|
{
|
|
using type = L1<T1..., T2...>;
|
|
};
|
|
|
|
template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
|
|
template<typename...> class L3, typename... T3>
|
|
struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>>
|
|
{
|
|
using type = L1<T1..., T2..., T3...>;
|
|
};
|
|
|
|
template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
|
|
template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4>
|
|
struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>>
|
|
{
|
|
using type = L1<T1..., T2..., T3..., T4...>;
|
|
};
|
|
|
|
template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
|
|
template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4,
|
|
template<typename...> class L5, typename... T5, typename... Lr>
|
|
struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L5<T5...>, Lr...>
|
|
{
|
|
using type = typename mp_append_impl<L1<T1..., T2..., T3..., T4..., T5...>, Lr...>::type;
|
|
};
|
|
}
|
|
|
|
template<typename... L>
|
|
using mp_append = typename detail::mp_append_impl<L...>::type;
|
|
|
|
namespace detail {
|
|
// Remove if
|
|
template<typename L, template<typename...> class P>
|
|
struct mp_remove_if_impl{};
|
|
|
|
template<template<typename...> class L, typename... T, template<typename...> class P>
|
|
struct mp_remove_if_impl<L<T...>, P>
|
|
{
|
|
template<typename U>
|
|
struct _f
|
|
{
|
|
using type = mp_if<P<U>, mp_list<>, mp_list<U>>;
|
|
};
|
|
|
|
using type = mp_append<L<>, typename _f<T>::type...>;
|
|
};
|
|
}
|
|
|
|
template<typename L, template<class...> class P>
|
|
using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type;
|
|
|
|
template<typename L, typename Q>
|
|
using mp_remove_if_q = mp_remove_if<L, Q::template fn>;
|
|
|
|
template<typename T, T... Index>
|
|
struct integer_sequence {};
|
|
|
|
template<boost::math::size_t... Index>
|
|
using index_sequence = integer_sequence<boost::math::size_t, Index...>;
|
|
|
|
namespace detail {
|
|
|
|
template<bool C, typename T, typename E>
|
|
struct iseq_if_c_impl {};
|
|
|
|
template<typename T, typename F>
|
|
struct iseq_if_c_impl<true, T, F>
|
|
{
|
|
using type = T;
|
|
};
|
|
|
|
template<typename T, typename F>
|
|
struct iseq_if_c_impl<false, T, F>
|
|
{
|
|
using type = F;
|
|
};
|
|
|
|
template<bool C, typename T, typename F>
|
|
using iseq_if_c = typename iseq_if_c_impl<C, T, F>::type;
|
|
|
|
template<typename T>
|
|
struct iseq_identity
|
|
{
|
|
using type = T;
|
|
};
|
|
|
|
template<typename T1, typename T2>
|
|
struct append_integer_sequence {};
|
|
|
|
template<typename T, T... Index, T... J>
|
|
struct append_integer_sequence<integer_sequence<T, Index...>, integer_sequence<T, J...>>
|
|
{
|
|
using type = integer_sequence<T, Index..., (J + sizeof...(Index))...>;
|
|
};
|
|
|
|
template<typename T, T N>
|
|
struct make_integer_sequence_impl;
|
|
|
|
template<typename T, T N>
|
|
class make_integer_sequence_impl_
|
|
{
|
|
private:
|
|
static_assert(N >= 0, "N must not be negative");
|
|
|
|
static constexpr T M = N / 2;
|
|
static constexpr T R = N % 2;
|
|
|
|
using seq1 = typename make_integer_sequence_impl<T, M>::type;
|
|
using seq2 = typename append_integer_sequence<seq1, seq1>::type;
|
|
using seq3 = typename make_integer_sequence_impl<T, R>::type;
|
|
using seq4 = typename append_integer_sequence<seq2, seq3>::type;
|
|
|
|
public:
|
|
using type = seq4;
|
|
};
|
|
|
|
template<typename T, T N>
|
|
struct make_integer_sequence_impl
|
|
{
|
|
using type = typename iseq_if_c<N == 0,
|
|
iseq_identity<integer_sequence<T>>,
|
|
iseq_if_c<N == 1, iseq_identity<integer_sequence<T, 0>>,
|
|
make_integer_sequence_impl_<T, N>>>::type;
|
|
};
|
|
|
|
} // namespace detail
|
|
|
|
template<typename T, T N>
|
|
using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type;
|
|
|
|
template<boost::math::size_t N>
|
|
using make_index_sequence = make_integer_sequence<boost::math::size_t, N>;
|
|
|
|
template<typename... T>
|
|
using index_sequence_for = make_integer_sequence<boost::math::size_t, sizeof...(T)>;
|
|
|
|
}}}} // namespaces
|
|
|
|
#endif // BOOST_MATH_TOOLS_MP
|