GCC Code Coverage Report


Directory: include/kumi/
File: include/kumi/algorithm/inner_product.hpp
Date: 2026-10-14 16:33:56
Exec Total Coverage
Lines: 15 15 100.0%
Functions: 10 10 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 //======================================================================================================================
2 /*
3 KUMI - Compact Tuple Tools
4 Copyright : KUMI Project Contributors
5 SPDX-License-Identifier: BSL-1.0
6 */
7 //======================================================================================================================
8 #pragma once
9
10 namespace kumi
11 {
12 namespace _
13 {
14 template<typename T, typename U, typename V, typename Sum, typename Prod, std::size_t... I>
15 8 KUMI_HIDDEN_ABI constexpr auto inner_product_(
16 kumi::_::adl_tag_t, T&& t, U&& u, V init, Sum sum, Prod prod, std::index_sequence<I...>) noexcept
17 {
18 if constexpr (kumi::concepts::record_type<T>)
19 16 return (kumi::function::foldable{init} >> ... >>
20 52 kumi::bind_back(sum, kumi::invoke(prod, get<kumi::identifier_of<kumi::element_t<I, T>>()>(KUMI_FWD(t)),
21 4 get<kumi::identifier_of<kumi::element_t<I, U>>()>(KUMI_FWD(u)))))();
22 else
23 16 return (kumi::function::foldable{init} >> ... >>
24 52 kumi::bind_back(sum, kumi::invoke(prod, get<I>(KUMI_FWD(t)), get<I>(KUMI_FWD(u)))))();
25 }
26
27 template<typename T, typename U, typename V, std::size_t... I>
28 10 KUMI_HIDDEN_ABI constexpr auto inner_product_fast_(
29 kumi::_::adl_tag_t, T&& t, U&& u, V init, std::index_sequence<I...>) noexcept
30 {
31 if constexpr (kumi::concepts::record_type<T>)
32 9 return (init + ... +
33 18 (get<kumi::identifier_of<kumi::element_t<I, T>>()>(KUMI_FWD(t)) *
34 18 get<kumi::identifier_of<kumi::element_t<I, U>>()>(KUMI_FWD(u))));
35
36 40 else return (init + ... + (get<I>(KUMI_FWD(t)) * get<I>(KUMI_FWD(u))));
37 }
38 }
39
40 struct inner_product_t
41 {
42 template<kumi::concepts::product_type S1,
43 kumi::concepts::sized_product_type<kumi::size_v<S1>> S2,
44 typename T,
45 typename Sum,
46 typename Prod>
47 [[nodiscard]] KUMI_ABI constexpr auto operator()(S1&& s1, S2&& s2, T init, Sum sum, Prod prod) const noexcept
48 requires(kumi::concepts::compatible_product_types<S1, S2>)
49 {
50 if constexpr (kumi::concepts::empty_product_type<S1>) return init;
51 else
52 4 return inner_product_(kumi::_::adl_tag, KUMI_FWD(s1), KUMI_FWD(s2), init, sum, prod,
53 4 kumi::function::indexes_for<S1>{});
54 }
55
56 template<kumi::concepts::product_type S1, kumi::concepts::sized_product_type<kumi::size_v<S1>> S2, typename T>
57 [[nodiscard]] KUMI_ABI constexpr auto operator()(S1&& s1, S2&& s2, T init) const noexcept
58 requires(kumi::concepts::compatible_product_types<S1, S2>)
59 {
60 if constexpr (kumi::concepts::empty_product_type<S1>) return init;
61 else
62 6 return inner_product_fast_(kumi::_::adl_tag, KUMI_FWD(s1), KUMI_FWD(s2), init,
63 6 kumi::function::indexes_for<S1>{});
64 }
65 };
66
67 //====================================================================================================================
68 /**
69 @ingroup kumi_reductions
70
71 @var inner_product
72 @brief Callable object computing the inner product (i.e. sum of products)
73
74 Computes the generalized sum of products of the elements of two product types. By default,
75 `+` and `*` are used.
76
77 On record types, operates by pair of fields sharing the same label.
78
79 @note Does not participate in overload resolution if product types' size are not equal or if any of
80 the binary operations can't be applied on the product types' elements. Similarly, doesn't participate
81 in overload resolution if the two inputs are not compatible. @see concepts::compatible_product_types.
82
83 @qualifier nodiscard
84 @qualifier inline
85 @qualifier constexpr
86 @qualifier noexcept
87
88 @groupheader{Header file}
89 @code
90 #include <kumi/algorithm/inner_product.hpp>
91 @endcode
92
93 @groupheader{Call Signature}
94
95 @code
96 template<product_type S1, product_type S2, typename T, typename Sum, typename Prod>
97 constexpr auto inner_product(S1 && s1, S2 && s2, T init, Sum sum, Prod prod) noexcept;
98 @endcode
99
100 @code
101 template<product_type S1, product_type S2, typename T>
102 constexpr auto inner_product(S1 && s1, S2 && s2, T init) noexcept;
103 @endcode
104
105 @subgroupheader{Parameters}
106
107 - `s1`: First product type to operate on
108 - `s2`: Second product type to operate on
109 - `init`: Initial value
110 - `sum`: Binary callable function to use as the sum operations
111 - `prod`: Binary callable function to use as the product operations
112
113 @subgroupheader{Return value}
114
115 - The inner product of `s1` and `s2` using the provided binary operations.
116
117 @groupheader{Helper type}
118
119 @snippet include/kumi/algorithm/inner_product.hpp inner_product_t
120
121 Computes the return type of a call to kumi::inner_product
122
123 @groupheader{Examples}
124
125 @tab_begin
126
127 @tab{Tuple}
128 @godbolt{doc/tuple/algo/inner_product.cpp}
129
130 @tab{Record}
131 @godbolt{doc/record/algo/inner_product.cpp}
132
133 @tab_end
134 **/
135 //====================================================================================================================
136 KUMI_VARIABLE_ABI constexpr inner_product_t inner_product{};
137
138 namespace result
139 {
140 //! [inner_product_t]
141 template<kumi::concepts::product_type S1,
142 kumi::concepts::sized_product_type<kumi::size_v<S1>> S2,
143 typename T,
144 typename... Operators>
145 requires((sizeof...(Operators) == 0) || (sizeof...(Operators) == 2))
146 using inner_product_t = decltype(kumi::inner_product(
147 std::declval<S1>(), std::declval<S2>(), std::declval<T>(), std::declval<Operators>()...));
148
149 template<kumi::concepts::product_type S1,
150 kumi::concepts::sized_product_type<kumi::size_v<S1>> S2,
151 typename T,
152 typename... Operators>
153 requires((sizeof...(Operators) == 0) || (sizeof...(Operators) == 2))
154 struct inner_product
155 {
156 using type = kumi::result::inner_product_t<S1, S2, T, Operators...>;
157 };
158
159 //! [inner_product_t]
160 }
161 }
162