GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/math/geommean.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 12 12 100.0%
Functions: 79 79 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/math/nthroot.hpp>
15
16 namespace plf
17 {
18
19 template<typename Options>
20 struct geommean_t : eve::strict_tuple_callable<geommean_t, Options, raw_option, pedantic_option>
21 {
22 template<typename... Ts> struct result : as_polyfloat_like<Ts...>
23 {
24 };
25
26 template<concepts::polyfloat_like Z1, concepts::polyfloat_like... Zs>
27 80 POLYFLOAT_ABI constexpr as_polyfloat_like_t<Z1, Zs...> operator()(Z1 z1, Zs... zs) const noexcept
28 {
29 80 return POLYFLOAT_CALL(z1, zs...);
30 }
31
32 template<eve::non_empty_product_type Tup>
33 POLYFLOAT_ABI constexpr kumi::apply_traits_t<result, Tup> operator()(Tup tup) const noexcept
34 requires(eve::same_lanes_or_scalar_tuple<Tup> && kumi::size_v<Tup> >= 1)
35 {
36 return POLYFLOAT_CALL(tup);
37 }
38
39 78 POLYFLOAT_CALLABLE_OBJECT(geommean_t, geommean_);
40 };
41 //======================================================================================================================
42 //! @addtogroup math
43 //! @{
44 //! @var geommean
45 //! @brief Callable object computing the geometric mean of the inputs \f$\left(\prod_{i = 1}^n z_i\right)^{\frac1n}\f$.
46 //!
47 //! @groupheader{Header file}
48 //!
49 //! @code
50 //! #include <polyfloat/core.hpp>
51 //! @endcode
52 //!
53 //! @groupheader{Callable Signatures}
54 //!
55 //! @code
56 //! namespace polyfloat
57 //! {
58 //! template<polyfloat::concepts::polyfloat_like T1, polyfloat_like Z2> constexpr auto geommean(T1 z1, T2 z2) noexcept;
59 //! }
60 //! @endcode
61 //!
62 //! **Parameters**
63 //!
64 //! * `z, zs...`: Values to process.
65 //!
66 //! **Return value**
67 //!
68 //! Returns the geommean of the parameters.
69 //!
70 //! @groupheader{Example}
71 //!
72 //! @godbolt{doc/math/geommean.cpp}
73 //======================================================================================================================
74
75 inline constexpr auto geommean = eve::functor<geommean_t>;
76 //======================================================================================================================
77 //! @}
78 //======================================================================================================================
79 }
80
81 namespace plf::_
82 {
83
84 template<typename T1, typename... Ts, eve::callable_options O>
85 78 constexpr auto geommean_(POLYFLOAT_DELAY(), O const& o, T1 a0, Ts... args) noexcept
86 {
87 using r_t = as_polyfloat_like_t<T1, Ts...>;
88 using e_t = eve::element_type_t<r_t>;
89 using u_t = eve::underlying_type_t<r_t>;
90 224 auto cvt = [](auto a) { return plf::convert(a, as<e_t>()); };
91 78 constexpr auto sz = sizeof...(Ts);
92 if constexpr (sz == 0) return a0;
93 else
94 {
95 78 auto e = -eve::maxmag(exponent(cvt(a0)), exponent(cvt(args))...);
96 78 auto p = plf::mul[o](cvt(ldexp[o](a0, e)), cvt(ldexp[o](args, e))...);
97 78 auto sgn = plf::sign(p);
98 78 p = plf::nthroot(p, u_t(sz + 1));
99 78 p = ldexp[pedantic](p, -e);
100 78 return if_else(plf::is_even(sz) && plf::is_ltz(sgn), eve::allbits, sgn * p);
101 }
102 }
103 }
104