GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/core/hypot.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 20 20 100.0%
Functions: 128 128 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 <type_traits>
14 #include <polyfloat/module/core/is_nan.hpp>
15 #include <polyfloat/module/core/maxmag.hpp>
16
17 namespace plf
18 {
19
20 template<typename Options>
21 struct hypot_t : plf::strict_tuple_callable<hypot_t, eve::hypot_t, Options, raw_option, pedantic_option>
22 {
23 template<typename... Ts> struct result : as_polyfloat_like<Ts...>
24 {
25 };
26
27 template<concepts::polyfloat_like... Ts>
28 requires(eve::same_lanes_or_scalar<Ts...>)
29 132 POLYFLOAT_ABI typename result<Ts...>::type constexpr operator()(Ts... ts) const noexcept
30 {
31 132 return POLYFLOAT_CALL(ts...);
32 }
33
34 template<eve::non_empty_product_type Tup>
35 requires(eve::same_lanes_or_scalar_tuple<Tup> && !concepts::polyfloat_like<Tup>)
36 16 POLYFLOAT_ABI constexpr kumi::apply_traits_t<result, Tup> operator()(Tup const& t) const noexcept
37 requires(kumi::size_v<Tup> >= 1)
38 {
39 16 return POLYFLOAT_CALL(t);
40 }
41
42 112 POLYFLOAT_CALLABLE_OBJECT(hypot_t, hypot_);
43 };
44 //======================================================================================================================
45 //! @addtogroup core
46 //! @{
47 //! @var hypot
48 //! @brief return the sum of the parameters.
49 //!
50 //! @groupheader{Header file}
51 //!
52 //! @code
53 //! #include <polyfloat/core.hpp>
54 //! @endcode
55 //!
56 //! @groupheader{Callable Signatures}
57 //!
58 //! @code
59 //! namespace polyfloat
60 //! {
61 //! template<polyfloat::concepts::polyfloat_like Z1, polyfloat_like Z2> constexpr auto hypot(Z1 z1, Z2 z2) noexcept;
62 //! }
63 //! @endcode
64 //!
65 //! **Parameters**
66 //!
67 //! * `z1`, `z2`: Values to process.
68 //!
69 //! **Return value**
70 //!
71 //! Returns the sum of the arguments.
72 //!
73 //! @groupheader{Example}
74 //!
75 //! @godbolt_todo{doc/core/hypot.cpp}
76 //======================================================================================================================
77
78 inline constexpr auto hypot = eve::functor<hypot_t>;
79 //======================================================================================================================
80 //! @}
81 //======================================================================================================================
82
83 template<typename Options> constexpr auto neutral(hypot_t<Options>) noexcept
84 {
85 return plf::zero;
86 }
87
88 // Required for optimisation detections
89 using callable_hypot_ = eve::tag_t<hypot>;
90
91 }
92
93 namespace plf::_
94 {
95 template<typename T0, eve::callable_options O> constexpr auto hypot_(POLYFLOAT_DELAY(), O const&, T0 t0) noexcept
96 {
97 return plf::abs(t0);
98 }
99
100 template<eve::callable_options O,
101 concepts::polyfloat_like T0,
102 concepts::polyfloat_like T1,
103 concepts::polyfloat_like... Ts>
104 112 constexpr auto hypot_(POLYFLOAT_DELAY(), O const& o, T0 const& r0, T1 const& r1, Ts const&... rs) noexcept
105 {
106 if constexpr (O::contains(raw))
107 {
108 4 return plf::sqrt(plf::sum_of_squares(r0, r1, rs...));
109 }
110 else
111 {
112 using r_t = as_polyfloat_t<T0, T1, Ts...>;
113 392 auto cvt = [](auto a) { return plf::convert(a, eve::as_element<r_t>{}); };
114 240 auto expo = [&](auto x) { return if_else(plf::is_nan(x), eve::zero, plf::exponent(cvt(x))); };
115 108 auto e = -eve::maxmag(expo(r0), expo(r1), expo(rs)...);
116 if constexpr (O::contains(pedantic))
117 {
118 4 auto nan_found = plf::false_(eve::as<r_t>());
119 8 auto f = [&](auto a) {
120 4 nan_found = plf::is_nan(a);
121 4 return if_else(nan_found, zero, plf::sqr(ldexp[o](cvt(a), e)));
122 };
123 4 r_t that = plf::add[o](f(r0), f(r1), f(rs)...);
124 4 auto r = plf::ldexp[pedantic](plf::sqrt(that), -e);
125 4 return if_else(nan_found && !is_infinite(r), plf::nan, r);
126 }
127 else
128 {
129 232 auto f = [&](auto a) { return cvt(plf::sqr(ldexp[o](cvt(a), e))); };
130 104 r_t that = plf::add[o](f(r0), f(r1), f(rs)...);
131 104 return plf::ldexp[pedantic](plf::sqrt(that), -e);
132 }
133 }
134 }
135
136 }
137