GCC Code Coverage Report


Directory: include/polyfloat/
File: include/polyfloat/module/core/dot.hpp
Date: 2026-11-09 15:28:50
Exec Total Coverage
Lines: 15 15 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/core/two_fma_approx.hpp>
15
16 namespace plf
17 {
18
19 template<typename Options>
20 struct dot_t : eve::strict_tuple_callable<dot_t, Options, kahan_option, raw_option, pedantic_option>
21 {
22 template<typename... Ts> struct result : as_polyfloat_like<Ts...>
23 {
24 };
25
26 template<concepts::polyfloat_like... Ts>
27 requires(eve::same_lanes_or_scalar<Ts...>)
28 52 POLYFLOAT_ABI typename result<Ts...>::type constexpr operator()(Ts... ts) const noexcept
29 {
30 52 return POLYFLOAT_CALL(ts...);
31 }
32
33 template<eve::non_empty_product_type Tup1, eve::non_empty_product_type Tup2>
34 12 POLYFLOAT_ABI constexpr kumi::apply_traits_t<result, kumi::result::cat_t<Tup1, Tup2>> operator()(
35 Tup1 const& t1, Tup2 const& t2) const noexcept
36 requires(eve::same_lanes_or_scalar_tuple<Tup1> && eve::same_lanes_or_scalar_tuple<Tup2> &&
37 (Tup1::size() == Tup2::size()) && !concepts::polyfloat_like<Tup1> && !concepts::polyfloat_like<Tup2>)
38 {
39 12 return POLYFLOAT_CALL(t1, t2);
40 }
41
42 template<eve::non_empty_product_type Tup>
43 requires(eve::same_lanes_or_scalar_tuple<Tup> && !concepts::polyfloat_like<Tup>)
44 POLYFLOAT_ABI constexpr kumi::apply_traits_t<result, Tup> operator()(Tup const& t) const noexcept
45 requires(kumi::size_v<Tup> >= 1)
46 {
47 return POLYFLOAT_CALL(t);
48 }
49
50 64 POLYFLOAT_CALLABLE_OBJECT(dot_t, dot_);
51 };
52 //======================================================================================================================
53 //! @addtogroup core
54 //! @{
55 //! @var dot
56 //! @brief return the dot product of the vector of the first half of parameters by
57 //! the vector of the second half.
58 //!
59 //! @groupheader{Header file}
60 //!
61 //! @code
62 //! #include <polyfloat/module/core.hpp>
63 //! @endcode
64 //!
65 //! @groupheader{Callable Signatures}
66 //!
67 //! @code
68 //! namespace polyfloat
69 //! {
70 //! // Regular overloads
71 //! constexpr auto dot(auto value... xs, auto value... ys) noexcept; // 1
72 //! constexpr auto dot(kumi::tuple xs, kumi::tuple ys) noexcept; // 2
73 //! }
74 //! @endcode
75 //!
76 //! **Parameters**
77 //!
78 //! * `z1`, `z2`: Values to process.
79 //!
80 //! **Return value**
81 //!
82 //! 1. dot product. \f$\sum_s x_s*y_s\f$.
83 //! 2. use the content of the tuples
84 //!
85 //! @groupheader{Example}
86 //!
87 //! @godbolt{doc/core/dot.cpp}
88 //======================================================================================================================
89
90 inline constexpr auto dot = eve::functor<dot_t>;
91 //======================================================================================================================
92 //! @}
93 //======================================================================================================================
94 }
95
96 namespace plf::_
97 {
98
99 template<eve::callable_options O, concepts::polyfloat_like... Ts>
100 52 constexpr auto dot_(POLYFLOAT_DELAY(), O const& o, Ts const&... args) noexcept
101 requires(sizeof...(Ts) > 1 && sizeof...(Ts) % 2 == 0)
102 {
103 if constexpr (sizeof...(Ts) == 2)
104 {
105 34 return plf::mul[o](args...);
106 }
107 else
108 {
109 using r_t = as_polyfloat_like_t<Ts...>;
110 using u_t = eve::element_type_t<r_t>;
111 38 auto cvt = [](auto a) { return plf::convert(a, as<u_t>()); };
112 18 auto coeffs = kumi::tuple{cvt(args)...};
113 54 auto [f, s] = kumi::split(coeffs, kumi::index<sizeof...(Ts) / 2>);
114 55 return add[o](kumi::map([](auto a, auto b) { return a * b; }, f, s));
115 }
116 }
117
118 template<eve::non_empty_product_type PT1, eve::non_empty_product_type PT2, eve::callable_options O>
119 12 constexpr auto dot_(POLYFLOAT_DELAY(), O const& o, PT1 f, PT2 s) noexcept
120 requires(kumi::as_tuple_t<PT1>::size() == kumi::as_tuple_t<PT2>::size() && !concepts::polyfloat_like<PT1> &&
121 !concepts::polyfloat_like<PT2>)
122 {
123 using Tup1 = kumi::as_tuple_t<PT1>;
124 using Tup2 = kumi::as_tuple_t<PT2>;
125 12 constexpr auto siz = Tup1::size();
126 if constexpr (siz == 1)
127 {
128 return get<0>(f) * get<0>(s);
129 }
130 else
131 {
132 using r1_t = kumi::apply_traits_t<plf::as_polyfloat_like, Tup1>;
133 using r2_t = kumi::apply_traits_t<plf::as_polyfloat_like, Tup2>;
134 using r_t = plf::as_polyfloat_like_t<r1_t, r2_t>;
135 using u_t = eve::element_type_t<r_t>;
136 12 auto cvt = [](auto a) { return plf::convert(a, as<u_t>()); };
137 36 return add[o](kumi::map([cvt](auto a, auto b) { return cvt(a * b); }, f, s));
138 }
139 }
140
141 }
142