GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/math/nthroot.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 18 18 100.0%
Functions: 92 92 100.0%
Branches: 0 0 -%

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