|
| 1 | +// Copyright 2023 - 2024 Matt Borland |
| 2 | +// Copyright 2023 - 2024 Christopher Kormanyos |
| 3 | +// Distributed under the Boost Software License, Version 1.0. |
| 4 | +// https://www.boost.org/LICENSE_1_0.txt |
| 5 | + |
| 6 | +#ifndef BOOST_DECIMAL_DETAIL_CMATH_IMPL_EXPM1_IMPL_HPP |
| 7 | +#define BOOST_DECIMAL_DETAIL_CMATH_IMPL_EXPM1_IMPL_HPP |
| 8 | + |
| 9 | +#include <boost/decimal/detail/concepts.hpp> |
| 10 | +#include <boost/decimal/detail/cmath/impl/taylor_series_result.hpp> |
| 11 | + |
| 12 | +#ifndef BOOST_DECIMAL_BUILD_MODULE |
| 13 | +#include <array> |
| 14 | +#include <cstddef> |
| 15 | +#include <cstdint> |
| 16 | +#endif |
| 17 | + |
| 18 | +namespace boost { |
| 19 | +namespace decimal { |
| 20 | +namespace detail { |
| 21 | + |
| 22 | +namespace expm1_detail { |
| 23 | + |
| 24 | +template <bool b> |
| 25 | +struct expm1_table_imp |
| 26 | +{ |
| 27 | +private: |
| 28 | + using d32_coeffs_t = std::array<decimal32, 10>; |
| 29 | + using d64_coeffs_t = std::array<decimal64, 14>; |
| 30 | + using d128_coeffs_t = std::array<decimal128, 32>; |
| 31 | + |
| 32 | +public: |
| 33 | + static constexpr d32_coeffs_t d32_coeffs = |
| 34 | + {{ |
| 35 | + // Specifically derive a polynomial expansion for Exp[x] - 1 for this work. |
| 36 | + // Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/60}] |
| 37 | + // N[%, 48] |
| 38 | + // Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10}, x] |
| 39 | + |
| 40 | + ::boost::decimal::decimal32 { UINT64_C(1000000000005449334), - 19 + 1 }, // * x |
| 41 | + ::boost::decimal::decimal32 { UINT64_C(5000000000003881336), - 19 - 0 }, // * x^2 |
| 42 | + ::boost::decimal::decimal32 { UINT64_C(1666666664242981149), - 19 - 0 }, // * x^3 |
| 43 | + ::boost::decimal::decimal32 { UINT64_C(4166666665026072773), - 19 - 1 }, // * x^4 |
| 44 | + ::boost::decimal::decimal32 { UINT64_C(8333336317448167991), - 19 - 2 }, // * x^5 |
| 45 | + ::boost::decimal::decimal32 { UINT64_C(1388889096793935619), - 19 - 2 }, // * x^6 |
| 46 | + ::boost::decimal::decimal32 { UINT64_C(1983978347911205530), - 19 - 3 }, // * x^7 |
| 47 | + ::boost::decimal::decimal32 { UINT64_C(2480049494648544583), - 19 - 4 }, // * x^8 |
| 48 | + ::boost::decimal::decimal32 { UINT64_C(2787876201220259352), - 19 - 5 }, // * x^9 |
| 49 | + ::boost::decimal::decimal32 { UINT64_C(2780855729673643225), - 19 - 6 }, // * x^10 |
| 50 | + }}; |
| 51 | + |
| 52 | + static constexpr d64_coeffs_t d64_coeffs = |
| 53 | + {{ |
| 54 | + // Specifically derive a polynomial expansion for Exp[x] - 1 for this work. |
| 55 | + // Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/60}] |
| 56 | + // N[%, 48] |
| 57 | + // Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10, x^11, x^12, x^13, x^14}, x] |
| 58 | + |
| 59 | + ::boost::decimal::decimal64 { UINT64_C(1000000000000000003), - 19 + 1 }, // * x |
| 60 | + ::boost::decimal::decimal64 { UINT64_C(4999999999999999998), - 19 - 0 }, // * x^2 |
| 61 | + ::boost::decimal::decimal64 { UINT64_C(1666666666666664035), - 19 - 0 }, // * x^3 |
| 62 | + ::boost::decimal::decimal64 { UINT64_C(4166666666666666934), - 19 - 1 }, // * x^4 |
| 63 | + ::boost::decimal::decimal64 { UINT64_C(8333333333339521841), - 19 - 2 }, // * x^5 |
| 64 | + ::boost::decimal::decimal64 { UINT64_C(1388888888888953513), - 19 - 2 }, // * x^6 |
| 65 | + ::boost::decimal::decimal64 { UINT64_C(1984126983488689186), - 19 - 3 }, // * x^7 |
| 66 | + ::boost::decimal::decimal64 { UINT64_C(2480158730001499149), - 19 - 4 }, // * x^8 |
| 67 | + ::boost::decimal::decimal64 { UINT64_C(2755732258782898252), - 19 - 5 }, // * x^9 |
| 68 | + ::boost::decimal::decimal64 { UINT64_C(2755732043147979013), - 19 - 6 }, // * x^10 |
| 69 | + ::boost::decimal::decimal64 { UINT64_C(2505116286861719378), - 19 - 7 }, // * x^11 |
| 70 | + ::boost::decimal::decimal64 { UINT64_C(2087632598463662328), - 19 - 8 }, // * x^12 |
| 71 | + ::boost::decimal::decimal64 { UINT64_C(1619385892296180390), - 19 - 9 }, // * x^13 |
| 72 | + ::boost::decimal::decimal64 { UINT64_C(1154399218598221557), - 19 - 10 } // * x^14 |
| 73 | + }}; |
| 74 | + |
| 75 | + static constexpr d128_coeffs_t d128_coeffs = |
| 76 | + {{ |
| 77 | + // Specifically derive a polynomial expansion for Exp[x] - 1 for this work. |
| 78 | + // Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/60}] |
| 79 | + // N[%, 48] |
| 80 | + // Fit[%, {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10, x^11, x^12, x^13, x^14, x^15, x^16, x^17, x^18, x^19, x^20, x^21, x^22, x^23, x^24, x^25, x^26, x^27, x^28, x^29, x^30, x^31, x^32 }, x] |
| 81 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(54210108624275), UINT64_C(4089650035136921600) }, -33 }, // * x |
| 82 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(271050543121376), UINT64_C(2001506101975056384) }, -34 }, // * x^2 |
| 83 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(90350181040458), UINT64_C(12964998083131386532) }, -34 }, // * x^3 |
| 84 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(225875452601146), UINT64_C(13965751134118914724) }, -35 }, // * x^4 |
| 85 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(451750905202293), UINT64_C(9484758194528277842) }, -36 }, // * x^5 |
| 86 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(75291817533715), UINT64_C(10804165069276155440) }, -36 }, // * x^6 |
| 87 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(107559739333879), UINT64_C(7528774067376128516) }, -37 }, // * x^7 |
| 88 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(134449674167349), UINT64_C(4799281565792772746) }, -38 }, // * x^8 |
| 89 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(149388526852610), UINT64_C(5332535073103080820) }, -39 }, // * x^9 |
| 90 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(149388526852610), UINT64_C(5332535073103080820) }, -40 }, // * x^10 |
| 91 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(135807751684191), UINT64_C(3170782423392841514) }, -41 }, // * x^11 |
| 92 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(113173126403492), UINT64_C(11865690723015477068) }, -42 }, // * x^12 |
| 93 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(87056251079609), UINT64_C(13384395342406416636) }, -43 }, // * x^13 |
| 94 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(62183036485435), UINT64_C(9560282387433156335) }, -44 }, // * x^14 |
| 95 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(414553576569570), UINT64_C(2246069003862680020) }, -46 }, // * x^15 |
| 96 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(259095985355981), UINT64_C(6015479145828949264) }, -47 }, // * x^16 |
| 97 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(152409403150577), UINT64_C(4623619732418095578) }, -48 }, // * x^17 |
| 98 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(84671890639209), UINT64_C(10767230558026320466) }, -49 }, // * x^18 |
| 99 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(445641529680050), UINT64_C(8125595620937745600) }, -51 }, // * x^19 |
| 100 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(222820764840025), UINT64_C(4062767274683195140) }, -52 }, // * x^20 |
| 101 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(106105126114297), UINT64_C(13344759429965740488) }, -53 }, // * x^21 |
| 102 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(482296027792262), UINT64_C(7088674266265745598) }, -55 }, // * x^22 |
| 103 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(209693925127072), UINT64_C(336105452763225878) }, -56 }, // * x^23 |
| 104 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(87372468802945), UINT64_C(10013088901203012320) }, -57 }, // * x^24 |
| 105 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(349489875208886), UINT64_C(9445768661182748344) }, -59 }, // * x^25 |
| 106 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(134419182774415), UINT64_C(9680981560342232810) }, -60 }, // * x^26 |
| 107 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(497848829278818), UINT64_C(16288994997110182382) }, -62 }, // * x^27 |
| 108 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(177803151475355), UINT64_C(16680206430774781810) }, -63 }, // * x^28 |
| 109 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(61311025561137), UINT64_C(7837795588749518446) }, -64 }, // * x^29 |
| 110 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(204371229207757), UINT64_C(18366861741830034248) }, -66 }, // * x^30 |
| 111 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(66162682638108), UINT64_C(6755035083974089930) }, -67 }, // * x^31 |
| 112 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(206436477688751), UINT64_C(15666750779045089894) }, -69 }, // * x^32 |
| 113 | + }}; |
| 114 | +}; |
| 115 | + |
| 116 | +#if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) |
| 117 | + |
| 118 | +template <bool b> |
| 119 | +constexpr typename expm1_table_imp<b>::d32_coeffs_t expm1_table_imp<b>::d32_coeffs; |
| 120 | + |
| 121 | +template <bool b> |
| 122 | +constexpr typename expm1_table_imp<b>::d64_coeffs_t expm1_table_imp<b>::d64_coeffs; |
| 123 | + |
| 124 | +template <bool b> |
| 125 | +constexpr typename expm1_table_imp<b>::d128_coeffs_t expm1_table_imp<b>::d128_coeffs; |
| 126 | + |
| 127 | +#endif |
| 128 | + |
| 129 | +} //namespace expm1_detail |
| 130 | + |
| 131 | +using expm1_table = expm1_detail::expm1_table_imp<true>; |
| 132 | + |
| 133 | +template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T> |
| 134 | +constexpr auto expm1_series_expansion(T x) noexcept; |
| 135 | + |
| 136 | +template <> |
| 137 | +constexpr auto expm1_series_expansion<decimal32>(decimal32 x) noexcept |
| 138 | +{ |
| 139 | + return taylor_series_result(x, expm1_table::d32_coeffs); |
| 140 | +} |
| 141 | + |
| 142 | +template <> |
| 143 | +constexpr auto expm1_series_expansion<decimal64>(decimal64 x) noexcept |
| 144 | +{ |
| 145 | + return taylor_series_result(x, expm1_table::d64_coeffs); |
| 146 | +} |
| 147 | + |
| 148 | +template <> |
| 149 | +constexpr auto expm1_series_expansion<decimal128>(decimal128 x) noexcept |
| 150 | +{ |
| 151 | + return taylor_series_result(x, expm1_table::d128_coeffs); |
| 152 | +} |
| 153 | + |
| 154 | +} //namespace detail |
| 155 | +} //namespace decimal |
| 156 | +} //namespace boost |
| 157 | + |
| 158 | +#endif //BOOST_DECIMAL_DETAIL_CMATH_IMPL_EXPM1_IMPL_HPP |
0 commit comments