Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
inner_product.hpp
Go to the documentation of this file.
1// parasoft-begin-suppress AUTOSAR-A2_8_1-a-2 "False positive: also defines arene::base::inner_product"
2
3// Copyright 2026, Toyota Motor Corporation
4//
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
7#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_INNER_PRODUCT_HPP_
8#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_INNER_PRODUCT_HPP_
9
10// IWYU pragma: private, include "arene/base/algorithm.hpp"
11// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
12
13// parasoft-begin-suppress AUTOSAR-A7_1_5-a-2 "Trailing return syntax permitted by A7-1-5 Permit #1 v1.0.0"
14
15// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
16#include "arene/base/algorithm/detail/generalized_transform_reduce.hpp"
17#include "arene/base/algorithm/detail/traits.hpp"
18#include "arene/base/compiler_support/cpp14_inline.hpp"
19#include "arene/base/constraints/constraints.hpp"
20#include "arene/base/stdlib_choice/enable_if.hpp"
21#include "arene/base/stdlib_choice/is_assignable.hpp"
22#include "arene/base/stdlib_choice/is_move_constructible.hpp"
23#include "arene/base/stdlib_choice/move.hpp"
24#include "arene/base/stdlib_choice/multiplies.hpp"
25#include "arene/base/stdlib_choice/plus.hpp"
26#include "arene/base/type_traits/is_copyable.hpp"
27#include "arene/base/type_traits/is_invocable.hpp"
28#include "arene/base/type_traits/iterator_category_traits.hpp"
29// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
30
31// IWYU pragma: no_include "arene/base/stdlib_choice/iterator_traits.hpp"
32
33// parasoft-begin-suppress AUTOSAR-M2_10_1-a-2 "Similar names permitted by M2-10-1 Permit #1"
34
35namespace arene {
36namespace base {
37namespace algorithm_detail {
38namespace inner_product_detail {
39
40/// @brief function object implementing 'inner_product'
41class inner_product_fn {
42 public:
43 /// @brief computes the inner product of two ranges of elements
44 /// @tparam InputIt1 type of the iterator for the first range
45 /// @tparam InputIt2 type of the iterator for the second range
46 /// @tparam Value type of the accumulated value
47 /// @tparam Plus type of the addition operation
48 /// @tparam Multiplies type of the multiplication operation
49 /// @param first1 iterator to the beginning of the first range
50 /// @param last1 iterator to one past the end of the first range
51 /// @param first2 iterator to the beginning of the second range
52 /// @param init initial value to start with
53 /// @param plus binary function object used to reduce transformed elements
54 /// to a single value
55 /// @param multiplies binary function object applied to each pair of elements
56 /// of the input ranges
57 ///
58 /// @return Initializes the accumulator @c acc (of type @c Value) with the
59 /// initial value @c init and then modifies it with the expression
60 /// <c> acc = plus(std::move(acc), multiplies(*i1, *i2)) </c> for every iterator
61 /// @c i1 in the range <c> [first1, last1) </c> in order and its
62 /// corresponding iterator @c i2 in the range beginning at @c first2.
63 ///
64 /// @pre <c> [first2, first2 + distance(first1, last1)) </c> is a valid range
65 /// @pre @c plus does not invalidate subranges, nor modify elements in the
66 /// ranges <c> [first1, last1) </c> and
67 /// <c> [first2, first2 + distance(first1, last1)) </c>
68 /// @pre @c multiplies does not invalidate subranges, nor modify elements in the
69 /// ranges <c> [first1, last1) </c> and
70 /// <c> [first2, first2 + distance(first1, last1)) </c>
71 ///
72 /// @note Constraints <br>
73 /// * @c InputIt1 must satisfy the input iterator requirements
74 /// * @c InputIt2 must satisfy the input iterator requirements
75 /// * @c Value is copy constructible
76 /// * @c Value is copy assignable
77 /// * <c> multiplies(*first1, *first2) </c> is a valid expression
78 /// * <c> plus(init, multiplies(*first1, *first2)) </c> is assignable
79 /// to @c Value
80 ///
81 /// @note Complexity <br>
82 /// O(N) applications of @c plus and @c multiplies, where
83 /// <c> N = distance(first1, last1) </c>.
84 ///
85 /// @note Unlike @c transform_reduce, @c inner_product always performs the
86 /// operations in the order given.
87 ///
88 template <
89 class InputIt1,
90 class InputIt2,
91 class Value,
92 class Plus,
93 class Multiplies,
94 constraints<
95 std::enable_if_t<is_input_iterator_v<InputIt1>>,
96 std::enable_if_t<is_input_iterator_v<InputIt2>>,
97 std::enable_if_t<is_copyable_v<Value>>,
98 std::enable_if_t<
99 std::is_assignable<
100 Value&,
101 invoke_result_t<
102 Plus&,
103 Value&&,
104 invoke_result_t<
105 Multiplies&,
106 iter_reference_t<InputIt1>,
107 iter_reference_t<InputIt2>
108 >
109 >
110 >::value>> = nullptr>
111 constexpr auto operator()(
112 InputIt1 first1,
113 InputIt1 last1,
114 InputIt2 first2,
115 Value init,
116 Plus plus,
117 Multiplies multiplies
118 ) const noexcept( //
119 std::is_nothrow_move_constructible<Value>::value &&
120 is_nothrow_invocable_v<
121 generalized_transform_reduce,
122 generalized_transform_reduce::default_reduce_value_policy<Value>,
123 InputIt1&,
124 InputIt1&,
125 InputIt2&,
126 Value,
127 Plus&,
128 Multiplies&>
129 )
130 -> Value
131 {
132 using policy = generalized_transform_reduce::default_reduce_value_policy<Value>;
133
134 return policy::access( //
135 generalized_transform_reduce{}( //
136 policy{},
137 first1,
138 last1,
139 first2,
140 std::move(init),
141 plus,
142 multiplies
143 )
144 );
145 }
146
147 /// @brief computes the inner product of two ranges of elements
148 /// @tparam InputIt1 type of the iterator for the first range
149 /// @tparam InputIt2 type of the iterator for the second range
150 /// @tparam Value type of the accumulated value
151 /// @param first1 iterator to the beginning of the first range
152 /// @param last1 iterator to one past the end of the first range
153 /// @param first2 iterator to the beginning of the second range
154 /// @param init initial value to start with
155 ///
156 /// @return Initializes the accumulator @c acc (of type @c Value) with the
157 /// initial value @c init and then modifies it with the expression
158 /// <c> acc = std::move(acc) + (*i1 * *i2)) </c> for every iterator
159 /// @c i1 in the range <c> [first1, last1) </c> in order and its
160 /// corresponding iterator @c i2 in the range beginning at @c first2.
161 ///
162 /// @pre <c> [first2, first2 + distance(first1, last1)) </c> is a valid range
163 /// @pre binary @c operator+ does not invalidate subranges, nor modify
164 /// elements in the ranges <c> [first1, last1) </c> and
165 /// <c> [first2, first2 + distance(first1, last1)) </c>
166 /// @pre binary @c operator* does not invalidate subranges, nor modify
167 /// elements in the ranges <c> [first1, last1) </c> and
168 /// <c> [first2, first2 + distance(first1, last1)) </c>
169 ///
170 /// @note Constraints <br>
171 /// * @c InputIt1 must satisfy the input iterator requirements
172 /// * @c InputIt2 must satisfy the input iterator requirements
173 /// * @c Value is copy constructible
174 /// * @c Value is copy assignable
175 /// * <c> *first1 * *first2 </c> is a valid expression
176 /// * <c> init + multiplies(*first1, *first2) </c> is assignable
177 /// to @c Value
178 ///
179 /// @note Complexity <br>
180 /// O(N) applications of @c plus and @c multiplies, where
181 /// <c> N = distance(first1, last1) </c>.
182 ///
183 /// @note Unlike @c transform_reduce, @c inner_product always performs the
184 /// operations in the order given.
185 ///
186 template <
187 class InputIt1,
188 class InputIt2,
189 class Value,
190 constraints<
191 std::enable_if_t<is_input_iterator_v<InputIt1>>,
192 std::enable_if_t<is_input_iterator_v<InputIt2>>,
193 std::enable_if_t<is_copyable_v<Value>>,
194 std::enable_if_t<std::is_assignable<
195 Value&,
196 invoke_result_t<
197 std::plus<>&,
198 Value&&,
199 invoke_result_t< //
200 std::multiplies<>&,
201 iter_reference_t<InputIt1>,
202 iter_reference_t<InputIt2>>>>::value>> = nullptr>
203 constexpr auto operator()( //
204 InputIt1 first1,
205 InputIt1 last1,
206 InputIt2 first2,
207 Value init
208 ) const
209 noexcept(is_nothrow_invocable_v<
210 inner_product_fn,
211 InputIt1&&,
212 InputIt1&&,
213 InputIt2&&,
214 Value&&,
215 std::plus<>&&,
216 std::multiplies<>&&>) -> Value {
217 return (*this)(
218 std::move(first1),
219 std::move(last1),
220 std::move(first2),
221 std::move(init),
222 std::plus<>{},
223 std::multiplies<>{}
224 );
225 }
226};
227} // namespace inner_product_detail
228} // namespace algorithm_detail
229
230/// @def arene::base::inner_product
231/// @brief computes the inner product of two ranges of elements
232/// @copydoc arene::base::algorithm_detail::inner_product_detail::inner_product_fn::operator()
233// parasoft-begin-suppress AUTOSAR-M7_3_3-a "An unnamed namespace is used to create a per-TU reference to a global
234// object used in multiple TUs."
235// parasoft-begin-suppress CERT_CPP-DCL59-a "An unnamed namespace is used to create a per-TU reference to a global
236// object used in multiple TUs."
237ARENE_CPP14_INLINE_VARIABLE(algorithm_detail::inner_product_detail::inner_product_fn, inner_product);
238// parasoft-end-suppress AUTOSAR-M7_3_3-a
239// parasoft-end-suppress CERT_CPP-DCL59-a
240
241} // namespace base
242} // namespace arene
243
244#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_INNER_PRODUCT_HPP_
Definition array_exceptions_disabled.cpp:11
ARENE_CPP14_INLINE_VARIABLE(algorithm_detail::inner_product_detail::inner_product_fn, inner_product)
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10