VCTR
Loading...
Searching...
No Matches
Multiply.h
1/*
2 ==============================================================================
3 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
5 Copyright 2022- by sonible GmbH.
6
7 This file is part of VCTR - Versatile Container Templates Reconceptualized.
8
9 VCTR is free software: you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License version 3
11 only, as published by the Free Software Foundation.
12
13 VCTR is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Lesser General Public License version 3 for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 version 3 along with VCTR. If not, see <https://www.gnu.org/licenses/>.
20 ==============================================================================
21*/
22
23namespace vctr::expressions
24{
25
26//==============================================================================
28template <size_t extent, class SrcAType, class SrcBType>
30{
31private:
32 static auto op (const ValueType<SrcAType>& a, const ValueType<SrcBType>& b) { return a * b; }
33
34public:
36
37 VCTR_COMMON_BINARY_VEC_VEC_EXPRESSION_MEMBERS (MultiplyVectors, srcA, srcB)
38
39 VCTR_FORCEDINLINE constexpr auto operator[] (size_t i) const
40 {
41 return srcA[i] * srcB[i];
42 }
43
44 VCTR_FORCEDINLINE const value_type* evalNextVectorOpInExpressionChain (value_type* dst) const
46 {
47 Expression::Accelerate::mul (srcA.evalNextVectorOpInExpressionChain (dst), srcB.evalNextVectorOpInExpressionChain (dst), dst, size());
48 return dst;
49 }
50
51 VCTR_FORCEDINLINE const value_type* evalNextVectorOpInExpressionChain (value_type* dst) const
53 {
54 Expression::IPP::mul (srcA.evalNextVectorOpInExpressionChain (dst), srcB.evalNextVectorOpInExpressionChain (dst), dst, sizeToInt (size()));
55 return dst;
56 }
57
58
59 VCTR_FORCEDINLINE void evalVectorOpMultiplyAccumulate (value_type* dst) const
61 {
62 Expression::Accelerate::multiplyAdd (srcA.data(), srcB.data(), dst, dst, size());
63 }
64
65 VCTR_FORCEDINLINE void evalVectorOpMultiplyAccumulate (value_type* dst) const
67 {
68 Expression::IPP::multiplyAccumulate (srcA.data(), srcB.data(), dst, sizeToInt (size()));
69 }
70
71 //==============================================================================
72 VCTR_FORWARD_PREPARE_SIMD_EVALUATION_BINARY_EXPRESSION_MEMBER_FUNCTIONS (srcA, srcB)
73
74 // AVX Implementation
75 VCTR_FORCEDINLINE VCTR_TARGET ("fma") AVXRegister<value_type> getAVX (size_t i) const
76 requires (archX64 && has::getAVX<SrcAType> && has::getAVX<SrcBType> && Expression::allElementTypesSame && Expression::CommonElement::isRealFloat)
77 {
78 return Expression::AVX::mul (srcA.getAVX (i), srcB.getAVX (i));
79 }
80
81 //==============================================================================
82 // NEON Implementation
83 NeonRegister<value_type> getNeon (size_t i) const
84 requires (archARM && has::getNeon<SrcAType> && has::getNeon<SrcBType> && Expression::allElementTypesSame && ! (Expression::CommonElement::isInt64 || Expression::CommonElement::isUint64))
85 {
86 return Expression::Neon::mul (srcA.getNeon (i), srcB.getNeon (i));
87 }
88};
89
90//==============================================================================
92template <size_t extent, class SrcType>
94{
95public:
96 using value_type = ValueType<SrcType>;
97
98 VCTR_COMMON_BINARY_SINGLE_VEC_EXPRESSION_MEMBERS (MultiplyVecBySingle, src, single)
99
100 VCTR_FORCEDINLINE constexpr value_type operator[] (size_t i) const
101 {
102 return single * src[i];
103 }
104
105 VCTR_FORCEDINLINE const value_type* evalNextVectorOpInExpressionChain (value_type* dst) const
107 {
108 Expression::Accelerate::mul (src.evalNextVectorOpInExpressionChain (dst), single, dst, size());
109 return dst;
110 }
111
112 VCTR_FORCEDINLINE const value_type* evalNextVectorOpInExpressionChain (value_type* dst) const
114 {
115 Expression::IPP::mul (src.evalNextVectorOpInExpressionChain (dst), single, dst, sizeToInt (size()));
116 return dst;
117 }
118
119 VCTR_FORCEDINLINE void evalVectorOpMultiplyAccumulate (value_type* dst) const
121 {
122 Expression::Accelerate::multiplyAdd (src.data(), single, dst, dst, size());
123 }
124
125 VCTR_FORCEDINLINE void evalVectorOpMultiplyAccumulate (value_type* dst) const
127 {
128 Expression::IPP::multiplyAccumulate (src.data(), single, dst, sizeToInt (size()));
129 }
130
131 //==============================================================================
132 // AVX Implementation
133 VCTR_FORCEDINLINE VCTR_TARGET ("avx") void prepareAVXEvaluation() const
135 {
136 src.prepareAVXEvaluation();
137 singleSIMD.avx = Expression::AVX::broadcast (single);
138 }
139
140 VCTR_FORCEDINLINE VCTR_TARGET ("fma") AVXRegister<value_type> getAVX (size_t i) const
141 requires (archX64 && has::getAVX<SrcType> && Expression::allElementTypesSame && Expression::CommonElement::isRealFloat)
142 {
143 return Expression::AVX::mul (singleSIMD.avx, src.getAVX (i));
144 }
145
146 // SSE Implementation
147 VCTR_FORCEDINLINE VCTR_TARGET ("sse4.1") void prepareSSEEvaluation() const
149 {
150 src.prepareSSEEvaluation();
151 singleSIMD.sse = Expression::SSE::broadcast (single);
152 }
153
154 VCTR_FORCEDINLINE VCTR_TARGET ("sse4.1") SSERegister<value_type> getSSE (size_t i) const
155 requires (archX64 && has::getSSE<SrcType> && Expression::allElementTypesSame && Expression::CommonElement::isRealFloat)
156 {
157 return Expression::SSE::mul (singleSIMD.sse, src.getSSE (i));
158 }
159private:
160 mutable SIMDRegisterUnion<Expression> singleSIMD {};
161};
162
163//==============================================================================
165template <size_t extent, class SrcType, is::constant ConstantType>
167{
168public:
169 using value_type = ValueType<SrcType>;
170
171 static constexpr auto constant = value_type (ConstantType::value);
172
173 VCTR_COMMON_UNARY_EXPRESSION_MEMBERS (MultiplyVecByConstant, src)
174
175 VCTR_FORCEDINLINE constexpr value_type operator[] (size_t i) const
176 {
177 return constant * src[i];
178 }
179
180 VCTR_FORCEDINLINE const value_type* evalNextVectorOpInExpressionChain (value_type* dst) const
182 {
183 Expression::Accelerate::mul (src.evalNextVectorOpInExpressionChain (dst), constant, dst, size());
184 return dst;
185 }
186
187 VCTR_FORCEDINLINE const value_type* evalNextVectorOpInExpressionChain (value_type* dst) const
189 {
190 Expression::IPP::mul (src.evalNextVectorOpInExpressionChain (dst), constant, dst, sizeToInt (size()));
191 return dst;
192 }
193
194 VCTR_FORCEDINLINE void evalVectorOpMultiplyAccumulate (value_type* dst) const
196 {
197 Expression::Accelerate::multiplyAdd (src.data(), constant, dst, dst, size());
198 }
199
200 VCTR_FORCEDINLINE void evalVectorOpMultiplyAccumulate (value_type* dst) const
202 {
203 Expression::IPP::multiplyAccumulate (src.data(), constant, dst, sizeToInt (size()));
204 }
205
206 //==============================================================================
207 // NEON Implementation
208 VCTR_FORCEDINLINE void prepareNeonEvaluation() const
210 {
211 src.prepareNeonEvaluation();
212 constantSIMD.neon = Expression::Neon::broadcast (constant);
213 }
214
215 VCTR_FORCEDINLINE NeonRegister<value_type> getNeon (size_t i) const
216 requires (archARM && has::getNeon<SrcType> && Expression::allElementTypesSame && Expression::CommonElement::isRealFloat)
217 {
218 return Expression::Neon::mul (constantSIMD.neon, src.getNeon (i));
219 }
220
221 // AVX Implementation
222 VCTR_FORCEDINLINE VCTR_TARGET ("avx") void prepareAVXEvaluation() const
224 {
225 src.prepareAVXEvaluation();
226 constantSIMD.avx = Expression::AVX::broadcast (constant);
227 }
228
229 VCTR_FORCEDINLINE VCTR_TARGET ("fma") AVXRegister<value_type> getAVX (size_t i) const
230 requires (archX64 && has::getAVX<SrcType> && Expression::allElementTypesSame && Expression::CommonElement::isRealFloat)
231 {
232 return Expression::AVX::mul (constantSIMD.avx, src.getAVX (i));
233 }
234
235 // SSE Implementation
236 VCTR_FORCEDINLINE VCTR_TARGET ("sse4.1") void prepareSSEEvaluation() const
238 {
239 src.prepareSSEEvaluation();
240 constantSIMD.sse = Expression::SSE::broadcast (constant);
241 }
242
243 VCTR_FORCEDINLINE VCTR_TARGET ("sse4.1") SSERegister<value_type> getSSE (size_t i) const
244 requires (archX64 && has::getSSE<SrcType> && Expression::allElementTypesSame && Expression::CommonElement::isRealFloat)
245 {
246 return Expression::SSE::mul (constantSIMD.sse, src.getSSE (i));
247 }
248
249private:
250 mutable SIMDRegisterUnion<Expression> constantSIMD {};
251};
252
253} // namespace vctr::expressions
254
255namespace vctr::detail
256{
257template <class T>
258struct IsMultiplicationExpression : std::false_type {};
259
260template <size_t e, class A, class B>
261struct IsMultiplicationExpression<expressions::MultiplyVectors<e, A, B>> : std::true_type {};
262
263template <size_t e, class A>
264struct IsMultiplicationExpression<expressions::MultiplyVecBySingle<e, A>> : std::true_type {};
265} // namespace vctr::detail
266
267namespace vctr
268{
269
274template <class SrcAType, class SrcBType>
275requires (is::anyVctrOrExpression<std::remove_cvref_t<SrcAType>> &&
276 is::anyVctrOrExpression<std::remove_cvref_t<SrcBType>>)
277constexpr auto operator* (SrcAType&& a, SrcBType&& b)
278{
279 assertCommonSize (a, b);
280 constexpr auto extent = getCommonExtent<SrcAType, SrcBType>();
281
282 return expressions::MultiplyVectors<extent, SrcAType, SrcBType> (std::forward<SrcAType> (a), std::forward<SrcBType> (b));
283}
284
289template <class Src>
290requires is::anyVctrOrExpression<Src>
291constexpr auto operator* (typename std::remove_cvref_t<Src>::value_type single, Src&& vec)
292{
293 return expressions::MultiplyVecBySingle<extentOf<Src>, Src> (single, std::forward<Src> (vec));
294}
295
300template <class Src>
301requires is::anyVctrOrExpression<Src>
302constexpr auto operator* (Src&& vec, typename std::remove_cvref_t<Src>::value_type single)
303{
304 return expressions::MultiplyVecBySingle<extentOf<Src>, Src> (single, std::forward<Src> (vec));
305}
306
307
312template <auto constantValue>
314} // namespace vctr
Multiplies a vector like type by a single compile time constant value.
Definition: Multiply.h:167
Multiplies a vector like type by a single value.
Definition: Multiply.h:94
Multiplies two vector like types.
Definition: Multiply.h:30
Constrains a type to have a member function getAVX (size_t) const.
Definition: ContainerAndExpressionConcepts.h:92
Constrains a type to have a member function getNeon (size_t) const.
Definition: ContainerAndExpressionConcepts.h:84
Constrains a type to have a member function getSSE (size_t) const.
Definition: ContainerAndExpressionConcepts.h:100
Constrains a type to have a member function prepareAVXEvaluation() const.
Definition: ContainerAndExpressionConcepts.h:88
Constrains a type to have a member function prepareNeonEvaluation() const.
Definition: ContainerAndExpressionConcepts.h:80
Constrains a type to have a member function prepareSSEEvaluation() const.
Definition: ContainerAndExpressionConcepts.h:96
Constrains a type to be any derived instance of VctrBase.
Definition: ContainerAndExpressionConcepts.h:210
A combined concept to check if Apple Accelerate is a suitable option for a real valued floating point...
Definition: ContainerAndExpressionConcepts.h:260
A combined concept to check if Apple Accelerate is a suitable option for a real or complex valued flo...
Definition: ContainerAndExpressionConcepts.h:329
A combined concept to check if Intel IPP is a suitable option for a real valued floating point vector...
Definition: ContainerAndExpressionConcepts.h:284
A combined concept to check if Intel IPP is a suitable option for a real or complex valued floating p...
Definition: ContainerAndExpressionConcepts.h:342
A combined concept to check if Intel IPP is a suitable option for a real or complex valued floating p...
Definition: ContainerAndExpressionConcepts.h:296
constexpr ExpressionChainBuilder< expressions::MultiplyVecByConstant, Constant< constantValue > > multiplyByConstant
Returns an expression that multiplies a vector or expression source with a compile time constant.
Definition: Multiply.h:313
constexpr auto operator*(SrcAType &&a, SrcBType &&b)
Returns an expression that multiplies vector or expression a with vector or expression b.
Definition: Multiply.h:277
The main namespace of the VCTR project.
Definition: Array.h:24
constexpr void assertCommonSize(const A &a, const B &b)
Ensures that both sources have the same size.
Definition: Traits.h:256
typename detail::ValueType< std::remove_cvref_t< T > >::Type ValueType
If T is an expression template, it equals its return type, if it's a type that defines value_type as ...
Definition: Traits.h:201
typename detail::CommonVecExpressionType< A, B, op >::type CommonVecExpressionType
Used to figure out the value_type for binary vector-vector operations.
Definition: ExpressionTemplate.h:177
int sizeToInt(size_t size)
Casts the size_t argument to an int.
Definition: PlatformVectorOpsHelpers.h:27
Definition: AVXRegister.h:28
An expression chain builder is an object which supplies various operator<< overloads which build chai...
Definition: ExpressionChainBuilder.h:157
The base class to every expression template.
Definition: ExpressionTemplate.h:37
Definition: NeonRegister.h:28
Definition: SSERegister.h:28
Helper template to define a union of all supported SIMD types.
Definition: ExpressionTemplate.h:123