// Copyright 2024 - 2025 Matt Borland // Copyright 2024 - 2025 Christopher Kormanyos // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #ifndef BOOST_DECIMAL_DETAIL_CMATH_ASIN_HPP #define BOOST_DECIMAL_DETAIL_CMATH_ASIN_HPP #include #include #include #include #include #include #include #include #include #ifndef BOOST_DECIMAL_BUILD_MODULE #include #include #endif namespace boost { namespace decimal { namespace detail { template constexpr auto asin_impl(const T x) noexcept BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T) { const auto fpc {fpclassify(x)}; const auto isneg {signbit(x)}; if (fpc == FP_ZERO #ifndef BOOST_DECIMAL_FAST_MATH || fpc == FP_NAN #endif ) { return x; } const auto absx { fabs(x) }; T result { }; constexpr T cbrt_eps { cbrt(std::numeric_limits::epsilon()) }; constexpr T one { 1 }; if (absx <= cbrt_eps) { result = absx * (one + (absx / 6) * absx); } else if (absx <= T { 5, -1 }) { result = asin_series(absx); } else { constexpr T half_pi { numbers::pi_v / 2 }; if (absx < one) { result = half_pi - 2 * asin_series(sqrt((1 - absx) / 2)); } else if (absx > one) { #ifndef BOOST_DECIMAL_FAST_MATH result = std::numeric_limits::quiet_NaN(); #else result = T{0}; #endif } else { result = half_pi; } } // arcsin(-x) == -arcsin(x) if (isneg) { result = -result; } return result; } } //namespace detail BOOST_DECIMAL_EXPORT template constexpr auto asin(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::asin_impl(static_cast(x))); } } //namespace decimal } //namespace boost #endif //BOOST_DECIMAL_DETAIL_CMATH_ASIN_HPP