KleidiCV Coverage Report


Directory: ./
File: kleidicv/include/kleidicv/operations.h
Date: 2025-09-25 14:13:34
Exec Total Coverage
Lines: 286 286 100.0%
Functions: 5265 5290 99.5%
Branches: 10 10 100.0%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2023 - 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 #ifndef KLEIDICV_OPERATIONS_H
6 #define KLEIDICV_OPERATIONS_H
7
8 #include <algorithm>
9 #include <utility>
10
11 #include "kleidicv/traits.h"
12 #include "kleidicv/types.h"
13
14 namespace KLEIDICV_TARGET_NAMESPACE {
15
16 // Base for classes that change the behaviour or extend the interface of an
17 // operation.
18 //
19 // This class conveniently forwards common types and methods without having to
20 // explicitly define them in all derived classes.
21 template <typename T>
22 class OperationBase {
23 public:
24 // Type of the inner operation.
25 using OperationType = T;
26
27 // The vector traits used by the inner operation.
28 using VecTraits = typename OperationType::VecTraits;
29
30 // The context type used by the inner operation, if any.
31 using ContextType = context_type_t<OperationType>;
32
33 // Returns a reference to the inner operation.
34 3371613 OperationType &operation() KLEIDICV_STREAMING { return operation_; }
35
36 // Forwards num_lanes() calls to the inner operation.
37 70351 static size_t num_lanes() KLEIDICV_STREAMING {
38 70351 return VecTraits::num_lanes();
39 }
40
41 // Forwards vector_path_2x() calls to the inner operation.
42 template <typename... ArgTypes>
43 346497 decltype(auto) vector_path_2x(ArgTypes &&...args) KLEIDICV_STREAMING {
44 346497 return operation().vector_path_2x(std::forward<ArgTypes>(args)...);
45 }
46
47 // Forwards vector_path() calls to the inner operation.
48 template <typename... ArgTypes>
49 178636 decltype(auto) vector_path(ArgTypes &&...args) KLEIDICV_STREAMING {
50 178636 return operation().vector_path(std::forward<ArgTypes>(args)...);
51 }
52
53 // Forwards remaining_path() calls to the inner operation.
54 template <typename... ArgTypes>
55 decltype(auto) remaining_path(ArgTypes &&...args) KLEIDICV_STREAMING {
56 return operation().remaining_path(std::forward<ArgTypes>(args)...);
57 }
58
59 // Forwards tail_path() calls to the inner operation.
60 template <typename... ArgTypes>
61 454 decltype(auto) tail_path(ArgTypes &&...args) KLEIDICV_STREAMING {
62 454 return operation().tail_path(std::forward<ArgTypes>(args)...);
63 }
64
65 // Forwards scalar_path() calls to the inner operation.
66 template <typename... ArgTypes>
67 decltype(auto) scalar_path(ArgTypes &&...args) KLEIDICV_STREAMING {
68 return operation().scalar_path(std::forward<ArgTypes>(args)...);
69 }
70
71 template <typename... ArgTypes>
72 30432 decltype(auto) load(ArgTypes &&...args) KLEIDICV_STREAMING {
73 30432 return VecTraits::load(std::forward<ArgTypes>(args)...);
74 }
75
76 template <typename... ArgTypes>
77 399933 decltype(auto) load_consecutive(ArgTypes &&...args) KLEIDICV_STREAMING {
78 399933 return VecTraits::load_consecutive(std::forward<ArgTypes>(args)...);
79 }
80
81 template <typename... ArgTypes>
82 28724 decltype(auto) store(ArgTypes &&...args) KLEIDICV_STREAMING {
83 28724 return VecTraits::store(std::forward<ArgTypes>(args)...);
84 }
85
86 template <typename... ArgTypes>
87 108089 decltype(auto) store_consecutive(ArgTypes &&...args) KLEIDICV_STREAMING {
88 108089 return VecTraits::store_consecutive(std::forward<ArgTypes>(args)...);
89 }
90
91 // Forwards max_vectors_per_block() calls to the inner operation.
92 4635 size_t max_vectors_per_block() KLEIDICV_STREAMING {
93 4635 return operation_.max_vectors_per_block();
94 }
95
96 // Forwards on_block_finished() calls to the inner operation.
97 12915 void on_block_finished(size_t vectors_in_block) KLEIDICV_STREAMING {
98 12915 return operation_.on_block_finished(vectors_in_block);
99 }
100
101 // Returns true if the innermost operation is unrolled twice, otherwise false.
102 static constexpr bool is_unrolled_twice() KLEIDICV_STREAMING {
103 return ::KLEIDICV_TARGET_NAMESPACE::is_unrolled_twice<
104 concrete_operation_type_t<OperationType>>;
105 }
106
107 // Returns true if the innermost operation is unrolled once, otherwise false.
108 static constexpr bool is_unrolled_once() KLEIDICV_STREAMING {
109 return ::KLEIDICV_TARGET_NAMESPACE::is_unrolled_once<
110 concrete_operation_type_t<OperationType>>;
111 }
112
113 // Returns true if the innermost operation uses tail path, otherwise false.
114 static constexpr bool uses_tail_path() KLEIDICV_STREAMING {
115 return ::KLEIDICV_TARGET_NAMESPACE::uses_tail_path<
116 concrete_operation_type_t<OperationType>>;
117 }
118
119 // Returns true if the innermost operation tries to avoid tail loop, otherwise
120 // false.
121 static constexpr bool try_to_avoid_tail_loop() KLEIDICV_STREAMING {
122 return ::KLEIDICV_TARGET_NAMESPACE::try_to_avoid_tail_loop<
123 concrete_operation_type_t<OperationType>>;
124 }
125
126 protected:
127 // Constructor is protected so that only derived classes can instantiate.
128 103206 explicit OperationBase(OperationType &operation) KLEIDICV_STREAMING
129 103206 : operation_{operation} {}
130
131 private:
132 // Reference to the inner operation.
133 OperationType &operation_;
134 }; // end of class OperationBase<OperationType>
135
136 // Mixin which simply forwards all operations as-is.
137 template <typename OperationType>
138 class ForwardingOperation : public OperationBase<OperationType> {
139 public:
140 13616 explicit ForwardingOperation(OperationType &operation) KLEIDICV_STREAMING
141 13616 : OperationBase<OperationType>(operation) {}
142 }; // end of class ForwardingOperation<OperationType>
143
144 // Facade to offer a simplified row-based operation interface.
145 //
146 // A row-based operation is executed row-by-row and is unrolled within the row.
147 //
148 // Facade layout:
149 // |- operation.vector_path_<N>x()
150 // process_row() -|- operation.vector_path()
151 // |- operation.remaining_path()
152 // |- operation.num_lanes()
153 template <typename OperationType>
154 class RowBasedOperation : public OperationBase<OperationType> {
155 public:
156 19930 explicit RowBasedOperation(OperationType &operation) KLEIDICV_STREAMING
157 19930 : OperationBase<OperationType>(operation) {}
158
159 // NOLINTBEGIN(cppcoreguidelines-avoid-goto, hicpp-avoid-goto)
160 template <typename... ColumnTypes>
161 31673 void process_row(size_t length, ColumnTypes... columns) KLEIDICV_STREAMING {
162 31673 LoopUnroll loop{length, this->num_lanes()};
163
164 // clang-format off
165
166 31673 loop.unroll_twice_if<OperationType::is_unrolled_twice()>(
167 154358 [&](size_t step) KLEIDICV_STREAMING {
168 122685 this->operation().vector_path_2x(columns...);
169 122685 ((columns += step), ...);
170 122685 });
171
172 avoid_tail_loop:
173
174 31866 loop.unroll_once_if<OperationType::is_unrolled_once()>(
175 49112 [&](size_t step) KLEIDICV_STREAMING {
176 17246 this->operation().vector_path(columns...);
177 17246 ((columns += step), ...);
178 17246 });
179
180 // Process leftover bytes on the unrolled-once vector path, if requested and
181 // possible.
182 if constexpr (OperationType::is_unrolled_once() && OperationType::try_to_avoid_tail_loop()) {
183
8/8
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 440 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 340 times.
✓ Branch 4 taken 42 times.
✓ Branch 5 taken 340 times.
✓ Branch 6 taken 42 times.
✓ Branch 7 taken 340 times.
1653 if (loop.try_avoid_tail_loop(
184 1846 [&](size_t backward_step) KLEIDICV_STREAMING {
185 // Adjust pointers backwards to include
186 // the leftover bytes.
187 193 ((columns -= backward_step), ...);
188 193 })) {
189 193 goto avoid_tail_loop;
190 }
191 }
192
193 31673 loop.remaining(
194 56742 [&](size_t length, size_t /* step */) KLEIDICV_STREAMING {
195 25069 this->operation().remaining_path(length, columns...);
196 25069 });
197
198 // clang-format on
199 31673 }
200 // NOLINTEND(cppcoreguidelines-avoid-goto, hicpp-avoid-goto)
201 }; // end of class RowBasedOperation<OperationType>
202
203 // Facade to offer a simplified row-based operation interface.
204 //
205 // A row-based operation is executed row-by-row, is unrolled within the row and
206 // split into blocks.
207 //
208 // Facade layout:
209 // |- operation.vector_path_<N>x()
210 // process_row() -|- operation.vector_path()
211 // |- operation.remaining_path()
212 // |- operation.num_lanes()
213 // |- operation.max_vectors_per_block()
214 // |- operation.on_block_finished()
215 template <typename OperationType>
216 class RowBasedBlockOperation : public OperationBase<OperationType> {
217 public:
218 468 explicit RowBasedBlockOperation(OperationType &operation) KLEIDICV_STREAMING
219 468 : OperationBase<OperationType>(operation) {}
220
221 template <typename... ColumnTypes>
222 927 void process_row(size_t length, ColumnTypes... columns) KLEIDICV_STREAMING {
223 if constexpr (OperationType::is_unrolled_twice()) {
224 224739 process_blocks<2>(length, [&](size_t step) KLEIDICV_STREAMING {
225 223812 this->operation().vector_path_2x(columns...);
226 223812 ((columns += step), ...);
227 223812 });
228 }
229
230 if constexpr (OperationType::is_unrolled_once()) {
231 process_blocks<1>(length, [&](size_t step) KLEIDICV_STREAMING {
232 this->operation().vector_path(columns...);
233 ((columns += step), ...);
234 });
235 }
236
237 // clang-format off
238 927 LoopUnroll loop{length, this->num_lanes()};
239 927 loop.remaining(
240 1644 [&](size_t length, size_t /* step */) KLEIDICV_STREAMING {
241 717 this->operation().remaining_path(length, columns...);
242 717 });
243 // clang-format on
244 927 }
245
246 private:
247 template <size_t UnrollFactor, typename CallbackType>
248 927 void process_blocks(size_t &length,
249 CallbackType callback) KLEIDICV_STREAMING {
250 // The number of elements a single iteration would process.
251 927 const size_t elements_per_iteration = UnrollFactor * this->num_lanes();
252 // The number of elements which will be processed when this method returns.
253 1854 const size_t processed_length =
254 927 (length / elements_per_iteration) * elements_per_iteration;
255 // The number of vectors which can be processed safely with the current
256 // unroll factor.
257 1854 const size_t max_vectors_per_block =
258 927 (this->max_vectors_per_block() / UnrollFactor) * UnrollFactor;
259
260 // Process data up to allowed number of blocks.
261
2/2
✓ Branch 0 taken 927 times.
✓ Branch 1 taken 2583 times.
3510 for (size_t index = 0, block_length = 0; index < processed_length;
262 2583 index += block_length) {
263 // Process max_vectors_per_block vectors, or less in the last iteration
264 // (remaining size).
265 2583 size_t remaining_vectors = (processed_length - index) / this->num_lanes();
266 5166 size_t vectors_in_block =
267 2583 std::min(max_vectors_per_block, remaining_vectors);
268 2583 block_length = vectors_in_block * this->num_lanes();
269
270 // clang-format off
271 // Process data with the appropriate unroll factor.
272 2583 LoopUnroll loop{block_length, this->num_lanes()};
273 2583 loop.unroll_n_times<UnrollFactor>(
274 226395 [&](size_t step) KLEIDICV_STREAMING {
275 223812 callback(step);
276 // Adjust remaining length here.
277 // This improves generated code.
278 223812 length -= step;
279 223812 });
280 // clang-format on
281
282 // Notify the operation that a block was processed.
283 2583 this->on_block_finished(vectors_in_block);
284 2583 }
285 927 }
286 }; // end of class RowBasedBlockOperation<OperationType>
287
288 // Adapter to offer an interface which allows users to use ParallelRows and to
289 // unpack them.
290 template <typename OperationType>
291 class ParallelRowsAdapter : public OperationBase<OperationType> {
292 public:
293 using VecTraits = typename OperationBase<OperationType>::VecTraits;
294 using ScalarType = typename VecTraits::ScalarType;
295 using ConstParallelColumnType = ParallelColumns<const ScalarType>;
296 using ParallelColumnType = ParallelColumns<ScalarType>;
297 using ConstColumnType = Columns<const ScalarType>;
298
299 1216 explicit ParallelRowsAdapter(OperationType &operation) KLEIDICV_STREAMING
300 1216 : OperationBase<OperationType>(operation) {}
301
302 // Forwards vector_path_2x() calls to the inner operation with one source and
303 // destination parallel columns.
304 void vector_path_2x(ConstParallelColumnType src_a, ConstColumnType src_b,
305 ParallelColumnType dst) KLEIDICV_STREAMING {
306 this->operation().vector_path_2x(src_a.first(), src_a.second(), src_b,
307 dst.first(), dst.second());
308 }
309
310 // Forwards vector_path() calls to the inner operation with one source and
311 // destination parallel columns.
312 96 void vector_path(ConstParallelColumnType src_a, ConstColumnType src_b,
313 ParallelColumnType dst) KLEIDICV_STREAMING {
314 192 this->operation().vector_path(src_a.first(), src_a.second(), src_b,
315 96 dst.first(), dst.second());
316 96 }
317
318 // Forwards remaining_path() calls to the inner operation with one source and
319 // destination parallel columns.
320 2768 void remaining_path(size_t length, ConstParallelColumnType src_a,
321 ConstColumnType src_b,
322 ParallelColumnType dst) KLEIDICV_STREAMING {
323 5536 this->operation().remaining_path(length, src_a.first(), src_a.second(),
324 2768 src_b, dst.first(), dst.second());
325 2768 }
326 }; // end of class ParallelRowsAdapter<OperationType>
327
328 // Adapter to offer an interface which allows users to apply unrolling to the
329 // adaptee operation. This adapter binds to the interface of the innermost
330 // operation in the chain.
331 //
332 // Provides specialized implementations using SFINAE principle for
333 // - vector_path_2x(),
334 // - vector_path(), and
335 // - tail_path(), and
336 // - scalar_path()
337 // methods.
338 template <typename OperationType>
339 class OperationAdapter : public OperationBase<OperationType> {
340 // Shorten rows: no need to write 'this->'.
341 using OperationBase<OperationType>::operation;
342 using OperationBase<OperationType>::num_lanes;
343 using OperationBase<OperationType>::load;
344 using OperationBase<OperationType>::load_consecutive;
345 using OperationBase<OperationType>::store;
346 using OperationBase<OperationType>::store_consecutive;
347 // The innermost operation in the chain.
348 using ConcreteOperationType = concrete_operation_type_t<OperationType>;
349
350 public:
351 using VecTraits = typename OperationBase<OperationType>::VecTraits;
352 using ContextType = typename OperationBase<OperationType>::ContextType;
353 using ScalarType = typename VecTraits::ScalarType;
354 using VectorType = typename VecTraits::VectorType;
355 using Vector2Type = typename VecTraits::Vector2Type;
356 using Vector3Type = typename VecTraits::Vector3Type;
357 using Vector4Type = typename VecTraits::Vector4Type;
358 using ConstColumnType = Columns<const ScalarType>;
359 using ColumnType = Columns<ScalarType>;
360
361 20398 explicit OperationAdapter(OperationType &operation) KLEIDICV_STREAMING
362 20398 : OperationBase<OperationType>(operation) {}
363
364 // ---------------------------------------------------------------------------
365 // Forwarding implementations for vector_path_2x().
366 // ---------------------------------------------------------------------------
367
368 // Required method:
369 // void T::vector_path([ContextType,] VectorType);
370 template <typename T = ConcreteOperationType>
371 229344 enable_if_has_vector_path_t<void, T, ContextType, VectorType> vector_path_2x(
372 ContextType ctx, ConstColumnType src) KLEIDICV_STREAMING {
373 229344 VectorType src_0, src_1;
374 229344 operation().load_consecutive(ctx, &src[0], src_0, src_1);
375 229344 operation().vector_path(ctx, src_0);
376 229344 operation().vector_path(ctx, src_1);
377 229344 }
378
379 // Required method:
380 // VectorType T::vector_path([ContextType,] VectorType);
381 template <typename T = ConcreteOperationType>
382 enable_if_has_vector_path_t<VectorType, T, ContextType, VectorType>
383 58883 vector_path_2x(ContextType ctx, ConstColumnType src,
384 ColumnType dst) KLEIDICV_STREAMING {
385 58883 VectorType src_0, src_1;
386 58883 operation().load_consecutive(ctx, &src[0], src_0, src_1);
387 58883 VectorType res_0 = operation().vector_path(ctx, src_0);
388 58883 VectorType res_1 = operation().vector_path(ctx, src_1);
389 58883 operation().store_consecutive(ctx, res_0, res_1, &dst[0]);
390 58883 }
391
392 // Required method:
393 // VectorType T::vector_path([ContextType,] VectorType, VectorType);
394 template <typename T = ConcreteOperationType>
395 enable_if_has_vector_path_t<VectorType, T, ContextType, VectorType,
396 VectorType>
397 49206 vector_path_2x(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
398 ColumnType dst) KLEIDICV_STREAMING {
399 49206 VectorType src_a_0, src_a_1, src_b_0, src_b_1;
400 49206 operation().load_consecutive(ctx, &src_a[0], src_a_0, src_a_1);
401 49206 operation().load_consecutive(ctx, &src_b[0], src_b_0, src_b_1);
402 49206 VectorType res_0 = operation().vector_path(ctx, src_a_0, src_b_0);
403 49206 VectorType res_1 = operation().vector_path(ctx, src_a_1, src_b_1);
404 49206 operation().store_consecutive(ctx, res_0, res_1, &dst[0]);
405 49206 }
406
407 // Required method:
408 // void T::vector_path([ContextType,] VectorType, ScalarType *);
409 template <typename T = ConcreteOperationType>
410 enable_if_has_vector_path_t<void, T, ContextType, VectorType, ScalarType *>
411 1006 vector_path_2x(ContextType ctx, ConstColumnType src,
412 ColumnType dst) KLEIDICV_STREAMING {
413 1006 VectorType src_0, src_1;
414 1006 operation().load_consecutive(ctx, &src[0], src_0, src_1);
415 1006 operation().vector_path(ctx, src_0, &dst[0]);
416 1006 operation().vector_path(ctx, src_1, &dst.at(num_lanes())[0]);
417 1006 }
418
419 // Required method:
420 // void T::vector_path([ContextType,] VectorType, VectorType, ScalarType *);
421 template <typename T = ConcreteOperationType>
422 enable_if_has_vector_path_t<void, T, ContextType, VectorType, VectorType,
423 ScalarType *>
424 480 vector_path_2x(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
425 ColumnType dst) KLEIDICV_STREAMING {
426 480 VectorType src_a_0, src_a_1, src_b_0, src_b_1;
427 480 operation().load_consecutive(ctx, &src_a[0], src_a_0, src_a_1);
428 480 operation().load_consecutive(ctx, &src_b[0], src_b_0, src_b_1);
429 480 operation().vector_path(ctx, src_a_0, src_b_0, &dst[0]);
430 480 operation().vector_path(ctx, src_a_1, src_b_1, &dst.at(num_lanes())[0]);
431 480 }
432
433 // Required method:
434 // void T::vector_path([ContextType,] VectorType, VectorType, VectorType,
435 // ScalarType *);
436 template <typename T = ConcreteOperationType>
437 enable_if_has_vector_path_t<void, T, ContextType, VectorType, VectorType,
438 VectorType, ScalarType *>
439 864 vector_path_2x(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
440 ConstColumnType src_c, ColumnType dst) KLEIDICV_STREAMING {
441 864 VectorType src_a_0, src_a_1, src_b_0, src_b_1, src_c_0, src_c_1;
442 864 operation().load_consecutive(ctx, &src_a[0], src_a_0, src_a_1);
443 864 operation().load_consecutive(ctx, &src_b[0], src_b_0, src_b_1);
444 864 operation().load_consecutive(ctx, &src_c[0], src_c_0, src_c_1);
445 864 operation().vector_path(ctx, src_a_0, src_b_0, src_c_0, &dst[0]);
446 1728 operation().vector_path(ctx, src_a_1, src_b_1, src_c_1,
447 864 &dst.at(num_lanes())[0]);
448 864 }
449
450 // Required method:
451 // void T::vector_path([ContextType,] VectorType, VectorType, VectorType,
452 // ScalarType *,
453 // ScalarType *);
454 template <typename T = ConcreteOperationType>
455 enable_if_has_vector_path_t<void, T, ContextType, VectorType, VectorType,
456 VectorType, ScalarType *, ScalarType *>
457 vector_path_2x(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
458 ConstColumnType src_c, ColumnType dst_a,
459 ColumnType dst_b) KLEIDICV_STREAMING {
460 VectorType src_a_0, src_a_1, src_b_0, src_b_1, src_c_0, src_c_1;
461 operation().load_consecutive(ctx, &src_a[0], src_a_0, src_a_1);
462 operation().load_consecutive(ctx, &src_b[0], src_b_0, src_b_1);
463 operation().load_consecutive(ctx, &src_c[0], src_c_0, src_c_1);
464 operation().vector_path(ctx, src_a_0, src_b_0, src_c_0, &dst_a[0],
465 &dst_b[0]);
466 operation().vector_path(ctx, src_a_1, src_b_1, src_c_1,
467 &dst_a.at(num_lanes())[0],
468 &dst_b.at(num_lanes())[0]);
469 }
470
471 // Required method:
472 // void T::vector_path([ContextType,] VectorType, VectorType, VectorType,
473 // VectorType,
474 // ScalarType *);
475 template <typename T = ConcreteOperationType>
476 enable_if_has_vector_path_t<void, T, ContextType, VectorType, VectorType,
477 VectorType, VectorType, ScalarType *>
478 1632 vector_path_2x(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
479 ConstColumnType src_c, ConstColumnType src_d,
480 ColumnType dst) KLEIDICV_STREAMING {
481 1632 VectorType src_a_0, src_a_1, src_b_0, src_b_1;
482 1632 VectorType src_c_0, src_c_1, src_d_0, src_d_1;
483 1632 operation().load_consecutive(ctx, &src_a[0], src_a_0, src_a_1);
484 1632 operation().load_consecutive(ctx, &src_b[0], src_b_0, src_b_1);
485 1632 operation().load_consecutive(ctx, &src_c[0], src_c_0, src_c_1);
486 1632 operation().load_consecutive(ctx, &src_d[0], src_d_0, src_d_1);
487 1632 operation().vector_path(ctx, src_a_0, src_b_0, src_c_0, src_d_0, &dst[0]);
488 3264 operation().vector_path(ctx, src_a_1, src_b_1, src_c_1, src_d_1,
489 1632 &dst.at(num_lanes())[0]);
490 1632 }
491
492 // Required method:
493 // void T::vector_path([ContextType,] const ScalarType *, ScalarType *);
494 template <typename T = ConcreteOperationType>
495 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
496 ScalarType *>
497 2874 vector_path_2x(ContextType ctx, ConstColumnType src,
498 ColumnType dst) KLEIDICV_STREAMING {
499 2874 operation().vector_path(ctx, &src[0], &dst[0]);
500 5748 operation().vector_path(ctx, &src.at(num_lanes())[0],
501 2874 &dst.at(num_lanes())[0]);
502 2874 }
503
504 // Required method:
505 // void T::vector_path([ContextType,] const ScalarType *, ScalarType *);
506 template <typename T = ConcreteOperationType>
507 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
508 const ScalarType *, ScalarType *>
509 vector_path_2x(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
510 ColumnType dst) KLEIDICV_STREAMING {
511 operation().vector_path(ctx, &src_a[0], &src_b[0], &dst[0]);
512 operation().vector_path(ctx, &src_a.at(num_lanes())[0],
513 &src_b.at(num_lanes())[0], &dst.at(num_lanes())[0]);
514 }
515
516 // Required method:
517 // void T::vector_path([ContextType,] const ScalarType *, const ScalarType *,
518 // const ScalarType *, ScalarType *, ScalarType *);
519 template <typename T = ConcreteOperationType>
520 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
521 const ScalarType *, const ScalarType *,
522 ScalarType *, ScalarType *>
523 vector_path_2x(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
524 ConstColumnType src_c, ColumnType dst_a,
525 ColumnType dst_b) KLEIDICV_STREAMING {
526 operation().vector_path(ctx, &src_a[0], &src_b[0], &src_c[0], &dst_a[0],
527 &dst_b[0]);
528 operation().vector_path(
529 ctx, &src_a.at(num_lanes())[0], &src_b.at(num_lanes())[0],
530 &src_c.at(num_lanes())[0], &dst_a.at(num_lanes())[0],
531 &dst_b.at(num_lanes())[0]);
532 }
533
534 // Required method:
535 // void T::vector_path([ContextType,] const ScalarType *, ScalarType *,
536 // ScalarType *);
537 template <typename T = ConcreteOperationType>
538 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
539 ScalarType *, ScalarType *>
540 vector_path_2x(ContextType ctx, ConstColumnType src, ColumnType dst_a,
541 ColumnType dst_b) KLEIDICV_STREAMING {
542 operation().vector_path(ctx, &src[0], &dst_a[0], &dst_b[0]);
543 operation().vector_path(ctx, &src.at(num_lanes())[0],
544 &dst_a.at(num_lanes())[0],
545 &dst_b.at(num_lanes())[0]);
546 }
547
548 // Required method:
549 // void T::vector_path([ContextType,] const ScalarType *, VectorType &,
550 // VectorType &);
551 template <typename T = ConcreteOperationType>
552 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
553 VectorType &, VectorType &>
554 vector_path_2x(ContextType ctx, ConstColumnType src, ColumnType dst_a,
555 ColumnType dst_b) KLEIDICV_STREAMING {
556 Vector2Type vdst_a, vdst_b;
557
558 operation().vector_path(ctx, &src[0], vdst_a.val[0], vdst_b.val[0]);
559 operation().vector_path(ctx, &src.at(num_lanes() * 2)[0], vdst_a.val[1],
560 vdst_b.val[1]);
561
562 store(vdst_a, &dst_a[0]);
563 store(vdst_b, &dst_b[0]);
564 }
565
566 // Required method:
567 // void T::vector_path([ContextType,] Vector2Type,
568 // VectorType &, VectorType &);
569 template <typename T = ConcreteOperationType>
570 enable_if_has_vector_path_t<void, T, ContextType, Vector2Type, VectorType &,
571 VectorType &>
572 480 vector_path_2x(ContextType ctx, ConstColumnType src, ColumnType dst_a,
573 ColumnType dst_b) KLEIDICV_STREAMING {
574 480 Vector2Type vsrc_0, vsrc_1;
575 480 Vector2Type vdst_a, vdst_b;
576
577 480 load_consecutive(&src[0], vsrc_0, vsrc_1);
578
579 480 operation().vector_path(ctx, vsrc_0, vdst_a.val[0], vdst_b.val[0]);
580 480 operation().vector_path(ctx, vsrc_1, vdst_a.val[1], vdst_b.val[1]);
581
582 480 store(vdst_a, &dst_a[0]);
583 480 store(vdst_b, &dst_b[0]);
584 480 }
585
586 // Required method:
587 // void T::vector_path([ContextType,] const ScalarType *, ScalarType *,
588 // ScalarType *, ScalarType *);
589 template <typename T = ConcreteOperationType>
590 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
591 ScalarType *, ScalarType *, ScalarType *>
592 vector_path_2x(ContextType ctx, ConstColumnType src, ColumnType dst_a,
593 ColumnType dst_b, ColumnType dst_c) KLEIDICV_STREAMING {
594 operation().vector_path(ctx, &src[0], &dst_a[0], &dst_b[0], &dst_c[0]);
595 operation().vector_path(
596 ctx, &src.at(num_lanes() * 3)[0], &dst_a.at(num_lanes())[0],
597 &dst_b.at(num_lanes())[0], &dst_c.at(num_lanes())[0]);
598 }
599
600 // Required method:
601 // void T::vector_path([ContextType,] const ScalarType *, VectorType &,
602 // VectorType &, VectorType &);
603 template <typename T = ConcreteOperationType>
604 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
605 VectorType &, VectorType &, VectorType &>
606 vector_path_2x(ContextType ctx, ConstColumnType src, ColumnType dst_a,
607 ColumnType dst_b, ColumnType dst_c) KLEIDICV_STREAMING {
608 Vector2Type vdst_a, vdst_b, vdst_c;
609
610 operation().vector_path(ctx, &src[0], vdst_a.val[0], vdst_b.val[0],
611 vdst_c.val[0]);
612 operation().vector_path(ctx, &src.at(num_lanes() * 3)[0], vdst_a.val[1],
613 vdst_b.val[1], vdst_c.val[1]);
614
615 store(vdst_a, &dst_a[0]);
616 store(vdst_b, &dst_b[0]);
617 store(vdst_c, &dst_c[0]);
618 }
619
620 // Required method:
621 // void T::vector_path([ContextType,] , Vector3Type , VectorType &
622 // VectorType &, VectorType &);
623 template <typename T = ConcreteOperationType>
624 enable_if_has_vector_path_t<void, T, ContextType, Vector3Type, VectorType &,
625 VectorType &, VectorType &>
626 864 vector_path_2x(ContextType ctx, ConstColumnType src, ColumnType dst_a,
627 ColumnType dst_b, ColumnType dst_c) KLEIDICV_STREAMING {
628 864 Vector3Type vsrc_0, vsrc_1;
629 864 Vector2Type vdst_a, vdst_b, vdst_c;
630
631 864 load_consecutive(&src[0], vsrc_0, vsrc_1);
632
633 1728 operation().vector_path(ctx, vsrc_0, vdst_a.val[0], vdst_b.val[0],
634 864 vdst_c.val[0]);
635 1728 operation().vector_path(ctx, vsrc_1, vdst_a.val[1], vdst_b.val[1],
636 864 vdst_c.val[1]);
637
638 864 store(vdst_a, &dst_a[0]);
639 864 store(vdst_b, &dst_b[0]);
640 864 store(vdst_c, &dst_c[0]);
641 864 }
642
643 // Required method:
644 // void T::vector_path([ContextType,] const ScalarType *, ScalarType *,
645 // ScalarType *, ScalarType *, ScalarType *);
646 template <typename T = ConcreteOperationType>
647 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
648 ScalarType *, ScalarType *, ScalarType *,
649 ScalarType *>
650 vector_path_2x(ContextType ctx, ConstColumnType src, ColumnType dst_a,
651 ColumnType dst_b, ColumnType dst_c,
652 ColumnType dst_d) KLEIDICV_STREAMING {
653 operation().vector_path(ctx, &src[0], &dst_a[0], &dst_b[0], &dst_c[0],
654 &dst_d[0]);
655 operation().vector_path(
656 ctx, &src.at(num_lanes() * 4)[0], &dst_a.at(num_lanes())[0],
657 &dst_b.at(num_lanes())[0], &dst_c.at(num_lanes())[0],
658 &dst_d.at(num_lanes())[0]);
659 }
660
661 // Required method:
662 // void T::vector_path([ContextType,] const ScalarType *,
663 // VectorType &, VectorType &, VectorType &,
664 // VectorType &);
665 // Operation with multiple destination address, and with store. This
666 // gives the possibility to store the 2 result vectors in 1 step
667 template <typename T = ConcreteOperationType>
668 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
669 VectorType &, VectorType &, VectorType &,
670 VectorType &>
671 vector_path_2x(ContextType ctx, ConstColumnType src, ColumnType dst_a,
672 ColumnType dst_b, ColumnType dst_c,
673 ColumnType dst_d) KLEIDICV_STREAMING {
674 Vector2Type vdst_a, vdst_b, vdst_c, vdst_d;
675
676 operation().vector_path(ctx, &src[0], vdst_a.val[0], vdst_b.val[0],
677 vdst_c.val[0], vdst_d.val[0]);
678
679 operation().vector_path(ctx, &src.at(num_lanes() * 4)[0], vdst_a.val[1],
680 vdst_b.val[1], vdst_c.val[1], vdst_d.val[1]);
681
682 store(vdst_a, &dst_a[0]);
683 store(vdst_b, &dst_b[0]);
684 store(vdst_c, &dst_c[0]);
685 store(vdst_d, &dst_d[0]);
686 }
687
688 // Required method:
689 // void T::vector_path([ContextType,] const Vector4Type
690 // VectorType &, VectorType &, VectorType &,
691 // VectorType &);
692 // Operation with multiple destination address, and with load and store.
693 // This gives the possibility to load the source x4 vectors and store
694 // the 2x4 result vectors in 1 step
695 template <typename T = ConcreteOperationType>
696 enable_if_has_vector_path_t<void, T, ContextType, const Vector4Type,
697 VectorType &, VectorType &, VectorType &,
698 VectorType &>
699 864 vector_path_2x(ContextType ctx, ConstColumnType src, ColumnType dst_a,
700 ColumnType dst_b, ColumnType dst_c,
701 ColumnType dst_d) KLEIDICV_STREAMING {
702 864 Vector4Type vsrc_0, vsrc_1;
703 864 Vector2Type vdst_a, vdst_b, vdst_c, vdst_d;
704
705 864 load_consecutive(&src[0], vsrc_0, vsrc_1);
706
707 1728 operation().vector_path(ctx, vsrc_0, vdst_a.val[0], vdst_b.val[0],
708 864 vdst_c.val[0], vdst_d.val[0]);
709
710 1728 operation().vector_path(ctx, vsrc_1, vdst_a.val[1], vdst_b.val[1],
711 864 vdst_c.val[1], vdst_d.val[1]);
712
713 864 store(vdst_a, &dst_a[0]);
714 864 store(vdst_b, &dst_b[0]);
715 864 store(vdst_c, &dst_c[0]);
716 864 store(vdst_d, &dst_d[0]);
717 864 }
718
719 // ---------------------------------------------------------------------------
720 // Forwarding implementations for vector_path().
721 // ---------------------------------------------------------------------------
722
723 // Required method:
724 // void T::vector_path([ContextType,] VectorType);
725 template <typename T = ConcreteOperationType>
726 3284 enable_if_has_vector_path_t<void, T, ContextType, VectorType> vector_path(
727 ContextType ctx, ConstColumnType src) KLEIDICV_STREAMING {
728 3284 VectorType src_0;
729 3284 operation().load(ctx, &src[0], src_0);
730 3284 operation().vector_path(ctx, src_0);
731 3284 }
732
733 // Required method:
734 // VectorType T::vector_path([ContextType,] VectorType);
735 template <typename T = ConcreteOperationType>
736 enable_if_has_vector_path_t<VectorType, T, ContextType, VectorType>
737 16812 vector_path(ContextType ctx, ConstColumnType src,
738 ColumnType dst) KLEIDICV_STREAMING {
739 16812 VectorType src_0;
740 16812 operation().load(ctx, &src[0], src_0);
741 16812 VectorType res_0 = operation().vector_path(ctx, src_0);
742 16812 operation().store(ctx, res_0, &dst[0]);
743 16812 }
744
745 // Required method:
746 // VectorType T::vector_path([ContextType,] VectorType, VectorType);
747 template <typename T = ConcreteOperationType>
748 enable_if_has_vector_path_t<VectorType, T, ContextType, VectorType,
749 VectorType>
750 4904 vector_path(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
751 ColumnType dst) KLEIDICV_STREAMING {
752 4904 VectorType src_a_0, src_b_0;
753 4904 operation().load(ctx, &src_a[0], src_a_0);
754 4904 operation().load(ctx, &src_b[0], src_b_0);
755 4904 VectorType res_0 = operation().vector_path(ctx, src_a_0, src_b_0);
756 4904 operation().store(ctx, res_0, &dst[0]);
757 4904 }
758
759 // Required method:
760 // void T::vector_path([ContextType,] VectorType, ScalarType *);
761 template <typename T = ConcreteOperationType>
762 enable_if_has_vector_path_t<void, T, ContextType, VectorType, ScalarType *>
763 4 vector_path(ContextType ctx, ConstColumnType src,
764 ColumnType dst) KLEIDICV_STREAMING {
765 4 VectorType src_0;
766 4 operation().load(ctx, &src[0], src_0);
767 4 operation().vector_path(ctx, src_0, &dst[0]);
768 4 }
769
770 // Required method:
771 // void T::vector_path([ContextType,] VectorType, VectorType, ScalarType *);
772 template <typename T = ConcreteOperationType>
773 enable_if_has_vector_path_t<void, T, ContextType, VectorType, VectorType,
774 ScalarType *>
775 vector_path(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
776 ColumnType dst) KLEIDICV_STREAMING {
777 VectorType src_a_0, src_b_0;
778 operation().load(ctx, &src_a[0], src_a_0);
779 operation().load(ctx, &src_b[0], src_b_0);
780 operation().vector_path(ctx, src_a_0, src_b_0, &dst[0]);
781 }
782
783 // Required method:
784 // void T::vector_path([ContextType,] VectorType, VectorType, VectorType,
785 // ScalarType *);
786 template <typename T = ConcreteOperationType>
787 enable_if_has_vector_path_t<void, T, ContextType, VectorType, VectorType,
788 VectorType, ScalarType *>
789 vector_path(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
790 ConstColumnType src_c, ColumnType dst) KLEIDICV_STREAMING {
791 VectorType src_a_0, src_b_0, src_c_0;
792 operation().load(ctx, &src_a[0], src_a_0);
793 operation().load(ctx, &src_b[0], src_b_0);
794 operation().load(ctx, &src_c[0], src_c_0);
795 operation().vector_path(ctx, src_a_0, src_b_0, src_c_0, &dst[0]);
796 }
797
798 // Required method:
799 // void T::vector_path([ContextType,] VectorType, VectorType, VectorType,
800 // ScalarType *, ScalarType *);
801 template <typename T = ConcreteOperationType>
802 enable_if_has_vector_path_t<void, T, ContextType, VectorType, VectorType,
803 VectorType, ScalarType *, ScalarType *>
804 96 vector_path(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
805 ConstColumnType src_c, ColumnType dst_a,
806 ColumnType dst_b) KLEIDICV_STREAMING {
807 96 VectorType src_a_0, src_b_0, src_c_0;
808 96 operation().load(ctx, &src_a[0], src_a_0);
809 96 operation().load(ctx, &src_b[0], src_b_0);
810 96 operation().load(ctx, &src_c[0], src_c_0);
811 192 operation().vector_path(ctx, src_a_0, src_b_0, src_c_0, &dst_a[0],
812 96 &dst_b[0]);
813 96 }
814
815 // Required method:
816 // void T::vector_path([ContextType,] VectorType, VectorType, VectorType,
817 // VectorType, ScalarType *);
818 template <typename T = ConcreteOperationType>
819 enable_if_has_vector_path_t<void, T, ContextType, VectorType, VectorType,
820 VectorType, VectorType, ScalarType *>
821 vector_path(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
822 ConstColumnType src_c, ConstColumnType src_d,
823 ColumnType dst) KLEIDICV_STREAMING {
824 VectorType src_a_0, src_b_0, src_c_0, src_d_0;
825 operation().load(ctx, &src_a[0], src_a_0);
826 operation().load(ctx, &src_b[0], src_b_0);
827 operation().load(ctx, &src_c[0], src_c_0);
828 operation().load(ctx, &src_d[0], src_d_0);
829 operation().vector_path(ctx, src_a_0, src_b_0, src_c_0, src_d_0, &dst[0]);
830 }
831
832 // Required method:
833 // void T::vector_path([ContextType,] const ScalarType *, ScalarType *);
834 template <typename T = ConcreteOperationType>
835 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
836 ScalarType *>
837 9736 vector_path(ContextType ctx, ConstColumnType src,
838 ColumnType dst) KLEIDICV_STREAMING {
839 9736 operation().vector_path(ctx, &src[0], &dst[0]);
840 9736 }
841
842 // Required method:
843 // void T::vector_path([ContextType,] const ScalarType *, const ScalarType *,
844 // ScalarType *);
845 template <typename T = ConcreteOperationType>
846 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
847 const ScalarType *, ScalarType *>
848 vector_path(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
849 ColumnType dst) KLEIDICV_STREAMING {
850 operation().vector_path(ctx, &src_a[0], &src_b[0], &dst[0]);
851 }
852
853 // Required method:
854 // void T::vector_path([ContextType,] const ScalarType *, const ScalarType *,
855 // const ScalarType *, ScalarType *, ScalarType *);
856 template <typename T = ConcreteOperationType>
857 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
858 const ScalarType *, const ScalarType *,
859 ScalarType *, ScalarType *>
860 2256 vector_path(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
861 ConstColumnType src_c, ColumnType dst_a,
862 ColumnType dst_b) KLEIDICV_STREAMING {
863 4512 operation().vector_path(ctx, &src_a[0], &src_b[0], &src_c[0], &dst_a[0],
864 2256 &dst_b[0]);
865 2256 }
866
867 // Required method:
868 // void T::vector_path([ContextType,] const ScalarType *, ScalarType *,
869 // ScalarType *);
870 template <typename T = ConcreteOperationType>
871 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
872 ScalarType *, ScalarType *>
873 vector_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
874 ColumnType dst_b) KLEIDICV_STREAMING {
875 operation().vector_path(ctx, &src[0], &dst_a[0], &dst_b[0]);
876 }
877
878 // Required method:
879 // void T::vector_path([ContextType,] const ScalarType *, VectorType &,
880 // VectorType &);
881 template <typename T = ConcreteOperationType>
882 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
883 VectorType &, VectorType &>
884 vector_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
885 ColumnType dst_b) KLEIDICV_STREAMING {
886 VectorType vdst_a, vdst_b;
887
888 operation().vector_path(ctx, &src[0], vdst_a, vdst_b);
889
890 store(vdst_a, &dst_a[0]);
891 store(vdst_b, &dst_b[0]);
892 }
893
894 // Required method:
895 // void T::vector_path([ContextType,] Vector2Type, VectorType &,
896 // VectorType &);
897 template <typename T = ConcreteOperationType>
898 enable_if_has_vector_path_t<void, T, ContextType, Vector2Type, VectorType &,
899 VectorType &>
900 vector_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
901 ColumnType dst_b) KLEIDICV_STREAMING {
902 VectorType vdst_a, vdst_b;
903 Vector2Type vsrc;
904
905 load(&src[0], vsrc);
906
907 operation().vector_path(ctx, vsrc, vdst_a, vdst_b);
908
909 store(vdst_a, &dst_a[0]);
910 store(vdst_b, &dst_b[0]);
911 }
912
913 // Required method:
914 // void T::vector_path([ContextType,] const ScalarType *, ScalarType *,
915 // ScalarType *, ScalarType *);
916 template <typename T = ConcreteOperationType>
917 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
918 ScalarType *, ScalarType *, ScalarType *>
919 vector_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
920 ColumnType dst_b, ColumnType dst_c) KLEIDICV_STREAMING {
921 operation().vector_path(ctx, &src[0], &dst_a[0], &dst_b[0], &dst_c[0]);
922 }
923
924 // Required method:
925 // void T::vector_path([ContextType,] const ScalarType *, VectorType &,
926 // VectorType &, VectorType &);
927 template <typename T = ConcreteOperationType>
928 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
929 VectorType &, VectorType &, VectorType &>
930 vector_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
931 ColumnType dst_b, ColumnType dst_c) KLEIDICV_STREAMING {
932 VectorType vdst_a, vdst_b, vdst_c;
933
934 operation().vector_path(ctx, &src[0], vdst_a, vdst_b, vdst_c);
935
936 store(vdst_a, &dst_a[0]);
937 store(vdst_b, &dst_b[0]);
938 store(vdst_c, &dst_c[0]);
939 }
940
941 // Required method:
942 // void T::vector_path([ContextType,] Vector3Type, VectorType &,
943 // VectorType &, VectorType &);
944 template <typename T = ConcreteOperationType>
945 enable_if_has_vector_path_t<void, T, ContextType, Vector3Type, VectorType &,
946 VectorType &, VectorType &>
947 vector_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
948 ColumnType dst_b, ColumnType dst_c) KLEIDICV_STREAMING {
949 VectorType vdst_a, vdst_b, vdst_c;
950 Vector3Type vsrc;
951
952 load(&src[0], vsrc);
953
954 operation().vector_path(ctx, vsrc, vdst_a, vdst_b, vdst_c);
955
956 store(vdst_a, &dst_a[0]);
957 store(vdst_b, &dst_b[0]);
958 store(vdst_c, &dst_c[0]);
959 }
960
961 // Required method:
962 // void T::vector_path([ContextType,] const ScalarType *, ScalarType *,
963 // ScalarType *, ScalarType *, ScalarType *);
964 // Operation type with multiple destination, store in the vectorpath
965 template <typename T = ConcreteOperationType>
966 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
967 ScalarType *, ScalarType *, ScalarType *,
968 ScalarType *>
969 vector_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
970 ColumnType dst_b, ColumnType dst_c,
971 ColumnType dst_d) KLEIDICV_STREAMING {
972 operation().vector_path(ctx, &src[0], &dst_a[0], &dst_b[0], &dst_c[0],
973 &dst_d[0]);
974 }
975
976 // Required method:
977 // void T::vector_path([ContextType,] const ScalarType *,
978 // VectorType &, VectorType &, VectorType &,
979 // VectorType &);
980 // Operation type with multiple destination, and with store
981 template <typename T = ConcreteOperationType>
982 enable_if_has_vector_path_t<void, T, ContextType, const ScalarType *,
983 VectorType &, VectorType &, VectorType &,
984 VectorType &>
985 vector_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
986 ColumnType dst_b, ColumnType dst_c,
987 ColumnType dst_d) KLEIDICV_STREAMING {
988 VectorType vdst_a, vdst_b, vdst_c, vdst_d;
989
990 operation().vector_path(ctx, &src[0], vdst_a, vdst_b, vdst_c, vdst_d);
991
992 store(vdst_a, &dst_a[0]);
993 store(vdst_b, &dst_b[0]);
994 store(vdst_c, &dst_c[0]);
995 store(vdst_d, &dst_d[0]);
996 }
997
998 // Required method:
999 // void T::vector_path([ContextType,] const Vector4Type,
1000 // VectorType &, VectorType &, VectorType &,
1001 // VectorType &);
1002 // Operation type with multiple destination, and with load and store
1003 template <typename T = ConcreteOperationType>
1004 enable_if_has_vector_path_t<void, T, ContextType, const Vector4Type,
1005 VectorType &, VectorType &, VectorType &,
1006 VectorType &>
1007 vector_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
1008 ColumnType dst_b, ColumnType dst_c,
1009 ColumnType dst_d) KLEIDICV_STREAMING {
1010 VectorType vdst_a, vdst_b, vdst_c, vdst_d;
1011 Vector4Type vsrc;
1012
1013 load(&src[0], vsrc);
1014
1015 operation().vector_path(ctx, vsrc, vdst_a, vdst_b, vdst_c, vdst_d);
1016
1017 store(vdst_a, &dst_a[0]);
1018 store(vdst_b, &dst_b[0]);
1019 store(vdst_c, &dst_c[0]);
1020 store(vdst_d, &dst_d[0]);
1021 }
1022
1023 // ---------------------------------------------------------------------------
1024 // Forwarding implementations for tail_path().
1025 // ---------------------------------------------------------------------------
1026
1027 // Required method:
1028 // void T::tail_path([ContextType,] VectorType, ScalarType *);
1029 template <typename T = ConcreteOperationType>
1030 enable_if_has_tail_path_t<void, T, ContextType, VectorType, ScalarType *>
1031 236 tail_path(ContextType ctx, ConstColumnType src,
1032 ColumnType dst) KLEIDICV_STREAMING {
1033 236 VectorType src_0;
1034 236 operation().load(ctx, &src[0], src_0);
1035 236 operation().tail_path(ctx, src_0, &dst[0]);
1036 236 }
1037
1038 // Required method:
1039 // void T::tail_path([ContextType,] const ScalarType *, ScalarType *);
1040 template <typename T = ConcreteOperationType>
1041 enable_if_has_tail_path_t<void, T, ContextType, const ScalarType *,
1042 ScalarType *>
1043 218 tail_path(ContextType ctx, ConstColumnType src,
1044 ColumnType dst) KLEIDICV_STREAMING {
1045 218 operation().tail_path(ctx, &src[0], &dst[0]);
1046 218 }
1047
1048 // ---------------------------------------------------------------------------
1049 // Forwarding implementations for scalar_path().
1050 // ---------------------------------------------------------------------------
1051
1052 // Required method:
1053 // void T::scalar_path([ContextType,] ScalarType);
1054 template <typename T = ConcreteOperationType>
1055 27821 enable_if_has_scalar_path_t<void, T, ContextType, ScalarType> scalar_path(
1056 ContextType ctx, ConstColumnType src) KLEIDICV_STREAMING {
1057 27821 operation().scalar_path(ctx, src[0]);
1058 27821 }
1059
1060 // Required method:
1061 // ScalarType T::scalar_path([ContextType,] ScalarType);
1062 template <typename T = ConcreteOperationType>
1063 enable_if_has_scalar_path_t<ScalarType, T, ContextType, ScalarType>
1064 11099 scalar_path(ContextType ctx, ConstColumnType src,
1065 ColumnType dst) KLEIDICV_STREAMING {
1066 11099 dst[0] = operation().scalar_path(ctx, src[0]);
1067 11099 }
1068
1069 // Required method:
1070 // ScalarType T::scalar_path([ContextType,] ScalarType, ScalarType);
1071 template <typename T = ConcreteOperationType>
1072 enable_if_has_scalar_path_t<ScalarType, T, ContextType, ScalarType,
1073 ScalarType>
1074 14694 scalar_path(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
1075 ColumnType dst) KLEIDICV_STREAMING {
1076 14694 dst[0] = operation().scalar_path(ctx, src_a[0], src_b[0]);
1077 14694 }
1078
1079 // Required method:
1080 // void T::scalar_path([ContextType,] const ScalarType *, ScalarType *);
1081 template <typename T = ConcreteOperationType>
1082 enable_if_has_scalar_path_t<void, T, ContextType, const ScalarType *,
1083 ScalarType *>
1084 4394 scalar_path(ContextType ctx, ConstColumnType src,
1085 ColumnType dst) KLEIDICV_STREAMING {
1086 4394 operation().scalar_path(ctx, &src[0], &dst[0]);
1087 4394 }
1088
1089 // Required method:
1090 // void T::scalar_path([ContextType,] const ScalarType *, const ScalarType *,
1091 // ScalarType *);
1092 template <typename T = ConcreteOperationType>
1093 enable_if_has_scalar_path_t<void, T, ContextType, const ScalarType *,
1094 const ScalarType *, ScalarType *>
1095 192 scalar_path(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
1096 ColumnType dst) KLEIDICV_STREAMING {
1097 192 operation().scalar_path(ctx, &src_a[0], &src_b[0], &dst[0]);
1098 192 }
1099
1100 // Required method:
1101 // void T::scalar_path([ContextType,] const ScalarType *, const ScalarType *,
1102 // const ScalarType *, ScalarType *);
1103 template <typename T = ConcreteOperationType>
1104 enable_if_has_scalar_path_t<void, T, ContextType, const ScalarType *,
1105 const ScalarType *, const ScalarType *,
1106 ScalarType *>
1107 384 scalar_path(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
1108 ConstColumnType src_c, ColumnType dst) KLEIDICV_STREAMING {
1109 384 operation().scalar_path(ctx, &src_a[0], &src_b[0], &src_c[0], &dst[0]);
1110 384 }
1111
1112 // Required method:
1113 // void T::scalar_path([ContextType,] const ScalarType *, const ScalarType *,
1114 // const ScalarType *, const ScalarType *, ScalarType *);
1115 template <typename T = ConcreteOperationType>
1116 enable_if_has_scalar_path_t<void, T, ContextType, const ScalarType *,
1117 const ScalarType *, const ScalarType *,
1118 const ScalarType *, ScalarType *>
1119 768 scalar_path(ContextType ctx, ConstColumnType src_a, ConstColumnType src_b,
1120 ConstColumnType src_c, ConstColumnType src_d,
1121 ColumnType dst) KLEIDICV_STREAMING {
1122 1536 operation().scalar_path(ctx, &src_a[0], &src_b[0], &src_c[0], &src_d[0],
1123 768 &dst[0]);
1124 768 }
1125
1126 // Required method:
1127 // void T::scalar_path([ContextType,] size_t, const ScalarType *,
1128 // const ScalarType *, const ScalarType *, ScalarType *,
1129 // ScalarType *);
1130 template <typename T = ConcreteOperationType>
1131 enable_if_has_scalar_path_t<void, T, ContextType, size_t, const ScalarType *,
1132 const ScalarType *, const ScalarType *,
1133 ScalarType *, ScalarType *>
1134 656 scalar_path(ContextType ctx, size_t length, ConstColumnType src_a,
1135 ConstColumnType src_b, ConstColumnType src_c, ColumnType dst_a,
1136 ColumnType dst_b) KLEIDICV_STREAMING {
1137 1312 operation().scalar_path(ctx, length, &src_a[0], &src_b[0], &src_c[0],
1138 656 &dst_a[0], &dst_b[0]);
1139 656 }
1140
1141 // Required method:
1142 // void T::scalar_path([ContextType,] const ScalarType *, ScalarType *,
1143 // ScalarType *);
1144 template <typename T = ConcreteOperationType>
1145 enable_if_has_scalar_path_t<void, T, ContextType, const ScalarType *,
1146 ScalarType *, ScalarType *>
1147 192 scalar_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
1148 ColumnType dst_b) KLEIDICV_STREAMING {
1149 192 operation().scalar_path(ctx, &src[0], &dst_a[0], &dst_b[0]);
1150 192 }
1151
1152 // Required method:
1153 // void T::scalar_path([ContextType,] const ScalarType *, ScalarType *,
1154 // ScalarType *, ScalarType *);
1155 template <typename T = ConcreteOperationType>
1156 enable_if_has_scalar_path_t<void, T, ContextType, const ScalarType *,
1157 ScalarType *, ScalarType *, ScalarType *>
1158 384 scalar_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
1159 ColumnType dst_b, ColumnType dst_c) KLEIDICV_STREAMING {
1160 384 operation().scalar_path(ctx, &src[0], &dst_a[0], &dst_b[0], &dst_c[0]);
1161 384 }
1162
1163 // Required method:
1164 // void T::scalar_path([ContextType,] const ScalarType *, ScalarType *,
1165 // ScalarType *, ScalarType *, ScalarType *);
1166 template <typename T = ConcreteOperationType>
1167 enable_if_has_scalar_path_t<void, T, ContextType, const ScalarType *,
1168 ScalarType *, ScalarType *, ScalarType *,
1169 ScalarType *>
1170 384 scalar_path(ContextType ctx, ConstColumnType src, ColumnType dst_a,
1171 ColumnType dst_b, ColumnType dst_c,
1172 ColumnType dst_d) KLEIDICV_STREAMING {
1173 768 operation().scalar_path(ctx, &src[0], &dst_a[0], &dst_b[0], &dst_c[0],
1174 384 &dst_d[0]);
1175 384 }
1176 }; // end of class OperationAdapter<OperationType>
1177
1178 // Removes context before forwarding calls.
1179 template <typename OperationType>
1180 class RemoveContextAdapter : public OperationBase<OperationType> {
1181 public:
1182 using ContextType = typename OperationBase<OperationType>::ContextType;
1183
1184 6782 explicit RemoveContextAdapter(OperationType &operation) KLEIDICV_STREAMING
1185 6782 : OperationBase<OperationType>(operation) {}
1186
1187 template <typename... ArgTypes>
1188 4622 decltype(auto) load(ContextType, ArgTypes &&...args) KLEIDICV_STREAMING {
1189 4622 return OperationBase<OperationType>::load(std::forward<ArgTypes>(args)...);
1190 }
1191
1192 template <typename... ArgTypes>
1193 304340 decltype(auto) load_consecutive(ContextType,
1194 ArgTypes &&...args) KLEIDICV_STREAMING {
1195 304340 return OperationBase<OperationType>::load_consecutive(
1196 304340 std::forward<ArgTypes>(args)...);
1197 }
1198
1199 template <typename... ArgTypes>
1200 4300 decltype(auto) store(ContextType, ArgTypes &&...args) KLEIDICV_STREAMING {
1201 4300 return OperationBase<OperationType>::store(std::forward<ArgTypes>(args)...);
1202 }
1203
1204 template <typename... ArgTypes>
1205 47556 decltype(auto) store_consecutive(ContextType,
1206 ArgTypes &&...args) KLEIDICV_STREAMING {
1207 47556 return OperationBase<OperationType>::store_consecutive(
1208 47556 std::forward<ArgTypes>(args)...);
1209 }
1210
1211 template <typename... ArgTypes>
1212 568696 decltype(auto) vector_path(ContextType,
1213 ArgTypes &&...args) KLEIDICV_STREAMING {
1214 568696 return this->operation().vector_path(std::forward<ArgTypes>(args)...);
1215 }
1216
1217 // Forwards remaining_path() calls to the inner operation.
1218 template <typename... ArgTypes>
1219 decltype(auto) remaining_path(ContextType,
1220 ArgTypes &&...args) KLEIDICV_STREAMING {
1221 return this->operation().remaining_path(std::forward<ArgTypes>(args)...);
1222 }
1223
1224 template <typename... ArgTypes>
1225 decltype(auto) tail_path(ContextType, ArgTypes &&...args) KLEIDICV_STREAMING {
1226 return this->operation().tail_path(std::forward<ArgTypes>(args)...);
1227 }
1228
1229 template <typename... ArgTypes>
1230 60968 decltype(auto) scalar_path(ContextType,
1231 ArgTypes &&...args) KLEIDICV_STREAMING {
1232 60968 return this->operation().scalar_path(std::forward<ArgTypes>(args)...);
1233 }
1234 }; // end of class RemoveContextAdapter<OperationType>
1235
1236 } // namespace KLEIDICV_TARGET_NAMESPACE
1237
1238 #endif // KLEIDICV_OPERATIONS_H
1239