diff --git a/sprout/math/bernoulli.hpp b/sprout/math/bernoulli.hpp new file mode 100644 index 00000000..674592bd --- /dev/null +++ b/sprout/math/bernoulli.hpp @@ -0,0 +1,231 @@ +#ifndef SPROUT_MATH_BERNOULLI_HPP +#define SPROUT_MATH_BERNOULLI_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace math { + namespace detail { + template + struct bernoulli_numbers; + + template<> + struct bernoulli_numbers { + public: + typedef float type; + public: + SPROUT_STATIC_CONSTEXPR std::size_t limit = 64; + public: + typedef sprout::array table_type; + public: + SPROUT_STATIC_CONSTEXPR table_type table = table_type{{ + 1.F, + 1.F / 6, + -1.F / 30, + 1.F / 42, + -1.F / 30, + 5.F / 66, + -691.F / 2730, + 7.F / 6, + -3617.F / 510, + 43867.F / 798, + -174611.F / 330, + 854513.F / 138, + -236364091.F / 2730, + 8553103.F / 6, + -236364091.F / 870, + 8615841276005.F / 14322, + -7709321041217.F / 510, + 2577687858367.F / 6, + -26315271553053477373.F / 1919190, + 2929993913841559.F / 6, + -261082718496449122051.F / 13530, + 1520097643918070802691.F / 1806, + -2.783326957930102423502e22F / 690, + 5.96451111593912163278e23F / 282, + -1.20866265222965259346e23F, + 7.500866746076964366856e24F, + -5.038778101481068914138e26F, + 3.65287764848181233351e28F, + -2.849876930245088222627e30F, + 2.386542749968362764465e32F, + -2.139994925722533366581e34F, + 2.050097572347809756992e36F, + -2.09380059113463784091e38F + }}; + }; + SPROUT_CONSTEXPR typename sprout::math::detail::bernoulli_numbers< + float + >::table_type sprout::math::detail::bernoulli_numbers< + float + >::table; + + template<> + struct bernoulli_numbers { + public: + typedef double type; + public: + SPROUT_STATIC_CONSTEXPR std::size_t limit = 100; + public: + typedef sprout::array table_type; + public: + SPROUT_STATIC_CONSTEXPR table_type table = table_type{{ + 1., + 1. / 6, + -1. / 30, + 1. / 42, + -1. / 30, + 5. / 66, + -691. / 2730, + 7. / 6, + -3617. / 510, + 43867. / 798, + -174611. / 330, + 854513. / 138, + -236364091. / 2730, + 8553103. / 6, + -236364091. / 870, + 8615841276005. / 14322, + -7709321041217. / 510, + 2577687858367. / 6, + -26315271553053477373. / 1919190, + 2929993913841559. / 6, + -261082718496449122051. / 13530, + 1520097643918070802691. / 1806, + -2.783326957930102423502e22 / 690, + 5.96451111593912163278e23 / 282, + -1.20866265222965259346e23, + 7.500866746076964366856e24, + -5.038778101481068914138e26, + 3.65287764848181233351e28, + -2.849876930245088222627e30, + 2.386542749968362764465e32, + -2.139994925722533366581e34, + 2.050097572347809756992e36, + -2.09380059113463784091e38, + 2.275269648846351555965e40, + -2.62577102862395760473e42, + 3.21250821027180325182e44, + -4.159827816679471091392e46, + 5.692069548203528002388e48, + -8.21836294197845756923e50, + 1.250290432716699301673e53, + -2.001558323324837027493e55, + 3.36749829153643742334e57, + -5.947097050313544771866e59, + 1.101191032362797755956e62, + -2.135525954525350118866e64, + 4.332889698664119241962e66, + -9.18855282416693282262e68 , + 2.034689677632907449346e71, + -4.70038339580357310786e73, + 1.131804344548424927068e76, + -2.838224957069370695926e78 + }}; + }; + SPROUT_CONSTEXPR typename sprout::math::detail::bernoulli_numbers< + double + >::table_type sprout::math::detail::bernoulli_numbers< + double + >::table; + + template<> + struct bernoulli_numbers { + public: + typedef long double type; + public: + SPROUT_STATIC_CONSTEXPR std::size_t limit = 100; + public: + typedef sprout::array table_type; + public: + SPROUT_STATIC_CONSTEXPR table_type table = table_type{{ + 1.L, + 1.L / 6, + -1.L / 30, + 1.L / 42, + -1.L / 30, + 5.L / 66, + -691.L / 2730, + 7.L / 6, + -3617.L / 510, + 43867.L / 798, + -174611.L / 330, + 854513.L / 138, + -236364091.L / 2730, + 8553103.L / 6, + -236364091.L / 870, + 8615841276005.L / 14322, + -7709321041217.L / 510, + 2577687858367.L / 6, + -26315271553053477373.L / 1919190, + 2929993913841559.L / 6, + -261082718496449122051.L / 13530, + 1520097643918070802691.L / 1806, + -2.783326957930102423502e22L / 690, + 5.96451111593912163278e23L / 282, + -1.20866265222965259346e23L, + 7.500866746076964366856e24L, + -5.038778101481068914138e26L, + 3.65287764848181233351e28L, + -2.849876930245088222627e30L, + 2.386542749968362764465e32L, + -2.139994925722533366581e34L, + 2.050097572347809756992e36L, + -2.09380059113463784091e38L, + 2.275269648846351555965e40L, + -2.62577102862395760473e42L, + 3.21250821027180325182e44L, + -4.159827816679471091392e46L, + 5.692069548203528002388e48L, + -8.21836294197845756923e50L, + 1.250290432716699301673e53L, + -2.001558323324837027493e55L, + 3.36749829153643742334e57L, + -5.947097050313544771866e59L, + 1.101191032362797755956e62L, + -2.135525954525350118866e64L, + 4.332889698664119241962e66L, + -9.18855282416693282262e68L, + 2.034689677632907449346e71L, + -4.70038339580357310786e73L, + 1.131804344548424927068e76L, + -2.838224957069370695926e78L + }}; + }; + SPROUT_CONSTEXPR typename sprout::math::detail::bernoulli_numbers< + long double + >::table_type sprout::math::detail::bernoulli_numbers< + long double + >::table; + } // namespace detail + // + // bernoulli_number_limit + // + template::value>::type> + SPROUT_CONSTEXPR std::size_t bernoulli_number_limit() { + typedef typename std::remove_cv::type type; + return sprout::math::detail::bernoulli_numbers::limit; + } + // + // bernoulli_number + // + template::value>::type> + SPROUT_CONSTEXPR T bernoulli_number(std::size_t x) { + typedef typename std::remove_cv::type type; + return x <= sprout::math::bernoulli_number_limit() + ? x == 1 ? type(-1) / 2 + : x % 2 ? type(0) + : sprout::math::detail::bernoulli_numbers::table[x / 2] + : throw std::invalid_argument("bernoulli_number(): argument limit exceeded") + ; + } + } // namespace math + + using sprout::math::bernoulli_number; +} // namespace sprout + +#endif // #ifndef SPROUT_MATH_BERNOULLI_HPP diff --git a/sprout/math/factorial.hpp b/sprout/math/factorial.hpp index 109aed89..8a36d00f 100644 --- a/sprout/math/factorial.hpp +++ b/sprout/math/factorial.hpp @@ -2,20 +2,23 @@ #define SPROUT_MATH_FACTORIAL_HPP #include -#include #include +#include #include #include +#include +#include namespace sprout { namespace math { namespace detail { - template + template struct factorials; - template<> - struct factorials { + + template + struct factorials::value && sizeof(T) == 1>::type> { public: - typedef std::int8_t type; + typedef T type; public: SPROUT_STATIC_CONSTEXPR std::size_t limit = 5; public: @@ -30,11 +33,17 @@ namespace sprout { 120 }}; }; - SPROUT_CONSTEXPR typename sprout::math::detail::factorials::table_type sprout::math::detail::factorials::table; - template<> - struct factorials { + template + SPROUT_CONSTEXPR typename sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 1>::type + >::table_type sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 1>::type + >::table; + + template + struct factorials::value && sizeof(T) == 1>::type> { public: - typedef std::uint8_t type; + typedef T type; public: SPROUT_STATIC_CONSTEXPR std::size_t limit = 5; public: @@ -49,11 +58,17 @@ namespace sprout { 120 }}; }; - SPROUT_CONSTEXPR typename sprout::math::detail::factorials::table_type sprout::math::detail::factorials::table; - template<> - struct factorials { + template + SPROUT_CONSTEXPR typename sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 1>::type + >::table_type sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 1>::type + >::table; + + template + struct factorials::value && sizeof(T) == 2>::type> { public: - typedef std::int16_t type; + typedef T type; public: SPROUT_STATIC_CONSTEXPR std::size_t limit = 7; public: @@ -70,11 +85,17 @@ namespace sprout { 5040 }}; }; - SPROUT_CONSTEXPR typename sprout::math::detail::factorials::table_type sprout::math::detail::factorials::table; - template<> - struct factorials { + template + SPROUT_CONSTEXPR typename sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 2>::type + >::table_type sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 2>::type + >::table; + + template + struct factorials::value && sizeof(T) == 2>::type> { public: - typedef std::uint16_t type; + typedef T type; public: SPROUT_STATIC_CONSTEXPR std::size_t limit = 8; public: @@ -92,11 +113,17 @@ namespace sprout { 40320 }}; }; - SPROUT_CONSTEXPR typename sprout::math::detail::factorials::table_type sprout::math::detail::factorials::table; - template<> - struct factorials { + template + SPROUT_CONSTEXPR typename sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 2>::type + >::table_type sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 2>::type + >::table; + + template + struct factorials::value && sizeof(T) == 4>::type> { public: - typedef std::int32_t type; + typedef T type; public: SPROUT_STATIC_CONSTEXPR std::size_t limit = 11; public: @@ -117,11 +144,17 @@ namespace sprout { 39916800 }}; }; - SPROUT_CONSTEXPR typename sprout::math::detail::factorials::table_type sprout::math::detail::factorials::table; - template<> - struct factorials { + template + SPROUT_CONSTEXPR typename sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 4>::type + >::table_type sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 4>::type + >::table; + + template + struct factorials::value && sizeof(T) == 4>::type> { public: - typedef std::uint32_t type; + typedef T type; public: SPROUT_STATIC_CONSTEXPR std::size_t limit = 11; public: @@ -142,11 +175,17 @@ namespace sprout { 39916800 }}; }; - SPROUT_CONSTEXPR typename sprout::math::detail::factorials::table_type sprout::math::detail::factorials::table; - template<> - struct factorials { + template + SPROUT_CONSTEXPR typename sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 4>::type + >::table_type sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 4>::type + >::table; + + template + struct factorials::value && sizeof(T) == 8>::type> { public: - typedef std::int64_t type; + typedef T type; public: SPROUT_STATIC_CONSTEXPR std::size_t limit = 20; public: @@ -176,11 +215,17 @@ namespace sprout { INT64_C(2432902008176640000) }}; }; - SPROUT_CONSTEXPR typename sprout::math::detail::factorials::table_type sprout::math::detail::factorials::table; - template<> - struct factorials { + template + SPROUT_CONSTEXPR typename sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 8>::type + >::table_type sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 8>::type + >::table; + + template + struct factorials::value && sizeof(T) == 8>::type> { public: - typedef std::uint64_t type; + typedef T type; public: SPROUT_STATIC_CONSTEXPR std::size_t limit = 20; public: @@ -210,11 +255,17 @@ namespace sprout { UINT64_C(2432902008176640000) }}; }; - SPROUT_CONSTEXPR typename sprout::math::detail::factorials::table_type sprout::math::detail::factorials::table; - template<> - struct factorials { + template + SPROUT_CONSTEXPR typename sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 8>::type + >::table_type sprout::math::detail::factorials< + T, typename std::enable_if::value && sizeof(T) == 8>::type + >::table; + + template + struct factorials::value>::type> { public: - typedef float type; + typedef T type; public: SPROUT_STATIC_CONSTEXPR std::size_t limit = 34; public: @@ -258,11 +309,17 @@ namespace sprout { 0.29523279903960414084761860964352e39F }}; }; - SPROUT_CONSTEXPR typename sprout::math::detail::factorials::table_type sprout::math::detail::factorials::table; - template<> - struct factorials { + template + SPROUT_CONSTEXPR typename sprout::math::detail::factorials< + T, typename std::enable_if::value>::type + >::table_type sprout::math::detail::factorials< + T, typename std::enable_if::value>::type + >::table; + + template + struct factorials::value>::type> { public: - typedef double type; + typedef T type; public: SPROUT_STATIC_CONSTEXPR std::size_t limit = 170; public: @@ -442,11 +499,17 @@ namespace sprout { 0.7257415615307998967396728211129263114717e307 }}; }; - SPROUT_CONSTEXPR typename sprout::math::detail::factorials::table_type sprout::math::detail::factorials::table; - template<> - struct factorials { + template + SPROUT_CONSTEXPR typename sprout::math::detail::factorials< + T, typename std::enable_if::value>::type + >::table_type sprout::math::detail::factorials< + T, typename std::enable_if::value>::type + >::table; + + template + struct factorials::value>::type> { public: - typedef long double type; + typedef T type; public: SPROUT_STATIC_CONSTEXPR std::size_t limit = 170; public: @@ -626,22 +689,29 @@ namespace sprout { 0.7257415615307998967396728211129263114717e307L }}; }; - SPROUT_CONSTEXPR typename sprout::math::detail::factorials::table_type sprout::math::detail::factorials::table; + template + SPROUT_CONSTEXPR typename sprout::math::detail::factorials< + T, typename std::enable_if::value>::type + >::table_type sprout::math::detail::factorials< + T, typename std::enable_if::value>::type + >::table; } // namespace detail // // factorial_limit // - template + template::value>::type> SPROUT_CONSTEXPR std::size_t factorial_limit() { - return sprout::math::detail::factorials::limit; + typedef typename std::remove_cv::type type; + return sprout::math::detail::factorials::limit; } // // factorial // - template + template::value>::type> SPROUT_CONSTEXPR T factorial(std::size_t x) { - return x <= sprout::math::factorial_limit() - ? sprout::math::detail::factorials::table[x] + typedef typename std::remove_cv::type type; + return x <= sprout::math::factorial_limit() + ? sprout::math::detail::factorials::table[x] : throw std::invalid_argument("factorial(): argument limit exceeded") ; } diff --git a/sprout/math/functions.hpp b/sprout/math/functions.hpp index 48aba0cc..5d2ef3c2 100644 --- a/sprout/math/functions.hpp +++ b/sprout/math/functions.hpp @@ -9,5 +9,6 @@ #include #include #include +#include #endif // #ifndef SPROUT_MATH_FUNCTIONS_HPP diff --git a/sprout/type_traits.hpp b/sprout/type_traits.hpp index 2349489f..45d0d21e 100644 --- a/sprout/type_traits.hpp +++ b/sprout/type_traits.hpp @@ -2,6 +2,8 @@ #define SPROUT_TYPE_TRAITS_HPP #include +#include +#include #include #include #include diff --git a/sprout/type_traits/is_int.hpp b/sprout/type_traits/is_int.hpp new file mode 100644 index 00000000..145ac547 --- /dev/null +++ b/sprout/type_traits/is_int.hpp @@ -0,0 +1,20 @@ +#ifndef SPROUT_TYPE_TRAITS_IS_INT_HPP +#define SPROUT_TYPE_TRAITS_IS_INT_HPP + +#include +#include + +namespace sprout { + // + // is_int + // + template + struct is_int + : public std::integral_constant< + bool, + std::is_integral::value && std::is_signed::value + > + {}; +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_TRAITS_IS_INT_HPP diff --git a/sprout/type_traits/is_uint.hpp b/sprout/type_traits/is_uint.hpp new file mode 100644 index 00000000..7924000a --- /dev/null +++ b/sprout/type_traits/is_uint.hpp @@ -0,0 +1,20 @@ +#ifndef SPROUT_TYPE_TRAITS_IS_UINT_HPP +#define SPROUT_TYPE_TRAITS_IS_UINT_HPP + +#include +#include + +namespace sprout { + // + // is_uint + // + template + struct is_uint + : public std::integral_constant< + bool, + std::is_integral::value && std::is_unsigned::value + > + {}; +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_TRAITS_IS_UINT_HPP