diff --git a/include/boost/decimal/detail/cmath/impl/cosh_impl.hpp b/include/boost/decimal/detail/cmath/impl/cosh_impl.hpp index 0ffaf7523..0812a9076 100644 --- a/include/boost/decimal/detail/cmath/impl/cosh_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/cosh_impl.hpp @@ -99,7 +99,7 @@ constexpr typename cosh_table_imp::d128_coeffs_t cosh_table_imp::d128_coef using cosh_table = cosh_detail::cosh_table_imp; template -constexpr auto cosh_series_expansion(T z) noexcept; +constexpr auto cosh_series_expansion(T z2) noexcept; template <> constexpr auto cosh_series_expansion(decimal32 z2) noexcept diff --git a/include/boost/decimal/detail/cmath/impl/log1p_impl.hpp b/include/boost/decimal/detail/cmath/impl/log1p_impl.hpp new file mode 100644 index 000000000..e2e864ed0 --- /dev/null +++ b/include/boost/decimal/detail/cmath/impl/log1p_impl.hpp @@ -0,0 +1,162 @@ +// Copyright 2023 - 2024 Matt Borland +// Copyright 2023 - 2024 Christopher Kormanyos +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_DECIMAL_DETAIL_CMATH_IMPL_LOG1P_IMPL_HPP +#define BOOST_DECIMAL_DETAIL_CMATH_IMPL_LOG1P_IMPL_HPP + +#include +#include + +#ifndef BOOST_DECIMAL_BUILD_MODULE +#include +#include +#include +#endif + +namespace boost { +namespace decimal { +namespace detail { + +namespace log1p_detail { + +template +struct log1p_table_imp +{ +private: + using d32_coeffs_t = std::array; + using d64_coeffs_t = std::array; + using d128_coeffs_t = std::array; + +public: + static constexpr d32_coeffs_t d32_coeffs = + {{ + // Series[Log[1 + x], {x, 0, 13}] + // (1), // * z + -boost::decimal::decimal32 { 5, -1 }, // * z^2 + boost::decimal::decimal32 { UINT64_C(3333333333333333333), -19 }, // * z^3 + -boost::decimal::decimal32 { 25, -2 }, // * z^4 + boost::decimal::decimal32 { 2, -1 }, // * z^5 + -boost::decimal::decimal32 { UINT64_C(1666666666666666667), -19 }, // * z^6 + boost::decimal::decimal32 { UINT64_C(1428571428571428571), -19 }, // * z^7 + -boost::decimal::decimal32 { 125, -3 }, // * z^8 + boost::decimal::decimal32 { UINT64_C(1111111111111111111), -19 }, // * z^9 + -boost::decimal::decimal32 { 1, -1 }, // * z^10 + boost::decimal::decimal32 { UINT64_C(9090909090909090909), -19 - 1 }, // * z^11 + -boost::decimal::decimal32 { UINT64_C(8333333333333333333), -19 - 1 }, // * z^12 + boost::decimal::decimal32 { UINT64_C(7692307692307692308), -19 - 1 }, // * z^13 + }}; + + static constexpr d64_coeffs_t d64_coeffs = + {{ + // Series[Log[1 + x], {x, 0, 21}] + // (1), // * z + -boost::decimal::decimal64 { 5, -1 }, // * z^2 + boost::decimal::decimal64 { UINT64_C(3333333333333333333), -19 }, // * z^3 + -boost::decimal::decimal64 { 25, -2 }, // * z^4 + boost::decimal::decimal64 { 2, -1 }, // * z^5 + -boost::decimal::decimal64 { UINT64_C(1666666666666666667), -19 }, // * z^6 + boost::decimal::decimal64 { UINT64_C(1428571428571428571), -19 }, // * z^7 + -boost::decimal::decimal64 { 125, -3 }, // * z^8 + boost::decimal::decimal64 { UINT64_C(1111111111111111111), -19 }, // * z^9 + -boost::decimal::decimal64 { 1, -1 }, // * z^10 + boost::decimal::decimal64 { UINT64_C(9090909090909090909), -19 - 1 }, // * z^11 + -boost::decimal::decimal64 { UINT64_C(8333333333333333333), -19 - 1 }, // * z^12 + boost::decimal::decimal64 { UINT64_C(7692307692307692308), -19 - 1 }, // * z^13 + -boost::decimal::decimal64 { UINT64_C(7142857142857142857), -19 - 1 }, // * z^14 + boost::decimal::decimal64 { UINT64_C(6666666666666666667), -19 - 1 }, // * z^15 + -boost::decimal::decimal64 { UINT64_C(6250000000000000000), -19 - 1 }, // * z^16 + boost::decimal::decimal64 { UINT64_C(5882352941176470588), -19 - 1 }, // * z^17 + -boost::decimal::decimal64 { UINT64_C(5555555555555555556), -19 - 1 }, // * z^18 + boost::decimal::decimal64 { UINT64_C(5263157894736842105), -19 - 1 }, // * z^19 + -boost::decimal::decimal64 { 5, -2 }, // * z^20 + boost::decimal::decimal64 { UINT64_C(4761904761904761905), -19 - 1 }, // * z^21 + }}; + + static constexpr d128_coeffs_t d128_coeffs = + {{ + // Series[Log[(1 + (z/2))/(1 - (z/2))], {z, 0, 43}] + // (1), // * z + -::boost::decimal::decimal128 { 5, -1 }, // * z^2 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(180700362080917), UINT64_C(7483252092553221458) }, -34 }, // * z^3 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(135525271560688), UINT64_C(1000753050987528192) }, -34 }, // * z^4 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(108420217248550), UINT64_C(8179300070273843200) }, -34 }, // * z^5 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(90350181040458), UINT64_C(12964998083131386532) }, -34 }, // * z^6 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(77443012320393), UINT64_C(3207108039665666332) }, -34 }, // * z^7 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(67762635780344), UINT64_C(500376525493764096) }, -34 }, // * z^8 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(60233454026972), UINT64_C(8643332055420924359) }, -34 }, // * z^9 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(54210108624275), UINT64_C(4089650035136921600) }, -34 }, // * z^10 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(492819169311592), UINT64_C(17054915875379776418) }, -35 }, // * z^11 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(451750905202293), UINT64_C(9484758194528277842) }, -35 }, // * z^12 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(417000835571347), UINT64_C(15850062977145160938) }, -35 }, // * z^13 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(387215061601965), UINT64_C(16035540198328331700) }, -35 }, // * z^14 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(361400724161834), UINT64_C(14966504185106442916) }, -35 }, // * z^15 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(338813178901720), UINT64_C(2501882627468820480) }, -35 }, // * z^16 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(318882991907501), UINT64_C(5610020838860575434) }, -35 }, // * z^17 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(301167270134862), UINT64_C(6323172129685518558) }, -35 }, // * z^18 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(285316361180395), UINT64_C(16670067533954968520) }, -35 }, // * z^19 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(271050543121376), UINT64_C(2001506101975056384) }, -35 }, // * z^20 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(258143374401310), UINT64_C(10690360132218887800) }, -35 }, // * z^21 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(246409584655796), UINT64_C(8527457937689888204) }, -35 }, // * z^22 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(235696124453370), UINT64_C(9760763598982462770) }, -35 }, // * z^23 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(225875452601146), UINT64_C(13965751134118914724) }, -35 }, // * z^24 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(216840434497100), UINT64_C(16358600140547686400) }, -35 }, // * z^25 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(208500417785673), UINT64_C(17148403525427356272) }, -35 }, // * z^26 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(200778180089908), UINT64_C(4215448086457012372) }, -35 }, // * z^27 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(193607530800982), UINT64_C(17241142136018941658) }, -35 }, // * z^28 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(186931409049224), UINT64_C(16646619993397598836) }, -35 }, // * z^29 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(180700362080917), UINT64_C(7483252092553221458) }, -35 }, // * z^30 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(174871318142823), UINT64_C(5456688082434451252) }, -35 }, // * z^31 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(169406589450860), UINT64_C(1250941313734410240) }, -35 }, // * z^32 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(164273056437197), UINT64_C(11833886649696442678) }, -35 }, // * z^33 + -::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(159441495953750), UINT64_C(12028382456285063520) }, -35 }, // * z^34 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(154886024640786), UINT64_C(6414216079331332674) }, -35 }, // * z^35 + -::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 + }}; +}; + +#if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) + +template +constexpr typename log1p_table_imp::d32_coeffs_t log1p_table_imp::d32_coeffs; + +template +constexpr typename log1p_table_imp::d64_coeffs_t log1p_table_imp::d64_coeffs; + +template +constexpr typename log1p_table_imp::d128_coeffs_t log1p_table_imp::d128_coeffs; + +#endif + +} //namespace log1p_detail + +using log1p_table = log1p_detail::log1p_table_imp; + +template +constexpr auto log1p_series_expansion(T z2) noexcept; + +template <> +constexpr auto log1p_series_expansion(decimal32 z2) noexcept +{ + return taylor_series_result(z2, log1p_table::d32_coeffs); +} + +template <> +constexpr auto log1p_series_expansion(decimal64 z2) noexcept +{ + return taylor_series_result(z2, log1p_table::d64_coeffs); +} + +template <> +constexpr auto log1p_series_expansion(decimal128 z2) noexcept +{ + return taylor_series_result(z2, log1p_table::d128_coeffs); +} + +} //namespace detail +} //namespace decimal +} //namespace boost + +#endif //BOOST_DECIMAL_DETAIL_CMATH_IMPL_LOG1P_IMPL_HPP diff --git a/include/boost/decimal/detail/cmath/impl/log_impl.hpp b/include/boost/decimal/detail/cmath/impl/log_impl.hpp new file mode 100644 index 000000000..ed0a14e3e --- /dev/null +++ b/include/boost/decimal/detail/cmath/impl/log_impl.hpp @@ -0,0 +1,134 @@ +// Copyright 2023 - 2024 Matt Borland +// Copyright 2023 - 2024 Christopher Kormanyos +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_DECIMAL_DETAIL_CMATH_IMPL_LOG_IMPL_HPP +#define BOOST_DECIMAL_DETAIL_CMATH_IMPL_LOG_IMPL_HPP + +#include +#include + +#ifndef BOOST_DECIMAL_BUILD_MODULE +#include +#include +#include +#endif + +namespace boost { +namespace decimal { +namespace detail { + +namespace log_detail { + +template +struct log_table_imp +{ +private: + using d32_coeffs_t = std::array; + using d64_coeffs_t = std::array; + using d128_coeffs_t = std::array; + +public: + static constexpr d32_coeffs_t d32_coeffs = + {{ + // Series[Log[(1 + (z/2))/(1 - (z/2))], {z, 0, 17}] + // (1), // * z + ::boost::decimal::decimal32 { UINT64_C(8333333333333333333), - 19 - 1 }, // * z^3 + ::boost::decimal::decimal32 { UINT64_C(1250000000000000000), - 19 - 1 }, // * z^5 + ::boost::decimal::decimal32 { UINT64_C(2232142857142857143), - 19 - 2 }, // * z^7 + ::boost::decimal::decimal32 { UINT64_C(4340277777777777778), - 19 - 3 }, // * z^9 + ::boost::decimal::decimal32 { UINT64_C(8877840909090909091), - 19 - 4 }, // * z^11 + ::boost::decimal::decimal32 { UINT64_C(1878004807692307692), - 19 - 4 }, // * z^13 + ::boost::decimal::decimal32 { UINT64_C(4069010416666666667), - 19 - 5 }, // * z^15 + ::boost::decimal::decimal32 { UINT64_C(8975758272058823529), - 19 - 6 }, // * z^17 + }}; + + static constexpr d64_coeffs_t d64_coeffs = + {{ + // Series[Log[(1 + (z/2))/(1 - (z/2))], {z, 0, 23}] + // (1), // * z + ::boost::decimal::decimal64 { UINT64_C(8333333333333333333), - 19 - 1 }, // * z^3 + ::boost::decimal::decimal64 { UINT64_C(1250000000000000000), - 19 - 1 }, // * z^5 + ::boost::decimal::decimal64 { UINT64_C(2232142857142857143), - 19 - 2 }, // * z^7 + ::boost::decimal::decimal64 { UINT64_C(4340277777777777778), - 19 - 3 }, // * z^9 + ::boost::decimal::decimal64 { UINT64_C(8877840909090909091), - 19 - 4 }, // * z^11 + ::boost::decimal::decimal64 { UINT64_C(1878004807692307692), - 19 - 4 }, // * z^13 + ::boost::decimal::decimal64 { UINT64_C(4069010416666666667), - 19 - 5 }, // * z^15 + ::boost::decimal::decimal64 { UINT64_C(8975758272058823529), - 19 - 6 }, // * z^17 + ::boost::decimal::decimal64 { UINT64_C(2007735402960526316), - 19 - 6 }, // * z^19 + ::boost::decimal::decimal64 { UINT64_C(4541306268601190476), - 19 - 7 }, // * z^21 + ::boost::decimal::decimal64 { UINT64_C(1036602517832880435), - 19 - 7 }, // * z^23 + }}; + + static constexpr d128_coeffs_t d128_coeffs = + {{ + // Series[Log[(1 + (z/2))/(1 - (z/2))], {z, 0, 43}] + // (1), // * z + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(451750905202293), UINT64_C(9484758194528277842) }, -35 }, // * z^3 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(67762635780344), UINT64_C(500376525493764096) }, -35 }, // * z^5 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(121004706750614), UINT64_C(6164027816584450626) }, -36 }, // * z^7 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(235286929792861), UINT64_C(3787056721709964394) }, -37 }, // * z^9 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(481268720030852), UINT64_C(8584740752302634068) }, -38 }, // * z^11 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(101806844621911), UINT64_C(1816002851448634124) }, -38 }, // * z^13 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(220581496680807), UINT64_C(7009130190423632548) }, -39 }, // * z^15 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(486576830913545), UINT64_C(12748560115094843630) }, -40 }, // * z^17 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(108839554283293), UINT64_C(2123490654414259032) }, -40 }, // * z^19 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(246184706116972), UINT64_C(9634423737622849438) }, -41 }, // * z^21 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(56194335091917), UINT64_C(11823550152479764302) }, -41 }, // * z^23 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(129246970711410), UINT64_C(10592095684364861440) }, -42 }, // * z^25 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(299182802572709), UINT64_C(12220910627630811506) }, -43 }, // * z^27 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(69637376460889), UINT64_C(5865971761607874066) }, -43 }, // * z^29 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(162861606239176), UINT64_C(11636108014793143194) }, -44 }, // * z^31 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(382478014652611), UINT64_C(14470401740943906374) }, -45 }, // * z^33 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(90155532025258), UINT64_C(9076666090147568782) }, -45 }, // * z^35 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(213205650059732), UINT64_C(16978042870933143358) }, -46 }, // * z^37 + ::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(505680067449366), UINT64_C(9996854995997550184) }, -47 }, // * z^39 + ::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 + }}; +}; + +#if !(defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L) && (!defined(_MSC_VER) || _MSC_VER != 1900) + +template +constexpr typename log_table_imp::d32_coeffs_t log_table_imp::d32_coeffs; + +template +constexpr typename log_table_imp::d64_coeffs_t log_table_imp::d64_coeffs; + +template +constexpr typename log_table_imp::d128_coeffs_t log_table_imp::d128_coeffs; + +#endif + +} //namespace log_detail + +using log_table = log_detail::log_table_imp; + +template +constexpr auto log_series_expansion(T z2) noexcept; + +template <> +constexpr auto log_series_expansion(decimal32 z2) noexcept +{ + return taylor_series_result(z2, log_table::d32_coeffs); +} + +template <> +constexpr auto log_series_expansion(decimal64 z2) noexcept +{ + return taylor_series_result(z2, log_table::d64_coeffs); +} + +template <> +constexpr auto log_series_expansion(decimal128 z2) noexcept +{ + return taylor_series_result(z2, log_table::d128_coeffs); +} + +} //namespace detail +} //namespace decimal +} //namespace boost + +#endif //BOOST_DECIMAL_DETAIL_CMATH_IMPL_LOG_IMPL_HPP diff --git a/include/boost/decimal/detail/cmath/impl/sinh_impl.hpp b/include/boost/decimal/detail/cmath/impl/sinh_impl.hpp index 67196e415..69d390ba7 100644 --- a/include/boost/decimal/detail/cmath/impl/sinh_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/sinh_impl.hpp @@ -99,7 +99,7 @@ constexpr typename sinh_table_imp::d128_coeffs_t sinh_table_imp::d128_coef using sinh_table = sinh_detail::sinh_table_imp; template -constexpr auto sinh_series_expansion(T z) noexcept; +constexpr auto sinh_series_expansion(T z2) noexcept; template <> constexpr auto sinh_series_expansion(decimal32 z2) noexcept diff --git a/include/boost/decimal/detail/cmath/impl/tanh_impl.hpp b/include/boost/decimal/detail/cmath/impl/tanh_impl.hpp index 68150939f..66a022652 100644 --- a/include/boost/decimal/detail/cmath/impl/tanh_impl.hpp +++ b/include/boost/decimal/detail/cmath/impl/tanh_impl.hpp @@ -107,7 +107,7 @@ constexpr typename tanh_table_imp::d128_coeffs_t tanh_table_imp::d128_coef using tanh_table = tanh_detail::tanh_table_imp; template -constexpr auto tanh_series_expansion(T z) noexcept; +constexpr auto tanh_series_expansion(T z2) noexcept; template <> constexpr auto tanh_series_expansion(decimal32 z2) noexcept diff --git a/include/boost/decimal/detail/cmath/log.hpp b/include/boost/decimal/detail/cmath/log.hpp index b8e1820cf..e71570b8e 100644 --- a/include/boost/decimal/detail/cmath/log.hpp +++ b/include/boost/decimal/detail/cmath/log.hpp @@ -1,16 +1,16 @@ -// Copyright 2023 Matt Borland -// Copyright 2023 Christopher Kormanyos +// Copyright 2023 - 2024 Matt Borland +// Copyright 2023 - 2024 Christopher Kormanyos // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #ifndef BOOST_DECIMAL_DETAIL_CMATH_LOG_HPP #define BOOST_DECIMAL_DETAIL_CMATH_LOG_HPP -#include -#include +#include // NOLINT(llvm-include-order) +#include #include -#include #include +#include #include #ifndef BOOST_DECIMAL_BUILD_MODULE @@ -21,67 +21,14 @@ namespace boost { namespace decimal { -namespace detail { - -#if (defined(__clang__) && (__clang__ < 6)) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wmissing-braces" -#endif - -template -BOOST_DECIMAL_CONSTEXPR_VARIABLE std::array small_coefficient_table { - // (1,) 12, 80, 448, 2304, 11264, 53248, 245760, 1114112, 4980736, 22020096, 96468992, ... - // See also Sloane's A058962 at: https://oeis.org/A058962 - - // See also - // Series[Log[(1 + (z/2))/(1 - (z/2))], {z, 0, 23}] - // Or at Wolfram Alpha: https://www.wolframalpha.com/input?i=Series%5BLog%5B%281+%2B+%28z%2F2%29%29%2F%281+-+%28z%2F2%29%29%5D%2C+%7Bz%2C+0%2C+21%7D%5D - - // TODO(ckormanyos) - // Consider also Pade expansion of Log[1 + z/2]. - // PadeApproximant[Log[1 + z/2], {z, 6, 6}] - // FullSimplify[%]. - - T { UINT64_C(833333333333333333), -18 - 1 }, // * z^3 - T { UINT64_C(125000000000000000), -18 - 1 }, // * z^5 - T { UINT64_C(223214285714285714), -18 - 2 }, // * z^7 - T { UINT64_C(434027777777777778), -18 - 3 }, // * z^9 - T { UINT64_C(887784090909090909), -18 - 4 }, // * z^11 - T { UINT64_C(187800480769230769), -18 - 4 }, // * z^13 - T { UINT64_C(406901041666666667), -18 - 5 }, // * z^15 - T { UINT64_C(897575827205882353), -18 - 6 }, // * z^17 - T { UINT64_C(200773540296052632), -18 - 6 }, // * z^19 - T { UINT64_C(454130626860119048), -18 - 7 }, // * z^21 - T { UINT64_C(103660251783288043), -18 - 7 } // * z^23 -}; - -template -BOOST_DECIMAL_CONSTEXPR_VARIABLE std::array large_coefficient_table { - T{uint128{UINT64_C(451750905202293), UINT64_C(9484758194528277842)}, -35}, // z^3 - T{uint128{UINT64_C(67762635780344), UINT64_C(500376525493764096)}, -35}, // z^5 - T{uint128{UINT64_C(121004706750614), UINT64_C(6164027816584450626)}, -36}, // z^7 - T{uint128{UINT64_C(235286929792861), UINT64_C(3787056721709964394)}, -37}, // z^9 - T{uint128{UINT64_C(481268720030852), UINT64_C(8584740752302634068)}, -38}, // z^11 - T{uint128{UINT64_C(101806844621911), UINT64_C(1816002851448634124)}, -38}, // z^13 - T{uint128{UINT64_C(220581496680807), UINT64_C(7009130190423632548)}, -40}, // z^15 - T{uint128{UINT64_C(486576830913545), UINT64_C(12748560115094843630)}, -41}, // z^17 - T{uint128{UINT64_C(108839554283293), UINT64_C(2123490654414259032)}, -41}, // z^19 - T{uint128{UINT64_C(246184706116972), UINT64_C(9634423737622849438)}, -42}, // z^21 - T{uint128{UINT64_C(56194335091917), UINT64_C(11823550152479764302)}, -42} // z^23 -}; - -#if (defined(__clang__) && (__clang__ < 6)) -# pragma clang diagnostic pop -#endif - -template -constexpr auto log_impl(T x) noexcept +BOOST_DECIMAL_EXPORT template +constexpr auto log(T x) noexcept BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T) { constexpr T zero { 0, 0 }; constexpr T one { 1, 0 }; - auto result = zero; + T result { }; if (isnan(x)) { @@ -89,14 +36,7 @@ constexpr auto log_impl(T x) noexcept } else if (isinf(x)) { - if (!signbit(x)) - { - result = x; - } - else - { - result = std::numeric_limits::quiet_NaN(); - } + result = (!signbit(x)) ? x: std::numeric_limits::quiet_NaN(); } else if (x < one) { @@ -138,18 +78,7 @@ constexpr auto log_impl(T x) noexcept const auto z = s + s; const auto zsq = z * z; - auto& coefficient_table = std::is_same::value ? detail::large_coefficient_table : detail::small_coefficient_table; - - auto rit = coefficient_table.crbegin() + static_cast((sizeof(T) == 4U) ? 5U : 0U); - - result = *rit; - - while(rit != coefficient_table.crend()) - { - result = fma(result, zsq, *rit++); - } - - result = z * fma(result, zsq, one); + result = z * fma(detail::log_series_expansion(zsq), zsq, one); if (exp2val > 0) { @@ -164,29 +93,6 @@ constexpr auto log_impl(T x) noexcept return result; } -} //namespace detail - -BOOST_DECIMAL_EXPORT template -constexpr auto log(T x) noexcept - BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T) -{ - #if BOOST_DECIMAL_DEC_EVAL_METHOD == 0 - - using evaluation_type = T; - - #elif BOOST_DECIMAL_DEC_EVAL_METHOD == 1 - - using evaluation_type = detail::promote_args_t; - - #else // BOOST_DECIMAL_DEC_EVAL_METHOD == 2 - - using evaluation_type = detail::promote_args_t; - - #endif - - return static_cast(detail::log_impl(static_cast(x))); -} - } // namespace decimal } // namespace boost diff --git a/include/boost/decimal/detail/cmath/log1p.hpp b/include/boost/decimal/detail/cmath/log1p.hpp index 7cf401f78..3c79bc4d4 100644 --- a/include/boost/decimal/detail/cmath/log1p.hpp +++ b/include/boost/decimal/detail/cmath/log1p.hpp @@ -7,9 +7,10 @@ #define BOOST_DECIMAL_DETAIL_CMATH_LOG1P_HPP #include // NOLINT(llvm-include-order) -#include +#include #include #include +#include #include #ifndef BOOST_DECIMAL_BUILD_MODULE @@ -20,18 +21,15 @@ namespace boost { namespace decimal { -namespace detail { - -template -constexpr auto log1p_impl(T x) noexcept +BOOST_DECIMAL_EXPORT template +constexpr auto log1p(T x) noexcept BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T) { - const auto fpc = fpclassify(x); + constexpr T one { 1, 0 }; - constexpr T zero { 0, 0 }; - constexpr T one { 1, 0 }; + T result { }; - auto result = zero; + const auto fpc = fpclassify(x); if (fpc == FP_ZERO) { @@ -39,32 +37,17 @@ constexpr auto log1p_impl(T x) noexcept } else if (fpc != FP_NORMAL) { - if (fpc == FP_INFINITE) - { - if (signbit(x)) - { - result = std::numeric_limits::quiet_NaN(); - } - else - { - result = x; - } - } - else if (fpc == FP_NAN) - { - result = x; - } + result = + ( + ((fpc == FP_INFINITE) && signbit(x)) ? std::numeric_limits::quiet_NaN() : x + ); } else if (-x >= one) { - if (-x == one) - { - result = -std::numeric_limits::infinity(); - } - else - { - result = std::numeric_limits::quiet_NaN(); - } + result = + ( + (-x == one) ? -std::numeric_limits::infinity() : std::numeric_limits::quiet_NaN() + ); } else { @@ -74,84 +57,13 @@ constexpr auto log1p_impl(T x) noexcept } else { - using coefficient_array_type = std::array(UINT8_C(21))>; - - #if (defined(__clang__) && (__clang__ < 6)) - # pragma clang diagnostic push - # pragma clang diagnostic ignored "-Wmissing-braces" - #endif - - constexpr auto coefficient_table = - coefficient_array_type - { - // Series[Log[1+x], {x, 0, 21}] - - T { 1, 0 }, // x - -T { 5, -1}, // (-1 / 2) * x^2 - T { UINT64_C(333333333333333333), -18 }, // ( 1 / 3) * x^3 - -T { 25, -2 }, // (-1 / 4) * x^4 - T { 2, -1 }, // ( 1 / 5) * x^5 - -T { UINT64_C(166666666666666667), -18 }, // ( 1 / 6) * x^6 - T { UINT64_C(142857142857142857), -18 }, // ( 1 / 7) * x^7 - -T { 125, -3 }, // (-1 / 8) * x^8 - T { UINT64_C(111111111111111111), -18 }, // ( 1 / 9) * x^9 - -T { 1, -1 }, // (-1 / 10) * x^10 - T { UINT64_C(909090909090909091), -18 - 1 }, // ( 1 / 11) * x^11 - -T { UINT64_C(833333333333333333), -18 - 1 }, // (-1 / 12) * x^12 - T { UINT64_C(769230769230769230), -18 - 1 }, // ( 1 / 13) * x^13 - -T { UINT64_C(714285714285714286), -18 - 1 }, // (-1 / 14) * x^14 - T { UINT64_C(666666666666666667), -18 - 1 }, // ( 1 / 15) * x^15 - -T { UINT64_C(625000000000000000), -18 - 1 }, // ( 1 / 16) * x^16 - T { UINT64_C(588235294117647059), -18 - 1 }, // ( 1 / 17) * x^17 - -T { UINT64_C(555555555555555556), -18 - 1 }, // ( 1 / 18) * x^18 - T { UINT64_C(526315789473684211), -18 - 1 }, // ( 1 / 19) * x^19 - -T { 5, -2 }, // ( 1 / 20) * x^20 - T { UINT64_C(476190476190476190), -18 - 1 } // ( 1 / 21) * x^21 - }; - - #if (defined(__clang__) && (__clang__ < 6)) - # pragma clang diagnostic pop - #endif - - auto rit = coefficient_table.crbegin() + static_cast((sizeof(T) == 4U) ? 7U : 0U); - - result = *rit; - - while(rit != coefficient_table.crend()) - { - result = fma(result, x, *rit++); - } - - result *= x; + result = x * fma(detail::log1p_series_expansion(x), x, one); } } return result; } -} // namespace detail - -BOOST_DECIMAL_EXPORT template -constexpr auto log1p(T x) noexcept - BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T) -{ - #if BOOST_DECIMAL_DEC_EVAL_METHOD == 0 - - using evaluation_type = T; - - #elif BOOST_DECIMAL_DEC_EVAL_METHOD == 1 - - using evaluation_type = detail::promote_args_t; - - #else // BOOST_DECIMAL_DEC_EVAL_METHOD == 2 - - using evaluation_type = detail::promote_args_t; - - #endif - - return static_cast(detail::log1p_impl(static_cast(x))); -} - } // namespace decimal } // namespace boost diff --git a/test/test_log.cpp b/test/test_log.cpp index 70d009d3a..c753d93bf 100644 --- a/test/test_log.cpp +++ b/test/test_log.cpp @@ -1,5 +1,5 @@ -// Copyright 2023 Matt Borland -// Copyright 2023 Christopher Kormanyos +// Copyright 2023 - 2024 Matt Borland +// Copyright 2023 - 2024 Christopher Kormanyos // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -56,17 +56,31 @@ namespace local auto result_is_ok = bool { }; + NumericType delta { }; + if(b == static_cast(0)) { - result_is_ok = (fabs(a - b) < tol); + delta = fabs(a - b); // LCOV_EXCL_LINE + + result_is_ok = (delta < tol); // LCOV_EXCL_LINE } else { - const auto delta = fabs(1 - (a / b)); + delta = fabs(1 - (a / b)); result_is_ok = (delta < tol); } + // LCOV_EXCL_START + if (!result_is_ok) + { + std::cerr << std::setprecision(std::numeric_limits::digits10) << "a: " << a + << "\nb: " << b + << "\ndelta: " << delta + << "\ntol: " << tol << std::endl; + } + // LCOV_EXCL_STOP + return result_is_ok; } @@ -93,7 +107,7 @@ namespace local auto trials = static_cast(UINT8_C(0)); #if !defined(BOOST_DECIMAL_REDUCE_TEST_DEPTH) - constexpr auto count = (sizeof(decimal_type) == static_cast(UINT8_C(4))) ? static_cast(UINT32_C(0x400)) : static_cast(UINT32_C(0x40)); + constexpr auto count = (sizeof(decimal_type) == static_cast(UINT8_C(4))) ? static_cast(UINT32_C(0x200)) : static_cast(UINT32_C(0x40)); #else constexpr auto count = (sizeof(decimal_type) == static_cast(UINT8_C(4))) ? static_cast(UINT32_C(0x40)) : static_cast(UINT32_C(0x4)); #endif @@ -114,13 +128,13 @@ namespace local if(!result_log_is_ok) { - // LCOV_EXCL_START - std::cout << "x_flt : " << std::scientific << std::setprecision(std::numeric_limits::digits10) << x_flt << std::endl; - std::cout << "val_flt: " << std::scientific << std::setprecision(std::numeric_limits::digits10) << val_flt << std::endl; - std::cout << "val_dec: " << std::scientific << std::setprecision(std::numeric_limits::digits10) << val_dec << std::endl; + // LCOV_EXCL_START + std::cerr << "x_flt : " << std::scientific << std::setprecision(std::numeric_limits::digits10) << x_flt << std::endl; + std::cerr << "val_flt: " << std::scientific << std::setprecision(std::numeric_limits::digits10) << val_flt << std::endl; + std::cerr << "val_dec: " << std::scientific << std::setprecision(std::numeric_limits::digits10) << val_dec << std::endl; break; - // LCOV_EXCL_STOP + // LCOV_EXCL_STOP } } @@ -155,13 +169,13 @@ namespace local if(!result_log_is_ok) { - // LCOV_EXCL_START - std::cout << "x_flt : " << std::scientific << std::setprecision(std::numeric_limits::digits10) << x_flt << std::endl; - std::cout << "val_flt: " << std::scientific << std::setprecision(std::numeric_limits::digits10) << val_flt << std::endl; - std::cout << "val_dec: " << std::scientific << std::setprecision(std::numeric_limits::digits10) << val_dec << std::endl; + // LCOV_EXCL_START + std::cerr << "x_flt : " << std::scientific << std::setprecision(std::numeric_limits::digits10) << x_flt << std::endl; + std::cerr << "val_flt: " << std::scientific << std::setprecision(std::numeric_limits::digits10) << val_flt << std::endl; + std::cerr << "val_dec: " << std::scientific << std::setprecision(std::numeric_limits::digits10) << val_dec << std::endl; break; - // LCOV_EXCL_START + // LCOV_EXCL_START } } @@ -312,7 +326,123 @@ namespace local return result_is_ok; } -} + + auto test_log_64(const int tol_factor) -> bool + { + using decimal_type = boost::decimal::decimal64; + + using val_ctrl_array_type = std::array; + + const val_ctrl_array_type ctrl_values = + {{ + // Table[N[Log[111 10^n], 17], {n, -3, 24, 1}] + -2.1982250776698029, 0.10436001532424277, 2.4069451083182885, + 4.7095302013123341, 7.0121152943063798, 9.3147003873004255, + 11.617285480294471, 13.919870573288517, 16.222455666282563, + 18.525040759276608, 20.827625852270654, 23.130210945264700, + 25.432796038258745, 27.735381131252791, 30.037966224246837, + 32.340551317240882, 34.643136410234928, 36.945721503228974, + 39.248306596223019, 41.550891689217065, 43.853476782211111, + 46.156061875205156, 48.458646968199202, 50.761232061193248, + 53.063817154187294, 55.366402247181339, 57.668987340175385, + 59.971572433169431 + }}; + + std::array::value> log_values { }; + + int nx { -3 }; + + bool result_is_ok { true }; + + const decimal_type my_tol { std::numeric_limits::epsilon() * static_cast(tol_factor) }; + + for(auto i = static_cast(UINT8_C(0)); i < std::tuple_size::value; ++i) + { + // Table[N[Log[111 10^n], 17], {n, -3, 24, 1}] + + const decimal_type x_arg { 111, nx }; + + log_values[i] = log(x_arg); + + ++nx; + + const auto result_log_is_ok = is_close_fraction(log_values[i], decimal_type(ctrl_values[i]), my_tol); + + result_is_ok = (result_log_is_ok && result_is_ok); + } + + return result_is_ok; + } + + auto test_log_128(const int tol_factor) -> bool + { + using decimal_type = boost::decimal::decimal128; + + using str_ctrl_array_type = std::array; + + const str_ctrl_array_type ctrl_strings = + {{ + // Table[N[Log[111 10^n], 36], {n, -3, 24, 1}] + "-2.19822507766980291629063345609911975", + "0.104360015324242767727357998585244453", + "2.40694510831828845174534945326960866", + "4.70953020131233413576334090795397287", + "7.01211529430637981978133236263833708", + "9.31470038730042550379932381732270128", + "11.6172854802944711878173152720070655", + "13.9198705732885168718353067266914297", + "16.2224556662825625558532981813757939", + "18.5250407592766082398712896360601581", + "20.8276258522706539238892810907445223", + "23.1302109452646996079072725454288865", + "25.4327960382587452919252640001132507", + "27.7353811312527909759432554547976149", + "30.0379662242468366599612469094819792", + "32.3405513172408823439792383641663434", + "34.6431364102349280279972298188507076", + "36.9457215032289737120152212735350718", + "39.2483065962230193960332127282194360", + "41.5508916892170650800512041829038002", + "43.8534767822111107640691956375881644", + "46.1560618752051564480871870922725286", + "48.4586469681992021321051785469568928", + "50.7612320611932478161231700016412570", + "53.0638171541872935001411614563256212", + "55.3664022471813391841591529110099854", + "57.6689873401753848681771443656943496", + "59.9715724331694305521951358203787139", + }}; + + std::array::value> log_values { }; + std::array::value> ctrl_values { }; + + int nx { -3 }; + + bool result_is_ok { true }; + + const decimal_type my_tol { std::numeric_limits::epsilon() * static_cast(tol_factor) }; + + for(auto i = static_cast(UINT8_C(0)); i < std::tuple_size::value; ++i) + { + const decimal_type x_arg { 111, nx }; + + ++nx; + + log_values[i] = log(x_arg); + + static_cast + ( + from_chars(ctrl_strings[i], ctrl_strings[i] + std::strlen(ctrl_strings[i]), ctrl_values[i]) + ); + + const auto result_log_is_ok = is_close_fraction(log_values[i], ctrl_values[i], my_tol); + + result_is_ok = (result_log_is_ok && result_is_ok); + } + + return result_is_ok; + } +} // namespace local auto main() -> int { @@ -340,6 +470,22 @@ auto main() -> int result_is_ok = (test_log_is_ok && test_log_between_1_and_2_is_ok && test_log_edge_is_ok && result_is_ok); } + { + const auto result_pos64_is_ok = local::test_log_64(512); + + BOOST_TEST(result_pos64_is_ok); + + result_is_ok = (result_pos64_is_ok && result_is_ok); + } + + { + const auto result_pos128_is_ok = local::test_log_128(1'400'000); + + BOOST_TEST(result_pos128_is_ok); + + result_is_ok = (result_pos128_is_ok && result_is_ok); + } + result_is_ok = ((boost::report_errors() == 0) && result_is_ok); return (result_is_ok ? 0 : -1); diff --git a/test/test_log1p.cpp b/test/test_log1p.cpp index 5147fec47..0343a7858 100644 --- a/test/test_log1p.cpp +++ b/test/test_log1p.cpp @@ -1,5 +1,5 @@ -// Copyright 2023 Matt Borland -// Copyright 2023 Christopher Kormanyos +// Copyright 2023 - 2024 Matt Borland +// Copyright 2023 - 2024 Christopher Kormanyos // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -56,17 +56,31 @@ namespace local auto result_is_ok = bool { }; + NumericType delta { }; + if(b == static_cast(0)) { - result_is_ok = (fabs(a - b) < tol); + delta = fabs(a - b); // LCOV_EXCL_LINE + + result_is_ok = (delta < tol); // LCOV_EXCL_LINE } else { - const auto delta = fabs(1 - (a / b)); + delta = fabs(1 - (a / b)); result_is_ok = (delta < tol); } + // LCOV_EXCL_START + if (!result_is_ok) + { + std::cerr << std::setprecision(std::numeric_limits::digits10) << "a: " << a + << "\nb: " << b + << "\ndelta: " << delta + << "\ntol: " << tol << std::endl; + } + // LCOV_EXCL_STOP + return result_is_ok; } @@ -114,13 +128,13 @@ namespace local if(!result_val_is_ok) { - // LCOV_EXCL_START - std::cout << "x_flt : " << x_flt << std::endl; - std::cout << "val_flt: " << std::scientific << val_flt << std::endl; - std::cout << "val_dec: " << std::scientific << val_dec << std::endl; + // LCOV_EXCL_START + std::cerr << "x_flt : " << x_flt << std::endl; + std::cerr << "val_flt: " << std::scientific << val_flt << std::endl; + std::cerr << "val_dec: " << std::scientific << val_dec << std::endl; break; - // LCOV_EXCL_STOP + // LCOV_EXCL_STOP } } @@ -235,6 +249,112 @@ namespace local return result_is_ok; } + auto test_log1p_64(const int tol_factor) -> bool + { + using decimal_type = boost::decimal::decimal64; + + using val_ctrl_array_type = std::array; + + const val_ctrl_array_type ctrl_values = + {{ + // Table[N[Log[1 + n/100], 17], {n, -10, 10, 1}] + -0.10536051565782630, -0.094310679471241327, -0.083381608939051058, + -0.072570692834835431, -0.061875403718087472, -0.051293294387550533, + -0.040821994520255130, -0.030459207484708546, -0.020202707317519448, + -0.010050335853501441, 0, 0.0099503308531680828, + 0.019802627296179713, 0.029558802241544403, 0.039220713153281296, + 0.048790164169432003, 0.058268908123975776, 0.067658648473814805, + 0.076961041136128325, 0.086177696241052332, 0.095310179804324860 + }}; + + std::array::value> log1p_values { }; + + int nx { -10 }; + + bool result_is_ok { true }; + + const decimal_type my_tol { std::numeric_limits::epsilon() * static_cast(tol_factor) }; + + for(auto i = static_cast(UINT8_C(0)); i < std::tuple_size::value; ++i) + { + // Table[N[Log[1 + n/100], 17], {n, -1, 10, 1}] + + const decimal_type x_arg { nx, -2 }; + + log1p_values[i] = log1p(x_arg); + + ++nx; + + const auto result_log1p_is_ok = is_close_fraction(log1p_values[i], decimal_type(ctrl_values[i]), my_tol); + + result_is_ok = (result_log1p_is_ok && result_is_ok); + } + + return result_is_ok; + } + + auto test_log1p_128(const int tol_factor) -> bool + { + using decimal_type = boost::decimal::decimal128; + + using str_ctrl_array_type = std::array; + + const str_ctrl_array_type ctrl_strings = + {{ + // Table[N[Log[1 + n/100], 36], {n, -1, 10, 1}] + "-0.105360515657826301227500980839312798", + "-0.0943106794712413268771427243602300808", + "-0.0833816089390510583947658346421791606", + "-0.0725706928348354307115733479038455001", + "-0.0618754037180874717978001181383781382", + "-0.0512932943875505334261961442546872384", + "-0.0408219945202551295545770651553198702", + "-0.0304592074847085459192612876647667014", + "-0.0202027073175194484080453010241923879", + "-0.0100503358535014411835488575585477061", + "0", + "0.00995033085316808284821535754426074169", + "0.0198026272961797130260290668851003931", + "0.0295588022415444027326194056847124054", + "0.0392207131532812962692008965711198938", + "0.0487901641694320030653744042231646586", + "0.0582689081239757755257183511185059232", + "0.0676586484738148052684159076545485864", + "0.0769610411361283249842170443152018349", + "0.0861776962410523323413335428404732359", + "0.0953101798043248600439521232807650922", + }}; + + std::array::value> log1p_values { }; + std::array::value> ctrl_values { }; + + int nx { -10 }; + + bool result_is_ok { true }; + + const decimal_type my_tol { std::numeric_limits::epsilon() * static_cast(tol_factor) }; + + for(auto i = static_cast(UINT8_C(0)); i < std::tuple_size::value; ++i) + { + const decimal_type x_arg { nx, -2 }; + + ++nx; + + log1p_values[i] = log1p(x_arg); + + static_cast + ( + from_chars(ctrl_strings[i], ctrl_strings[i] + std::strlen(ctrl_strings[i]), ctrl_values[i]) + ); + + const auto result_log1p_is_ok = is_close_fraction(log1p_values[i], ctrl_values[i], my_tol); + + result_is_ok = (result_log1p_is_ok && result_is_ok); + } + + return result_is_ok; + } + } // namespace local auto main() -> int @@ -259,6 +379,22 @@ auto main() -> int result_is_ok = (result_pos_wide_is_ok && result_is_ok); result_is_ok = (result_edge_is_ok && result_is_ok); + { + const auto result_pos64_is_ok = local::test_log1p_64(64); + + BOOST_TEST(result_pos64_is_ok); + + result_is_ok = (result_pos64_is_ok && result_is_ok); + } + + { + const auto result_pos128_is_ok = local::test_log1p_128(400'000); + + BOOST_TEST(result_pos128_is_ok); + + result_is_ok = (result_pos128_is_ok && result_is_ok); + } + result_is_ok = ((boost::report_errors() == 0) && result_is_ok); return (result_is_ok ? 0 : -1);