diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc4eca4ba..7e7674c5e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -248,7 +248,7 @@ jobs: cxxstd: "03,11,14,17,20,2b" os: macos-14 - timeout-minutes: 120 + timeout-minutes: 180 runs-on: ${{matrix.os}} container: ${{matrix.container}} diff --git a/include/boost/decimal/charconv.hpp b/include/boost/decimal/charconv.hpp index 036ed0abc..dd8693150 100644 --- a/include/boost/decimal/charconv.hpp +++ b/include/boost/decimal/charconv.hpp @@ -113,6 +113,11 @@ BOOST_DECIMAL_EXPORT constexpr auto from_chars(const char* first, const char* la return detail::from_chars_general_impl(first, last, value, fmt); } +BOOST_DECIMAL_EXPORT constexpr auto from_chars(const char* first, const char* last, decimal128_fast& value, chars_format fmt = chars_format::general) noexcept +{ + return detail::from_chars_general_impl(first, last, value, fmt); +} + // --------------------------------------------------------------------------------------------------------------------- // to_chars and implementation // --------------------------------------------------------------------------------------------------------------------- @@ -242,7 +247,7 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_scientific_impl(char* first, char* last, c int exp {}; auto significand {frexp10(value, &exp)}; - using uint_type = std::conditional_t::value, uint128, std::uint64_t>; + using uint_type = std::conditional_t::value || std::is_same::value, uint128, std::uint64_t>; auto significand_digits = num_digits(significand); exp += significand_digits - 1; bool append_zeros = false; @@ -473,7 +478,8 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_fixed_impl(char* first, char* last, const } } - using uint_type = std::conditional_t::value, uint128, std::uint64_t>; + using uint_type = std::conditional_t::value || + std::is_same::value, uint128, std::uint64_t>; auto r = to_chars_integer_impl(first, last, significand, 10); if (BOOST_DECIMAL_UNLIKELY(!r)) @@ -579,7 +585,8 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_fixed_impl(char* first, char* last, const template BOOST_DECIMAL_CONSTEXPR auto to_chars_hex_impl(char* first, char* last, const TargetDecimalType& value, int precision = -1) noexcept -> to_chars_result { - using Unsigned_Integer = std::conditional_t::value, std::uint64_t, uint128>; + using Unsigned_Integer = std::conditional_t::value || + std::is_same::value, uint128, std::uint64_t>; if (signbit(value)) { @@ -868,6 +875,26 @@ BOOST_DECIMAL_EXPORT BOOST_DECIMAL_CONSTEXPR auto to_chars(char* first, char* la return detail::to_chars_impl(first, last, value, fmt, precision); } +BOOST_DECIMAL_EXPORT BOOST_DECIMAL_CONSTEXPR auto to_chars(char* first, char* last, decimal128_fast value) noexcept -> to_chars_result +{ + return detail::to_chars_impl(first, last, value); +} + +BOOST_DECIMAL_EXPORT BOOST_DECIMAL_CONSTEXPR auto to_chars(char* first, char* last, decimal128_fast value, chars_format fmt) noexcept -> to_chars_result +{ + return detail::to_chars_impl(first, last, value, fmt); +} + +BOOST_DECIMAL_EXPORT BOOST_DECIMAL_CONSTEXPR auto to_chars(char* first, char* last, decimal128_fast value, chars_format fmt, int precision) noexcept -> to_chars_result +{ + if (precision < 0) + { + precision = 6; + } + + return detail::to_chars_impl(first, last, value, fmt, precision); +} + template struct limits { diff --git a/include/boost/decimal/decimal128_fast.hpp b/include/boost/decimal/decimal128_fast.hpp index 062f670d7..4e9c8700a 100644 --- a/include/boost/decimal/decimal128_fast.hpp +++ b/include/boost/decimal/decimal128_fast.hpp @@ -107,6 +107,14 @@ class decimal128_fast final -> std::enable_if_t<(detail::is_decimal_floating_point_v && detail::is_decimal_floating_point_v), bool>; + template + friend constexpr auto ilogb(T d) noexcept + BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, T, int); + + template + friend constexpr auto logb(T num) noexcept + BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T); + public: constexpr decimal128_fast() noexcept = default; @@ -253,6 +261,31 @@ class decimal128_fast final friend constexpr auto operator/(Integer lhs, decimal128_fast rhs) noexcept BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast); + // Compound Arithmetic Operators + constexpr auto operator+=(decimal128_fast rhs) noexcept -> decimal128_fast&; + + template + constexpr auto operator+=(Integer rhs) noexcept + BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&); + + constexpr auto operator-=(decimal128_fast rhs) noexcept -> decimal128_fast&; + + template + constexpr auto operator-=(Integer rhs) noexcept + BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&); + + constexpr auto operator*=(decimal128_fast rhs) noexcept -> decimal128_fast&; + + template + constexpr auto operator*=(Integer rhs) noexcept + BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&); + + constexpr auto operator/=(decimal128_fast rhs) noexcept -> decimal128_fast&; + + template + constexpr auto operator/=(Integer rhs) noexcept + BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&); + // Conversions explicit constexpr operator bool() const noexcept; explicit constexpr operator int() const noexcept; @@ -295,35 +328,10 @@ class decimal128_fast final template friend constexpr auto frexp10(T num, int* expptr) noexcept -> typename T::significand_type; - #if !defined(BOOST_DECIMAL_DISABLE_CLIB) - - // LCOV_EXCL_START - // TODO(mborland): Fix with STL bindings and delete - template - friend auto operator<<(std::basic_ostream& os, const decimal128_fast& d) -> std::basic_ostream& - { - if (d.sign_) - { - os << "-"; - } - else - { - os << "+"; - } - - os << d.significand_ << "e"; - const auto biased_exp {d.biased_exponent()}; - if (biased_exp > 0) - { - os << '+'; - } - os << biased_exp; - - return os; - } - // LCOV_EXCL_STOP - - #endif + friend constexpr auto copysignd128f(decimal128_fast mag, decimal128_fast sgn) noexcept -> decimal128_fast; + friend constexpr auto scalblnd128f(decimal128_fast num, long exp) noexcept -> decimal128_fast; + friend constexpr auto scalbnd128f(decimal128_fast num, int exp) noexcept -> decimal128_fast; + friend constexpr auto fmad128f(decimal128_fast x, decimal128_fast y, decimal128 z) noexcept -> decimal128; }; #ifdef BOOST_DECIMAL_HAS_CONCEPTS @@ -986,6 +994,7 @@ constexpr auto operator*(decimal128_fast lhs, decimal128_fast rhs) noexcept -> d } #endif + // TODO(mborland): Is trimming the zeros really necessary? Doesn't seem like it auto lhs_sig {lhs.full_significand()}; auto lhs_exp {lhs.biased_exponent()}; const auto lhs_zeros {detail::remove_trailing_zeros(lhs_sig)}; @@ -1238,6 +1247,62 @@ constexpr auto operator%(decimal128_fast lhs, decimal128_fast rhs) noexcept -> d return r; }; +constexpr auto decimal128_fast::operator+=(decimal128_fast rhs) noexcept -> decimal128_fast& +{ + *this = *this + rhs; + return *this; +} + +template +constexpr auto decimal128_fast::operator+=(Integer rhs) noexcept + BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&) +{ + *this = *this + rhs; + return *this; +} + +constexpr auto decimal128_fast::operator-=(decimal128_fast rhs) noexcept -> decimal128_fast& +{ + *this = *this - rhs; + return *this; +} + +template +constexpr auto decimal128_fast::operator-=(Integer rhs) noexcept + BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&) +{ + *this = *this - rhs; + return *this; +} + +constexpr auto decimal128_fast::operator*=(decimal128_fast rhs) noexcept -> decimal128_fast& +{ + *this = *this * rhs; + return *this; +} + +template +constexpr auto decimal128_fast::operator*=(Integer rhs) noexcept + BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&) +{ + *this = *this * rhs; + return *this; +} + +constexpr auto decimal128_fast::operator/=(decimal128_fast rhs) noexcept -> decimal128_fast& +{ + *this = *this / rhs; + return *this; +} + +template +constexpr auto decimal128_fast::operator/=(Integer rhs) noexcept + BOOST_DECIMAL_REQUIRES_RETURN(detail::is_integral_v, Integer, decimal128_fast&) +{ + *this = *this / rhs; + return *this; +} + constexpr decimal128_fast::operator bool() const noexcept { constexpr decimal128_fast zero {0, 0}; @@ -1354,6 +1419,33 @@ constexpr decimal128_fast::operator Decimal() const noexcept return to_decimal(*this); } +constexpr auto copysignd128f(decimal128_fast mag, decimal128_fast sgn) noexcept -> decimal128_fast +{ + mag.sign_ = sgn.sign_; + return mag; +} + +constexpr auto scalblnd128f(decimal128_fast num, long exp) noexcept -> decimal128_fast +{ + #ifndef BOOST_DECIMAL_FAST_MATH + constexpr decimal128_fast zero {0, 0}; + + if (num == zero || exp == 0 || isinf(num) || isnan(num)) + { + return num; + } + #endif + + num.exponent_ = static_cast(static_cast(num.biased_exponent()) + exp); + + return num; +} + +constexpr auto scalbnd128f(decimal128_fast num, int exp) noexcept -> decimal128_fast +{ + return scalblnd128f(num, static_cast(exp)); +} + } // namespace decimal } // namespace boost diff --git a/include/boost/decimal/detail/attributes.hpp b/include/boost/decimal/detail/attributes.hpp index 1ede3edd1..9d490131f 100644 --- a/include/boost/decimal/detail/attributes.hpp +++ b/include/boost/decimal/detail/attributes.hpp @@ -26,36 +26,54 @@ BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto storage_wid template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto storage_width_v = 128; +template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto storage_width_v = 128; + template , bool> = true> BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto precision_v = std::is_same::value || std::is_same::value ? 7 : 16; template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto precision_v = 34; +template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto precision_v = 34; + template , bool> = true> BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto bias_v = std::is_same::value || std::is_same::value ? 101 : 398; template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto bias_v = 6176; +template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto bias_v = 6176; + template , bool> = true> BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto max_biased_exp_v = std::is_same::value || std::is_same::value ? 191 : 767; template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_biased_exp_v = 12287; +template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_biased_exp_v = 12287; + template , bool> = true> BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto emax_v = std::is_same::value || std::is_same::value ? 96 : 384; template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto emax_v = 6144; +template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto emax_v = 6144; + template , bool> = true> BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto emin_v = std::is_same::value || std::is_same::value ? -95 : -383; template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto emin_v = -6143; +template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto emin_v = -6143; + template , bool> = true> BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto etiny_v = -bias_v; @@ -65,12 +83,18 @@ BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto combination template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto combination_field_width_v = 17; +template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto combination_field_width_v = 17; + template , bool> = true> BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto trailing_significand_field_width_v = std::is_same::value || std::is_same::value ? 20 : 50; template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto trailing_significand_field_width_v = 110; +template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto trailing_significand_field_width_v = 110; + template , bool> = true> BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto max_significand_v = std::is_same::value || std::is_same::value ? 9'999'999 : 9'999'999'999'999'999; @@ -78,6 +102,10 @@ template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_significand_v = uint128{UINT64_C(0b1111111111'1111111111'1111111111'1111111111'111111), UINT64_MAX}; +template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_significand_v = + uint128{UINT64_C(0b1111111111'1111111111'1111111111'1111111111'111111), UINT64_MAX}; + // sign + decimal digits + '.' + 'e' + '+/-' + max digits of exponent + null term template , bool> = true> BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto max_string_length_v = std::is_same::value || std::is_same::value ? 15 : 25; @@ -85,6 +113,9 @@ BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto max_string_ template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_string_length_v = 41; +template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION auto max_string_length_v = 41; + BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto storage_width {storage_width_v}; BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto precision {precision_v}; BOOST_DECIMAL_ATTRIBUTE_UNUSED BOOST_DECIMAL_CONSTEXPR_VARIABLE auto bias {bias_v}; diff --git a/include/boost/decimal/detail/cmath/fma.hpp b/include/boost/decimal/detail/cmath/fma.hpp index 76559ea5f..f7ec9bccf 100644 --- a/include/boost/decimal/detail/cmath/fma.hpp +++ b/include/boost/decimal/detail/cmath/fma.hpp @@ -300,6 +300,11 @@ constexpr auto fmad64f(decimal64_fast x, decimal64_fast y, decimal64_fast z) noe return {result.sig, result.exp, result.sign}; } +constexpr auto fmad128f(decimal128_fast x, decimal128_fast y, decimal128_fast z) noexcept -> decimal128_fast +{ + return x * y + z; +} + BOOST_DECIMAL_EXPORT constexpr auto fma(decimal32 x, decimal32 y, decimal32 z) noexcept -> decimal32 { return fmad32(x, y, z); @@ -325,6 +330,11 @@ BOOST_DECIMAL_EXPORT constexpr auto fma(decimal64_fast x, decimal64_fast y, deci return fmad64f(x, y, z); } +BOOST_DECIMAL_EXPORT constexpr auto fma(decimal128_fast x, decimal128_fast y, decimal128_fast z) noexcept -> decimal128_fast +{ + return fmad128f(x, y, z); +} + } //namespace decimal } //namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/asin_impl.hpp b/include/boost/decimal/detail/cmath/impl/asin_impl.hpp index b58d1739b..6101f06a4 100644 --- a/include/boost/decimal/detail/cmath/impl/asin_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/asin_impl.hpp @@ -33,8 +33,9 @@ struct asin_table_imp using d64_coeffs_t = std::array; using d128_coeffs_t = std::array; - using d32_fast_coeffs_t = std::array; - using d64_fast_coeffs_t = std::array; + using d32_fast_coeffs_t = std::array; + using d64_fast_coeffs_t = std::array; + using d128_fast_coeffs_t = std::array; public: @@ -163,6 +164,50 @@ struct asin_table_imp decimal128 {uint128{UINT64_C(542101086242752), UINT64_C(4003012203950105568)}, -34}, decimal128 {uint128{UINT64_C(58790996908969), UINT64_C(5250765973560640036)}, -67} }}; + + static constexpr d128_fast_coeffs_t d128_fast_coeffs = {{ + decimal128_fast {uint128{UINT64_C(236367828732266), UINT64_C(4865873281479238114)}, -31}, + decimal128_fast {uint128{UINT64_C(218966359248756), UINT64_C(1393338271545593644)}, -30, true}, + decimal128_fast {uint128{UINT64_C(98104038983693), UINT64_C(4819646069944316372)}, -29}, + decimal128_fast {uint128{UINT64_C(282853615727310), UINT64_C(10104044375051504970)}, -29, true}, + decimal128_fast {uint128{UINT64_C(58930987436658), UINT64_C(3829646337759276014)}, -28}, + decimal128_fast {uint128{UINT64_C(94467942291578), UINT64_C(14212526794757587650)}, -28, true}, + decimal128_fast {uint128{UINT64_C(121156109355190), UINT64_C(6171523396929956760)}, -28}, + decimal128_fast {uint128{UINT64_C(127640043209581), UINT64_C(8369619306382995314)}, -28, true}, + decimal128_fast {uint128{UINT64_C(112556984011870), UINT64_C(14401172681696800280)}, -28}, + decimal128_fast {uint128{UINT64_C(84240716950351), UINT64_C(10152945328926072964)}, -28, true}, + decimal128_fast {uint128{UINT64_C(540724366020485), UINT64_C(8813105586620168570)}, -29}, + decimal128_fast {uint128{UINT64_C(300054630162323), UINT64_C(4862687399308912842)}, -29, true}, + decimal128_fast {uint128{UINT64_C(144827005285082), UINT64_C(4790810090757542758)}, -29}, + decimal128_fast {uint128{UINT64_C(61085784025333), UINT64_C(3908625641731373429)}, -29, true}, + decimal128_fast {uint128{UINT64_C(225929173229512), UINT64_C(18404095637827467688)}, -30}, + decimal128_fast {uint128{UINT64_C(73452862511516), UINT64_C(2655967943189644664)}, -30, true}, + decimal128_fast {uint128{UINT64_C(210254502661653), UINT64_C(14174199201997297032)}, -31}, + decimal128_fast {uint128{UINT64_C(530269670900176), UINT64_C(3023877239296322874)}, -32, true}, + decimal128_fast {uint128{UINT64_C(117870705400334), UINT64_C(8785618254907029456)}, -32}, + decimal128_fast {uint128{UINT64_C(230285265351731), UINT64_C(8107756519153341434)}, -33, true}, + decimal128_fast {uint128{UINT64_C(397318429350031), UINT64_C(567549410172969484)}, -34}, + decimal128_fast {uint128{UINT64_C(54772616787306), UINT64_C(4168475956004989379)}, -34, true}, + decimal128_fast {uint128{UINT64_C(79509164538790), UINT64_C(17928590725399689320)}, -35}, + decimal128_fast {uint128{UINT64_C(534376054761824), UINT64_C(1987644731805023176)}, -36}, + decimal128_fast {uint128{UINT64_C(92204817966183), UINT64_C(17576450582561384882)}, -37}, + decimal128_fast {uint128{UINT64_C(75623542590285), UINT64_C(990523592779300020)}, -35}, + decimal128_fast {uint128{UINT64_C(59680570668825), UINT64_C(14870623164911255928)}, -39}, + decimal128_fast {uint128{UINT64_C(94069144841714), UINT64_C(11353995396932754836)}, -35}, + decimal128_fast {uint128{UINT64_C(204081757431333), UINT64_C(1300964680833664202)}, -42}, + decimal128_fast {uint128{UINT64_C(121279716530202), UINT64_C(3054546075061258708)}, -35}, + decimal128_fast {uint128{UINT64_C(340541736068294), UINT64_C(674620373211314186)}, -45}, + decimal128_fast {uint128{UINT64_C(164700850853976), UINT64_C(1203142186405381614)}, -35}, + decimal128_fast {uint128{UINT64_C(246590930469756), UINT64_C(6088477928552847004)}, -48}, + decimal128_fast {uint128{UINT64_C(242009413501228), UINT64_C(3841246034215456962)}, -35}, + decimal128_fast {uint128{UINT64_C(64561634810301), UINT64_C(5259904364587721972)}, -51}, + decimal128_fast {uint128{UINT64_C(406575814682064), UINT64_C(3001055340328133406)}, -35}, + decimal128_fast {uint128{UINT64_C(447242814330412), UINT64_C(4234427805033793948)}, -56}, + decimal128_fast {uint128{UINT64_C(90350181040458), UINT64_C(12964998079628443792)}, -34}, + decimal128_fast {uint128{UINT64_C(430604756670586), UINT64_C(9888097447655546704)}, -61}, + decimal128_fast {uint128{UINT64_C(542101086242752), UINT64_C(4003012203950105568)}, -34}, + decimal128_fast {uint128{UINT64_C(58790996908969), UINT64_C(5250765973560640036)}, -67} + }}; }; #if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) @@ -182,6 +227,9 @@ constexpr typename asin_table_imp::d32_fast_coeffs_t asin_table_imp::d32_f template constexpr typename asin_table_imp::d64_fast_coeffs_t asin_table_imp::d64_fast_coeffs; +template +constexpr typename asin_table_imp::d128_fast_coeffs_t asin_table_imp::d128_fast_coeffs; + #endif using asin_table = asin_table_imp; @@ -221,6 +269,12 @@ constexpr auto asin_series(decimal128 x) noexcept return remez_series_result(x, asin_detail::asin_table::d128_coeffs); } +template <> +constexpr auto asin_series(decimal128_fast x) noexcept +{ + return remez_series_result(x, asin_detail::asin_table::d128_fast_coeffs); +} + } //namespace detail } //namespace decimal } //namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/assoc_legendre_lookup.hpp b/include/boost/decimal/detail/cmath/impl/assoc_legendre_lookup.hpp index e0c8b9642..56327220a 100644 --- a/include/boost/decimal/detail/cmath/impl/assoc_legendre_lookup.hpp +++ b/include/boost/decimal/detail/cmath/impl/assoc_legendre_lookup.hpp @@ -544,6 +544,110 @@ struct assoc_legendre_lookup { decimal128{detail::uint128{UINT64_C(185632893076863),UINT64_C(16002051557646139392)},44}, decimal128{detail::uint128{UINT64_C(147743803939632),UINT64_C(16999359510947954688)},45}, }}; + + static constexpr std::array d128_fast_values = + {{ + decimal128_fast{detail::uint128{UINT64_C(54210108624275),UINT64_C(4089650035136921600)},-33}, + decimal128_fast{detail::uint128{UINT64_C(54210108624275),UINT64_C(4089650035136921600)},-33}, + decimal128_fast{detail::uint128{UINT64_C(108420217248550),UINT64_C(8179300070273843200)},-33}, + decimal128_fast{detail::uint128{UINT64_C(162630325872825),UINT64_C(12268950105410764800)},-33}, + decimal128_fast{detail::uint128{UINT64_C(433680868994201),UINT64_C(14270456207385821184)},-33}, + decimal128_fast{detail::uint128{UINT64_C(81315162936412),UINT64_C(15357847089560158208)},-32}, + decimal128_fast{detail::uint128{UINT64_C(260208521396521),UINT64_C(1183576094947672064)},-32}, + decimal128_fast{detail::uint128{UINT64_C(56920614055488),UINT64_C(18129190592175931392)},-31}, + decimal128_fast{detail::uint128{UINT64_C(208166817117216),UINT64_C(15704256134925778944)},-31}, + decimal128_fast{detail::uint128{UINT64_C(512285526499400),UINT64_C(15588762739906969600)},-31}, + decimal128_fast{detail::uint128{UINT64_C(208166817117216),UINT64_C(15704256134925778944)},-30}, + decimal128_fast{detail::uint128{UINT64_C(56351407914934),UINT64_C(1714763901389766656)},-29}, + decimal128_fast{detail::uint128{UINT64_C(249800180540660),UINT64_C(4087712102943293440)},-29}, + decimal128_fast{detail::uint128{UINT64_C(73256830289414),UINT64_C(5918541886548606976)},-28}, + decimal128_fast{detail::uint128{UINT64_C(349720252756924),UINT64_C(5722796944120610816)},-28}, + decimal128_fast{detail::uint128{UINT64_C(109885245434121),UINT64_C(8877812829822910464)},-27}, + decimal128_fast{detail::uint128{UINT64_C(55955240441107),UINT64_C(16410912532975321088)},-26}, + decimal128_fast{detail::uint128{UINT64_C(186804917238006),UINT64_C(9558258588586082304)},-26}, + decimal128_fast{detail::uint128{UINT64_C(100719432793994),UINT64_C(3714200856162205696)},-25}, + decimal128_fast{detail::uint128{UINT64_C(354929342752212),UINT64_C(7092644874087825408)},-25}, + decimal128_fast{detail::uint128{UINT64_C(201438865587988),UINT64_C(7428401712324411392)},-24}, + decimal128_fast{detail::uint128{UINT64_C(74535161977964),UINT64_C(11081762341887410176)},-23}, + decimal128_fast{detail::uint128{UINT64_C(443165504293574),UINT64_C(8963786137629884416)},-23}, + decimal128_fast{detail::uint128{UINT64_C(171430872549318),UINT64_C(10730658127373402112)},-22}, + decimal128_fast{detail::uint128{UINT64_C(106359721030457),UINT64_C(16170834169050431488)},-21}, + decimal128_fast{detail::uint128{UINT64_C(428577181373296),UINT64_C(8379901244723953664)},-21}, + decimal128_fast{detail::uint128{UINT64_C(276535274679190),UINT64_C(8840029506853928960)},-20}, + decimal128_fast{detail::uint128{UINT64_C(115715838970790),UINT64_C(786833810178703360)},-19}, + decimal128_fast{detail::uint128{UINT64_C(77429876910173),UINT64_C(6164557076661010432)},-18}, + decimal128_fast{detail::uint128{UINT64_C(335575933015291),UINT64_C(2281818049518239744)},-18}, + decimal128_fast{detail::uint128{UINT64_C(232289630730520),UINT64_C(46927156273479680)},-17}, + decimal128_fast{detail::uint128{UINT64_C(104028539234740),UINT64_C(4531179850829660160)},-16}, + decimal128_fast{detail::uint128{UINT64_C(74332681833766),UINT64_C(7393714319491334144)},-15}, + decimal128_fast{detail::uint128{UINT64_C(343294179474642),UINT64_C(14492893507737878528)},-15}, + decimal128_fast{detail::uint128{UINT64_C(252731118234805),UINT64_C(13870582242044805120)},-14}, + decimal128_fast{detail::uint128{UINT64_C(120152962816124),UINT64_C(18085233579304943616)},-13}, + decimal128_fast{detail::uint128{UINT64_C(90983202564530),UINT64_C(1344060792394219520)},-12}, + decimal128_fast{detail::uint128{UINT64_C(444565962419662),UINT64_C(8765783207557726208)},-12}, + decimal128_fast{detail::uint128{UINT64_C(345736169745214),UINT64_C(5067431011098034176)},-11}, + decimal128_fast{detail::uint128{UINT64_C(173380725343668),UINT64_C(6359069384215232512)},-10}, + decimal128_fast{detail::uint128{UINT64_C(138294467898085),UINT64_C(13195018848664944640)},-9}, + decimal128_fast{detail::uint128{UINT64_C(71086097390904),UINT64_C(418609158683099136)},-8}, + decimal128_fast{detail::uint128{UINT64_C(58083676517196),UINT64_C(37884694326411264)},-7}, + decimal128_fast{detail::uint128{UINT64_C(305670218780887),UINT64_C(5649368197079236608)},-7}, + decimal128_fast{detail::uint128{UINT64_C(255568176675662),UINT64_C(7345390284520030208)},-6}, + decimal128_fast{detail::uint128{UINT64_C(137551598451399),UINT64_C(5159227299742089216)},-5}, + decimal128_fast{detail::uint128{UINT64_C(117561361270804),UINT64_C(13111186449208180736)},-4}, + decimal128_fast{detail::uint128{UINT64_C(64649251272157),UINT64_C(12369611189944844288)},-3}, + decimal128_fast{detail::uint128{UINT64_C(56429453409986),UINT64_C(4705629969723162624)},-2}, + decimal128_fast{detail::uint128{UINT64_C(316781331233572),UINT64_C(10224885831713947648)},-2}, + decimal128_fast{detail::uint128{UINT64_C(282147267049931),UINT64_C(5081405774906261504)},-1}, + decimal128_fast{detail::uint128{UINT64_C(161558478929122),UINT64_C(279603433535438848)},0}, + decimal128_fast{detail::uint128{UINT64_C(146716578865964),UINT64_C(5035940291796402176)},1}, + decimal128_fast{detail::uint128{UINT64_C(85625993832434),UINT64_C(12193040908422086656)},2}, + decimal128_fast{detail::uint128{UINT64_C(79226952587620),UINT64_C(12939584438847406080)},3}, + decimal128_fast{detail::uint128{UINT64_C(470942966078390),UINT64_C(11871492775192821760)},3}, + decimal128_fast{detail::uint128{UINT64_C(443670934490675),UINT64_C(18241440636416819200)},4}, + decimal128_fast{detail::uint128{UINT64_C(268437490664682),UINT64_C(12230774103972773888)},5}, + decimal128_fast{detail::uint128{UINT64_C(257329142004592),UINT64_C(876663532266979328)},6}, + decimal128_fast{detail::uint128{UINT64_C(158378119492162),UINT64_C(14405919469353566208)},7}, + decimal128_fast{detail::uint128{UINT64_C(154397485202755),UINT64_C(4415346934102097920)},8}, + decimal128_fast{detail::uint128{UINT64_C(96610652890219),UINT64_C(5497196943037956096)},9}, + decimal128_fast{detail::uint128{UINT64_C(95726440825708),UINT64_C(4374189506514255872)},10}, + decimal128_fast{detail::uint128{UINT64_C(60864711320838),UINT64_C(2767831751902625792)},11}, + decimal128_fast{detail::uint128{UINT64_C(61264922128453),UINT64_C(5053090573014269952)},12}, + decimal128_fast{detail::uint128{UINT64_C(395620623585447),UINT64_C(18290906387367067648)},12}, + decimal128_fast{detail::uint128{UINT64_C(404348486047791),UINT64_C(11054304893442719744)},13}, + decimal128_fast{detail::uint128{UINT64_C(265065817802250),UINT64_C(3047067801944064000)},14}, + decimal128_fast{detail::uint128{UINT64_C(274956970512498),UINT64_C(5583318038695903232)},15}, + decimal128_fast{detail::uint128{UINT64_C(182895414283552),UINT64_C(11365848820196179968)},16}, + decimal128_fast{detail::uint128{UINT64_C(192469879358748),UINT64_C(14976369071312863232)},17}, + decimal128_fast{detail::uint128{UINT64_C(129855744141322),UINT64_C(6569013136442523648)},18}, + decimal128_fast{detail::uint128{UINT64_C(138578313138299),UINT64_C(2926418338913058816)},19}, + decimal128_fast{detail::uint128{UINT64_C(94794693223165),UINT64_C(5842184234025615360)},20}, + decimal128_fast{detail::uint128{UINT64_C(102547951722341),UINT64_C(6951703029960146944)},21}, + decimal128_fast{detail::uint128{UINT64_C(71096019917373),UINT64_C(18166696230801375232)},22}, + decimal128_fast{detail::uint128{UINT64_C(77936443308979),UINT64_C(8194773354563239936)},23}, + decimal128_fast{detail::uint128{UINT64_C(54743935336377),UINT64_C(17966172353196064768)},24}, + decimal128_fast{detail::uint128{UINT64_C(60790425781003),UINT64_C(17768904542259249152)},25}, + decimal128_fast{detail::uint128{UINT64_C(432477089157385),UINT64_C(17869576296394915840)},25}, + decimal128_fast{detail::uint128{UINT64_C(486323406248031),UINT64_C(11424027822107131904)},26}, + decimal128_fast{detail::uint128{UINT64_C(350306442217482),UINT64_C(11437345189023449088)},27}, + decimal128_fast{detail::uint128{UINT64_C(398785193123386),UINT64_C(268591251376308224)},28}, + decimal128_fast{detail::uint128{UINT64_C(290754347040510),UINT64_C(10849801151312035840)},29}, + decimal128_fast{detail::uint128{UINT64_C(334979562223644),UINT64_C(4552835228846391296)},30}, + decimal128_fast{detail::uint128{UINT64_C(247141194984434),UINT64_C(348958941760454656)},31}, + decimal128_fast{detail::uint128{UINT64_C(288082423512334),UINT64_C(593959245014368256)},32}, + decimal128_fast{detail::uint128{UINT64_C(215012839636457),UINT64_C(11152705842083135488)},33}, + decimal128_fast{detail::uint128{UINT64_C(253512532690853),UINT64_C(17753688683425431552)},34}, + decimal128_fast{detail::uint128{UINT64_C(191361427276447),UINT64_C(4960287299552411648)},35}, + decimal128_fast{detail::uint128{UINT64_C(228161279421768),UINT64_C(10074296592970022912)},36}, + decimal128_fast{detail::uint128{UINT64_C(174138898821566),UINT64_C(18167854379349049344)},37}, + decimal128_fast{detail::uint128{UINT64_C(209908377068027),UINT64_C(1491785473100218368)},38}, + decimal128_fast{detail::uint128{UINT64_C(161949175904057),UINT64_C(5819123247094693888)},39}, + decimal128_fast{detail::uint128{UINT64_C(197313874443945),UINT64_C(8022041092723834880)},40}, + decimal128_fast{detail::uint128{UINT64_C(153851717108854),UINT64_C(8045178695796391936)},41}, + decimal128_fast{detail::uint128{UINT64_C(189421319466187),UINT64_C(11630508263756791808)},42}, + decimal128_fast{detail::uint128{UINT64_C(149236165595588),UINT64_C(14983586082932129792)},43}, + decimal128_fast{detail::uint128{UINT64_C(185632893076863),UINT64_C(16002051557646139392)},44}, + decimal128_fast{detail::uint128{UINT64_C(147743803939632),UINT64_C(16999359510947954688)},45}, + }}; }; #if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) @@ -563,6 +667,8 @@ constexpr std::array assoc_legendre_lookup::d32_fast_val template constexpr std::array assoc_legendre_lookup::d64_fast_values; +template +constexpr std::array assoc_legendre_lookup::d128_fast_values; #endif @@ -603,6 +709,12 @@ constexpr auto assoc_legendre_p0_lookup(unsigned n) -> decimal128 return assoc_legendre_detail::assoc_legendre_lookup_table::d128_values[static_cast(n)]; } +template <> +constexpr auto assoc_legendre_p0_lookup(unsigned n) -> decimal128_fast +{ + return assoc_legendre_detail::assoc_legendre_lookup_table::d128_fast_values[static_cast(n)]; +} + } //namespace detail } //namespace decimal } //namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/atan_impl.hpp b/include/boost/decimal/detail/cmath/impl/atan_impl.hpp index ea789c78a..9f8528984 100644 --- a/include/boost/decimal/detail/cmath/impl/atan_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/atan_impl.hpp @@ -60,6 +60,13 @@ struct atan_table_imp ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(532773544924935), UINT64_C(16408933314882201700) }, -34 }, // atan_three_halves }}; + static constexpr std::array<::boost::decimal::decimal128_fast, 3> d128_fast_atan_values = + {{ + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(251343872473191), UINT64_C(15780610568723885484) }, -34 }, // atan_half + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(425765197510819), UINT64_C(5970600460659265246) }, -34 }, // atan_one + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(532773544924935), UINT64_C(16408933314882201700) }, -34 }, // atan_three_halves + }}; + // 10th degree remez polynomial calculated from 0, 0.4375 // Estimated max error: 2.3032664387910605e-12 static constexpr std::array<::boost::decimal::decimal32, 11> d32_coeffs = @@ -135,6 +142,7 @@ template constexpr std::array atan_table_imp::d3 template constexpr std::array atan_table_imp::d64_atan_values; template constexpr std::array atan_table_imp::d64_fast_atan_values; template constexpr std::array atan_table_imp::d128_atan_values; +template constexpr std::array atan_table_imp::d128_fast_atan_values; #endif @@ -197,12 +205,57 @@ constexpr auto atan_series(decimal128 x) noexcept return (x * top) / bot; } +template <> +constexpr auto atan_series(decimal128_fast x) noexcept +{ + // PadeApproximant[ArcTan[x]/x, {x, 0, {18, 18}}] + // FullSimplify[%] + // HornerForm[Numerator[Out[2]]] + // HornerForm[Denominator[Out[2]]] + + const decimal128_fast x2 { x * x }; + + const decimal128_fast + top + { + decimal128_fast { UINT64_C(21427381364263875) } + + x2 * (decimal128_fast { UINT64_C(91886788553059500) } + + x2 * (decimal128_fast { UINT64_C(163675410390191700) } + + x2 * (decimal128_fast { UINT64_C(156671838074852100) } + + x2 * (decimal128_fast { UINT64_C(87054123957610810) } + + x2 * (decimal128_fast { UINT64_C(28283323008669300) } + + x2 * (decimal128_fast { UINT64_C(5134145876036100) } + + x2 * (decimal128_fast { UINT64_C(463911017673180) } + + x2 * (decimal128_fast { UINT64_C(16016872057515) } + + x2 * decimal128_fast { UINT64_C(90194313216) })))))))) + }; + + const decimal128_fast + bot + { + decimal128_fast { UINT64_C(21427381364263875) } + + x2 * (decimal128_fast { UINT64_C(99029249007814125) } + + x2 * (decimal128_fast { UINT64_C(192399683786610300) } + + x2 * (decimal128_fast { UINT64_C(204060270682768500) } + + x2 * (decimal128_fast { UINT64_C(128360492848838250) } + + x2 * (decimal128_fast { UINT64_C(48688462804731750) } + + x2 * (decimal128_fast { UINT64_C(10819658401051500) } + + x2 * (decimal128_fast { UINT64_C(1298359008126180) } + + x2 * (decimal128_fast { UINT64_C(70562989572075) } + + x2 * decimal128_fast { UINT64_C(1120047453525) })))))))) + }; + + return (x * top) / bot; +} + + template <> constexpr auto atan_values (std::size_t idx) noexcept -> decimal32 { return atan_detail::atan_table::d32_atan_values [idx]; } template <> constexpr auto atan_values (std::size_t idx) noexcept -> decimal64 { return atan_detail::atan_table::d64_atan_values [idx]; } template <> constexpr auto atan_values(std::size_t idx) noexcept -> decimal128 { return atan_detail::atan_table::d128_atan_values[idx]; } template <> constexpr auto atan_values (std::size_t idx) noexcept -> decimal32_fast { return atan_detail::atan_table::d32_fast_atan_values [idx]; } template <> constexpr auto atan_values (std::size_t idx) noexcept -> decimal64_fast { return atan_detail::atan_table::d64_fast_atan_values [idx]; } +template <> constexpr auto atan_values(std::size_t idx) noexcept -> decimal128_fast { return atan_detail::atan_table::d128_fast_atan_values[idx]; } } //namespace detail } //namespace decimal diff --git a/include/boost/decimal/detail/cmath/impl/cos_impl.hpp b/include/boost/decimal/detail/cmath/impl/cos_impl.hpp index cc23a9681..0350130f2 100644 --- a/include/boost/decimal/detail/cmath/impl/cos_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/cos_impl.hpp @@ -145,22 +145,22 @@ constexpr auto cos_series_expansion(decimal128 x) noexcept // HornerForm[Numerator[Out[2]]] // HornerForm[Denominator[Out[2]]] - const decimal128 c0 { boost::decimal::detail::uint128 { UINT64_C(307807346375396), UINT64_C(9191352932158695424) }, 3 }; - const decimal128 c1 { boost::decimal::detail::uint128 { UINT64_C(149996550055690), UINT64_C(222763958071016960) }, 3, true }; - const decimal128 c2 { boost::decimal::detail::uint128 { UINT64_C(108967212479807), UINT64_C(3937477076487471608) }, 2 }; - const decimal128 c3 { boost::decimal::detail::uint128 { UINT64_C(277096228519262), UINT64_C(6277888927557284608) }, 0, true }; - const decimal128 c4 { boost::decimal::detail::uint128 { UINT64_C(319580269604048), UINT64_C(10708241405247058432) }, -2 }; - const decimal128 c5 { boost::decimal::detail::uint128 { UINT64_C(183739194803716), UINT64_C(9003931728965394944) }, -4, true }; - const decimal128 c6 { boost::decimal::detail::uint128 { UINT64_C(518817586019902), UINT64_C(14598542072727738368) }, -7 }; - const decimal128 c7 { boost::decimal::detail::uint128 { UINT64_C(58205916937364), UINT64_C(13388002334603019776) }, -9, true }; - - const decimal128 d1 { boost::decimal::detail::uint128 { UINT64_C(390712313200823), UINT64_C(13016137105513388032) }, 1 }; - const decimal128 d2 { boost::decimal::detail::uint128 { UINT64_C(249767150099857), UINT64_C(14534865724066009088) }, -1 }; - const decimal128 d3 { boost::decimal::detail::uint128 { UINT64_C(105535117882474), UINT64_C(16245151810017622016) }, -3 }; - const decimal128 d4 { boost::decimal::detail::uint128 { UINT64_C(322928599993793), UINT64_C(8055050913586880512) }, -6 }; - const decimal128 d5 { boost::decimal::detail::uint128 { UINT64_C(72777849685460), UINT64_C(10172723920765296640) }, -8 }; - const decimal128 d6 { boost::decimal::detail::uint128 { UINT64_C(114133059907344), UINT64_C(3036923607254532096) }, -11 }; - const decimal128 d7 { boost::decimal::detail::uint128 { UINT64_C(98470690251347), UINT64_C(1521187190289973248) }, -14 }; + constexpr decimal128 c0 { boost::decimal::detail::uint128 { UINT64_C(307807346375396), UINT64_C(9191352932158695424) }, 3 }; + constexpr decimal128 c1 { boost::decimal::detail::uint128 { UINT64_C(149996550055690), UINT64_C(222763958071016960) }, 3, true }; + constexpr decimal128 c2 { boost::decimal::detail::uint128 { UINT64_C(108967212479807), UINT64_C(3937477076487471608) }, 2 }; + constexpr decimal128 c3 { boost::decimal::detail::uint128 { UINT64_C(277096228519262), UINT64_C(6277888927557284608) }, 0, true }; + constexpr decimal128 c4 { boost::decimal::detail::uint128 { UINT64_C(319580269604048), UINT64_C(10708241405247058432) }, -2 }; + constexpr decimal128 c5 { boost::decimal::detail::uint128 { UINT64_C(183739194803716), UINT64_C(9003931728965394944) }, -4, true }; + constexpr decimal128 c6 { boost::decimal::detail::uint128 { UINT64_C(518817586019902), UINT64_C(14598542072727738368) }, -7 }; + constexpr decimal128 c7 { boost::decimal::detail::uint128 { UINT64_C(58205916937364), UINT64_C(13388002334603019776) }, -9, true }; + + constexpr decimal128 d1 { boost::decimal::detail::uint128 { UINT64_C(390712313200823), UINT64_C(13016137105513388032) }, 1 }; + constexpr decimal128 d2 { boost::decimal::detail::uint128 { UINT64_C(249767150099857), UINT64_C(14534865724066009088) }, -1 }; + constexpr decimal128 d3 { boost::decimal::detail::uint128 { UINT64_C(105535117882474), UINT64_C(16245151810017622016) }, -3 }; + constexpr decimal128 d4 { boost::decimal::detail::uint128 { UINT64_C(322928599993793), UINT64_C(8055050913586880512) }, -6 }; + constexpr decimal128 d5 { boost::decimal::detail::uint128 { UINT64_C(72777849685460), UINT64_C(10172723920765296640) }, -8 }; + constexpr decimal128 d6 { boost::decimal::detail::uint128 { UINT64_C(114133059907344), UINT64_C(3036923607254532096) }, -11 }; + constexpr decimal128 d7 { boost::decimal::detail::uint128 { UINT64_C(98470690251347), UINT64_C(1521187190289973248) }, -14 }; const decimal128 x2 { x * x }; @@ -170,6 +170,39 @@ constexpr auto cos_series_expansion(decimal128 x) noexcept return decimal128 { top / bot }; } +template <> +constexpr auto cos_series_expansion(decimal128_fast x) noexcept +{ + // PadeApproximant[Cos[x], {x, 0, {14, 14}}] + // FullSimplify[%] + // HornerForm[Numerator[Out[2]]] + // HornerForm[Denominator[Out[2]]] + + constexpr decimal128_fast c0 { boost::decimal::detail::uint128 { UINT64_C(307807346375396), UINT64_C(9191352932158695424) }, 3 }; + constexpr decimal128_fast c1 { boost::decimal::detail::uint128 { UINT64_C(149996550055690), UINT64_C(222763958071016960) }, 3, true }; + constexpr decimal128_fast c2 { boost::decimal::detail::uint128 { UINT64_C(108967212479807), UINT64_C(3937477076487471608) }, 2 }; + constexpr decimal128_fast c3 { boost::decimal::detail::uint128 { UINT64_C(277096228519262), UINT64_C(6277888927557284608) }, 0, true }; + constexpr decimal128_fast c4 { boost::decimal::detail::uint128 { UINT64_C(319580269604048), UINT64_C(10708241405247058432) }, -2 }; + constexpr decimal128_fast c5 { boost::decimal::detail::uint128 { UINT64_C(183739194803716), UINT64_C(9003931728965394944) }, -4, true }; + constexpr decimal128_fast c6 { boost::decimal::detail::uint128 { UINT64_C(518817586019902), UINT64_C(14598542072727738368) }, -7 }; + constexpr decimal128_fast c7 { boost::decimal::detail::uint128 { UINT64_C(58205916937364), UINT64_C(13388002334603019776) }, -9, true }; + + constexpr decimal128_fast d1 { boost::decimal::detail::uint128 { UINT64_C(390712313200823), UINT64_C(13016137105513388032) }, 1 }; + constexpr decimal128_fast d2 { boost::decimal::detail::uint128 { UINT64_C(249767150099857), UINT64_C(14534865724066009088) }, -1 }; + constexpr decimal128_fast d3 { boost::decimal::detail::uint128 { UINT64_C(105535117882474), UINT64_C(16245151810017622016) }, -3 }; + constexpr decimal128_fast d4 { boost::decimal::detail::uint128 { UINT64_C(322928599993793), UINT64_C(8055050913586880512) }, -6 }; + constexpr decimal128_fast d5 { boost::decimal::detail::uint128 { UINT64_C(72777849685460), UINT64_C(10172723920765296640) }, -8 }; + constexpr decimal128_fast d6 { boost::decimal::detail::uint128 { UINT64_C(114133059907344), UINT64_C(3036923607254532096) }, -11 }; + constexpr decimal128_fast d7 { boost::decimal::detail::uint128 { UINT64_C(98470690251347), UINT64_C(1521187190289973248) }, -14 }; + + const decimal128_fast x2 { x * x }; + + const decimal128_fast top { c0 + x2 * (c1 + x2 * (c2 + x2 * (c3 + x2 * (c4 + x2 * (c5 + x2 * (c6 + x2 * c7)))))) }; + const decimal128_fast bot { c0 + x2 * (d1 + x2 * (d2 + x2 * (d3 + x2 * (d4 + x2 * (d5 + x2 * (d6 + x2 * d7)))))) }; + + return decimal128_fast { top / bot }; +} + } // namespace detail } // namespace decimal } // namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/cosh_impl.hpp b/include/boost/decimal/detail/cmath/impl/cosh_impl.hpp index aab115c98..94d5262e2 100644 --- a/include/boost/decimal/detail/cmath/impl/cosh_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/cosh_impl.hpp @@ -29,8 +29,9 @@ struct cosh_table_imp using d64_coeffs_t = std::array; using d128_coeffs_t = std::array; - using d32_fast_coeffs_t = std::array; - using d64_fast_coeffs_t = std::array; + using d32_fast_coeffs_t = std::array; + using d64_fast_coeffs_t = std::array; + using d128_fast_coeffs_t = std::array; public: static constexpr d32_coeffs_t d32_coeffs = @@ -109,6 +110,29 @@ struct cosh_table_imp ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(206019595635366), UINT64_C(17625897212400736954) }, -69 }, // * x^32 ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(183618177928134), UINT64_C(9987905770721758456) }, -72 }, // * x^34 }}; + + static constexpr d128_fast_coeffs_t d128_fast_coeffs = + {{ + // Series[Cosh[x], {x, 0, 34}] + // (1), // * 1 + ::boost::decimal::decimal128_fast { 5, -1 }, // * x^2 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(225875452601146), UINT64_C(13965751134118914724) }, -35 }, // * x^4 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(75291817533715), UINT64_C(10804165069276155440) }, -36 }, // * x^6 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(134449674167349), UINT64_C(4799281565792772746) }, -38 }, // * x^8 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(149388526852610), UINT64_C(5332535073103080820) }, -40 }, // * x^10 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(113173126403492), UINT64_C(11865690723015477068) }, -42 }, // * x^12 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(62183036485435), UINT64_C(9560282387433155251) }, -44 }, // * x^14 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(259095985355981), UINT64_C(6015479145837302244) }, -47 }, // * x^16 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(84671890639209), UINT64_C(10767230553416093986) }, -49 }, // * x^18 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(222820764840025), UINT64_C(4062785569898205740) }, -52 }, // * x^20 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(482296027792262), UINT64_C(7037075391028107068) }, -55 }, // * x^22 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(87372468802946), UINT64_C(1542176615384940434) }, -57 }, // * x^24 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(134419182773763), UINT64_C(3791559721646796942) }, -60 }, // * x^26 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(177803151817147), UINT64_C(1794430560736952558) }, -63 }, // * x^28 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(204371438870284), UINT64_C(366311534299067156) }, -66 }, // * x^30 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(206019595635366), UINT64_C(17625897212400736954) }, -69 }, // * x^32 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(183618177928134), UINT64_C(9987905770721758456) }, -72 }, // * x^34 + }}; }; #if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) @@ -128,6 +152,9 @@ constexpr typename cosh_table_imp::d32_fast_coeffs_t cosh_table_imp::d32_f template constexpr typename cosh_table_imp::d64_fast_coeffs_t cosh_table_imp::d64_fast_coeffs; +template +constexpr typename cosh_table_imp::d128_fast_coeffs_t cosh_table_imp::d128_fast_coeffs; + #endif } //namespace cosh_detail @@ -167,6 +194,12 @@ constexpr auto cosh_series_expansion(decimal64_fast z2) noexcept return taylor_series_result(z2, cosh_table::d64_fast_coeffs); } +template <> +constexpr auto cosh_series_expansion(decimal128_fast z2) noexcept +{ + return taylor_series_result(z2, cosh_table::d128_fast_coeffs); +} + } //namespace detail } //namespace decimal } //namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/expm1_impl.hpp b/include/boost/decimal/detail/cmath/impl/expm1_impl.hpp index aa05cf27f..8326c867a 100644 --- a/include/boost/decimal/detail/cmath/impl/expm1_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/expm1_impl.hpp @@ -29,8 +29,9 @@ struct expm1_table_imp using d64_coeffs_t = std::array; using d128_coeffs_t = std::array; - using d32_fast_coeffs_t = std::array; - using d64_fast_coeffs_t = std::array; + using d32_fast_coeffs_t = std::array; + using d64_fast_coeffs_t = std::array; + using d128_fast_coeffs_t = std::array; public: static constexpr d32_coeffs_t d32_coeffs = @@ -156,6 +157,46 @@ struct expm1_table_imp ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(66162682638108), UINT64_C(6755035083974089930) }, -67 }, // * x^31 ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(206436477688751), UINT64_C(15666750779045089894) }, -69 }, // * x^32 }}; + + static constexpr d128_fast_coeffs_t d128_fast_coeffs = + {{ + // Specifically derive a polynomial expansion for Exp[x] - 1 for this work. + // Table[{x, Exp[x] - 1}, {x, -Log[2], Log[2], 1/60}] + // N[%, 48] + // 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] + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(54210108624275), UINT64_C(4089650035136921600) }, -33 }, // * x + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(271050543121376), UINT64_C(2001506101975056384) }, -34 }, // * x^2 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(90350181040458), UINT64_C(12964998083131386532) }, -34 }, // * x^3 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(225875452601146), UINT64_C(13965751134118914724) }, -35 }, // * x^4 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(451750905202293), UINT64_C(9484758194528277842) }, -36 }, // * x^5 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(75291817533715), UINT64_C(10804165069276155440) }, -36 }, // * x^6 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(107559739333879), UINT64_C(7528774067376128516) }, -37 }, // * x^7 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(134449674167349), UINT64_C(4799281565792772746) }, -38 }, // * x^8 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(149388526852610), UINT64_C(5332535073103080820) }, -39 }, // * x^9 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(149388526852610), UINT64_C(5332535073103080820) }, -40 }, // * x^10 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(135807751684191), UINT64_C(3170782423392841514) }, -41 }, // * x^11 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(113173126403492), UINT64_C(11865690723015477068) }, -42 }, // * x^12 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(87056251079609), UINT64_C(13384395342406416636) }, -43 }, // * x^13 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(62183036485435), UINT64_C(9560282387433156335) }, -44 }, // * x^14 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(414553576569570), UINT64_C(2246069003862680020) }, -46 }, // * x^15 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(259095985355981), UINT64_C(6015479145828949264) }, -47 }, // * x^16 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(152409403150577), UINT64_C(4623619732418095578) }, -48 }, // * x^17 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(84671890639209), UINT64_C(10767230558026320466) }, -49 }, // * x^18 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(445641529680050), UINT64_C(8125595620937745600) }, -51 }, // * x^19 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(222820764840025), UINT64_C(4062767274683195140) }, -52 }, // * x^20 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(106105126114297), UINT64_C(13344759429965740488) }, -53 }, // * x^21 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(482296027792262), UINT64_C(7088674266265745598) }, -55 }, // * x^22 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(209693925127072), UINT64_C(336105452763225878) }, -56 }, // * x^23 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(87372468802945), UINT64_C(10013088901203012320) }, -57 }, // * x^24 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(349489875208886), UINT64_C(9445768661182748344) }, -59 }, // * x^25 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(134419182774415), UINT64_C(9680981560342232810) }, -60 }, // * x^26 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(497848829278818), UINT64_C(16288994997110182382) }, -62 }, // * x^27 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(177803151475355), UINT64_C(16680206430774781810) }, -63 }, // * x^28 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(61311025561137), UINT64_C(7837795588749518446) }, -64 }, // * x^29 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(204371229207757), UINT64_C(18366861741830034248) }, -66 }, // * x^30 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(66162682638108), UINT64_C(6755035083974089930) }, -67 }, // * x^31 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(206436477688751), UINT64_C(15666750779045089894) }, -69 }, // * x^32 + }}; }; #if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) @@ -214,6 +255,12 @@ constexpr auto expm1_series_expansion(decimal128 x) noexcept return taylor_series_result(x, expm1_table::d128_coeffs); } +template <> +constexpr auto expm1_series_expansion(decimal128_fast x) noexcept +{ + return taylor_series_result(x, expm1_table::d128_fast_coeffs); +} + } //namespace detail } //namespace decimal } //namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/lgamma_impl.hpp b/include/boost/decimal/detail/cmath/impl/lgamma_impl.hpp index 3d2c8e3be..29687fb60 100644 --- a/include/boost/decimal/detail/cmath/impl/lgamma_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/lgamma_impl.hpp @@ -29,8 +29,9 @@ struct lgamma_taylor_series_imp using d64_coeffs_t = std::array; using d128_coeffs_t = std::array; - using d32_fast_coeffs_t = std::array; - using d64_fast_coeffs_t = std::array; + using d32_fast_coeffs_t = std::array; + using d64_fast_coeffs_t = std::array; + using d128_fast_coeffs_t = std::array; static constexpr d32_coeffs_t d32_coeffs = {{ @@ -203,6 +204,58 @@ struct lgamma_taylor_series_imp + decimal128 { detail::uint128 { UINT64_C(123204792327905), UINT64_C(4326111080777755730) }, -35 }, // x^44 - decimal128 { detail::uint128 { UINT64_C(120466908053948), UINT64_C(6659042857988127932) }, -35 }, // x^45 }}; + + static constexpr d128_fast_coeffs_t d128_fast_coeffs = + {{ + // Use a Taylor series expansion of the logarithm of the gamma function. + // N[Series[Log[Gamma[x]], {x, 0, 46}], 36] + // log(1/x) + // -EulerGamma // * x + + decimal128_fast { detail::uint128 { UINT64_C(445860272218065), UINT64_C(14203420802908087080) }, -34 }, // x^2 + - decimal128_fast { detail::uint128 { UINT64_C(217212117642804), UINT64_C(17657476868182733566) }, -34 }, // x^3 + + decimal128_fast { detail::uint128 { UINT64_C(146682150165144), UINT64_C(868910464649280216) }, -34 }, // x^4 + - decimal128_fast { detail::uint128 { UINT64_C(112423932483695), UINT64_C(16359302115292012940) }, -34 }, // x^5 + + decimal128_fast { detail::uint128 { UINT64_C(91917129830549), UINT64_C(10691428771700534346) }, -34 }, // x^6 + - decimal128_fast { detail::uint128 { UINT64_C(78089605511547), UINT64_C(14820105259104989758) }, -34 }, // x^7 + + decimal128_fast { detail::uint128 { UINT64_C(68038928183332), UINT64_C(1064388729383271304) }, -34 }, // x^8 + - decimal128_fast { detail::uint128 { UINT64_C(60354426463930), UINT64_C(7248291600601936245) }, -34 }, // x^9 + + decimal128_fast { detail::uint128 { UINT64_C(54264024649989), UINT64_C(4473690885429568095) }, -34 }, // x^10 + - decimal128_fast { detail::uint128 { UINT64_C(493062714928958), UINT64_C(6174527806367053599) }, -35 }, // x^11 + + decimal128_fast { detail::uint128 { UINT64_C(451862075025508), UINT64_C(9914131103541110236) }, -35 }, // x^12 + - decimal128_fast { detail::uint128 { UINT64_C(417052007139823), UINT64_C(15614141522487214162) }, -35 }, // x^13 + + decimal128_fast { detail::uint128 { UINT64_C(387238777802355), UINT64_C(11643663834403323860) }, -35 }, // x^14 + - decimal128_fast { detail::uint128 { UINT64_C(361411778772587), UINT64_C(34493970254387038) }, -35 }, // x^15 + + decimal128_fast { detail::uint128 { UINT64_C(338818356732611), UINT64_C(3351583636956848354) }, -35 }, // x^16 + - decimal128_fast { detail::uint128 { UINT64_C(318885427279933), UINT64_C(15984063291116028642) }, -35 }, // x^17 + + decimal128_fast { detail::uint128 { UINT64_C(301168419778654), UINT64_C(4924861572478909706) }, -35 }, // x^18 + - decimal128_fast { detail::uint128 { UINT64_C(285316905624704), UINT64_C(10127525246402845676) }, -35 }, // x^19 + + decimal128_fast { detail::uint128 { UINT64_C(271050801693303), UINT64_C(9350577868080165772) }, -35 }, // x^20 + - decimal128_fast { detail::uint128 { UINT64_C(258143497518401), UINT64_C(2808067049374616864) }, -35 }, // x^21 + + decimal128_fast { detail::uint128 { UINT64_C(246409643412285), UINT64_C(14764422888076943740) }, -35 }, // x^22 + - decimal128_fast { detail::uint128 { UINT64_C(235696152553045), UINT64_C(678353819689262840) }, -35 }, // x^23 + + decimal128_fast { detail::uint128 { UINT64_C(225875466065173), UINT64_C(8075483572721697962) }, -35 }, // x^24 + - decimal128_fast { detail::uint128 { UINT64_C(216840440959705), UINT64_C(9932733544470621540) }, -35 }, // x^25 + + decimal128_fast { detail::uint128 { UINT64_C(208500420892654), UINT64_C(6216313969171226926) }, -35 }, // x^26 + - decimal128_fast { detail::uint128 { UINT64_C(200778181585848), UINT64_C(10737065351264354832) }, -35 }, // x^27 + + decimal128_fast { detail::uint128 { UINT64_C(193607531522235), UINT64_C(12111991390268743970) }, -35 }, // x^28 + - decimal128_fast { detail::uint128 { UINT64_C(186931409397414), UINT64_C(9391433164642506256) }, -35 }, // x^29 + + decimal128_fast { detail::uint128 { UINT64_C(180700362249208), UINT64_C(11251075665678452422) }, -35 }, // x^30 + - decimal128_fast { detail::uint128 { UINT64_C(174871318224254), UINT64_C(7048097254153902066) }, -35 }, // x^31 + + decimal128_fast { detail::uint128 { UINT64_C(169406589490303), UINT64_C(3772465895856270802) }, -35 }, // x^32 + - decimal128_fast { detail::uint128 { UINT64_C(164273056456321), UINT64_C(10547878619739699804) }, -35 }, // x^33 + + decimal128_fast { detail::uint128 { UINT64_C(159441495963031), UINT64_C(6975690319727375544) }, -35 }, // x^34 + - decimal128_fast { detail::uint128 { UINT64_C(154886024645294), UINT64_C(2350345999520845736) }, -35 }, // x^35 + + decimal128_fast { detail::uint128 { UINT64_C(150583635069622), UINT64_C(8350573461615823988) }, -35 }, // x^36 + - decimal128_fast { detail::uint128 { UINT64_C(146513807093701), UINT64_C(14073039848059635994) }, -35 }, // x^37 + + decimal128_fast { detail::uint128 { UINT64_C(142658180590716), UINT64_C(17328619387130735144) }, -35 }, // x^38 + - decimal128_fast { detail::uint128 { UINT64_C(139000278524035), UINT64_C(8482044796809236580) }, -35 }, // x^39 + + decimal128_fast { detail::uint128 { UINT64_C(135525271560811), UINT64_C(5788192050685000054) }, -35 }, // x^40 + - decimal128_fast { detail::uint128 { UINT64_C(132219777132438), UINT64_C(13209900018467184292) }, -35 }, // x^41 + + decimal128_fast { detail::uint128 { UINT64_C(129071687200684), UINT64_C(11755517601068760186) }, -35 }, // x^42 + - decimal128_fast { detail::uint128 { UINT64_C(126070020056468), UINT64_C(6206529728400242912) }, -35 }, // x^43 + + decimal128_fast { detail::uint128 { UINT64_C(123204792327905), UINT64_C(4326111080777755730) }, -35 }, // x^44 + - decimal128_fast { detail::uint128 { UINT64_C(120466908053948), UINT64_C(6659042857988127932) }, -35 }, // x^45 + }}; }; #if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) @@ -261,6 +314,12 @@ constexpr auto lgamma_taylor_series_expansion(decimal128 x) noexcept return taylor_series_result(x, lgamma_taylor_series_table::d128_coeffs); } +template <> +constexpr auto lgamma_taylor_series_expansion(decimal128_fast x) noexcept +{ + return taylor_series_result(x, lgamma_taylor_series_table::d128_fast_coeffs); +} + } //namespace detail } //namespace decimal } //namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/log1p_impl.hpp b/include/boost/decimal/detail/cmath/impl/log1p_impl.hpp index 81f136c6b..c0843ead6 100644 --- a/include/boost/decimal/detail/cmath/impl/log1p_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/log1p_impl.hpp @@ -6,6 +6,7 @@ #ifndef BOOST_DECIMAL_DETAIL_CMATH_IMPL_LOG1P_IMPL_HPP #define BOOST_DECIMAL_DETAIL_CMATH_IMPL_LOG1P_IMPL_HPP +#include #include #include @@ -29,8 +30,9 @@ struct log1p_table_imp using d64_coeffs_t = std::array; using d128_coeffs_t = std::array; - using d32_fast_coeffs_t = std::array; - using d64_fast_coeffs_t = std::array; + using d32_fast_coeffs_t = std::array; + using d64_fast_coeffs_t = std::array; + using d128_fast_coeffs_t = std::array; public: static constexpr d32_coeffs_t d32_coeffs = @@ -162,6 +164,48 @@ struct log1p_table_imp -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(150583635067431), UINT64_C(3161586064842759274) }, -35 }, // * z^36 ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(146513807092635), UINT64_C(13545911456276754540) }, -35 }, // * z^37 }}; + + static constexpr d128_fast_coeffs_t d128_fast_coeffs = + {{ + // Series[Log[(1 + (z/2))/(1 - (z/2))], {z, 0, 43}] + // (1), // * z + -::boost::decimal::decimal128_fast { 5, -1 }, // * z^2 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(180700362080917), UINT64_C(7483252092553221458) }, -34 }, // * z^3 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(135525271560688), UINT64_C(1000753050987528192) }, -34 }, // * z^4 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(108420217248550), UINT64_C(8179300070273843200) }, -34 }, // * z^5 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(90350181040458), UINT64_C(12964998083131386532) }, -34 }, // * z^6 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(77443012320393), UINT64_C(3207108039665666332) }, -34 }, // * z^7 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(67762635780344), UINT64_C(500376525493764096) }, -34 }, // * z^8 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(60233454026972), UINT64_C(8643332055420924359) }, -34 }, // * z^9 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(54210108624275), UINT64_C(4089650035136921600) }, -34 }, // * z^10 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(492819169311592), UINT64_C(17054915875379776418) }, -35 }, // * z^11 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(451750905202293), UINT64_C(9484758194528277842) }, -35 }, // * z^12 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(417000835571347), UINT64_C(15850062977145160938) }, -35 }, // * z^13 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(387215061601965), UINT64_C(16035540198328331700) }, -35 }, // * z^14 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(361400724161834), UINT64_C(14966504185106442916) }, -35 }, // * z^15 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(338813178901720), UINT64_C(2501882627468820480) }, -35 }, // * z^16 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(318882991907501), UINT64_C(5610020838860575434) }, -35 }, // * z^17 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(301167270134862), UINT64_C(6323172129685518558) }, -35 }, // * z^18 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(285316361180395), UINT64_C(16670067533954968520) }, -35 }, // * z^19 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(271050543121376), UINT64_C(2001506101975056384) }, -35 }, // * z^20 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(258143374401310), UINT64_C(10690360132218887800) }, -35 }, // * z^21 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(246409584655796), UINT64_C(8527457937689888204) }, -35 }, // * z^22 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(235696124453370), UINT64_C(9760763598982462770) }, -35 }, // * z^23 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(225875452601146), UINT64_C(13965751134118914724) }, -35 }, // * z^24 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(216840434497100), UINT64_C(16358600140547686400) }, -35 }, // * z^25 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(208500417785673), UINT64_C(17148403525427356272) }, -35 }, // * z^26 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(200778180089908), UINT64_C(4215448086457012372) }, -35 }, // * z^27 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(193607530800982), UINT64_C(17241142136018941658) }, -35 }, // * z^28 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(186931409049224), UINT64_C(16646619993397598836) }, -35 }, // * z^29 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(180700362080917), UINT64_C(7483252092553221458) }, -35 }, // * z^30 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(174871318142823), UINT64_C(5456688082434451252) }, -35 }, // * z^31 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(169406589450860), UINT64_C(1250941313734410240) }, -35 }, // * z^32 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(164273056437197), UINT64_C(11833886649696442678) }, -35 }, // * z^33 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(159441495953750), UINT64_C(12028382456285063520) }, -35 }, // * z^34 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(154886024640786), UINT64_C(6414216079331332674) }, -35 }, // * z^35 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(150583635067431), UINT64_C(3161586064842759274) }, -35 }, // * z^36 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(146513807092635), UINT64_C(13545911456276754540) }, -35 }, // * z^37 + }}; }; #if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) @@ -221,6 +265,12 @@ constexpr auto log1p_series_expansion(decimal128 z2) noexcept return taylor_series_result(z2, log1p_table::d128_coeffs); } +template <> +constexpr auto log1p_series_expansion(decimal128_fast z2) noexcept +{ + return taylor_series_result(z2, log1p_table::d128_fast_coeffs); +} + } //namespace detail } //namespace decimal } //namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/log_impl.hpp b/include/boost/decimal/detail/cmath/impl/log_impl.hpp index b7694c37c..f67fc6eb0 100644 --- a/include/boost/decimal/detail/cmath/impl/log_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/log_impl.hpp @@ -29,8 +29,9 @@ struct log_table_imp using d64_coeffs_t = std::array; using d128_coeffs_t = std::array; - using d32_fast_coeffs_t = std::array; - using d64_fast_coeffs_t = std::array; + using d32_fast_coeffs_t = std::array; + using d64_fast_coeffs_t = std::array; + using d128_fast_coeffs_t = std::array; public: static constexpr d32_coeffs_t d32_coeffs = @@ -121,6 +122,33 @@ struct log_table_imp ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(120253186771495), UINT64_C(12950434681540257980) }, -47 }, // * z^41 ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(286650038234379), UINT64_C(5345076336561816786) }, -48 }, // * z^43 }}; + + static constexpr d128_fast_coeffs_t d128_fast_coeffs = + {{ + // Series[Log[(1 + (z/2))/(1 - (z/2))], {z, 0, 43}] + // (1), // * z + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(451750905202293), UINT64_C(9484758194528277842) }, -35 }, // * z^3 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(67762635780344), UINT64_C(500376525493764096) }, -35 }, // * z^5 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(121004706750614), UINT64_C(6164027816584450626) }, -36 }, // * z^7 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(235286929792861), UINT64_C(3787056721709964394) }, -37 }, // * z^9 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(481268720030852), UINT64_C(8584740752302634068) }, -38 }, // * z^11 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(101806844621911), UINT64_C(1816002851448634124) }, -38 }, // * z^13 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(220581496680807), UINT64_C(7009130190423632548) }, -39 }, // * z^15 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(486576830913545), UINT64_C(12748560115094843630) }, -40 }, // * z^17 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(108839554283293), UINT64_C(2123490654414259032) }, -40 }, // * z^19 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(246184706116972), UINT64_C(9634423737622849438) }, -41 }, // * z^21 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(56194335091917), UINT64_C(11823550152479764302) }, -41 }, // * z^23 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(129246970711410), UINT64_C(10592095684364861440) }, -42 }, // * z^25 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(299182802572709), UINT64_C(12220910627630811506) }, -43 }, // * z^27 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(69637376460889), UINT64_C(5865971761607874066) }, -43 }, // * z^29 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(162861606239176), UINT64_C(11636108014793143194) }, -44 }, // * z^31 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(382478014652611), UINT64_C(14470401740943906374) }, -45 }, // * z^33 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(90155532025258), UINT64_C(9076666090147568782) }, -45 }, // * z^35 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(213205650059732), UINT64_C(16978042870933143358) }, -46 }, // * z^37 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(505680067449366), UINT64_C(9996854995997550184) }, -47 }, // * z^39 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(120253186771495), UINT64_C(12950434681540257980) }, -47 }, // * z^41 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(286650038234379), UINT64_C(5345076336561816786) }, -48 }, // * z^43 + }}; }; #if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) @@ -140,6 +168,9 @@ constexpr typename log_table_imp::d32_fast_coeffs_t log_table_imp::d32_fas template constexpr typename log_table_imp::d64_fast_coeffs_t log_table_imp::d64_fast_coeffs; +template +constexpr typename log_table_imp::d128_fast_coeffs_t log_table_imp::d128_fast_coeffs; + #endif } //namespace log_detail @@ -179,6 +210,12 @@ constexpr auto log_series_expansion(decimal128 z2) noexcept return taylor_series_result(z2, log_table::d128_coeffs); } +template <> +constexpr auto log_series_expansion(decimal128_fast z2) noexcept +{ + return taylor_series_result(z2, log_table::d128_fast_coeffs); +} + } //namespace detail } //namespace decimal } //namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/riemann_zeta_impl.hpp b/include/boost/decimal/detail/cmath/impl/riemann_zeta_impl.hpp index 23d0401dc..56b750f85 100644 --- a/include/boost/decimal/detail/cmath/impl/riemann_zeta_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/riemann_zeta_impl.hpp @@ -48,11 +48,12 @@ template struct riemann_zeta_table_imp { private: - using d32_coeffs_t = std::array; - using d32_fast_coeffs_t = std::array; - using d64_coeffs_t = std::array; - using d64_fast_coeffs_t = std::array; - using d128_coeffs_t = std::array; + using d32_coeffs_t = std::array; + using d32_fast_coeffs_t = std::array; + using d64_coeffs_t = std::array; + using d64_fast_coeffs_t = std::array; + using d128_coeffs_t = std::array; + using d128_fast_coeffs_t = std::array; public: static constexpr d32_coeffs_t d32_coeffs = @@ -133,6 +134,27 @@ struct riemann_zeta_table_imp +::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(239089604329878), UINT64_C(14831803080673374292) }, -48 }, -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(130092671757244), UINT64_C(16458215134170057406) }, -48 }, }}; + + static constexpr d128_fast_coeffs_t d128_fast_coeffs = + {{ + // N[Series[Zeta[x], {x, 1, 14}], 36] + + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(312909238939453), UINT64_C(7916302232898517972) }, -34 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(394735489323855), UINT64_C(10282954930524890450) }, -35 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(262657820647143), UINT64_C(7801536535536173172) }, -36 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(185564311701532), UINT64_C(15687007158497646588) }, -37 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(525244016002584), UINT64_C(12277750447068982866) }, -38 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(358384752584293), UINT64_C(18370286456371002882) }, -39 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(179773779887752), UINT64_C(17772011513518515048) }, -40 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(56715128386205), UINT64_C(15292499466693711883) }, -40 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(473428701855329), UINT64_C(926484760170384186) }, -42 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(513818468174601), UINT64_C(18105240268308765734) }, -44 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(306743667337648), UINT64_C(15567754919026551912) }, -44 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(366931412745108), UINT64_C(2220247416524400302) }, -45 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(189307984255553), UINT64_C(8448217616480074192) }, -46 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(239089604329878), UINT64_C(14831803080673374292) }, -48 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(130092671757244), UINT64_C(16458215134170057406) }, -48 }, + }}; }; #if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) @@ -149,6 +171,9 @@ constexpr typename riemann_zeta_table_imp::d64_coeffs_t riemann_zeta_table_im template constexpr typename riemann_zeta_table_imp::d128_coeffs_t riemann_zeta_table_imp::d128_coeffs; +template +constexpr typename riemann_zeta_table_imp::d128_fast_coeffs_t riemann_zeta_table_imp::d128_fast_coeffs; + template constexpr typename prime_table_imp::prime_table_t prime_table_imp::primes; @@ -295,6 +320,16 @@ constexpr auto riemann_zeta_series_or_pade_expansion(decimal128 x) n return one / dx + taylor_series_result(dx, riemann_zeta_table::d128_coeffs); } +template <> +constexpr auto riemann_zeta_series_or_pade_expansion(decimal128_fast x) noexcept +{ + constexpr decimal128_fast one { 1 }; + + const decimal128_fast dx { x - one }; + + return one / dx + taylor_series_result(dx, riemann_zeta_table::d128_fast_coeffs); +} + template using prime_table_t = typename riemann_zeta_detail::prime_table_imp::prime_table_t; diff --git a/include/boost/decimal/detail/cmath/impl/sin_impl.hpp b/include/boost/decimal/detail/cmath/impl/sin_impl.hpp index 29a89a3bf..cc246b26e 100644 --- a/include/boost/decimal/detail/cmath/impl/sin_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/sin_impl.hpp @@ -153,20 +153,20 @@ constexpr auto sin_series_expansion(decimal128 x) noexcept // HornerForm[Numerator[Out[2]]] // HornerForm[Denominator[Out[2]]] - const decimal128 c0 { boost::decimal::detail::uint128 { UINT64_C(72470724512963), UINT64_C(12010094287581601792) }, -1 }; - const decimal128 c1 { boost::decimal::detail::uint128 { UINT64_C(111100426260665), UINT64_C(12001293056709775360) }, -2, true }; - const decimal128 c2 { boost::decimal::detail::uint128 { UINT64_C(448976101608303), UINT64_C(8651619847551332352) }, -4 }; - const decimal128 c3 { boost::decimal::detail::uint128 { UINT64_C(73569920121966), UINT64_C(7922026052315602944) }, -5, true }; - const decimal128 c4 { boost::decimal::detail::uint128 { UINT64_C(56791565109495), UINT64_C(18025512837605806080) }, -7 }; - const decimal128 c5 { boost::decimal::detail::uint128 { UINT64_C(208944907042123), UINT64_C(1905626912845279232) }, -10, true }; - const decimal128 c6 { boost::decimal::detail::uint128 { UINT64_C(301324799882787), UINT64_C(8861120840873566208) }, -13 }; - - const decimal128 d1 { boost::decimal::detail::uint128 { UINT64_C(96841145942737), UINT64_C(12517245955660587008) }, -3 }; - const decimal128 d2 { boost::decimal::detail::uint128 { UINT64_C(64553072381691), UINT64_C(13718792646062137344) }, -5 }; - const decimal128 d3 { boost::decimal::detail::uint128 { UINT64_C(279090388104865), UINT64_C(5072548100861788160) }, -8 }; - const decimal128 d4 { boost::decimal::detail::uint128 { UINT64_C(84086452204639), UINT64_C(9046779044634853376) }, -10 }; - const decimal128 d5 { boost::decimal::detail::uint128 { UINT64_C(171178955723736), UINT64_C(18053324302671642624) }, -13 }; - const decimal128 d6 { boost::decimal::detail::uint128 { UINT64_C(189091057352841), UINT64_C(2258222749986258944) }, -16 }; + constexpr decimal128 c0 { boost::decimal::detail::uint128 { UINT64_C(72470724512963), UINT64_C(12010094287581601792) }, -1 }; + constexpr decimal128 c1 { boost::decimal::detail::uint128 { UINT64_C(111100426260665), UINT64_C(12001293056709775360) }, -2, true }; + constexpr decimal128 c2 { boost::decimal::detail::uint128 { UINT64_C(448976101608303), UINT64_C(8651619847551332352) }, -4 }; + constexpr decimal128 c3 { boost::decimal::detail::uint128 { UINT64_C(73569920121966), UINT64_C(7922026052315602944) }, -5, true }; + constexpr decimal128 c4 { boost::decimal::detail::uint128 { UINT64_C(56791565109495), UINT64_C(18025512837605806080) }, -7 }; + constexpr decimal128 c5 { boost::decimal::detail::uint128 { UINT64_C(208944907042123), UINT64_C(1905626912845279232) }, -10, true }; + constexpr decimal128 c6 { boost::decimal::detail::uint128 { UINT64_C(301324799882787), UINT64_C(8861120840873566208) }, -13 }; + + constexpr decimal128 d1 { boost::decimal::detail::uint128 { UINT64_C(96841145942737), UINT64_C(12517245955660587008) }, -3 }; + constexpr decimal128 d2 { boost::decimal::detail::uint128 { UINT64_C(64553072381691), UINT64_C(13718792646062137344) }, -5 }; + constexpr decimal128 d3 { boost::decimal::detail::uint128 { UINT64_C(279090388104865), UINT64_C(5072548100861788160) }, -8 }; + constexpr decimal128 d4 { boost::decimal::detail::uint128 { UINT64_C(84086452204639), UINT64_C(9046779044634853376) }, -10 }; + constexpr decimal128 d5 { boost::decimal::detail::uint128 { UINT64_C(171178955723736), UINT64_C(18053324302671642624) }, -13 }; + constexpr decimal128 d6 { boost::decimal::detail::uint128 { UINT64_C(189091057352841), UINT64_C(2258222749986258944) }, -16 }; const decimal128 x2 { x * x }; @@ -178,6 +178,43 @@ constexpr auto sin_series_expansion(decimal128 x) noexcept return b_neg ? -result : result; } +template <> +constexpr auto sin_series_expansion(decimal128_fast x) noexcept +{ + const bool b_neg { signbit(x) }; + + x = abs(x); + + // PadeApproximant[Sin[x], {x, 0, {14, 13}}] + // FullSimplify[%] + // HornerForm[Numerator[Out[2]]] + // HornerForm[Denominator[Out[2]]] + + constexpr decimal128_fast c0 { boost::decimal::detail::uint128 { UINT64_C(72470724512963), UINT64_C(12010094287581601792) }, -1 }; + constexpr decimal128_fast c1 { boost::decimal::detail::uint128 { UINT64_C(111100426260665), UINT64_C(12001293056709775360) }, -2, true }; + constexpr decimal128_fast c2 { boost::decimal::detail::uint128 { UINT64_C(448976101608303), UINT64_C(8651619847551332352) }, -4 }; + constexpr decimal128_fast c3 { boost::decimal::detail::uint128 { UINT64_C(73569920121966), UINT64_C(7922026052315602944) }, -5, true }; + constexpr decimal128_fast c4 { boost::decimal::detail::uint128 { UINT64_C(56791565109495), UINT64_C(18025512837605806080) }, -7 }; + constexpr decimal128_fast c5 { boost::decimal::detail::uint128 { UINT64_C(208944907042123), UINT64_C(1905626912845279232) }, -10, true }; + constexpr decimal128_fast c6 { boost::decimal::detail::uint128 { UINT64_C(301324799882787), UINT64_C(8861120840873566208) }, -13 }; + + constexpr decimal128_fast d1 { boost::decimal::detail::uint128 { UINT64_C(96841145942737), UINT64_C(12517245955660587008) }, -3 }; + constexpr decimal128_fast d2 { boost::decimal::detail::uint128 { UINT64_C(64553072381691), UINT64_C(13718792646062137344) }, -5 }; + constexpr decimal128_fast d3 { boost::decimal::detail::uint128 { UINT64_C(279090388104865), UINT64_C(5072548100861788160) }, -8 }; + constexpr decimal128_fast d4 { boost::decimal::detail::uint128 { UINT64_C(84086452204639), UINT64_C(9046779044634853376) }, -10 }; + constexpr decimal128_fast d5 { boost::decimal::detail::uint128 { UINT64_C(171178955723736), UINT64_C(18053324302671642624) }, -13 }; + constexpr decimal128_fast d6 { boost::decimal::detail::uint128 { UINT64_C(189091057352841), UINT64_C(2258222749986258944) }, -16 }; + + const decimal128_fast x2 { x * x }; + + const decimal128_fast top { x * (c0 + x2 * (c1 + x2 * (c2 + x2 * (c3 + x2 * (c4 + x2 * (c5 + x2 * c6)))))) }; + const decimal128_fast bot { c0 + x2 * (d1 + x2 * (d2 + x2 * (d3 + x2 * (d4 + x2 * (d5 + x2 * d6))))) }; + + const decimal128_fast result { top / bot }; + + return b_neg ? -result : result; +} + } // namespace detail } // namespace decimal } // namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/sinh_impl.hpp b/include/boost/decimal/detail/cmath/impl/sinh_impl.hpp index 2e92fdae0..72d09d62c 100644 --- a/include/boost/decimal/detail/cmath/impl/sinh_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/sinh_impl.hpp @@ -29,8 +29,9 @@ struct sinh_table_imp using d64_coeffs_t = std::array; using d128_coeffs_t = std::array; - using d32_fast_coeffs_t = std::array; - using d64_fast_coeffs_t = std::array; + using d32_fast_coeffs_t = std::array; + using d64_fast_coeffs_t = std::array; + using d128_fast_coeffs_t = std::array; public: static constexpr d32_coeffs_t d32_coeffs = @@ -109,6 +110,29 @@ struct sinh_table_imp ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(62430180495565), UINT64_C(13726064643322746782) }, -70 }, // * x^33 ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(524623365508955), UINT64_C(15360627863698201590) }, -74 }, // * x^35 }}; + + static constexpr d128_fast_coeffs_t d128_fast_coeffs = + {{ + // Series[Sinh[x], {x, 0, 34}] + // (1), // * x + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(90350181040458), UINT64_C(12964998083131386532) }, -34 }, // * x^3 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(451750905202293), UINT64_C(9484758194528277842) }, -36 }, // * x^5 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(107559739333879), UINT64_C(7528774067376128516) }, -37 }, // * x^7 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(149388526852610), UINT64_C(5332535073103080820) }, -39 }, // * x^9 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(135807751684191), UINT64_C(3170782423392841514) }, -41 }, // * x^11 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(87056251079609), UINT64_C(13384395342406417346) }, -43 }, // * x^13 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(414553576569570), UINT64_C(2246069003855862950) }, -46 }, // * x^15 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(152409403150577), UINT64_C(4623619737181327888) }, -48 }, // * x^17 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(445641529680050), UINT64_C(8125571139796411480) }, -51 }, // * x^19 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(106105126114297), UINT64_C(13354072793200296588) }, -53 }, // * x^21 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(209693925127070), UINT64_C(11079921506407677690) }, -56 }, // * x^23 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(349489875211784), UINT64_C(6168706461539761736) }, -59 }, // * x^25 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(497848825088011), UINT64_C(16092452014289198134) }, -62 }, // * x^27 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(61311431661085), UINT64_C(3799242275031630472) }, -64 }, // * x^29 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(65926270603317), UINT64_C(7853896396813382020) }, -67 }, // * x^31 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(62430180495565), UINT64_C(13726064643322746782) }, -70 }, // * x^33 + ::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(524623365508955), UINT64_C(15360627863698201590) }, -74 }, // * x^35 + }}; }; #if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) @@ -128,6 +152,9 @@ constexpr typename sinh_table_imp::d32_fast_coeffs_t sinh_table_imp::d32_f template constexpr typename sinh_table_imp::d64_fast_coeffs_t sinh_table_imp::d64_fast_coeffs; +template +constexpr typename sinh_table_imp::d128_fast_coeffs_t sinh_table_imp::d128_fast_coeffs; + #endif } //namespace sinh_detail @@ -167,6 +194,12 @@ constexpr auto sinh_series_expansion(decimal128 z2) noexcept return taylor_series_result(z2, sinh_table::d128_coeffs); } +template <> +constexpr auto sinh_series_expansion(decimal128_fast z2) noexcept +{ + return taylor_series_result(z2, sinh_table::d128_fast_coeffs); +} + } //namespace detail } //namespace decimal } //namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/tanh_impl.hpp b/include/boost/decimal/detail/cmath/impl/tanh_impl.hpp index 49faf25a5..6003e372b 100644 --- a/include/boost/decimal/detail/cmath/impl/tanh_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/tanh_impl.hpp @@ -29,8 +29,9 @@ struct tanh_table_imp using d64_coeffs_t = std::array; using d128_coeffs_t = std::array; - using d32_fast_coeffs_t = std::array; - using d64_fast_coeffs_t = std::array; + using d32_fast_coeffs_t = std::array; + using d64_fast_coeffs_t = std::array; + using d128_fast_coeffs_t = std::array; public: static constexpr d32_coeffs_t d32_coeffs = @@ -120,6 +121,34 @@ struct tanh_table_imp -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(254586683669781), UINT64_C(685051056553551574) }, -42 }, // * x^43 +::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(103180096515998), UINT64_C(10260917890244709612) }, -42 }, // * x^45 }}; + + static constexpr d128_fast_coeffs_t d128_fast_coeffs = + {{ + // Series[Tanh[x], {x, 0, 45}] + // (1), // * x + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(180700362080917), UINT64_C(7483252092553221458) }, -34 }, // * x^3 + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(72280144832366), UINT64_C(17750696095988929874) }, -34 }, // * x^5 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(292562490988151), UINT64_C(18264656174417923374) }, -35 }, // * x^7 + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(118554734910231), UINT64_C(9692136079832632224) }, -35 }, // * x^9 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(480476960838533), UINT64_C(11637084576724682862) }, -36 }, // * x^11 + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(194729651054898), UINT64_C(12399216788389290642) }, -36 }, // * x^13 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(78920940261007), UINT64_C(1837289537202064798) }, -36 }, // * x^15 + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(319854516649633), UINT64_C(9164231904936043282) }, -37 }, // * x^17 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(129632152583696), UINT64_C(18287072186516798384) }, -37 }, // * x^19 + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(525379325381431), UINT64_C(15812750027817946304) }, -38 }, // * x^21 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(212928220429406), UINT64_C(17197028753568092234) }, -38 }, // * x^23 + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(86296557298784), UINT64_C(15970280607199622056) }, -38 }, // * x^25 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(349746773190745), UINT64_C(16747878178724308630) }, -39 }, // * x^27 + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(141747028139092), UINT64_C(18150782588055037068) }, -39 }, // * x^29 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(57447906675346), UINT64_C(7219349788452465642) }, -39 }, // * x^31 + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(232827596084826), UINT64_C(637032669719018454) }, -40 }, // * x^33 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(94361470479658), UINT64_C(14765552217602302942) }, -40 }, // * x^35 + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(382432635169221), UINT64_C(13797141926350469414) }, -41 }, // * x^37 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(154994109035215), UINT64_C(9538263982529984200) }, -41 }, // * x^39 + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(62816746340150), UINT64_C(7041711327684726779) }, -41 }, // * x^41 + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(254586683669781), UINT64_C(685051056553551574) }, -42 }, // * x^43 + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(103180096515998), UINT64_C(10260917890244709612) }, -42 }, // * x^45 + }}; }; #if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) @@ -178,6 +207,12 @@ constexpr auto tanh_series_expansion(decimal128 z2) noexcept return taylor_series_result(z2, tanh_table::d128_coeffs); } +template <> +constexpr auto tanh_series_expansion(decimal128_fast z2) noexcept +{ + return taylor_series_result(z2, tanh_table::d128_fast_coeffs); +} + } //namespace detail } //namespace decimal } //namespace boost diff --git a/include/boost/decimal/detail/cmath/impl/tgamma_impl.hpp b/include/boost/decimal/detail/cmath/impl/tgamma_impl.hpp index 015635943..52ad606ad 100644 --- a/include/boost/decimal/detail/cmath/impl/tgamma_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/tgamma_impl.hpp @@ -28,15 +28,17 @@ struct tgamma_table_imp using d64_coeffs_t = std::array; using d128_coeffs_t = std::array; - using d32_fast_coeffs_t = std::array; - using d64_fast_coeffs_t = std::array; + using d32_fast_coeffs_t = std::array; + using d64_fast_coeffs_t = std::array; + using d128_fast_coeffs_t = std::array; using d32_coeffs_asymp_t = std::array; using d64_coeffs_asymp_t = std::array; using d128_coeffs_asymp_t = std::array; - using d32_fast_coeffs_asymp_t = std::array; - using d64_fast_coeffs_asymp_t = std::array; + using d32_fast_coeffs_asymp_t = std::array; + using d64_fast_coeffs_asymp_t = std::array; + using d128_fast_coeffs_asymp_t = std::array; static constexpr d32_coeffs_t d32_coeffs = {{ @@ -295,6 +297,91 @@ struct tgamma_table_imp +::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(93943319594850), UINT64_C(9012698938647704180) }, -27 }, }}; + static constexpr d128_fast_coeffs_t d128_fast_coeffs = + {{ + // N[Series[1/Gamma[z], {z, 0, 46}], 36] + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(312909238939453), UINT64_C(7916302232898517972) }, -34 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(355552215013931), UINT64_C(2875353717947891404) }, -34 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(227696740770409), UINT64_C(1287992959696612036) }, -35 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(90280762131699), UINT64_C(14660682722320745466) }, -34 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(228754377395439), UINT64_C(1086189775515439306) }, -35 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(521608121705894), UINT64_C(2882773517907923486) }, -36 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(391339697554084), UINT64_C(12203646426790846826) }, -36 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(63163861720165), UINT64_C(1793625582468481749) }, -36 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(116682745342423), UINT64_C(7466931387917530902) }, -37 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(69416197176288), UINT64_C(17486507952476000235) }, -37 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(109151266480053), UINT64_C(14157573701904186532) }, -38 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(67789387500902), UINT64_C(6337242598258275460) }, -39 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(61421529319989), UINT64_C(11330812743044278521) }, -39 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(111474328952626), UINT64_C(4349913604764276954) }, -40 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(331554179970335), UINT64_C(8536598537651543980) }, -42 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(271159377746131), UINT64_C(11232450780359262294) }, -42 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(64037022781195), UINT64_C(7729482665838775386) }, -42 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(56564275382244), UINT64_C(15921046388084405946) }, -43 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(421877346419979), UINT64_C(12114109382397224706) }, -45 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(200404234149424), UINT64_C(17191629897693416576) }, -45 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(276491627306932), UINT64_C(18075235341994261118) }, -46 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(111582078948016), UINT64_C(1315679057212061374) }, -47 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(289922303798056), UINT64_C(8236273575746269444) }, -48 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(66503802694735), UINT64_C(8619931044472680662) }, -48 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(64036195058454), UINT64_C(13570784405336680634) }, -49 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(64330716033670), UINT64_C(6228121739584017954) }, -51 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(76565308743615), UINT64_C(9665163337994634860) }, -51 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(124615253252825), UINT64_C(5713012462345318490) }, -52 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(92938152937825), UINT64_C(2160517649493992050) }, -53 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(72497982578925), UINT64_C(10055707640313829460) }, -55 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(111360223980902), UINT64_C(528747408384118098) }, -55 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(148320486134320), UINT64_C(12662323637555269860) }, -56 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(93911231108772), UINT64_C(8663955293807189228) }, -57 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(127969413738636), UINT64_C(17978922200959991754) }, -59 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(101100927852914), UINT64_C(16158702556622869636) }, -59 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(120243204727301), UINT64_C(13141135468649758444) }, -60 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(70352901832557), UINT64_C(2975454173305568482) }, -61 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(64005738370342), UINT64_C(18063645830042937300) }, -63 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(60963839731470), UINT64_C(14965217315129705920) }, -63 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(69230926066837), UINT64_C(16656915204960392533) }, -64 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(400691370795862), UINT64_C(16972369904241895558) }, -66 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(61514934723438), UINT64_C(5918930041313493498) }, -68 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(251487992814431), UINT64_C(6680121266003781724) }, -68 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(289879709778175), UINT64_C(4432551928123929090) }, -69 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(173905807485311), UINT64_C(17752316546962770214) }, -70 }, + }}; + + static constexpr d128_fast_coeffs_asymp_t d128_fast_coeffs_asymp = + {{ + // N[Series[Gamma[x] Sqrt[x], {x, Infinity, 29}], 36] + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(135884591048426), UINT64_C(2199768757482254624) }, -33 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(113237159207021), UINT64_C(14130970013708246594) }, -34 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(471821496695924), UINT64_C(464352157037447386) }, -36 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(364351044670741), UINT64_C(6097570099755222654) }, -36 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(311817215987699), UINT64_C(14568946901511994136) }, -37 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(106538849009357), UINT64_C(10090636838411945598) }, -36 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(94749794601238), UINT64_C(6866971493329372072) }, -37 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(80466294172410), UINT64_C(2547924282344488810) }, -36 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(70276669255695), UINT64_C(16334355597894868319) }, -37 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(114074940344203), UINT64_C(9044723431924593842) }, -36 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(97903426715255), UINT64_C(16799883086492113070) }, -37 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(260142692464932), UINT64_C(15263500517507471568) }, -36 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(220834559071109), UINT64_C(9975868582270637886) }, -37 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(87011834000670), UINT64_C(1012280154922930780) }, -35 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(73400068583854), UINT64_C(10697903424322046536) }, -36 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(401238402683293), UINT64_C(16385890397153029532) }, -35 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(337230714209057), UINT64_C(16967592325356259778) }, -36 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(243967353836524), UINT64_C(9499344852909361366) }, -34 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(204589376322286), UINT64_C(11872292347365127784) }, -35 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(189124322379112), UINT64_C(14090568112327257998) }, -33 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(158368431339348), UINT64_C(2168574764773383622) }, -34 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(182057977444481), UINT64_C(3733389993208297254) }, -32 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(152300056275284), UINT64_C(17612360680536377126) }, -33 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(213068958411016), UINT64_C(2976936113300142334) }, -31 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(178115660634938), UINT64_C(17553310597074079872) }, -32 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(297934512372623), UINT64_C(8697957613905306402) }, -30 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(248927979034058), UINT64_C(1995178765856766712) }, -31 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(490558583154992), UINT64_C(14703601007071441008) }, -29 }, + -::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(409702547605069), UINT64_C(12211101634789053596) }, -30 }, + +::boost::decimal::decimal128_fast { boost::decimal::detail::uint128 { UINT64_C(93943319594850), UINT64_C(9012698938647704180) }, -27 }, + }}; + }; #if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) @@ -305,6 +392,7 @@ template constexpr typename tgamma_table_imp::d128_coeffs_t tgamma_t template constexpr typename tgamma_table_imp::d32_fast_coeffs_t tgamma_table_imp::d32_fast_coeffs; template constexpr typename tgamma_table_imp::d64_fast_coeffs_t tgamma_table_imp::d64_fast_coeffs; +template constexpr typename tgamma_table_imp::d128_fast_coeffs_t tgamma_table_imp::d128_fast_coeffs; template constexpr typename tgamma_table_imp::d32_coeffs_asymp_t tgamma_table_imp::d32_coeffs_asymp; template constexpr typename tgamma_table_imp::d64_coeffs_asymp_t tgamma_table_imp::d64_coeffs_asymp; @@ -312,6 +400,7 @@ template constexpr typename tgamma_table_imp::d128_coeffs_asymp_t tg template constexpr typename tgamma_table_imp::d32_fast_coeffs_asymp_t tgamma_table_imp::d32_fast_coeffs_asymp; template constexpr typename tgamma_table_imp::d64_fast_coeffs_asymp_t tgamma_table_imp::d64_fast_coeffs_asymp; +template constexpr typename tgamma_table_imp::d128_fast_coeffs_asymp_t tgamma_table_imp::d128_fast_coeffs_asymp; #endif @@ -352,6 +441,12 @@ constexpr auto tgamma_series_expansion(decimal128 z) noexcept return taylor_series_result(z, tgamma_table::d128_coeffs); } +template <> +constexpr auto tgamma_series_expansion(decimal128_fast z) noexcept +{ + return taylor_series_result(z, tgamma_table::d128_fast_coeffs); +} + template constexpr auto tgamma_series_expansion_asymp(T z) noexcept; @@ -385,6 +480,12 @@ constexpr auto tgamma_series_expansion_asymp(decimal128 z) noexcept return taylor_series_result(z, tgamma_table::d128_coeffs_asymp); } +template <> +constexpr auto tgamma_series_expansion_asymp(decimal128_fast z) noexcept +{ + return taylor_series_result(z, tgamma_table::d128_fast_coeffs_asymp); +} + } //namespace detail } //namespace decimal } //namespace boost diff --git a/include/boost/decimal/detail/cmath/remquo.hpp b/include/boost/decimal/detail/cmath/remquo.hpp index e60492981..13fed3da8 100644 --- a/include/boost/decimal/detail/cmath/remquo.hpp +++ b/include/boost/decimal/detail/cmath/remquo.hpp @@ -24,7 +24,8 @@ template constexpr auto remquo(T x, T y, int* quo) noexcept BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T) { - using unsigned_significand_type = std::conditional_t::value, detail::uint128, std::uint64_t>; + using unsigned_significand_type = std::conditional_t::value || std::is_same::value, + detail::uint128, std::uint64_t>; constexpr T zero {0, 0}; constexpr T half {5, -1}; diff --git a/include/boost/decimal/detail/div_impl.hpp b/include/boost/decimal/detail/div_impl.hpp index 9ea12cf06..a9062116d 100644 --- a/include/boost/decimal/detail/div_impl.hpp +++ b/include/boost/decimal/detail/div_impl.hpp @@ -101,6 +101,7 @@ constexpr auto d128_generic_div_impl(T lhs, T rhs, T& q) noexcept -> void auto res_sig {big_sig_lhs / detail::uint256_t(rhs.sig)}; auto res_exp {lhs.exp - rhs.exp}; + // TODO(mborland): Since the values are normalized is sig_dig always near 34? const auto sig_dig {detail::num_digits(res_sig)}; if (sig_dig > std::numeric_limits::digits10) diff --git a/include/boost/decimal/detail/fenv_rounding.hpp b/include/boost/decimal/detail/fenv_rounding.hpp index 3e55d0f42..55cb7087a 100644 --- a/include/boost/decimal/detail/fenv_rounding.hpp +++ b/include/boost/decimal/detail/fenv_rounding.hpp @@ -20,7 +20,7 @@ namespace detail { template , bool> = true> constexpr auto fenv_round(T& val, bool = false) noexcept -> int { - using significand_type = std::conditional_t::value, detail::uint128, int>; + using significand_type = std::conditional_t::value || std::is_same::value, detail::uint128, int>; const auto trailing_num {val % 10}; int exp_delta {}; @@ -46,7 +46,7 @@ constexpr auto fenv_round(T& val, bool = false) noexcept -> int template , bool> = true> constexpr auto fenv_round(T& val, bool is_neg = false) noexcept -> int // NOLINT(readability-function-cognitive-complexity) { - using significand_type = std::conditional_t::value, detail::uint128, int>; + using significand_type = std::conditional_t::value || std::is_same::value, detail::uint128, int>; if (BOOST_DECIMAL_IS_CONSTANT_EVALUATED(coeff)) { diff --git a/include/boost/decimal/detail/mul_impl.hpp b/include/boost/decimal/detail/mul_impl.hpp index 7687ac68c..0c10a9e25 100644 --- a/include/boost/decimal/detail/mul_impl.hpp +++ b/include/boost/decimal/detail/mul_impl.hpp @@ -137,6 +137,7 @@ constexpr auto d128_mul_impl(T1 lhs_sig, std::int32_t lhs_exp, bool lhs_sign, sign = false; } + BOOST_DECIMAL_ASSERT(res_sig.high == uint128(0,0)); return {res_sig.low, res_exp, sign}; } diff --git a/include/boost/decimal/detail/promotion.hpp b/include/boost/decimal/detail/promotion.hpp index 00975dd67..9e0063b2b 100644 --- a/include/boost/decimal/detail/promotion.hpp +++ b/include/boost/decimal/detail/promotion.hpp @@ -60,6 +60,12 @@ struct decimal_val static constexpr int value = 128; }; +template <> +struct decimal_val +{ + static constexpr int value = 129; +}; + template constexpr int decimal_val_v = decimal_val::value; diff --git a/include/boost/decimal/numbers.hpp b/include/boost/decimal/numbers.hpp index cf183702c..d99b12fbe 100644 --- a/include/boost/decimal/numbers.hpp +++ b/include/boost/decimal/numbers.hpp @@ -24,6 +24,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 e_v = decimal128{detail::uint128{UINT64_C(147358353192158), UINT64_C(5661142159003925334)}, -33}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast e_v = decimal128_fast{detail::uint128{UINT64_C(147358353192158), + UINT64_C(5661142159003925334)}, -33}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec log2e_v = Dec{UINT64_C(1442695040888963407), -18}; @@ -31,6 +35,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 log2e_v = decimal128{detail::uint128{UINT64_C(78208654878293), UINT64_C(16395798456599530402)}, -33}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast log2e_v = decimal128_fast{detail::uint128{UINT64_C(78208654878293), + UINT64_C(16395798456599530402)}, -33}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec log10e_v = Dec{UINT64_C(4342944819032518277), -19}; @@ -38,12 +46,19 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 log10e_v = decimal128{detail::uint128{UINT64_C(235431510388986), UINT64_C(2047877485384264674)}, -34}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast log10e_v = decimal128_fast{detail::uint128{UINT64_C(235431510388986), + UINT64_C(2047877485384264674)}, -34}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec log10_2_v = Dec{UINT64_C(3010299956639811952), -19}; BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 log10_2_v = decimal128{detail::uint128{UINT64_C(163188687641095), UINT64_C(3612628795761985410)}, -34}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast log10_2_v = decimal128_fast{detail::uint128{UINT64_C(163188687641095), + UINT64_C(3612628795761985410)}, -34}; BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec pi_v = Dec{UINT64_C(3141592653589793238), -18}; @@ -52,6 +67,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 pi_v = decimal128{detail::uint128{UINT64_C(170306079004327), UINT64_C(13456286628489437068)}, -33}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast pi_v = decimal128_fast{detail::uint128{UINT64_C(170306079004327), + UINT64_C(13456286628489437068)}, -33}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec pi_over_four_v = Dec{UINT64_C(7853981633974483096), -19}; @@ -63,6 +82,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 pi_over_four_v = decimal128{detail::uint128{UINT64_C(42576519751081932), UINT64_C(6764235707220873609)}, -38}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast pi_over_four_v = decimal128_fast{detail::uint128{UINT64_C(42576519751081932), + UINT64_C(6764235707220873609)}, -38}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec inv_pi_v = Dec{UINT64_C(3183098861837906715), -19}; @@ -70,6 +93,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 inv_pi_v = decimal128{detail::uint128{UINT64_C(172556135062039), UINT64_C(13820348844234745256)}, -34}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast inv_pi_v = decimal128_fast{detail::uint128{UINT64_C(172556135062039), + UINT64_C(13820348844234745256)}, -34}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec inv_sqrtpi_v = Dec{UINT64_C(5641895835477562869), -19}; @@ -77,6 +104,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 inv_sqrtpi_v = decimal128{detail::uint128{UINT64_C(305847786088084), UINT64_C(12695685840195063976)}, -34}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast inv_sqrtpi_v = decimal128_fast{detail::uint128{UINT64_C(305847786088084), + UINT64_C(12695685840195063976)}, -34}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec ln2_v = Dec{UINT64_C(6931471805599453094), -19}; @@ -84,6 +115,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 ln2_v = decimal128{detail::uint128{UINT64_C(375755839507647), UINT64_C(8395602002641374208)}, -34}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast ln2_v = decimal128_fast{detail::uint128{UINT64_C(375755839507647), + UINT64_C(8395602002641374208)}, -34}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec ln10_v = Dec{UINT64_C(2302585092994045684), -18}; @@ -91,6 +126,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 ln10_v = decimal128{detail::uint128{UINT64_C(124823388007844), UINT64_C(1462833818723808456)}, -33}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast ln10_v = decimal128_fast{detail::uint128{UINT64_C(124823388007844), + UINT64_C(1462833818723808456)}, -33}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec sqrt2_v = Dec{UINT64_C(1414213562373095049), -18}; @@ -98,6 +137,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 sqrt2_v = decimal128{detail::uint128{UINT64_C(76664670834168), UINT64_C(12987834932751794202)}, -33}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast sqrt2_v = decimal128_fast{detail::uint128{UINT64_C(76664670834168), + UINT64_C(12987834932751794202)}, -33}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec sqrt3_v = Dec{UINT64_C(1732050807568877294), -18}; @@ -105,6 +148,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 sqrt3_v = decimal128{detail::uint128{UINT64_C(93894662421072), UINT64_C(8437766544231453518)}, -33}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast sqrt3_v = decimal128_fast{detail::uint128{UINT64_C(93894662421072), + UINT64_C(8437766544231453518)}, -33}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec sqrt10_v = Dec{UINT64_C(3162277660168379332), -18}; @@ -112,6 +159,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 sqrt10_v = decimal128{detail::uint128{UINT64_C(171427415457846), UINT64_C(13450487317535253574)}, -33}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast sqrt10_v = decimal128_fast{detail::uint128{UINT64_C(171427415457846), + UINT64_C(13450487317535253574)}, -33}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec cbrt2_v = Dec{UINT64_C(1259921049894873165), -18}; @@ -119,6 +170,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 cbrt2_v = decimal128{detail::uint128{UINT64_C(68300456972811), UINT64_C(17628749411094165652)}, -33}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast cbrt2_v = decimal128_fast{detail::uint128{UINT64_C(68300456972811), + UINT64_C(17628749411094165652)}, -33}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec cbrt10_v = Dec{UINT64_C(2154434690031883722), -18}; @@ -126,6 +181,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 cbrt10_v = decimal128{detail::uint128{UINT64_C(116792138570535), UINT64_C(2467411419527284790)}, -33}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast cbrt10_v = decimal128_fast{detail::uint128{UINT64_C(116792138570535), + UINT64_C(2467411419527284790)}, -33}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec inv_sqrt2_v = Dec{UINT64_C(7071067811865475244), -19}; @@ -133,6 +192,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 inv_sqrt2_v = decimal128{detail::uint128{UINT64_C(383323354170843), UINT64_C(9598942442630316202)}, -34}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast inv_sqrt2_v = decimal128_fast{detail::uint128{UINT64_C(383323354170843), + UINT64_C(9598942442630316202)}, -34}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec inv_sqrt3_v = Dec{UINT64_C(5773502691896257645), -19}; @@ -140,6 +203,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 inv_sqrt3_v = decimal128{detail::uint128{UINT64_C(312982208070241), UINT64_C(9679144407061960114)}, -34}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast inv_sqrt3_v = decimal128_fast{detail::uint128{UINT64_C(312982208070241), + UINT64_C(9679144407061960114)}, -34}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec egamma_v = Dec{UINT64_C(5772156649015328606), -19}; @@ -147,6 +214,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 egamma_v = decimal128{detail::uint128{UINT64_C(312909238939453), UINT64_C(7916302232898517972)}, -34}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast egamma_v = decimal128_fast{detail::uint128{UINT64_C(312909238939453), + UINT64_C(7916302232898517972)}, -34}; + BOOST_DECIMAL_EXPORT template , bool> = true> BOOST_DECIMAL_CONSTEXPR_VARIABLE Dec phi_v = Dec{UINT64_C(1618033988749894848), -18}; @@ -154,6 +225,10 @@ BOOST_DECIMAL_EXPORT template <> BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128 phi_v = decimal128{detail::uint128{UINT64_C(87713798287901), UINT64_C(2061523135646567614)}, -33}; +BOOST_DECIMAL_EXPORT template <> +BOOST_DECIMAL_CONSTEXPR_VARIABLE_SPECIALIZATION decimal128_fast phi_v = decimal128_fast{detail::uint128{UINT64_C(87713798287901), + UINT64_C(2061523135646567614)}, -33}; + BOOST_DECIMAL_EXPORT BOOST_DECIMAL_CONSTEXPR_VARIABLE auto e {e_v}; BOOST_DECIMAL_EXPORT BOOST_DECIMAL_CONSTEXPR_VARIABLE auto log10_2 {log10_2_v}; BOOST_DECIMAL_EXPORT BOOST_DECIMAL_CONSTEXPR_VARIABLE auto log10e {log10e_v}; diff --git a/test/test_asin.cpp b/test/test_asin.cpp index 3602c0672..62c161a72 100644 --- a/test/test_asin.cpp +++ b/test/test_asin.cpp @@ -42,8 +42,8 @@ using namespace boost::decimal; template void test_asin() { - constexpr auto max_iter {std::is_same::value ? 2 : N}; - constexpr auto tol {std::is_same::value ? 25000 : 50}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? 2 : N}; + constexpr auto tol {std::is_same::value || std::is_same::value ? 25000 : 50}; for (std::size_t n {}; n < max_iter; ++n) { @@ -76,6 +76,11 @@ void test_asin() auto ret_val {std::asin(val1)}; auto ret_dec {static_cast(asin(d1))}; + if (std::isinf(ret_dec)) + { + std::cerr << "INF: " << d1 << " iter: n = " << n << std::endl; + } + const auto distance {std::fabs(boost::math::float_distance(ret_val, ret_dec))}; if (!BOOST_TEST(distance < tol)) { diff --git a/test/test_cmath.cpp b/test/test_cmath.cpp index ee6db1483..3305c074b 100644 --- a/test/test_cmath.cpp +++ b/test/test_cmath.cpp @@ -311,7 +311,7 @@ void test_div_fmod() { std::uniform_real_distribution dist(0.0F, 1e30F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -349,7 +349,7 @@ void test_copysign() { std::uniform_real_distribution dist(0.0F, 1e30F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -391,7 +391,7 @@ void test_fma() std::uniform_real_distribution dist(-1e3, 1e3); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -445,7 +445,7 @@ void test_fdim() { std::uniform_real_distribution dist(1.0F, 1e5F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -543,7 +543,7 @@ void test_sqrt() using comp_type = std::conditional_t::value || std::is_same::value, float, double>; std::uniform_real_distribution dist(0, 1e5); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -581,7 +581,7 @@ void test_two_val_hypot() { std::uniform_real_distribution dist(1.0F, 1e5F); - constexpr auto max_iter {std::is_same::value ? 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -629,7 +629,7 @@ void test_mixed_two_val_hypot() { std::uniform_real_distribution dist(1.0F, 1e5F); - constexpr auto max_iter {std::is_same::value ? 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -667,7 +667,7 @@ void test_three_val_hypot() std::uniform_real_distribution dist(1.0F, 1e5F); - constexpr auto max_iter {std::is_same::value ? 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -722,7 +722,7 @@ void test_rint() { std::uniform_real_distribution dist(-1e20F, 1e20F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { @@ -790,7 +790,7 @@ void test_lrint() std::uniform_real_distribution dist(-1e5F, 1e5F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -869,7 +869,7 @@ void test_llrint() { std::uniform_real_distribution dist(-1e20F, 1e20F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; std::uniform_real_distribution dist2(-1e5F, 1e5F); @@ -912,7 +912,7 @@ void test_nearbyint() { std::uniform_real_distribution dist(-1e20F, 1e20F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -976,7 +976,7 @@ void test_round() { std::uniform_real_distribution dist(-1e5F, 1e5F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -1018,7 +1018,7 @@ void test_lround() { std::uniform_real_distribution dist(-1e20F, 1e20F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; std::uniform_real_distribution dist2(-1e5F, 1e5F); @@ -1061,7 +1061,7 @@ void test_llround() { std::uniform_real_distribution dist(-1e20F, 1e20F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; std::uniform_real_distribution dist2(-1e5F, 1e5F); @@ -1104,7 +1104,7 @@ void test_nextafter() { std::uniform_real_distribution dist(1.0F, 1e5F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -1147,7 +1147,7 @@ void test_nexttoward() { std::uniform_real_distribution dist(1.0F, 1e5F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -1223,7 +1223,7 @@ void test_log2() { std::uniform_real_distribution dist(-0.5F, 0.5F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -1256,7 +1256,7 @@ void test_log10() { std::uniform_real_distribution dist(-0.5F, 0.5F); - constexpr auto max_iter {std::is_same::value ? N / 4 : N}; + constexpr auto max_iter {std::is_same::value || std::is_same::value ? N / 4 : N}; for (std::size_t n {}; n < max_iter; ++n) { const auto val1 {dist(rng)}; @@ -1331,6 +1331,15 @@ int main() test_islessgreater(); test_isunordered(); + test_fmax(); + test_isgreater(); + test_isgreaterequal(); + test_fmin(); + test_isless(); + test_islessequal(); + test_islessgreater(); + test_isunordered(); + test_floor(); test_ceil(); test_trunc(); @@ -1351,6 +1360,10 @@ int main() test_ceil(); test_trunc(); + test_floor(); + test_ceil(); + test_trunc(); + test_frexp10(); test_scalbn(); test_scalbln(); @@ -1378,6 +1391,7 @@ int main() test_fma(); test_fma(); test_fma(); + test_fma(); test_modf(); test_modf(); @@ -1394,12 +1408,14 @@ int main() test_ilogb(); test_ilogb(); test_ilogb(); + test_ilogb(); test_logb(); test_logb(); test_logb(); test_logb(); test_logb(); + test_logb(); test_sqrt(); test_sqrt(); @@ -1416,9 +1432,16 @@ int main() test_three_val_hypot(); #if !defined(BOOST_DECIMAL_REDUCE_TEST_DEPTH) + test_sqrt(); + test_sqrt(); + test_two_val_hypot(); test_three_val_hypot(); test_mixed_two_val_hypot(); + + test_two_val_hypot(); + test_three_val_hypot(); + test_mixed_two_val_hypot(); #endif test_mixed_two_val_hypot(); @@ -1499,6 +1522,9 @@ int main() #if !defined(BOOST_DECIMAL_REDUCE_TEST_DEPTH) test_log2(); test_log10(); + + test_log2(); + test_log10(); #endif return boost::report_errors(); diff --git a/test/test_promotion.cpp b/test/test_promotion.cpp index 9729af313..8a046645f 100644 --- a/test/test_promotion.cpp +++ b/test/test_promotion.cpp @@ -108,5 +108,14 @@ int main() static_assert(std::is_same, decimal64_fast>::value, "False"); static_assert(std::is_same, decimal64_fast>::value, "False"); + static_assert(std::is_same, decimal128_fast>::value, "False"); + static_assert(std::is_same, decimal128_fast>::value, "False"); + static_assert(std::is_same, decimal128_fast>::value, "False"); + static_assert(std::is_same, decimal128_fast>::value, "False"); + static_assert(std::is_same, decimal128_fast>::value, "False"); + static_assert(std::is_same, decimal128_fast>::value, "False"); + static_assert(std::is_same, decimal128_fast>::value, "False"); + static_assert(std::is_same, decimal128_fast>::value, "False"); + return 0; }