GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/core/sum_of_squares.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 12 12 100.0%
Functions: 112 112 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/details/force_if_any.hpp>
15
16 namespace plf
17 {
18
19 template<typename Options>
20 struct sum_of_squares_t
21 : plf::callable<sum_of_squares_t, eve::sum_of_squares_t, Options, kahan_option, raw_option, pedantic_option>
22 {
23 template<typename... Ts> struct result : as_polyfloat_like<Ts...>
24 {
25 };
26
27 template<concepts::polyfloat_like T0, concepts::polyfloat_like... Ts>
28 136 POLYFLOAT_ABI plf::as_polyfloat_like_t<T0, Ts...> constexpr operator()(T0 t0, Ts... ts) const noexcept
29 requires(eve::same_lanes_or_scalar<T0, Ts...>)
30 {
31 136 return POLYFLOAT_CALL(t0, ts...);
32 }
33
34 template<eve::non_empty_product_type Tup>
35 16 POLYFLOAT_ABI constexpr kumi::apply_traits_t<result, Tup> operator()(Tup const& t) const noexcept
36 requires(eve::same_lanes_or_scalar_tuple<Tup> && !concepts::polyfloat_like<Tup> && kumi::size_v<Tup> >= 1)
37 {
38 16 return POLYFLOAT_CALL(t);
39 }
40
41 150 POLYFLOAT_CALLABLE_OBJECT(sum_of_squares_t, sum_of_squares_);
42 };
43 //======================================================================================================================
44 //! @addtogroup core
45 //! @{
46 //! @var sum_of_squares
47 //! @brief return the sum of squares of the vector components.
48 //!
49 //! @groupheader{Header file}
50 //!
51 //! @code
52 //! #include <polyfloat/module/core.hpp>
53 //! @endcode
54 //!
55 //! @groupheader{Callable Signatures}
56 //!
57 //! @code
58 //! namespace polyfloat
59 //! {
60 //! // Regular overloads
61 //! constexpr auto sum_of_squares(auto ... xss) noexcept; // 1
62 //! constexpr auto sum_of_squares(kumi::tuple xs) noexcept; // 2
63 //! }
64 //! @endcode
65 //!
66 //! **Parameters**
67 //!
68 //! * `xs`: Values to process.
69 //!
70 //! **Return value**
71 //!
72 //! 1. sum of squares. \f$\\sum_s x_s^2\f$.
73 //! 2. use the content of the tuple
74 //!
75 //! @groupheader{Example}
76 //!
77 //! @godbolt{doc/core/sum_of_squares.cpp}
78 //======================================================================================================================
79
80 inline constexpr auto sum_of_squares = eve::functor<sum_of_squares_t>;
81 //======================================================================================================================
82 //! @}
83 //======================================================================================================================
84 }
85
86 namespace plf::_
87 {
88
89 template<eve::callable_options O, concepts::polyfloat_like T0, concepts::polyfloat_like... Ts>
90 134 constexpr plf::as_polyfloat_like_t<T0, Ts...> sum_of_squares_(POLYFLOAT_DELAY(),
91 O const& o,
92 T0 const& a0,
93 Ts const&... args) noexcept
94 {
95 using r_t = plf::as_polyfloat_like_t<T0, Ts...>;
96 4 if constexpr (sizeof...(Ts) == 0) return plf::sqr[o](a0);
97 else if constexpr (O::contains(kahan))
98 {
99 auto pair_sqr_add = [](auto pair0, auto r1) {
100 auto [r0, e0] = pair0;
101 auto [s, e1] = plf::two_fma_approx(r1, r1, r0);
102 return zip(s, e0 + e1);
103 };
104 auto p0 = two_prod(a0, a0);
105 ((p0 = pair_sqr_add(p0, args)), ...);
106 auto [r, e] = p0;
107 auto res = r + e;
108 res = plf::_::force_if_any(o, res, eve::is_infinite, inf(as(res)), a0, args...);
109 return if_else(is_nan(res), inf(as(res)), res);
110 }
111 else
112 {
113 308 auto cvt = [](auto a) { return plf::convert(a, eve::as_element<r_t>{}); };
114 130 r_t r = plf::add(sqr(cvt(a0)), sqr(cvt(args))...);
115 130 return plf::_::force_if_any(o, r, eve::is_infinite, inf(as(r)), cvt(a0), cvt(args)...);
116 }
117 }
118
119 template<eve::product_type PT, eve::callable_options O>
120 16 constexpr auto sum_of_squares_(POLYFLOAT_DELAY(), O const& o, PT tup) noexcept
121 requires(eve::same_lanes_or_scalar_tuple<PT> && !concepts::polyfloat_like<PT> && kumi::size_v<PT> >= 1)
122 {
123 24 return kumi::apply([o](auto... m) { return sum_of_squares[o](m...); }, tup);
124 }
125 }
126