| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | //====================================================================================================================== | ||
| 2 | /* | ||
| 3 | POLYFLOAT - Extended precision floating points | ||
| 4 | Copyright : POLYFLOAT Contributors & Maintainers | ||
| 5 | SPDX-License-Identifier: BSL-1.0 | ||
| 6 | */ | ||
| 7 | //====================================================================================================================== | ||
| 8 | #pragma once | ||
| 9 | |||
| 10 | #include <polyfloat/details/callable.hpp> | ||
| 11 | #include <polyfloat/types/concepts.hpp> | ||
| 12 | #include <polyfloat/types/traits.hpp> | ||
| 13 | #include <polyfloat/module/math/pow.hpp> | ||
| 14 | #include <polyfloat/module/core/pown.hpp> | ||
| 15 | #include <type_traits> | ||
| 16 | |||
| 17 | namespace plf | ||
| 18 | { | ||
| 19 | |||
| 20 | template<typename Options> | ||
| 21 | struct nthroot_t : plf::callable<nthroot_t, eve::nthroot_t, Options, raw_option, pedantic_option> | ||
| 22 | { | ||
| 23 | template<concepts::polyfloat_like Z1, eve::integral_value N> | ||
| 24 | 104 | POLYFLOAT_ABI constexpr eve::as_wide_as_t<Z1, N> operator()(Z1 z1, N n) const noexcept | |
| 25 | { | ||
| 26 | 104 | return POLYFLOAT_CALL(z1, n); | |
| 27 | } | ||
| 28 | |||
| 29 | template<concepts::polyfloat_like Z, concepts::polyfloat_like N> | ||
| 30 | 236 | POLYFLOAT_ABI constexpr as_polyfloat_like_t<Z, N> operator()(Z z, N n) const noexcept | |
| 31 | requires(!eve::integral_value<N>) | ||
| 32 | { | ||
| 33 | 236 | return POLYFLOAT_CALL(z, n); | |
| 34 | } | ||
| 35 | |||
| 36 | 318 | POLYFLOAT_CALLABLE_OBJECT(nthroot_t, nthroot_); | |
| 37 | }; | ||
| 38 | //====================================================================================================================== | ||
| 39 | //! @addtogroup math | ||
| 40 | //! @{ | ||
| 41 | //! @var nthroot | ||
| 42 | //! @brief return the nth root: \f$x^{1/n}\f$. | ||
| 43 | //! | ||
| 44 | //! @groupheader{Header file} | ||
| 45 | //! | ||
| 46 | //! @code | ||
| 47 | //! #include <polyfloat/core.hpp> | ||
| 48 | //! @endcode | ||
| 49 | //! | ||
| 50 | //! @groupheader{Callable Signatures} | ||
| 51 | //! | ||
| 52 | //! @code | ||
| 53 | //! namespace polyfloat | ||
| 54 | //! { | ||
| 55 | //! template<polyfloat::concepts::polyfloat_like T> constexpr auto nthroot(T x, auto n) noexcept; | ||
| 56 | //! } | ||
| 57 | //! @endcode | ||
| 58 | //! | ||
| 59 | //! **Parameters** | ||
| 60 | //! | ||
| 61 | //! * `z`: Value to process. | ||
| 62 | //! * `n`: flint or integral value. If n does not represent an integral value it is truncated before use. | ||
| 63 | //! | ||
| 64 | //! **Return value** | ||
| 65 | //! | ||
| 66 | //! Returns \f$x^{1/n}\f$. | ||
| 67 | //! | ||
| 68 | //! @groupheader{Example} | ||
| 69 | //! | ||
| 70 | //! @godbolt{doc/math/nthroot.cpp} | ||
| 71 | //====================================================================================================================== | ||
| 72 | |||
| 73 | inline constexpr auto nthroot = eve::functor<nthroot_t>; | ||
| 74 | //====================================================================================================================== | ||
| 75 | //! @} | ||
| 76 | //====================================================================================================================== | ||
| 77 | } | ||
| 78 | |||
| 79 | namespace plf::_ | ||
| 80 | { | ||
| 81 | |||
| 82 | template<typename Z1, eve::integral_value N, eve::callable_options O> | ||
| 83 | 92 | constexpr auto nthroot_(POLYFLOAT_DELAY(), O const& o, Z1 xx, N n) noexcept | |
| 84 | { | ||
| 85 | using r_t = eve::as_wide_as_t<Z1, N>; | ||
| 86 | using e_t = eve::element_type_t<r_t>; | ||
| 87 | 92 | return nthroot[o](plf::convert(xx, eve::as<e_t>()), plf::convert(n, eve::as<e_t>())); | |
| 88 | } | ||
| 89 | |||
| 90 | template<typename T, typename N, eve::callable_options O> | ||
| 91 | 226 | constexpr auto nthroot_(POLYFLOAT_DELAY(), O const& o, T x, N n) noexcept | |
| 92 | requires(!eve::integral_value<N>) | ||
| 93 | { | ||
| 94 | using r_t = plf::as_polyfloat_like_t<T, N>; | ||
| 95 | using e_t = eve::element_type_t<r_t>; | ||
| 96 | 226 | auto xx = plf::convert(x, eve::as<e_t>()); | |
| 97 | 226 | auto nn = plf::convert(n, eve::as<e_t>()); | |
| 98 | 226 | auto ltz = plf::is_ltz(xx); | |
| 99 | 226 | r_t r{}; | |
| 100 | 226 | hi(r) = eve::pow[o](plf::abs(plf::hi(xx)), eve::rec[pedantic](hi(nn))); | |
| 101 | 226 | r = (plf::dec(nn) * r + xx * plf::pown(r, -dec(nn))) / nn; | |
| 102 | if constexpr (dimension_v<T> == 3) | ||
| 103 | { | ||
| 104 | 116 | r = (plf::dec(nn) * r + xx * plf::pown(r, -dec(nn))) / nn; | |
| 105 | } | ||
| 106 | 226 | auto res = plf::if_else(plf::is_eqz(xx), xx, r); | |
| 107 | 226 | if constexpr (!O::contains(raw)) res = plf::if_else(plf::is_not_finite(xx), xx, res); | |
| 108 | 226 | return plf::if_else(ltz && plf::is_even(nn), plf::nan(eve::as(res)), res); | |
| 109 | } | ||
| 110 | } | ||
| 111 |