// Copyright 2023 Matt Borland // Copyright 2023 Christopher Kormanyos // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #ifndef BOOST_DECIMAL_DETAIL_CMATH_LOG1P_HPP #define BOOST_DECIMAL_DETAIL_CMATH_LOG1P_HPP #include // NOLINT(llvm-include-order) #include #include #include #include #include #ifndef BOOST_DECIMAL_BUILD_MODULE #include #include #endif namespace boost { namespace decimal { namespace detail { template constexpr auto log1p_impl(const T x) noexcept BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T) { constexpr T one { 1, 0 }; T result { }; const auto fpc = fpclassify(x); if (fpc == FP_ZERO) { result = x; } #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc != FP_NORMAL) { result = ( ((fpc == FP_INFINITE) && signbit(x)) ? std::numeric_limits::quiet_NaN() : x ); } #endif else if (-x >= one) { #ifndef BOOST_DECIMAL_FAST_MATH result = ( (-x == one) ? -std::numeric_limits::infinity() : std::numeric_limits::quiet_NaN() ); #else result = T{0}; #endif } else { if (x > T { 5, -1 }) { result = log(x + one); } else { result = x * fma(detail::log1p_series_expansion(x), x, one); } } return result; } } // namespace detail BOOST_DECIMAL_EXPORT template constexpr auto log1p(const T x) noexcept BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T) { using evaluation_type = detail::evaluation_type_t; return static_cast(detail::log1p_impl(static_cast(x))); } } // namespace decimal } // namespace boost #endif // BOOST_DECIMAL_DETAIL_CMATH_LOG1P_HPP