|
| 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_LOG1P_IMPL_HPP |
| 7 | +#define BOOST_DECIMAL_DETAIL_CMATH_IMPL_LOG1P_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 log1p_detail { |
| 23 | + |
| 24 | +template <bool b> |
| 25 | +struct log1p_table_imp |
| 26 | +{ |
| 27 | +private: |
| 28 | + using d32_coeffs_t = std::array<decimal32, 12>; |
| 29 | + using d64_coeffs_t = std::array<decimal64, 20>; |
| 30 | + using d128_coeffs_t = std::array<decimal128, 36>; |
| 31 | + |
| 32 | +public: |
| 33 | + static constexpr d32_coeffs_t d32_coeffs = |
| 34 | + {{ |
| 35 | + // Series[Log[1 + x], {x, 0, 13}] |
| 36 | + // (1), // * z |
| 37 | + -boost::decimal::decimal32 { 5, -1 }, // * z^2 |
| 38 | + boost::decimal::decimal32 { UINT64_C(3333333333333333333), -19 }, // * z^3 |
| 39 | + -boost::decimal::decimal32 { 25, -2 }, // * z^4 |
| 40 | + boost::decimal::decimal32 { 2, -1 }, // * z^5 |
| 41 | + -boost::decimal::decimal32 { UINT64_C(1666666666666666667), -19 }, // * z^6 |
| 42 | + boost::decimal::decimal32 { UINT64_C(1428571428571428571), -19 }, // * z^7 |
| 43 | + -boost::decimal::decimal32 { 125, -3 }, // * z^8 |
| 44 | + boost::decimal::decimal32 { UINT64_C(1111111111111111111), -19 }, // * z^9 |
| 45 | + -boost::decimal::decimal32 { 1, -1 }, // * z^10 |
| 46 | + boost::decimal::decimal32 { UINT64_C(9090909090909090909), -19 - 1 }, // * z^11 |
| 47 | + -boost::decimal::decimal32 { UINT64_C(8333333333333333333), -19 - 1 }, // * z^12 |
| 48 | + boost::decimal::decimal32 { UINT64_C(7692307692307692308), -19 - 1 }, // * z^13 |
| 49 | + }}; |
| 50 | + |
| 51 | + static constexpr d64_coeffs_t d64_coeffs = |
| 52 | + {{ |
| 53 | + // Series[Log[1 + x], {x, 0, 21}] |
| 54 | + // (1), // * z |
| 55 | + -boost::decimal::decimal64 { 5, -1 }, // * z^2 |
| 56 | + boost::decimal::decimal64 { UINT64_C(3333333333333333333), -19 }, // * z^3 |
| 57 | + -boost::decimal::decimal64 { 25, -2 }, // * z^4 |
| 58 | + boost::decimal::decimal64 { 2, -1 }, // * z^5 |
| 59 | + -boost::decimal::decimal64 { UINT64_C(1666666666666666667), -19 }, // * z^6 |
| 60 | + boost::decimal::decimal64 { UINT64_C(1428571428571428571), -19 }, // * z^7 |
| 61 | + -boost::decimal::decimal64 { 125, -3 }, // * z^8 |
| 62 | + boost::decimal::decimal64 { UINT64_C(1111111111111111111), -19 }, // * z^9 |
| 63 | + -boost::decimal::decimal64 { 1, -1 }, // * z^10 |
| 64 | + boost::decimal::decimal64 { UINT64_C(9090909090909090909), -19 - 1 }, // * z^11 |
| 65 | + -boost::decimal::decimal64 { UINT64_C(8333333333333333333), -19 - 1 }, // * z^12 |
| 66 | + boost::decimal::decimal64 { UINT64_C(7692307692307692308), -19 - 1 }, // * z^13 |
| 67 | + -boost::decimal::decimal64 { UINT64_C(7142857142857142857), -19 - 1 }, // * z^14 |
| 68 | + boost::decimal::decimal64 { UINT64_C(6666666666666666667), -19 - 1 }, // * z^15 |
| 69 | + -boost::decimal::decimal64 { UINT64_C(6250000000000000000), -19 - 1 }, // * z^16 |
| 70 | + boost::decimal::decimal64 { UINT64_C(5882352941176470588), -19 - 1 }, // * z^17 |
| 71 | + -boost::decimal::decimal64 { UINT64_C(5555555555555555556), -19 - 1 }, // * z^18 |
| 72 | + boost::decimal::decimal64 { UINT64_C(5263157894736842105), -19 - 1 }, // * z^19 |
| 73 | + -boost::decimal::decimal64 { 5, -2 }, // * z^20 |
| 74 | + boost::decimal::decimal64 { UINT64_C(4761904761904761905), -19 - 1 }, // * z^21 |
| 75 | + }}; |
| 76 | + |
| 77 | + static constexpr d128_coeffs_t d128_coeffs = |
| 78 | + {{ |
| 79 | + // Series[Log[(1 + (z/2))/(1 - (z/2))], {z, 0, 43}] |
| 80 | + // (1), // * z |
| 81 | + -::boost::decimal::decimal128 { 5, -1 }, // * z^2 |
| 82 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(180700362080917), UINT64_C(7483252092553221458) }, -34 }, // * z^3 |
| 83 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(135525271560688), UINT64_C(1000753050987528192) }, -34 }, // * z^4 |
| 84 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(108420217248550), UINT64_C(8179300070273843200) }, -34 }, // * z^5 |
| 85 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(90350181040458), UINT64_C(12964998083131386532) }, -34 }, // * z^6 |
| 86 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(77443012320393), UINT64_C(3207108039665666332) }, -34 }, // * z^7 |
| 87 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(67762635780344), UINT64_C(500376525493764096) }, -34 }, // * z^8 |
| 88 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(60233454026972), UINT64_C(8643332055420924359) }, -34 }, // * z^9 |
| 89 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(54210108624275), UINT64_C(4089650035136921600) }, -34 }, // * z^10 |
| 90 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(492819169311592), UINT64_C(17054915875379776418) }, -35 }, // * z^11 |
| 91 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(451750905202293), UINT64_C(9484758194528277842) }, -35 }, // * z^12 |
| 92 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(417000835571347), UINT64_C(15850062977145160938) }, -35 }, // * z^13 |
| 93 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(387215061601965), UINT64_C(16035540198328331700) }, -35 }, // * z^14 |
| 94 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(361400724161834), UINT64_C(14966504185106442916) }, -35 }, // * z^15 |
| 95 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(338813178901720), UINT64_C(2501882627468820480) }, -35 }, // * z^16 |
| 96 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(318882991907501), UINT64_C(5610020838860575434) }, -35 }, // * z^17 |
| 97 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(301167270134862), UINT64_C(6323172129685518558) }, -35 }, // * z^18 |
| 98 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(285316361180395), UINT64_C(16670067533954968520) }, -35 }, // * z^19 |
| 99 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(271050543121376), UINT64_C(2001506101975056384) }, -35 }, // * z^20 |
| 100 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(258143374401310), UINT64_C(10690360132218887800) }, -35 }, // * z^21 |
| 101 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(246409584655796), UINT64_C(8527457937689888204) }, -35 }, // * z^22 |
| 102 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(235696124453370), UINT64_C(9760763598982462770) }, -35 }, // * z^23 |
| 103 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(225875452601146), UINT64_C(13965751134118914724) }, -35 }, // * z^24 |
| 104 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(216840434497100), UINT64_C(16358600140547686400) }, -35 }, // * z^25 |
| 105 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(208500417785673), UINT64_C(17148403525427356272) }, -35 }, // * z^26 |
| 106 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(200778180089908), UINT64_C(4215448086457012372) }, -35 }, // * z^27 |
| 107 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(193607530800982), UINT64_C(17241142136018941658) }, -35 }, // * z^28 |
| 108 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(186931409049224), UINT64_C(16646619993397598836) }, -35 }, // * z^29 |
| 109 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(180700362080917), UINT64_C(7483252092553221458) }, -35 }, // * z^30 |
| 110 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(174871318142823), UINT64_C(5456688082434451252) }, -35 }, // * z^31 |
| 111 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(169406589450860), UINT64_C(1250941313734410240) }, -35 }, // * z^32 |
| 112 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(164273056437197), UINT64_C(11833886649696442678) }, -35 }, // * z^33 |
| 113 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(159441495953750), UINT64_C(12028382456285063520) }, -35 }, // * z^34 |
| 114 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(154886024640786), UINT64_C(6414216079331332674) }, -35 }, // * z^35 |
| 115 | + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(150583635067431), UINT64_C(3161586064842759274) }, -35 }, // * z^36 |
| 116 | + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(146513807092635), UINT64_C(13545911456276754540) }, -35 }, // * z^37 |
| 117 | + }}; |
| 118 | +}; |
| 119 | + |
| 120 | +#if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) |
| 121 | + |
| 122 | +template <bool b> |
| 123 | +constexpr typename log1p_table_imp<b>::d32_coeffs_t log1p_table_imp<b>::d32_coeffs; |
| 124 | + |
| 125 | +template <bool b> |
| 126 | +constexpr typename log1p_table_imp<b>::d64_coeffs_t log1p_table_imp<b>::d64_coeffs; |
| 127 | + |
| 128 | +template <bool b> |
| 129 | +constexpr typename log1p_table_imp<b>::d128_coeffs_t log1p_table_imp<b>::d128_coeffs; |
| 130 | + |
| 131 | +#endif |
| 132 | + |
| 133 | +} //namespace log1p_detail |
| 134 | + |
| 135 | +using log1p_table = log1p_detail::log1p_table_imp<true>; |
| 136 | + |
| 137 | +template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T> |
| 138 | +constexpr auto log1p_series_expansion(T z2) noexcept; |
| 139 | + |
| 140 | +template <> |
| 141 | +constexpr auto log1p_series_expansion<decimal32>(decimal32 z2) noexcept |
| 142 | +{ |
| 143 | + return taylor_series_result(z2, log1p_table::d32_coeffs); |
| 144 | +} |
| 145 | + |
| 146 | +template <> |
| 147 | +constexpr auto log1p_series_expansion<decimal64>(decimal64 z2) noexcept |
| 148 | +{ |
| 149 | + return taylor_series_result(z2, log1p_table::d64_coeffs); |
| 150 | +} |
| 151 | + |
| 152 | +template <> |
| 153 | +constexpr auto log1p_series_expansion<decimal128>(decimal128 z2) noexcept |
| 154 | +{ |
| 155 | + return taylor_series_result(z2, log1p_table::d128_coeffs); |
| 156 | +} |
| 157 | + |
| 158 | +} //namespace detail |
| 159 | +} //namespace decimal |
| 160 | +} //namespace boost |
| 161 | + |
| 162 | +#endif //BOOST_DECIMAL_DETAIL_CMATH_IMPL_LOG1P_IMPL_HPP |
0 commit comments