VCTR
Loading...
Searching...
No Matches
ExpressionTemplate.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
24{
25
37{
39 template <class ReturnElementType, class... SrcTypes>
41 {
43 template <class T>
45 {
46 using Type = T;
47
48 static constexpr auto isRealFloat = is::realFloatNumber<Type>;
49
50 static constexpr auto isSigned = std::is_signed_v<Type>;
51
52 static constexpr auto isUnsigned = std::is_unsigned_v<Type>;
53
54 static constexpr auto isInt = std::is_integral_v<Type>;
55
56 static constexpr auto isSignedInt = isSigned & isInt;
57
58 static constexpr auto isComplexFloat = is::complexFloatNumber<Type>;
59
60 static constexpr auto isInt32 = std::same_as<int32_t, Type>;
61
62 static constexpr auto isUint32 = std::same_as<uint32_t, Type>;
63
64 static constexpr auto isInt64 = std::same_as<int64_t, Type>;
65
66 static constexpr auto isUint64 = std::same_as<uint64_t, Type>;
67
68 static constexpr auto isFloat = std::same_as<float, Type>;
69
70 static constexpr auto isDouble = std::same_as<double, Type>;
71 };
72
75
78
81
82 //==============================================================================
85
88
91
92 //==============================================================================
95
98
101
102 //==============================================================================
105
108
111
112 //==============================================================================
114 using Accelerate = platform_vec_ops::AppleAccelerate<typename CommonElement::Type>;
115
117 using IPP = platform_vec_ops::IntelIPP<typename CommonElement::Type>;
118 };
119
121 template <class ExpressionTypes>
123 {
124 typename ExpressionTypes::NeonSrc neon;
125 typename ExpressionTypes::SSESrc sse;
126 typename ExpressionTypes::AVXSrc avx;
127 };
128};
129
130namespace detail
131{
132
133template <size_t i, class RuntimeArgs, is::expression Expression>
134constexpr void tryApplyingRuntimeArgsToThisExpression (const RuntimeArgs& args, Expression& e)
135{
136 if constexpr (RuntimeArgs::template hasValue<i>())
137 {
138 std::apply ([&] (const auto&... args)
139 {
140 static_assert (has::applyRuntimeArgs<Expression, decltype (args)...>,
141 "The expression does not implement a applyRuntimeArgs overload that matches the argument types passed.");
142 e.applyRuntimeArgs (args...);
143 }, args.template get<i>());
144 }
145 else if constexpr (has::applyRuntimeArgs<Expression>)
146 {
147 // Some expressions need to initialize runtime values that depend on their source before every
148 // evaluation rather than being injected as external arguments (see e.g. NormalizeSum).
149 e.applyRuntimeArgs();
150 }
151}
152
153template <size_t i, class RuntimeArgs, is::anyVctrOrExpression Src>
154constexpr void tryApplyingRuntimeArgsToSrc (const RuntimeArgs& args, Src& src)
155{
156 if constexpr (has::iterateOverRuntimeArgChain<Src, i, RuntimeArgs> && i < RuntimeArgs::size())
157 src.template iterateOverRuntimeArgChain<i> (args);
158}
159
160template <class A, class B, auto op>
162{
163 using type = decltype (op (std::declval<A>(), std::declval<B>()));
164};
165
166template <class A, std::common_with<A> B, auto op>
167struct CommonVecExpressionType<A, B, op> : std::common_type<A, B> {};
168
169} // namespace detail
170
176template <class A, class B, auto op>
177using CommonVecExpressionType = typename detail::CommonVecExpressionType<A, B, op>::type;
178
184template <is::expressionChainBuilder ChainBuilder, is::anyVctrOrExpression SourceType>
185using ExpressionTypeForSourceType = typename ChainBuilder::template Expression<extentOf<SourceType>, SourceType>;
186
187} // namespace vctr
188
202// clang-format off
203#define VCTR_COMMON_UNARY_EXPRESSION_MEMBERS(ExpressionName, srcName) \
204private: \
205 using Expression = ExpressionTypes<value_type, SrcType>; \
206 SrcType srcName; \
207public: \
208 \
209 template <class Src> \
210 constexpr ExpressionName (Src&& s) : srcName (std::forward<Src> (s)) {} \
211 \
212 constexpr const auto& getStorageInfo() const { return srcName.getStorageInfo(); } \
213 \
214 constexpr size_t size() const { return srcName.size (); } \
215 \
216 constexpr bool isNotAliased (const void* other) const { return srcName.isNotAliased (other); } \
217 \
218 template <size_t i, class RuntimeArgs> \
219 constexpr void iterateOverRuntimeArgChain (const RuntimeArgs& rtArgs) \
220 { \
221 tryApplyingRuntimeArgsToThisExpression<i> (rtArgs, *this); \
222 tryApplyingRuntimeArgsToSrc<i + 1> (rtArgs, srcName); \
223 }
224
240#define VCTR_COMMON_BINARY_VEC_VEC_EXPRESSION_MEMBERS(ExpressionName, srcAName, srcBName) \
241private: \
242 using Expression = ExpressionTypes<value_type, SrcAType, SrcBType>; \
243 using SrcAStorageInfoType = std::invoke_result_t<decltype (&std::remove_cvref_t<SrcAType>::getStorageInfo), SrcAType>; \
244 using SrcBStorageInfoType = std::invoke_result_t<decltype (&std::remove_cvref_t<SrcBType>::getStorageInfo), SrcBType>; \
245 \
246 SrcAType srcAName; \
247 SrcBType srcBName; \
248 const ::vctr::CombinedStorageInfo<std::remove_cvref_t<SrcAStorageInfoType>, std::remove_cvref_t<SrcBStorageInfoType>> storageInfo; \
249 \
250public: \
251 template <class SrcA, class SrcB> \
252 constexpr ExpressionName (SrcA&& a, SrcB&& b) \
253 : srcAName (std::forward<SrcA> (a)), \
254 srcBName (std::forward<SrcB> (b)), \
255 storageInfo (srcAName.getStorageInfo(), srcBName.getStorageInfo()) \
256 {} \
257 \
258 constexpr const auto& getStorageInfo() const { return storageInfo; } \
259 \
260 constexpr size_t size() const { return srcAName.size(); } \
261 \
262 constexpr bool isNotAliased (const void* dst) const \
263 { \
264 if constexpr (is::expression<SrcAType> && is::anyVctr<SrcBType>) \
265 { \
266 return dst != srcBName.data(); \
267 } \
268 \
269 if constexpr (is::anyVctr<SrcAType> && is::expression<SrcBType>) \
270 { \
271 return dst != srcAName.data(); \
272 } \
273 \
274 return true; \
275 }
276
291#define VCTR_COMMON_BINARY_SINGLE_VEC_EXPRESSION_MEMBERS(ExpressionName, srcVecName, srcSingleName) \
292private: \
293 using Expression = ExpressionTypes<value_type, SrcType>; \
294 \
295 SrcType srcVecName; \
296 typename Expression::CommonSrcElement::Type srcSingleName; \
297public: \
298 \
299 template <class Src> \
300 constexpr ExpressionName (typename Expression::CommonSrcElement::Type a, Src&& b) \
301 : srcVecName (std::forward<Src> (b)), \
302 srcSingleName (a) \
303 {} \
304 \
305 constexpr const auto& getStorageInfo() const { return srcVecName.getStorageInfo(); } \
306 \
307 constexpr size_t size() const { return srcVecName.size(); } \
308 constexpr bool isNotAliased (const void* other) const { return srcVecName.isNotAliased (other); }
309
311#define VCTR_FORWARD_PREPARE_SIMD_EVALUATION_UNARY_EXPRESSION_MEMBER_FUNCTIONS \
312 void prepareNeonEvaluation() const \
313 requires ::vctr::has::prepareNeonEvaluation<SrcType> \
314 { \
315 src.prepareNeonEvaluation(); \
316 } \
317 \
318 VCTR_FORCEDINLINE VCTR_TARGET ("avx") void prepareAVXEvaluation() const \
319 requires ::vctr::has::prepareAVXEvaluation<SrcType> && Expression::CommonElement::isRealFloat \
320 { \
321 src.prepareAVXEvaluation(); \
322 } \
323 \
324 VCTR_FORCEDINLINE VCTR_TARGET ("avx2") void prepareAVXEvaluation() const \
325 requires ::vctr::has::prepareAVXEvaluation<SrcType> && Expression::CommonElement::isInt \
326 { \
327 src.prepareAVXEvaluation(); \
328 } \
329 \
330 VCTR_FORCEDINLINE VCTR_TARGET ("sse4.1") void prepareSSEEvaluation() const \
331 requires ::vctr::has::prepareSSEEvaluation<SrcType> \
332 { \
333 src.prepareSSEEvaluation(); \
334 }
335
337#define VCTR_FORWARD_PREPARE_SIMD_EVALUATION_BINARY_EXPRESSION_MEMBER_FUNCTIONS(srcAName, srcBName) \
338 void prepareNeonEvaluation() const \
339 requires ::vctr::has::prepareNeonEvaluation<SrcAType> && ::vctr::has::prepareNeonEvaluation<SrcBType> \
340 { \
341 srcAName.prepareNeonEvaluation(); \
342 srcBName.prepareNeonEvaluation(); \
343 } \
344 \
345 VCTR_FORCEDINLINE VCTR_TARGET ("avx") void prepareAVXEvaluation() const \
346 requires ::vctr::has::prepareAVXEvaluation<SrcAType> && ::vctr::has::prepareAVXEvaluation<SrcBType> && Expression::CommonElement::isRealFloat \
347 { \
348 srcAName.prepareAVXEvaluation(); \
349 srcBName.prepareAVXEvaluation(); \
350 } \
351 \
352 VCTR_FORCEDINLINE VCTR_TARGET ("avx2") void prepareAVXEvaluation() const \
353 requires ::vctr::has::prepareAVXEvaluation<SrcAType> && ::vctr::has::prepareAVXEvaluation<SrcBType> && Expression::CommonElement::isInt \
354 { \
355 srcAName.prepareAVXEvaluation(); \
356 srcBName.prepareAVXEvaluation(); \
357 } \
358 \
359 VCTR_FORCEDINLINE VCTR_TARGET ("sse4.1") void prepareSSEEvaluation() const \
360 requires ::vctr::has::prepareSSEEvaluation<SrcAType> && ::vctr::has::prepareSSEEvaluation<SrcBType> \
361 { \
362 srcAName.prepareSSEEvaluation(); \
363 srcBName.prepareSSEEvaluation(); \
364 }
365// clang-format on
Constrains a pack of elements to be the same type.
Definition: GenericConcepts.h:144
Constrains a type to have a function applyRuntimeArgs (const Args&...)
Definition: ContainerAndExpressionConcepts.h:180
Constrains a type to represent a complex valued floating point number (e.g.
Definition: NumericTypeConcepts.h:87
Constrains a type to represent a real valued floating point number.
Definition: NumericTypeConcepts.h:83
The main namespace of the VCTR project.
Definition: Array.h:24
typename detail::CommonVecExpressionType< A, B, op >::type CommonVecExpressionType
Used to figure out the value_type for binary vector-vector operations.
Definition: ExpressionTemplate.h:177
typename ChainBuilder::template Expression< extentOf< SourceType >, SourceType > ExpressionTypeForSourceType
Derives the type of the expression that is created when prepending an expression chain builder with a...
Definition: ExpressionTemplate.h:185
Definition: AVXRegister.h:28
Definition: Config.h:298
Some common traits you want to check when constraining expression template functions.
Definition: ExpressionTemplate.h:45
Supplies some handy typedefs and traits needed when implementing expression templates.
Definition: ExpressionTemplate.h:41
static constexpr auto allElementTypesSame
Indicates if all source element types and the return types are same.
Definition: ExpressionTemplate.h:80
platform_vec_ops::AppleAccelerate< typename CommonElement::Type > Accelerate
The platform_vec_ops::AppleAccelerate type for the common element type.
Definition: ExpressionTemplate.h:114
platform_vec_ops::IntelIPP< typename CommonElement::Type > IPP
The platform_vec_ops::IntelIPP type for the common element type.
Definition: ExpressionTemplate.h:117
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