deal.II version GIT relicensing-2287-g6548a49e0a 2024-12-20 18:30:00+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
vector_operations_internal.h
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 2016 - 2023 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15
16#ifndef dealii_vector_operations_internal_h
17#define dealii_vector_operations_internal_h
18
19#include <deal.II/base/config.h>
20
25#include <deal.II/base/types.h>
27
29
30#include <cstdio>
31#include <cstring>
32
34
35namespace internal
36{
37 namespace VectorOperations
38 {
40
41 template <typename T>
42 bool
43 is_non_negative(const T &t)
44 {
45 return t >= 0;
46 }
47
48
49 template <typename T>
50 bool
51 is_non_negative(const std::complex<T> &)
52 {
53 Assert(false, ExcMessage("Complex numbers do not have an ordering."));
54
55 return false;
56 }
57
58
59 // call std::copy, except for in
60 // the case where we want to copy
61 // from std::complex to a
62 // non-complex type
63 template <typename T, typename U>
64 void
65 copy(const T *begin, const T *end, U *dest)
66 {
67 std::copy(begin, end, dest);
68 }
69
70 template <typename T, typename U>
71 void
72 copy(const std::complex<T> *begin,
73 const std::complex<T> *end,
74 std::complex<U> *dest)
75 {
76 std::copy(begin, end, dest);
77 }
78
79 template <typename T, typename U>
80 void
81 copy(const std::complex<T> *, const std::complex<T> *, U *)
82 {
83 Assert(false,
84 ExcMessage("Can't convert a vector of complex numbers "
85 "into a vector of reals/doubles"));
86 }
87
88
89
90#ifdef DEAL_II_WITH_TBB
99 template <typename Functor>
101 {
103 const size_type start,
104 const size_type end)
106 , start(start)
107 , end(end)
108 {
109 const size_type vec_size = end - start;
110 // set chunk size for sub-tasks
111 const unsigned int gs =
113 n_chunks =
115 vec_size / gs);
116 chunk_size = vec_size / n_chunks;
117
118 // round to next multiple of 512 (or minimum grain size if that happens
119 // to be smaller). this is advantageous because our accumulation
120 // algorithms favor lengths of a power of 2 due to pairwise summation ->
121 // at most one 'oddly' sized chunk
122 if (chunk_size > 512)
123 chunk_size = ((chunk_size + 511) / 512) * 512;
124 n_chunks = (vec_size + chunk_size - 1) / chunk_size;
125 AssertIndexRange((n_chunks - 1) * chunk_size, vec_size);
126 AssertIndexRange(vec_size, n_chunks * chunk_size + 1);
127 }
128
129 void
130 operator()(const tbb::blocked_range<size_type> &range) const
131 {
132 const size_type r_begin = start + range.begin() * chunk_size;
133 const size_type r_end = std::min(start + range.end() * chunk_size, end);
134 functor(r_begin, r_end);
135 }
136
137 Functor &functor;
140 unsigned int n_chunks;
142 };
143#endif
144
145 template <typename Functor>
146 void
148 Functor &functor,
149 const size_type start,
150 const size_type end,
151 const std::shared_ptr<::parallel::internal::TBBPartitioner>
152 &partitioner)
153 {
154#ifdef DEAL_II_WITH_TBB
155 const size_type vec_size = end - start;
156 // only go to the parallel function in case there are at least 4 parallel
157 // items, otherwise the overhead is too large
158 if (vec_size >=
161 {
162 Assert(partitioner.get() != nullptr,
164 "Unexpected initialization of Vector that does "
165 "not set the TBB partitioner to a usable state."));
166 std::shared_ptr<tbb::affinity_partitioner> tbb_partitioner =
167 partitioner->acquire_one_partitioner();
168
169 TBBForFunctor<Functor> generic_functor(functor, start, end);
170 // We use a minimum grain size of 1 here since the grains at this
171 // stage of dividing the work refer to the number of vector chunks
172 // that are processed by (possibly different) threads in the
173 // parallelized for loop (i.e., they do not refer to individual
174 // vector entries). The number of chunks here is calculated inside
175 // TBBForFunctor. See also GitHub issue #2496 for further discussion
176 // of this strategy.
178 static_cast<size_type>(0),
179 static_cast<size_type>(generic_functor.n_chunks),
180 generic_functor,
181 1,
182 tbb_partitioner);
183 partitioner->release_one_partitioner(tbb_partitioner);
184 }
185 else if (vec_size > 0)
186 functor(start, end);
187#else
188 functor(start, end);
189 (void)partitioner;
190#endif
191 }
192
193
194 // Define the functors necessary to use SIMD with TBB. we also include the
195 // simple copy and set operations
196
197 template <typename Number>
199 {
200 Vector_set(const Number value, Number *const dst)
201 : value(value)
202 , dst(dst)
203 {
204 Assert(dst != nullptr, ExcInternalError());
205 }
206
207 void
208 operator()(const size_type begin, const size_type end) const
209 {
210 Assert(end >= begin, ExcInternalError());
211
212 if (value == Number())
213 std::fill(dst + begin, dst + end, Number());
214 else
215 std::fill(dst + begin, dst + end, value);
216 }
217
218 const Number value;
219 Number *const dst;
220 };
221
222 template <typename Number, typename OtherNumber>
224 {
225 Vector_copy(const OtherNumber *const src, Number *const dst)
226 : src(src)
227 , dst(dst)
228 {
229 Assert(src != nullptr, ExcInternalError());
230 Assert(dst != nullptr, ExcInternalError());
231 }
232
233 void
234 operator()(const size_type begin, const size_type end) const
235 {
236 Assert(end >= begin, ExcInternalError());
237
238 if constexpr (std::is_trivially_copyable<Number>() &&
239 std::is_same_v<Number, OtherNumber>)
240 std::memcpy(dst + begin, src + begin, (end - begin) * sizeof(Number));
241 else
242 {
244 for (size_type i = begin; i < end; ++i)
245 dst[i] = src[i];
246 }
247 }
248
249 const OtherNumber *const src;
250 Number *const dst;
251 };
252
253 template <typename Number>
255 {
256 Vectorization_multiply_factor(Number *const val, const Number factor)
257 : val(val)
258 , stored_factor(factor)
259 {}
260
261 void
262 operator()(const size_type begin, const size_type end) const
263 {
264 // create a local copy of the variable to help the compiler with the
265 // aliasing analysis
266 const Number factor = stored_factor;
267
269 {
271 for (size_type i = begin; i < end; ++i)
272 val[i] *= factor;
273 }
274 else
275 {
276 for (size_type i = begin; i < end; ++i)
277 val[i] *= factor;
278 }
279 }
280
281 Number *const val;
282 const Number stored_factor;
283 };
284
285 template <typename Number>
287 {
289 const Number *const v_val,
290 const Number factor)
291 : val(val)
292 , v_val(v_val)
293 , stored_factor(factor)
294 {}
295
296 void
297 operator()(const size_type begin, const size_type end) const
298 {
299 // create a local copy of the variable to help the compiler with the
300 // aliasing analysis
301 const Number factor = stored_factor;
303 {
305 for (size_type i = begin; i < end; ++i)
306 val[i] += factor * v_val[i];
307 }
308 else
309 {
310 for (size_type i = begin; i < end; ++i)
311 val[i] += factor * v_val[i];
312 }
313 }
314
315 Number *const val;
316 const Number *const v_val;
317 const Number stored_factor;
318 };
319
320 template <typename Number>
322 {
324 const Number *const v_val,
325 const Number a,
326 const Number x)
327 : val(val)
328 , v_val(v_val)
329 , stored_a(a)
330 , stored_x(x)
331 {}
332
333 void
334 operator()(const size_type begin, const size_type end) const
335 {
336 // create a local copy of the variable to help the compiler with the
337 // aliasing analysis
338 const Number x = stored_x, a = stored_a;
339
341 {
343 for (size_type i = begin; i < end; ++i)
344 val[i] = x * val[i] + a * v_val[i];
345 }
346 else
347 {
348 for (size_type i = begin; i < end; ++i)
349 val[i] = x * val[i] + a * v_val[i];
350 }
351 }
352
353 Number *const val;
354 const Number *const v_val;
355 const Number stored_a;
356 const Number stored_x;
357 };
358
359 template <typename Number>
361 {
362 Vectorization_subtract_v(Number *val, const Number *const v_val)
363 : val(val)
364 , v_val(v_val)
365 {}
366
367 void
368 operator()(const size_type begin, const size_type end) const
369 {
371 {
373 for (size_type i = begin; i < end; ++i)
374 val[i] -= v_val[i];
375 }
376 else
377 {
378 for (size_type i = begin; i < end; ++i)
379 val[i] -= v_val[i];
380 }
381 }
382
383 Number *const val;
384 const Number *const v_val;
385 };
386
387 template <typename Number>
389 {
390 Vectorization_add_factor(Number *const val, const Number factor)
391 : val(val)
392 , stored_factor(factor)
393 {}
394
395 void
396 operator()(const size_type begin, const size_type end) const
397 {
398 const Number factor = stored_factor;
399
401 {
403 for (size_type i = begin; i < end; ++i)
404 val[i] += factor;
405 }
406 else
407 {
408 for (size_type i = begin; i < end; ++i)
409 val[i] += factor;
410 }
411 }
412
413 Number *const val;
414 const Number stored_factor;
415 };
416
417 template <typename Number>
419 {
420 Vectorization_add_v(Number *const val, const Number *const v_val)
421 : val(val)
422 , v_val(v_val)
423 {}
424
425 void
426 operator()(const size_type begin, const size_type end) const
427 {
429 {
431 for (size_type i = begin; i < end; ++i)
432 val[i] += v_val[i];
433 }
434 else
435 {
436 for (size_type i = begin; i < end; ++i)
437 val[i] += v_val[i];
438 }
439 }
440
441 Number *const val;
442 const Number *const v_val;
443 };
444
445 template <typename Number>
447 {
449 const Number *const v_val,
450 const Number *const w_val,
451 const Number a,
452 const Number b)
453 : val(val)
454 , v_val(v_val)
455 , w_val(w_val)
456 , stored_a(a)
457 , stored_b(b)
458 {}
459
460 void
461 operator()(const size_type begin, const size_type end) const
462 {
463 const Number a = stored_a, b = stored_b;
464
466 {
468 for (size_type i = begin; i < end; ++i)
469 val[i] = val[i] + a * v_val[i] + b * w_val[i];
470 }
471 else
472 {
473 for (size_type i = begin; i < end; ++i)
474 val[i] = val[i] + a * v_val[i] + b * w_val[i];
475 }
476 }
477
478 Number *const val;
479 const Number *const v_val;
480 const Number *const w_val;
481 const Number stored_a;
482 const Number stored_b;
483 };
484
485 template <typename Number>
487 {
489 const Number *const v_val,
490 const Number x)
491 : val(val)
492 , v_val(v_val)
493 , stored_x(x)
494 {}
495
496 void
497 operator()(const size_type begin, const size_type end) const
498 {
499 const Number x = stored_x;
500
502 {
504 for (size_type i = begin; i < end; ++i)
505 val[i] = x * val[i] + v_val[i];
506 }
507 else
508 {
509 for (size_type i = begin; i < end; ++i)
510 val[i] = x * val[i] + v_val[i];
511 }
512 }
513
514 Number *const val;
515 const Number *const v_val;
516 const Number stored_x;
517 };
518
519 template <typename Number>
521 {
523 const Number *v_val,
524 const Number *w_val,
525 Number x,
526 Number a,
527 Number b)
528 : val(val)
529 , v_val(v_val)
530 , w_val(w_val)
531 , stored_x(x)
532 , stored_a(a)
533 , stored_b(b)
534 {}
535
536 void
537 operator()(const size_type begin, const size_type end) const
538 {
539 const Number x = stored_x, a = stored_a, b = stored_b;
540
542 {
544 for (size_type i = begin; i < end; ++i)
545 val[i] = x * val[i] + a * v_val[i] + b * w_val[i];
546 }
547 else
548 {
549 for (size_type i = begin; i < end; ++i)
550 val[i] = x * val[i] + a * v_val[i] + b * w_val[i];
551 }
552 }
553
554 Number *const val;
555 const Number *const v_val;
556 const Number *const w_val;
557 const Number stored_x;
558 const Number stored_a;
559 const Number stored_b;
560 };
561
562 template <typename Number>
564 {
565 Vectorization_scale(Number *const val, const Number *const v_val)
566 : val(val)
567 , v_val(v_val)
568 {}
569
570 void
571 operator()(const size_type begin, const size_type end) const
572 {
574 {
576 for (size_type i = begin; i < end; ++i)
577 val[i] *= v_val[i];
578 }
579 else
580 {
581 for (size_type i = begin; i < end; ++i)
582 val[i] *= v_val[i];
583 }
584 }
585
586 Number *const val;
587 const Number *const v_val;
588 };
589
590 template <typename Number>
592 {
594 const Number *const u_val,
595 const Number a)
596 : val(val)
597 , u_val(u_val)
598 , stored_a(a)
599 {}
600
601 void
602 operator()(const size_type begin, const size_type end) const
603 {
604 const Number a = stored_a;
605
607 {
609 for (size_type i = begin; i < end; ++i)
610 val[i] = a * u_val[i];
611 }
612 else
613 {
614 for (size_type i = begin; i < end; ++i)
615 val[i] = a * u_val[i];
616 }
617 }
618
619 Number *const val;
620 const Number *const u_val;
621 const Number stored_a;
622 };
623
624 template <typename Number>
626 {
628 const Number *const u_val,
629 const Number *const v_val,
630 const Number a,
631 const Number b)
632 : val(val)
633 , u_val(u_val)
634 , v_val(v_val)
635 , stored_a(a)
636 , stored_b(b)
637 {}
638
639 void
640 operator()(const size_type begin, const size_type end) const
641 {
642 const Number a = stored_a, b = stored_b;
643
645 {
647 for (size_type i = begin; i < end; ++i)
648 val[i] = a * u_val[i] + b * v_val[i];
649 }
650 else
651 {
652 for (size_type i = begin; i < end; ++i)
653 val[i] = a * u_val[i] + b * v_val[i];
654 }
655 }
656
657 Number *const val;
658 const Number *const u_val;
659 const Number *const v_val;
660 const Number stored_a;
661 const Number stored_b;
662 };
663
664 template <typename Number>
666 {
668 const Number *u_val,
669 const Number *v_val,
670 const Number *w_val,
671 const Number a,
672 const Number b,
673 const Number c)
674 : val(val)
675 , u_val(u_val)
676 , v_val(v_val)
677 , w_val(w_val)
678 , stored_a(a)
679 , stored_b(b)
680 , stored_c(c)
681 {}
682
683 void
684 operator()(const size_type begin, const size_type end) const
685 {
686 const Number a = stored_a, b = stored_b, c = stored_c;
687
689 {
691 for (size_type i = begin; i < end; ++i)
692 val[i] = a * u_val[i] + b * v_val[i] + c * w_val[i];
693 }
694 else
695 {
696 for (size_type i = begin; i < end; ++i)
697 val[i] = a * u_val[i] + b * v_val[i] + c * w_val[i];
698 }
699 }
700
701 Number *const val;
702 const Number *const u_val;
703 const Number *const v_val;
704 const Number *const w_val;
705 const Number stored_a;
706 const Number stored_b;
707 const Number stored_c;
708 };
709
710 template <typename Number>
712 {
713 Vectorization_ratio(Number *val, const Number *a_val, const Number *b_val)
714 : val(val)
715 , a_val(a_val)
716 , b_val(b_val)
717 {}
718
719 void
720 operator()(const size_type begin, const size_type end) const
721 {
723 {
725 for (size_type i = begin; i < end; ++i)
726 val[i] = a_val[i] / b_val[i];
727 }
728 else
729 {
730 for (size_type i = begin; i < end; ++i)
731 val[i] = a_val[i] / b_val[i];
732 }
733 }
734
735 Number *const val;
736 const Number *const a_val;
737 const Number *const b_val;
738 };
739
740
741
742 // All sums over all the vector entries (l2-norm, inner product, etc.) are
743 // performed with the same code, using a templated operation defined
744 // here. There are always two versions defined, a standard one that covers
745 // most cases and a vectorized one which is only for equal types and float
746 // and double.
747 template <typename Number, typename Number2>
748 struct Dot
749 {
750 static constexpr bool vectorizes = std::is_same_v<Number, Number2> &&
752
753 Dot(const Number *const X, const Number2 *const Y)
754 : X(X)
755 , Y(Y)
756 {}
757
758 Number
759 operator()(const size_type i) const
760 {
761 return X[i] * Number(numbers::NumberTraits<Number2>::conjugate(Y[i]));
762 }
763
766 {
768 x.load(X + i);
769 y.load(Y + i);
770
771 // the following operation in VectorizedArray does an element-wise
772 // scalar product without taking into account complex values and
773 // the need to take the complex-conjugate of one argument. this
774 // may be a bug, but because all VectorizedArray classes only
775 // work on real scalars, it doesn't really matter very much.
776 // in any case, assert that we really don't get here for
777 // complex-valued objects
778 static_assert(numbers::NumberTraits<Number>::is_complex == false,
779 "This operation is not correctly implemented for "
780 "complex-valued objects.");
781 return x * y;
782 }
783
784 const Number *const X;
785 const Number2 *const Y;
786 };
787
788 template <typename Number, typename RealType>
789 struct Norm2
790 {
791 static const bool vectorizes = VectorizedArray<Number>::size() > 1;
792
793 Norm2(const Number *const X)
794 : X(X)
795 {}
796
797 RealType
798 operator()(const size_type i) const
799 {
801 }
802
805 {
807 x.load(X + i);
808 return x * x;
809 }
810
811 const Number *const X;
812 };
813
814 template <typename Number, typename RealType>
815 struct Norm1
816 {
817 static const bool vectorizes = VectorizedArray<Number>::size() > 1;
818
819 Norm1(const Number *X)
820 : X(X)
821 {}
822
823 RealType
824 operator()(const size_type i) const
825 {
827 }
828
831 {
833 x.load(X + i);
834 return std::abs(x);
835 }
836
837 const Number *X;
838 };
839
840 template <typename Number, typename RealType>
841 struct NormP
842 {
843 static const bool vectorizes = VectorizedArray<Number>::size() > 1;
844
845 NormP(const Number *X, RealType p)
846 : X(X)
847 , p(p)
848 {}
849
850 RealType
851 operator()(const size_type i) const
852 {
854 }
855
858 {
860 x.load(X + i);
861 return std::pow(std::abs(x), p);
862 }
863
864 const Number *X;
865 const RealType p;
866 };
867
868 template <typename Number>
870 {
871 static const bool vectorizes = VectorizedArray<Number>::size() > 1;
872
873 MeanValue(const Number *X)
874 : X(X)
875 {}
876
877 Number
878 operator()(const size_type i) const
879 {
880 return X[i];
881 }
882
885 {
887 x.load(X + i);
888 return x;
889 }
890
891 const Number *X;
892 };
893
894 template <typename Number>
896 {
897 static const bool vectorizes = VectorizedArray<Number>::size() > 1;
898
899 AddAndDot(Number *const X,
900 const Number *const V,
901 const Number *const W,
902 const Number a)
903 : X(X)
904 , V(V)
905 , W(W)
906 , a(a)
907 {}
908
909 Number
910 operator()(const size_type i) const
911 {
912 X[i] += a * V[i];
913 return X[i] * Number(numbers::NumberTraits<Number>::conjugate(W[i]));
914 }
915
918 {
920 x.load(X + i);
921 v.load(V + i);
922 x += a * v;
923 x.store(X + i);
924 // may only load from W after storing in X because the pointers might
925 // point to the same memory
926 w.load(W + i);
927
928 // the following operation in VectorizedArray does an element-wise
929 // scalar product without taking into account complex values and
930 // the need to take the complex-conjugate of one argument. this
931 // may be a bug, but because all VectorizedArray classes only
932 // work on real scalars, it doesn't really matter very much.
933 // in any case, assert that we really don't get here for
934 // complex-valued objects
935 static_assert(numbers::NumberTraits<Number>::is_complex == false,
936 "This operation is not correctly implemented for "
937 "complex-valued objects.");
938 return x * w;
939 }
940
941 Number *const X;
942 const Number *const V;
943 const Number *const W;
944 const Number a;
945 };
946
947
948
949 // this is the main working loop for all vector sums using the templated
950 // operation above. it accumulates the sums using a block-wise summation
951 // algorithm with post-update. this blocked algorithm has been proposed in
952 // a similar form by Castaldo, Whaley and Chronopoulos (SIAM
953 // J. Sci. Comput. 31, 1156-1174, 2008) and we use the smallest possible
954 // block size, 2. Sometimes it is referred to as pairwise summation. The
955 // worst case error made by this algorithm is on the order O(eps *
956 // log2(vec_size)), whereas a naive summation is O(eps * vec_size). Even
957 // though the Kahan summation is even more accurate with an error O(eps)
958 // by carrying along remainders not captured by the main sum, that involves
959 // additional costs which are not worthwhile. See the Wikipedia article on
960 // the Kahan summation algorithm.
961
962 // The algorithm implemented here has the additional benefit that it is
963 // easily parallelized without changing the order of how the elements are
964 // added (floating point addition is not associative). For the same vector
965 // size and minimum_parallel_grainsize, the blocks are always the
966 // same and added pairwise.
967
968 // The depth of recursion is controlled by the 'magic' parameter
969 // vector_accumulation_recursion_threshold: If the length is below
970 // vector_accumulation_recursion_threshold * 32 (32 is the part of code we
971 // unroll), a straight loop instead of recursion will be used. At the
972 // innermost level, eight values are added consecutively in order to better
973 // balance multiplications and additions.
974
975 // Loops are unrolled as follows: the range [first,last) is broken into
976 // @p n_chunks each of size 32 plus the @p remainder.
977 // accumulate_regular() does the work on 32*n_chunks elements employing SIMD
978 // if possible and stores the result of the operation for each chunk in @p outer_results.
979
980 // The code returns the result as the last argument in order to make
981 // spawning tasks simpler and use automatic template deduction.
982
983
990
991 template <typename Operation, typename ResultType>
992 void
993 accumulate_recursive(const Operation &op,
994 const size_type first,
995 const size_type last,
996 ResultType &result)
997 {
998 if (first == last)
999 {
1000 result = ResultType();
1001 return;
1002 }
1003
1004 const size_type vec_size = last - first;
1005 if (vec_size <= vector_accumulation_recursion_threshold * 32)
1006 {
1007 // The vector is short enough so we perform the summation. We store
1008 // the number of chunks (each 32 indices) for the given vector
1009 // length; all results are stored in outer_results[0,n_chunks). We
1010 // keep twice the number around to be able to do the pairwise
1011 // summation with a single for loop (see the loop over j below)
1012 ResultType outer_results[vector_accumulation_recursion_threshold * 2];
1013
1014 // Select between the regular version and vectorized version based
1015 // on the number types we are given. To choose the vectorized
1016 // version often enough, we need to have all tasks but the last one
1017 // to be divisible by the vectorization length
1018 size_type n_chunks =
1019 do_accumulate(op,
1020 vec_size,
1021 first,
1022 outer_results,
1023 std::bool_constant<Operation::vectorizes>());
1024
1025 AssertIndexRange(n_chunks,
1027
1028 // now sum the results from the chunks stored in
1029 // outer_results[0,n_chunks) recursively
1030 unsigned int j = 0;
1031 constexpr unsigned int n_lanes = VectorizedArray<ResultType>::size();
1032 for (; j + 2 * n_lanes - 1 < n_chunks;
1033 j += 2 * n_lanes, n_chunks += n_lanes)
1034 {
1036 a.load(outer_results + j);
1037 b.load(outer_results + j + n_lanes);
1038 a += b;
1039 a.store(outer_results + n_chunks);
1040 }
1041
1042 // In the vectorized case, we know the loop bounds and can do things
1043 // more efficiently
1044 if (Operation::vectorizes)
1045 {
1046 AssertDimension(j + n_lanes, n_chunks);
1047 AssertIndexRange(n_chunks,
1049 ResultType *result_ptr = outer_results + j;
1050 if (n_lanes >= 16)
1051 for (unsigned int i = 0; i < 8; ++i)
1052 result_ptr[i] = result_ptr[i] + result_ptr[i + 8];
1053 if (n_lanes >= 8)
1054 for (unsigned int i = 0; i < 4; ++i)
1055 result_ptr[i] = result_ptr[i] + result_ptr[i + 4];
1056 if (n_lanes >= 4)
1057 for (unsigned int i = 0; i < 2; ++i)
1058 result_ptr[i] = result_ptr[i] + result_ptr[i + 2];
1059 result = result_ptr[0] + result_ptr[1];
1060 }
1061 else
1062 {
1063 // Without vectorization, we do not know the exact bounds, so we
1064 // need to continue the variable-length pairwise summation loop
1065 // from above
1066 for (; j + 1 < n_chunks; j += 2, ++n_chunks)
1067 outer_results[n_chunks] =
1068 outer_results[j] + outer_results[j + 1];
1069
1070 AssertIndexRange(n_chunks,
1072 Assert(n_chunks > 0, ExcInternalError());
1073 result = outer_results[n_chunks - 1];
1074 }
1075 }
1076 else
1077 {
1078 // split vector into four pieces and work on the pieces
1079 // recursively. Make pieces (except last) divisible by one fourth the
1080 // recursion threshold.
1081 const size_type new_size =
1082 (vec_size / (vector_accumulation_recursion_threshold * 32)) *
1084 Assert(first + 3 * new_size < last, ExcInternalError());
1085 ResultType r0, r1, r2, r3;
1086 accumulate_recursive(op, first, first + new_size, r0);
1087 accumulate_recursive(op, first + new_size, first + 2 * new_size, r1);
1089 first + 2 * new_size,
1090 first + 3 * new_size,
1091 r2);
1092 accumulate_recursive(op, first + 3 * new_size, last, r3);
1093 result = (r0 + r1) + (r2 + r3);
1094 }
1095 }
1096
1097
1098 // this is the inner working routine for the accumulation loops below. We
1099 // pulled this part out of the regular accumulate routine because we might
1100 // do this thing vectorized (see specialized function below; this is the
1101 // un-vectorized version). As opposed to the vector add functions above,
1102 // we here pass the functor 'op' by value, because we cannot create a copy
1103 // of the scalar inline, and instead make sure that the numbers get local
1104 // (and thus definitely not aliased) for the compiler
1105 template <typename Operation, typename ResultType>
1106 size_type
1107 do_accumulate(const Operation op,
1108 const size_type vec_size,
1109 const size_type start_index,
1110 ResultType *outer_results,
1111 std::bool_constant<false>)
1112 {
1113 // Create local copy to indicate no aliasing to the compiler
1114 size_type index = start_index;
1115
1116 // choose each chunk to have a width of 32, thereby the index
1117 // is incremented by 4*8 for each @p i.
1118 size_type n_chunks = vec_size / 32;
1119 for (size_type i = 0; i < n_chunks; ++i)
1120 {
1121 ResultType r = {};
1122 for (unsigned int k = 0; k < 2; ++k)
1123 {
1124 ResultType r0 = op(index);
1125 ResultType r1 = op(index + 1);
1126 ResultType r2 = op(index + 2);
1127 ResultType r3 = op(index + 3);
1128 index += 4;
1129 for (size_type j = 1; j < 4; ++j, index += 4)
1130 {
1131 r0 += op(index);
1132 r1 += op(index + 1);
1133 r2 += op(index + 2);
1134 r3 += op(index + 3);
1135 }
1136 r += (r0 + r1) + (r2 + r3);
1137 }
1138 outer_results[i] = r;
1139 }
1140
1141 if (n_chunks * 32 < vec_size)
1142 {
1143 const size_type remainder = vec_size - n_chunks * 32;
1144 const size_type inner_chunks = remainder / 8;
1145 const size_type remainder_inner = remainder % 8;
1146 ResultType r0 = ResultType(), r1 = ResultType(), r2 = ResultType();
1147 switch (inner_chunks)
1148 {
1149 case 3:
1150 r2 = op(index++);
1151 for (size_type j = 1; j < 8; ++j)
1152 r2 += op(index++);
1154 case 2:
1155 r1 = op(index++);
1156 for (size_type j = 1; j < 8; ++j)
1157 r1 += op(index++);
1158 r1 += r2;
1160 case 1:
1161 r2 = op(index++);
1162 for (size_type j = 1; j < 8; ++j)
1163 r2 += op(index++);
1165 default:
1166 for (size_type j = 0; j < remainder_inner; ++j)
1167 r0 += op(index++);
1168 outer_results[n_chunks++] = (r0 + r2) + r1;
1169 break;
1170 }
1171 }
1172
1173 // make sure we worked through all indices
1174 AssertDimension(index, start_index + vec_size);
1175
1176 return n_chunks;
1177 }
1178
1179
1180
1181 // this is the inner working routine for the accumulation loops
1182 // below. This is the specialized case where we can vectorize. We request
1183 // the 'do_vectorized' routine of the operation instead of the regular one
1184 // which does several operations at once. As above, pass in the functor by
1185 // value to create a local copy of the scalar factors in the function (if
1186 // there are any).
1187 template <typename Operation, typename Number>
1188 size_type
1189 do_accumulate(const Operation op,
1190 const size_type vec_size,
1191 const size_type start_index,
1192 Number *outer_results,
1193 std::bool_constant<true>)
1194 {
1195 // Create local copy to indicate no aliasing to the compiler
1196 size_type index = start_index;
1197
1198 // we start from @p index and workout @p n_chunks each of size 32.
1199 // in order employ SIMD and work on @p nvecs at a time, we split this
1200 // loop yet again:
1201 // First we work on (n_chunks/nvecs) chunks, where each chunk processes
1202 // nvecs*(4*8) elements.
1203
1204 constexpr size_type n_lanes = VectorizedArray<Number>::size();
1205 const size_type regular_chunks = vec_size / (32 * n_lanes);
1206 for (size_type i = 0; i < regular_chunks; ++i)
1207 {
1209 for (unsigned int k = 0; k < 2; ++k)
1210 {
1211 VectorizedArray<Number> r0 = op.do_vectorized(index);
1212 VectorizedArray<Number> r1 = op.do_vectorized(index + n_lanes);
1214 op.do_vectorized(index + 2 * n_lanes);
1216 op.do_vectorized(index + 3 * n_lanes);
1217 index += n_lanes * 4;
1218 for (size_type j = 1; j < 4; ++j, index += n_lanes * 4)
1219 {
1220 r0 += op.do_vectorized(index);
1221 r1 += op.do_vectorized(index + n_lanes);
1222 r2 += op.do_vectorized(index + 2 * n_lanes);
1223 r3 += op.do_vectorized(index + 3 * n_lanes);
1224 }
1225 r += (r0 + r1) + (r2 + r3);
1226 }
1227 r.store(&outer_results[i * n_lanes]);
1228 }
1229
1230 // If we are treating a case where the vector length is not divisible by
1231 // the vectorization length, need a cleanup loop
1232 // The remaining chunks are processed one by one starting from
1233 // regular_chunks * n_lanes; We do as much as possible with 2 SIMD
1234 // operations within each chunk. Here we assume that n_lanes < 32/2 = 16
1235 // as well as 16 % n_lanes == 0.
1236 static_assert(n_lanes <= 16 && 16 % n_lanes == 0,
1237 "VectorizedArray::size() must be 1, 2, 4, 8, or 16");
1238 size_type n_chunks = regular_chunks * n_lanes;
1239 const size_type start_irregular = regular_chunks * n_lanes * 32;
1240 if (start_irregular < vec_size)
1241 {
1244 const size_type remainder = vec_size - start_irregular;
1245 const size_type loop_length = remainder / (2 * n_lanes);
1246 for (size_type j = 0; j < loop_length; ++j, index += 2 * n_lanes)
1247 {
1248 r0 += op.do_vectorized(index);
1249 r1 += op.do_vectorized(index + n_lanes);
1250 }
1251 Number scalar_part = Number();
1252 size_type last = remainder % (2 * n_lanes);
1253 if (last > 0)
1254 {
1255 if (last >= n_lanes)
1256 {
1257 r0 += op.do_vectorized(index);
1258 index += n_lanes;
1259 last -= n_lanes;
1260 }
1261 for (unsigned int i = 0; i < last; ++i)
1262 scalar_part += op(index++);
1263 }
1264
1265 r0 += r1;
1266 r0.store(&outer_results[n_chunks]);
1267 outer_results[n_chunks] += scalar_part;
1268
1269 // update n_chunks to denote range of entries to sum up in
1270 // outer_results[].
1271 n_chunks += n_lanes;
1272 }
1273
1274 // make sure we worked through all indices
1275 AssertDimension(index, start_index + vec_size);
1276
1277 return n_chunks;
1278 }
1279
1280
1281
1282#ifdef DEAL_II_WITH_TBB
1311 template <typename Operation, typename ResultType>
1313 {
1314 static const unsigned int threshold_array_allocate = 512;
1315
1316 TBBReduceFunctor(const Operation &op,
1317 const size_type start,
1318 const size_type end)
1319 : op(op)
1320 , start(start)
1321 , end(end)
1322 {
1323 const size_type vec_size = end - start;
1324 // set chunk size for sub-tasks
1325 const unsigned int gs =
1327 n_chunks =
1328 std::min(static_cast<size_type>(4 * MultithreadInfo::n_threads()),
1329 vec_size / gs);
1330 chunk_size = vec_size / n_chunks;
1331
1332 // round to next multiple of 512 (or leave it at the minimum grain size
1333 // if that happens to be smaller). this is advantageous because our
1334 // algorithm favors lengths of a power of 2 due to pairwise summation ->
1335 // at most one 'oddly' sized chunk
1336 if (chunk_size > 512)
1337 chunk_size = ((chunk_size + 511) / 512) * 512;
1338 n_chunks = (vec_size + chunk_size - 1) / chunk_size;
1339 AssertIndexRange((n_chunks - 1) * chunk_size, vec_size);
1340 AssertIndexRange(vec_size, n_chunks * chunk_size + 1);
1341
1343 {
1344 // make sure we allocate an even number of elements,
1345 // access to the new last element is needed in do_sum()
1346 large_array.resize(2 * ((n_chunks + 1) / 2));
1347 array_ptr = large_array.data();
1348 }
1349 else
1350 array_ptr = &small_array[0];
1351 }
1352
1357 void
1358 operator()(const tbb::blocked_range<size_type> &range) const
1359 {
1360 for (size_type i = range.begin(); i < range.end(); ++i)
1362 start + i * chunk_size,
1363 std::min(start + (i + 1) * chunk_size, end),
1364 array_ptr[i]);
1365 }
1366
1367 ResultType
1368 do_sum() const
1369 {
1370 while (n_chunks > 1)
1371 {
1372 if (n_chunks % 2 == 1)
1373 array_ptr[n_chunks++] = ResultType();
1374 for (size_type i = 0; i < n_chunks; i += 2)
1375 array_ptr[i / 2] = array_ptr[i] + array_ptr[i + 1];
1376 n_chunks /= 2;
1377 }
1378 return array_ptr[0];
1379 }
1380
1381 const Operation &op;
1384
1385 mutable unsigned int n_chunks;
1386 unsigned int chunk_size;
1388 std::vector<ResultType> large_array;
1389 // this variable either points to small_array or large_array depending on
1390 // the number of threads we want to feed
1391 mutable ResultType *array_ptr;
1392 };
1393#endif
1394
1395
1396
1401 template <typename Operation, typename ResultType>
1402#ifndef DEBUG
1404#endif
1405 inline void
1407 const Operation &op,
1408 const size_type start,
1409 const size_type end,
1410 ResultType &result,
1411 const std::shared_ptr<::parallel::internal::TBBPartitioner>
1412 &partitioner)
1413 {
1414#ifdef DEAL_II_WITH_TBB
1415 const size_type vec_size = end - start;
1416 // only go to the parallel function in case there are at least 4 parallel
1417 // items, otherwise the overhead is too large
1418 if (vec_size >=
1421 {
1422 Assert(partitioner.get() != nullptr,
1424 "Unexpected initialization of Vector that does "
1425 "not set the TBB partitioner to a usable state."));
1426 std::shared_ptr<tbb::affinity_partitioner> tbb_partitioner =
1427 partitioner->acquire_one_partitioner();
1428
1429 TBBReduceFunctor<Operation, ResultType> generic_functor(op,
1430 start,
1431 end);
1432 // We use a minimum grain size of 1 here since the grains at this
1433 // stage of dividing the work refer to the number of vector chunks
1434 // that are processed by (possibly different) threads in the
1435 // parallelized for loop (i.e., they do not refer to individual
1436 // vector entries). The number of chunks here is calculated inside
1437 // TBBForFunctor. See also GitHub issue #2496 for further discussion
1438 // of this strategy.
1440 static_cast<size_type>(0),
1441 static_cast<size_type>(generic_functor.n_chunks),
1442 generic_functor,
1443 1,
1444 tbb_partitioner);
1445 partitioner->release_one_partitioner(tbb_partitioner);
1446 result = generic_functor.do_sum();
1447 }
1448 else
1449 accumulate_recursive(op, start, end, result);
1450#else
1451 accumulate_recursive(op, start, end, result);
1452 (void)partitioner;
1453#endif
1454 }
1455
1456
1457 template <typename Number, typename Number2, typename MemorySpace>
1459 {
1460 static void
1462 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1463 /*thread_loop_partitioner*/,
1464 const size_type /*size*/,
1465 const ::MemorySpace::MemorySpaceData<Number2, MemorySpace>
1466 & /*v_data*/,
1468 {
1469 static_assert(
1470 std::is_same_v<MemorySpace, ::MemorySpace::Default> &&
1471 std::is_same_v<Number, Number2>,
1472 "For the Default MemorySpace Number and Number2 should be the same type");
1473 }
1474
1475 static void
1477 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1478 /*thread_loop_partitioner*/,
1479 const size_type /*size*/,
1480 const Number /*s*/,
1482 {}
1483
1484 static void
1486 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1487 /*thread_loop_partitioner*/,
1488 const size_type /*size*/,
1489 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1490 & /*v_data*/,
1492 {}
1493
1494 static void
1496 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1497 /*thread_loop_partitioner*/,
1498 const size_type /*size*/,
1499 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1500 & /*v_data*/,
1502 {}
1503
1504 static void
1506 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1507 /*thread_loop_partitioner*/,
1508 const size_type /*size*/,
1509 Number /*a*/,
1511 {}
1512
1513 static void
1515 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1516 /*thread_loop_partitioner*/,
1517 const size_type /*size*/,
1518 const Number /*a*/,
1519 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1520 & /*v_data*/,
1522 {}
1523
1524 static void
1526 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1527 /*thread_loop_partitioner*/,
1528 const size_type /*size*/,
1529 const Number /*a*/,
1530 const Number /*b*/,
1531 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1532 & /*v_data*/,
1533 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1534 & /*w_data*/,
1536 {}
1537
1538 static void
1540 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1541 /*thread_loop_partitioner*/,
1542 const size_type /*size*/,
1543 const Number /*x*/,
1544 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1545 & /*v_data*/,
1547 {}
1548
1549 static void
1551 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1552 /*thread_loop_partitioner*/,
1553 const size_type /*size*/,
1554 const Number /*x*/,
1555 const Number /*a*/,
1556 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1557 & /*v_data*/,
1559 {}
1560
1561 static void
1563 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1564 /*thread_loop_partitioner*/,
1565 const size_type /*size*/,
1566 const Number /*x*/,
1567 const Number /*a*/,
1568 const Number /*b*/,
1569 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1570 & /*v_data*/,
1571 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1572 & /*w_data*/,
1574 {}
1575
1576 static void
1578 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1579 /*thread_loop_partitioner*/,
1580 const size_type /*size*/,
1581 const Number /*factor*/,
1583 {}
1584
1585 static void
1587 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1588 /*thread_loop_partitioner*/,
1589 const size_type /*size*/,
1590 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1591 & /*v_data*/,
1593 {}
1594
1595 static void
1597 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1598 /*thread_loop_partitioner*/,
1599 const size_type /*size*/,
1600 const Number /*a*/,
1601 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1602 & /*v_data*/,
1604 {}
1605
1606 static void
1608 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1609 /*thread_loop_partitioner*/,
1610 const size_type /*size*/,
1611 const Number /*a*/,
1612 const Number /*b*/,
1613 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1614 & /*v_data*/,
1615 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1616 & /*w_data*/,
1618 {}
1619
1620 static Number
1622 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1623 /*thread_loop_partitioner*/,
1624 const size_type /*size*/,
1625 const ::MemorySpace::MemorySpaceData<Number2, MemorySpace>
1626 & /*v_data*/,
1628 {
1629 return Number();
1630 }
1631
1632 template <typename real_type>
1633 static void
1635 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1636 /*thread_loop_partitioner*/,
1637 const size_type /*size*/,
1638 real_type & /*sum*/,
1639 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1640 & /*v_data*/,
1642 {}
1643
1644 static Number
1646 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1647 /*thread_loop_partitioner*/,
1648 const size_type /*size*/,
1649 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1650 & /*data*/)
1651 {
1652 return Number();
1653 }
1654
1655 template <typename real_type>
1656 static void
1658 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1659 /*thread_loop_partitioner*/,
1660 const size_type /*size*/,
1661 real_type & /*sum*/,
1662 Number * /*values*/,
1663 Number * /*values*/)
1664 {}
1665
1666 template <typename real_type>
1667 static void
1669 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1670 /*thread_loop_partitioner*/,
1671 const size_type /*size*/,
1672 real_type & /*sum*/,
1673 real_type /*p*/,
1675 {}
1676
1677 static Number
1679 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1680 /*thread_loop_partitioner*/,
1681 const size_type /*size*/,
1682 const Number /*a*/,
1683 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1684 & /*v_data*/,
1685 const ::MemorySpace::MemorySpaceData<Number, MemorySpace>
1686 & /*w_data*/,
1688 {
1689 return Number();
1690 }
1691
1692 template <typename MemorySpace2>
1693 static void
1695 const std::shared_ptr<::parallel::internal::TBBPartitioner> &
1696 /*thread_loop_partitioner*/,
1697 const size_type /*size*/,
1698 VectorOperation::values /*operation*/,
1699 const ::MemorySpace::MemorySpaceData<Number, MemorySpace2>
1700 & /*v_data*/,
1702 {}
1703 };
1704
1705
1706
1707 template <typename Number, typename Number2>
1708 struct functions<Number, Number2, ::MemorySpace::Host>
1709 {
1710 static void
1711 copy(const std::shared_ptr<::parallel::internal::TBBPartitioner>
1712 &thread_loop_partitioner,
1713 const size_type size,
1714 const ::MemorySpace::
1715 MemorySpaceData<Number2, ::MemorySpace::Host> &v_data,
1716 ::MemorySpace::MemorySpaceData<Number,
1717 ::MemorySpace::Host>
1718 &data)
1719 {
1720 Vector_copy<Number, Number2> copier(v_data.values.data(),
1721 data.values.data());
1722 parallel_for(copier, 0, size, thread_loop_partitioner);
1723 }
1724
1725 static void
1726 set(const std::shared_ptr<::parallel::internal::TBBPartitioner>
1727 &thread_loop_partitioner,
1728 const size_type size,
1729 const Number s,
1732 &data)
1733 {
1734 Vector_set<Number> setter(s, data.values.data());
1735 parallel_for(setter, 0, size, thread_loop_partitioner);
1736 }
1737
1738 static void
1740 const std::shared_ptr<::parallel::internal::TBBPartitioner>
1741 &thread_loop_partitioner,
1742 const size_type size,
1743 const ::MemorySpace::
1744 MemorySpaceData<Number, ::MemorySpace::Host> &v_data,
1745 ::MemorySpace::MemorySpaceData<Number,
1746 ::MemorySpace::Host>
1747 &data)
1748 {
1749 Vectorization_add_v<Number> vector_add(data.values.data(),
1750 v_data.values.data());
1751 parallel_for(vector_add, 0, size, thread_loop_partitioner);
1752 }
1753
1754 static void
1756 const std::shared_ptr<::parallel::internal::TBBPartitioner>
1757 &thread_loop_partitioner,
1758 const size_type size,
1759 const ::MemorySpace::
1760 MemorySpaceData<Number, ::MemorySpace::Host> &v_data,
1761 ::MemorySpace::MemorySpaceData<Number,
1762 ::MemorySpace::Host>
1763 &data)
1764 {
1765 Vectorization_subtract_v<Number> vector_subtract(data.values.data(),
1766 v_data.values.data());
1767 parallel_for(vector_subtract, 0, size, thread_loop_partitioner);
1768 }
1769
1770 static void
1772 const std::shared_ptr<::parallel::internal::TBBPartitioner>
1773 &thread_loop_partitioner,
1774 const size_type size,
1775 Number a,
1778 &data)
1779 {
1780 Vectorization_add_factor<Number> vector_add(data.values.data(), a);
1781 parallel_for(vector_add, 0, size, thread_loop_partitioner);
1782 }
1783
1784 static void
1785 add_av(const std::shared_ptr<::parallel::internal::TBBPartitioner>
1786 &thread_loop_partitioner,
1787 const size_type size,
1788 const Number a,
1789 const ::MemorySpace::
1790 MemorySpaceData<Number, ::MemorySpace::Host> &v_data,
1791 ::MemorySpace::MemorySpaceData<Number,
1792 ::MemorySpace::Host>
1793 &data)
1794 {
1795 Vectorization_add_av<Number> vector_add(data.values.data(),
1796 v_data.values.data(),
1797 a);
1798 parallel_for(vector_add, 0, size, thread_loop_partitioner);
1799 }
1800
1801 static void
1803 const std::shared_ptr<::parallel::internal::TBBPartitioner>
1804 &thread_loop_partitioner,
1805 const size_type size,
1806 const Number a,
1807 const Number b,
1808 const ::MemorySpace::
1809 MemorySpaceData<Number, ::MemorySpace::Host> &v_data,
1810 const ::MemorySpace::
1811 MemorySpaceData<Number, ::MemorySpace::Host> &w_data,
1812 ::MemorySpace::MemorySpaceData<Number,
1813 ::MemorySpace::Host>
1814 &data)
1815 {
1817 data.values.data(), v_data.values.data(), w_data.values.data(), a, b);
1818 parallel_for(vector_add, 0, size, thread_loop_partitioner);
1819 }
1820
1821 static void
1823 const std::shared_ptr<::parallel::internal::TBBPartitioner>
1824 &thread_loop_partitioner,
1825 const size_type size,
1826 const Number x,
1827 const ::MemorySpace::
1828 MemorySpaceData<Number, ::MemorySpace::Host> &v_data,
1829 ::MemorySpace::MemorySpaceData<Number,
1830 ::MemorySpace::Host>
1831 &data)
1832 {
1833 Vectorization_sadd_xv<Number> vector_sadd(data.values.data(),
1834 v_data.values.data(),
1835 x);
1836 parallel_for(vector_sadd, 0, size, thread_loop_partitioner);
1837 }
1838
1839 static void
1841 const std::shared_ptr<::parallel::internal::TBBPartitioner>
1842 &thread_loop_partitioner,
1843 const size_type size,
1844 const Number x,
1845 const Number a,
1846 const ::MemorySpace::
1847 MemorySpaceData<Number, ::MemorySpace::Host> &v_data,
1848 ::MemorySpace::MemorySpaceData<Number,
1849 ::MemorySpace::Host>
1850 &data)
1851 {
1852 Vectorization_sadd_xav<Number> vector_sadd(data.values.data(),
1853 v_data.values.data(),
1854 a,
1855 x);
1856 parallel_for(vector_sadd, 0, size, thread_loop_partitioner);
1857 }
1858
1859 static void
1861 const std::shared_ptr<::parallel::internal::TBBPartitioner>
1862 &thread_loop_partitioner,
1863 const size_type size,
1864 const Number x,
1865 const Number a,
1866 const Number b,
1867 const ::MemorySpace::
1868 MemorySpaceData<Number, ::MemorySpace::Host> &v_data,
1869 const ::MemorySpace::
1870 MemorySpaceData<Number, ::MemorySpace::Host> &w_data,
1871 ::MemorySpace::MemorySpaceData<Number,
1872 ::MemorySpace::Host>
1873 &data)
1874 {
1875 Vectorization_sadd_xavbw<Number> vector_sadd(data.values.data(),
1876 v_data.values.data(),
1877 w_data.values.data(),
1878 x,
1879 a,
1880 b);
1881 parallel_for(vector_sadd, 0, size, thread_loop_partitioner);
1882 }
1883
1884 static void
1886 const std::shared_ptr<::parallel::internal::TBBPartitioner>
1887 &thread_loop_partitioner,
1888 const size_type size,
1889 const Number factor,
1892 &data)
1893 {
1895 data.values.data(), factor);
1896 parallel_for(vector_multiply, 0, size, thread_loop_partitioner);
1897 }
1898
1899 static void
1900 scale(const std::shared_ptr<::parallel::internal::TBBPartitioner>
1901 &thread_loop_partitioner,
1902 const size_type size,
1903 const ::MemorySpace::
1904 MemorySpaceData<Number, ::MemorySpace::Host> &v_data,
1905 ::MemorySpace::MemorySpaceData<Number,
1906 ::MemorySpace::Host>
1907 &data)
1908 {
1909 Vectorization_scale<Number> vector_scale(data.values.data(),
1910 v_data.values.data());
1911 parallel_for(vector_scale, 0, size, thread_loop_partitioner);
1912 }
1913
1914 static void
1915 equ_au(const std::shared_ptr<::parallel::internal::TBBPartitioner>
1916 &thread_loop_partitioner,
1917 const size_type size,
1918 const Number a,
1919 const ::MemorySpace::
1920 MemorySpaceData<Number, ::MemorySpace::Host> &v_data,
1921 ::MemorySpace::MemorySpaceData<Number,
1922 ::MemorySpace::Host>
1923 &data)
1924 {
1925 Vectorization_equ_au<Number> vector_equ(data.values.data(),
1926 v_data.values.data(),
1927 a);
1928 parallel_for(vector_equ, 0, size, thread_loop_partitioner);
1929 }
1930
1931 static void
1933 const std::shared_ptr<::parallel::internal::TBBPartitioner>
1934 &thread_loop_partitioner,
1935 const size_type size,
1936 const Number a,
1937 const Number b,
1938 const ::MemorySpace::
1939 MemorySpaceData<Number, ::MemorySpace::Host> &v_data,
1940 const ::MemorySpace::
1941 MemorySpaceData<Number, ::MemorySpace::Host> &w_data,
1942 ::MemorySpace::MemorySpaceData<Number,
1943 ::MemorySpace::Host>
1944 &data)
1945 {
1947 data.values.data(), v_data.values.data(), w_data.values.data(), a, b);
1948 parallel_for(vector_equ, 0, size, thread_loop_partitioner);
1949 }
1950
1951 static Number
1952 dot(const std::shared_ptr<::parallel::internal::TBBPartitioner>
1953 &thread_loop_partitioner,
1954 const size_type size,
1955 const ::MemorySpace::
1956 MemorySpaceData<Number2, ::MemorySpace::Host> &v_data,
1957 ::MemorySpace::MemorySpaceData<Number,
1958 ::MemorySpace::Host>
1959 &data)
1960 {
1961 Number sum;
1963 data.values.data(), v_data.values.data());
1965 dot, 0, size, sum, thread_loop_partitioner);
1966 AssertIsFinite(sum);
1967
1968 return sum;
1969 }
1970
1971 template <typename real_type>
1972 static void
1973 norm_2(const std::shared_ptr<::parallel::internal::TBBPartitioner>
1974 &thread_loop_partitioner,
1975 const size_type size,
1976 real_type &sum,
1979 &data)
1980 {
1981 Norm2<Number, real_type> norm2(data.values.data());
1982 parallel_reduce(norm2, 0, size, sum, thread_loop_partitioner);
1983 }
1984
1985 static Number
1987 const std::shared_ptr<::parallel::internal::TBBPartitioner>
1988 &thread_loop_partitioner,
1989 const size_type size,
1990 const ::MemorySpace::
1991 MemorySpaceData<Number, ::MemorySpace::Host> &data)
1992 {
1993 Number sum;
1994 MeanValue<Number> mean(data.values.data());
1995 parallel_reduce(mean, 0, size, sum, thread_loop_partitioner);
1996
1997 return sum;
1998 }
1999
2000 template <typename real_type>
2001 static void
2002 norm_1(const std::shared_ptr<::parallel::internal::TBBPartitioner>
2003 &thread_loop_partitioner,
2004 const size_type size,
2005 real_type &sum,
2008 &data)
2009 {
2010 Norm1<Number, real_type> norm1(data.values.data());
2011 parallel_reduce(norm1, 0, size, sum, thread_loop_partitioner);
2012 }
2013
2014 template <typename real_type>
2015 static void
2016 norm_p(const std::shared_ptr<::parallel::internal::TBBPartitioner>
2017 &thread_loop_partitioner,
2018 const size_type size,
2019 real_type &sum,
2020 const real_type p,
2023 &data)
2024 {
2025 NormP<Number, real_type> normp(data.values.data(), p);
2026 parallel_reduce(normp, 0, size, sum, thread_loop_partitioner);
2027 }
2028
2029 static Number
2031 const std::shared_ptr<::parallel::internal::TBBPartitioner>
2032 &thread_loop_partitioner,
2033 const size_type size,
2034 const Number a,
2035 const ::MemorySpace::
2036 MemorySpaceData<Number, ::MemorySpace::Host> &v_data,
2037 const ::MemorySpace::
2038 MemorySpaceData<Number, ::MemorySpace::Host> &w_data,
2039 ::MemorySpace::MemorySpaceData<Number,
2040 ::MemorySpace::Host>
2041 &data)
2042 {
2043 Number sum;
2044 AddAndDot<Number> adder(data.values.data(),
2045 v_data.values.data(),
2046 w_data.values.data(),
2047 a);
2048 parallel_reduce(adder, 0, size, sum, thread_loop_partitioner);
2049
2050 return sum;
2051 }
2052
2053 template <typename MemorySpace2>
2054 static void
2056 const std::shared_ptr<::parallel::internal::TBBPartitioner>
2057 &thread_loop_partitioner,
2058 const size_type size,
2059 VectorOperation::values operation,
2060 const ::MemorySpace::MemorySpaceData<Number, MemorySpace2>
2061 &v_data,
2064 &data,
2065 std::enable_if_t<
2066 std::is_same_v<MemorySpace2, ::MemorySpace::Host>,
2067 int> = 0)
2068 {
2069 if (operation == VectorOperation::insert)
2070 {
2071 copy(thread_loop_partitioner, size, v_data, data);
2072 }
2073 else if (operation == VectorOperation::add)
2074 {
2075 add_vector(thread_loop_partitioner, size, v_data, data);
2076 }
2077 else
2078 {
2080 }
2081 }
2082
2083 template <typename MemorySpace2>
2084 static void
2086 const std::shared_ptr<::parallel::internal::TBBPartitioner>
2087 & /*thread_loop_partitioner*/,
2088 const size_type size,
2089 VectorOperation::values operation,
2090 const ::MemorySpace::MemorySpaceData<Number, MemorySpace2>
2091 &v_data,
2094 &data,
2095 std::enable_if_t<
2096 std::is_same_v<MemorySpace2, ::MemorySpace::Default>,
2097 int> = 0)
2098 {
2099 if (operation == VectorOperation::insert)
2100 {
2101 Kokkos::deep_copy(
2102 Kokkos::subview(data.values,
2103 Kokkos::pair<size_type, size_type>(0, size)),
2104 Kokkos::subview(v_data.values,
2105 Kokkos::pair<size_type, size_type>(0, size)));
2106 }
2107 else
2108 {
2110 }
2111 }
2112 };
2113
2114
2115
2116 template <typename Number>
2117 struct functions<Number, Number, ::MemorySpace::Default>
2118 {
2119 static void
2121 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2122 const size_type size,
2123 const ::MemorySpace::
2124 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2125 ::MemorySpace::MemorySpaceData<Number,
2126 ::MemorySpace::Default>
2127 &data)
2128 {
2129 Kokkos::deep_copy(
2130 Kokkos::subview(data.values,
2131 Kokkos::pair<size_type, size_type>(0, size)),
2132 Kokkos::subview(v_data.values,
2133 Kokkos::pair<size_type, size_type>(0, size)));
2134 }
2135
2136 static void
2137 set(const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2138 const size_type size,
2139 const Number s,
2142 &data)
2143 {
2144 Kokkos::deep_copy(
2145 Kokkos::subview(data.values,
2146 Kokkos::pair<size_type, size_type>(0, size)),
2147 s);
2148 }
2149
2150 static void
2152 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2153 const size_type size,
2154 const ::MemorySpace::
2155 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2156 ::MemorySpace::MemorySpaceData<Number,
2157 ::MemorySpace::Default>
2158 &data)
2159 {
2160 auto exec = typename ::MemorySpace::Default::kokkos_space::
2161 execution_space{};
2162 Kokkos::parallel_for(
2163 "::add_vector",
2164 Kokkos::RangePolicy<
2165 ::MemorySpace::Default::kokkos_space::execution_space>(
2166 exec, 0, size),
2167 KOKKOS_LAMBDA(int i) { data.values(i) += v_data.values(i); });
2168 exec.fence();
2169 }
2170
2171 static void
2173 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2174 const size_type size,
2175 const ::MemorySpace::
2176 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2177 ::MemorySpace::MemorySpaceData<Number,
2178 ::MemorySpace::Default>
2179 &data)
2180 {
2181 auto exec = typename ::MemorySpace::Default::kokkos_space::
2182 execution_space{};
2183 Kokkos::parallel_for(
2184 "::subtract_vector",
2185 Kokkos::RangePolicy<
2186 ::MemorySpace::Default::kokkos_space::execution_space>(
2187 exec, 0, size),
2188 KOKKOS_LAMBDA(size_type i) { data.values(i) -= v_data.values(i); });
2189 exec.fence();
2190 }
2191
2192 static void
2194 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2195 const size_type size,
2196 Number a,
2199 &data)
2200 {
2201 auto exec = typename ::MemorySpace::Default::kokkos_space::
2202 execution_space{};
2203 Kokkos::parallel_for(
2204 "::add_factor",
2205 Kokkos::RangePolicy<
2206 ::MemorySpace::Default::kokkos_space::execution_space>(
2207 exec, 0, size),
2208 KOKKOS_LAMBDA(size_type i) { data.values(i) += a; });
2209 exec.fence();
2210 }
2211
2212 static void
2214 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2215 const size_type size,
2216 const Number a,
2217 const ::MemorySpace::
2218 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2219 ::MemorySpace::MemorySpaceData<Number,
2220 ::MemorySpace::Default>
2221 &data)
2222 {
2223 auto exec = typename ::MemorySpace::Default::kokkos_space::
2224 execution_space{};
2225 Kokkos::parallel_for(
2226 "::add_av",
2227 Kokkos::RangePolicy<
2228 ::MemorySpace::Default::kokkos_space::execution_space>(
2229 exec, 0, size),
2230 KOKKOS_LAMBDA(size_type i) {
2231 data.values(i) += a * v_data.values(i);
2232 });
2233 exec.fence();
2234 }
2235
2236 static void
2238 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2239 const size_type size,
2240 const Number a,
2241 const Number b,
2242 const ::MemorySpace::
2243 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2244 const ::MemorySpace::
2245 MemorySpaceData<Number, ::MemorySpace::Default> &w_data,
2246 ::MemorySpace::MemorySpaceData<Number,
2247 ::MemorySpace::Default>
2248 &data)
2249 {
2250 auto exec = typename ::MemorySpace::Default::kokkos_space::
2251 execution_space{};
2252 Kokkos::parallel_for(
2253 "::add_avpbw",
2254 Kokkos::RangePolicy<
2255 ::MemorySpace::Default::kokkos_space::execution_space>(
2256 exec, 0, size),
2257 KOKKOS_LAMBDA(size_type i) {
2258 data.values(i) += a * v_data.values(i) + b * w_data.values(i);
2259 });
2260 exec.fence();
2261 }
2262
2263 static void
2265 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2266 const size_type size,
2267 const Number x,
2268 const ::MemorySpace::
2269 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2270 ::MemorySpace::MemorySpaceData<Number,
2271 ::MemorySpace::Default>
2272 &data)
2273 {
2274 auto exec = typename ::MemorySpace::Default::kokkos_space::
2275 execution_space{};
2276 Kokkos::parallel_for(
2277 "::sadd_xv",
2278 Kokkos::RangePolicy<
2279 ::MemorySpace::Default::kokkos_space::execution_space>(
2280 exec, 0, size),
2281 KOKKOS_LAMBDA(size_type i) {
2282 data.values(i) = x * data.values(i) + v_data.values(i);
2283 });
2284 exec.fence();
2285 }
2286
2287 static void
2289 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2290 const size_type size,
2291 const Number x,
2292 const Number a,
2293 const ::MemorySpace::
2294 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2295 ::MemorySpace::MemorySpaceData<Number,
2296 ::MemorySpace::Default>
2297 &data)
2298 {
2299 auto exec = typename ::MemorySpace::Default::kokkos_space::
2300 execution_space{};
2301 Kokkos::parallel_for(
2302 "::sadd_xav",
2303 Kokkos::RangePolicy<
2304 ::MemorySpace::Default::kokkos_space::execution_space>(
2305 exec, 0, size),
2306 KOKKOS_LAMBDA(size_type i) {
2307 data.values(i) = x * data.values(i) + a * v_data.values(i);
2308 });
2309 exec.fence();
2310 }
2311
2312 static void
2314 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2315 const size_type size,
2316 const Number x,
2317 const Number a,
2318 const Number b,
2319 const ::MemorySpace::
2320 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2321 const ::MemorySpace::
2322 MemorySpaceData<Number, ::MemorySpace::Default> &w_data,
2323 ::MemorySpace::MemorySpaceData<Number,
2324 ::MemorySpace::Default>
2325 &data)
2326 {
2327 auto exec = typename ::MemorySpace::Default::kokkos_space::
2328 execution_space{};
2329 Kokkos::parallel_for(
2330 "::sadd_xavbw",
2331 Kokkos::RangePolicy<
2332 ::MemorySpace::Default::kokkos_space::execution_space>(
2333 exec, 0, size),
2334 KOKKOS_LAMBDA(size_type i) {
2335 data.values(i) =
2336 x * data.values(i) + a * v_data.values(i) + b * w_data.values(i);
2337 });
2338 exec.fence();
2339 }
2340
2341 static void
2343 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2344 const size_type size,
2345 const Number factor,
2348 &data)
2349 {
2350 auto exec = typename ::MemorySpace::Default::kokkos_space::
2351 execution_space{};
2352 Kokkos::parallel_for(
2353 "::multiply_factor",
2354 Kokkos::RangePolicy<
2355 ::MemorySpace::Default::kokkos_space::execution_space>(
2356 exec, 0, size),
2357 KOKKOS_LAMBDA(size_type i) { data.values(i) *= factor; });
2358 exec.fence();
2359 }
2360
2361 static void
2363 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2364 const size_type size,
2365 const ::MemorySpace::
2366 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2367 ::MemorySpace::MemorySpaceData<Number,
2368 ::MemorySpace::Default>
2369 &data)
2370 {
2371 auto exec = typename ::MemorySpace::Default::kokkos_space::
2372 execution_space{};
2373 Kokkos::parallel_for(
2374 "::scale",
2375 Kokkos::RangePolicy<
2376 ::MemorySpace::Default::kokkos_space::execution_space>(
2377 exec, 0, size),
2378 KOKKOS_LAMBDA(size_type i) { data.values(i) *= v_data.values(i); });
2379 exec.fence();
2380 }
2381
2382 static void
2384 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2385 const size_type size,
2386 const Number a,
2387 const ::MemorySpace::
2388 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2389 ::MemorySpace::MemorySpaceData<Number,
2390 ::MemorySpace::Default>
2391 &data)
2392 {
2393 auto exec = typename ::MemorySpace::Default::kokkos_space::
2394 execution_space{};
2395 Kokkos::parallel_for(
2396 "::equ_au",
2397 Kokkos::RangePolicy<
2398 ::MemorySpace::Default::kokkos_space::execution_space>(
2399 exec, 0, size),
2400 KOKKOS_LAMBDA(size_type i) {
2401 data.values(i) = a * v_data.values(i);
2402 });
2403 exec.fence();
2404 }
2405
2406 static void
2408 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2409 const size_type size,
2410 const Number a,
2411 const Number b,
2412 const ::MemorySpace::
2413 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2414 const ::MemorySpace::
2415 MemorySpaceData<Number, ::MemorySpace::Default> &w_data,
2416 ::MemorySpace::MemorySpaceData<Number,
2417 ::MemorySpace::Default>
2418 &data)
2419 {
2420 auto exec = typename ::MemorySpace::Default::kokkos_space::
2421 execution_space{};
2422 Kokkos::parallel_for(
2423 "::equ_aubv",
2424 Kokkos::RangePolicy<
2425 ::MemorySpace::Default::kokkos_space::execution_space>(
2426 exec, 0, size),
2427 KOKKOS_LAMBDA(size_type i) {
2428 data.values(i) = a * v_data.values(i) + b * w_data.values(i);
2429 });
2430 exec.fence();
2431 }
2432
2433 static Number
2434 dot(const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2435 const size_type size,
2436 const ::MemorySpace::
2437 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2438 ::MemorySpace::MemorySpaceData<Number,
2439 ::MemorySpace::Default>
2440 &data)
2441 {
2442 Number result;
2443
2444 auto exec = typename ::MemorySpace::Default::kokkos_space::
2445 execution_space{};
2446 Kokkos::parallel_reduce(
2447 "::dot",
2448 Kokkos::RangePolicy<
2449 ::MemorySpace::Default::kokkos_space::execution_space>(
2450 exec, 0, size),
2451 KOKKOS_LAMBDA(size_type i, Number & update) {
2452 update += data.values(i) * v_data.values(i);
2453 },
2454 result);
2455
2456 AssertIsFinite(result);
2457 return result;
2458 }
2459
2460 template <typename real_type>
2461 static void
2462 norm_2(const std::shared_ptr<::parallel::internal::TBBPartitioner>
2463 &thread_loop_partitioner,
2464 const size_type size,
2465 real_type &sum,
2466 ::MemorySpace::
2467 MemorySpaceData<Number, ::MemorySpace::Default> &data)
2468 {
2469 sum = dot(thread_loop_partitioner, size, data, data);
2470 }
2471
2472 static Number
2474 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2475 const size_type size,
2476 const ::MemorySpace::
2477 MemorySpaceData<Number, ::MemorySpace::Default> &data)
2478 {
2479 Number result;
2480
2481 auto exec = typename ::MemorySpace::Default::kokkos_space::
2482 execution_space{};
2483 Kokkos::parallel_reduce(
2484 "::mean_value",
2485 Kokkos::RangePolicy<
2486 ::MemorySpace::Default::kokkos_space::execution_space>(
2487 exec, 0, size),
2488 KOKKOS_LAMBDA(size_type i, Number & update) {
2489 update += data.values(i);
2490 },
2491 result);
2492
2493 AssertIsFinite(result);
2494 return result;
2495 }
2496
2497 template <typename real_type>
2498 static void
2500 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2501 const size_type size,
2502 real_type &sum,
2505 &data)
2506 {
2507 auto exec = typename ::MemorySpace::Default::kokkos_space::
2508 execution_space{};
2509 Kokkos::parallel_reduce(
2510 "::norm_1",
2511 Kokkos::RangePolicy<
2512 ::MemorySpace::Default::kokkos_space::execution_space>(
2513 exec, 0, size),
2514 KOKKOS_LAMBDA(size_type i, Number & update) {
2515#if KOKKOS_VERSION < 30400
2516 update += std::abs(data.values(i));
2517#elif KOKKOS_VERSION < 30700
2518 update += Kokkos::Experimental::fabs(data.values(i));
2519#else
2520 update += Kokkos::abs(data.values(i));
2521#endif
2522 },
2523 sum);
2524 }
2525
2526 template <typename real_type>
2527 static void
2529 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2530 const size_type size,
2531 real_type &sum,
2532 real_type exp,
2535 &data)
2536 {
2537 auto exec = typename ::MemorySpace::Default::kokkos_space::
2538 execution_space{};
2539 Kokkos::parallel_reduce(
2540 "::norm_p",
2541 Kokkos::RangePolicy<
2542 ::MemorySpace::Default::kokkos_space::execution_space>(
2543 exec, 0, size),
2544 KOKKOS_LAMBDA(size_type i, Number & update) {
2545#if KOKKOS_VERSION < 30400
2546 update += std::pow(fabs(data.values(i)), exp);
2547#elif KOKKOS_VERSION < 30700
2548 update += Kokkos::Experimental::pow(
2549 Kokkos::Experimental::fabs(data.values(i)), exp);
2550#else
2551 update += Kokkos::pow(Kokkos::abs(data.values(i)), exp);
2552#endif
2553 },
2554 sum);
2555 }
2556
2557 static Number
2559 const std::shared_ptr<::parallel::internal::TBBPartitioner> &,
2560 const size_type size,
2561 const Number a,
2562 const ::MemorySpace::
2563 MemorySpaceData<Number, ::MemorySpace::Default> &v_data,
2564 const ::MemorySpace::
2565 MemorySpaceData<Number, ::MemorySpace::Default> &w_data,
2566 ::MemorySpace::MemorySpaceData<Number,
2567 ::MemorySpace::Default>
2568 &data)
2569 {
2570 Number res;
2571
2572 auto exec = typename ::MemorySpace::Default::kokkos_space::
2573 execution_space{};
2574 Kokkos::parallel_reduce(
2575 "::add_and_dot",
2576 Kokkos::RangePolicy<
2577 ::MemorySpace::Default::kokkos_space::execution_space>(
2578 exec, 0, size),
2579 KOKKOS_LAMBDA(size_type i, Number & update) {
2580 data.values(i) += a * v_data.values(i);
2581 update +=
2583 w_data.values(i)));
2584 },
2585 res);
2586
2587 return res;
2588 }
2589
2590 template <typename MemorySpace2>
2591 static void
2593 const std::shared_ptr<::parallel::internal::TBBPartitioner>
2594 &thread_loop_partitioner,
2595 const size_type size,
2596 VectorOperation::values operation,
2597 const ::MemorySpace::MemorySpaceData<Number, MemorySpace2>
2598 &v_data,
2601 &data,
2602 std::enable_if_t<
2603 std::is_same_v<MemorySpace2, ::MemorySpace::Default>,
2604 int> = 0)
2605 {
2606 if (operation == VectorOperation::insert)
2607 {
2608 copy(thread_loop_partitioner, size, v_data, data);
2609 }
2610 else if (operation == VectorOperation::add)
2611 {
2612 add_vector(thread_loop_partitioner, size, v_data, data);
2613 }
2614 else
2615 {
2617 }
2618 }
2619
2620 template <typename MemorySpace2>
2621 static void
2623 const std::shared_ptr<::parallel::internal::TBBPartitioner>
2624 & /*thread_loop_partitioner*/,
2625 const size_type size,
2626 VectorOperation::values operation,
2627 const ::MemorySpace::MemorySpaceData<Number, MemorySpace2>
2628 &v_data,
2631 &data,
2632 std::enable_if_t<
2633 std::is_same_v<MemorySpace2, ::MemorySpace::Host>,
2634 int> = 0)
2635 {
2636 if (operation == VectorOperation::insert)
2637 {
2638 Kokkos::deep_copy(
2639 Kokkos::subview(data.values,
2640 Kokkos::pair<size_type, size_type>(0, size)),
2641 Kokkos::subview(v_data.values,
2642 Kokkos::pair<size_type, size_type>(0, size)));
2643 }
2644 else
2645 {
2647 }
2648 }
2649 };
2650 } // namespace VectorOperations
2651} // namespace internal
2652
2654
2655#endif
static unsigned int n_threads()
void store(OtherNumber *ptr) const
void load(const OtherNumber *ptr)
#define DEAL_II_ALWAYS_INLINE
Definition config.h:109
#define DEAL_II_OPENMP_SIMD_PRAGMA
Definition config.h:141
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:498
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:499
#define DEAL_II_FALLTHROUGH
Definition config.h:233
Point< 2 > first
Definition grid_out.cc:4629
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertIsFinite(number)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::vector< index_type > data
Definition mpi.cc:735
std::size_t size
Definition mpi.cc:734
unsigned int minimum_parallel_grain_size
Definition parallel.cc:33
void accumulate_recursive(const Operation &op, const size_type first, const size_type last, ResultType &result)
size_type do_accumulate(const Operation op, const size_type vec_size, const size_type start_index, ResultType *outer_results, std::bool_constant< false >)
void parallel_reduce(const Operation &op, const size_type start, const size_type end, ResultType &result, const std::shared_ptr<::parallel::internal::TBBPartitioner > &partitioner)
void copy(const T *begin, const T *end, U *dest)
void parallel_for(Functor &functor, const size_type start, const size_type end, const std::shared_ptr<::parallel::internal::TBBPartitioner > &partitioner)
const unsigned int vector_accumulation_recursion_threshold
void parallel_for(Iterator x_begin, Iterator x_end, const Functor &functor, const unsigned int grainsize)
Definition parallel.h:83
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int global_dof_index
Definition types.h:81
AddAndDot(Number *const X, const Number *const V, const Number *const W, const Number a)
VectorizedArray< Number > do_vectorized(const size_type i) const
Dot(const Number *const X, const Number2 *const Y)
Number operator()(const size_type i) const
VectorizedArray< Number > do_vectorized(const size_type i) const
VectorizedArray< Number > do_vectorized(const size_type i) const
RealType operator()(const size_type i) const
VectorizedArray< Number > do_vectorized(const size_type i) const
RealType operator()(const size_type i) const
VectorizedArray< Number > do_vectorized(const size_type i) const
RealType operator()(const size_type i) const
VectorizedArray< Number > do_vectorized(const size_type i) const
void operator()(const tbb::blocked_range< size_type > &range) const
TBBForFunctor(Functor &functor, const size_type start, const size_type end)
TBBReduceFunctor(const Operation &op, const size_type start, const size_type end)
void operator()(const tbb::blocked_range< size_type > &range) const
Vector_copy(const OtherNumber *const src, Number *const dst)
void operator()(const size_type begin, const size_type end) const
Vector_set(const Number value, Number *const dst)
void operator()(const size_type begin, const size_type end) const
Vectorization_add_av(Number *const val, const Number *const v_val, const Number factor)
void operator()(const size_type begin, const size_type end) const
Vectorization_add_avpbw(Number *const val, const Number *const v_val, const Number *const w_val, const Number a, const Number b)
void operator()(const size_type begin, const size_type end) const
void operator()(const size_type begin, const size_type end) const
Vectorization_add_factor(Number *const val, const Number factor)
void operator()(const size_type begin, const size_type end) const
Vectorization_add_v(Number *const val, const Number *const v_val)
Vectorization_equ_au(Number *const val, const Number *const u_val, const Number a)
void operator()(const size_type begin, const size_type end) const
Vectorization_equ_aubv(Number *const val, const Number *const u_val, const Number *const v_val, const Number a, const Number b)
void operator()(const size_type begin, const size_type end) const
Vectorization_equ_aubvcw(Number *val, const Number *u_val, const Number *v_val, const Number *w_val, const Number a, const Number b, const Number c)
void operator()(const size_type begin, const size_type end) const
Vectorization_multiply_factor(Number *const val, const Number factor)
void operator()(const size_type begin, const size_type end) const
void operator()(const size_type begin, const size_type end) const
Vectorization_ratio(Number *val, const Number *a_val, const Number *b_val)
Vectorization_sadd_xav(Number *val, const Number *const v_val, const Number a, const Number x)
void operator()(const size_type begin, const size_type end) const
void operator()(const size_type begin, const size_type end) const
Vectorization_sadd_xavbw(Number *val, const Number *v_val, const Number *w_val, Number x, Number a, Number b)
Vectorization_sadd_xv(Number *const val, const Number *const v_val, const Number x)
void operator()(const size_type begin, const size_type end) const
void operator()(const size_type begin, const size_type end) const
Vectorization_scale(Number *const val, const Number *const v_val)
Vectorization_subtract_v(Number *val, const Number *const v_val)
void operator()(const size_type begin, const size_type end) const
static void set(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const Number s, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void norm_2(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, real_type &sum, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void norm_p(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, real_type &sum, const real_type p, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void import_elements(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, VectorOperation::values operation, const ::MemorySpace::MemorySpaceData< Number, MemorySpace2 > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data, std::enable_if_t< std::is_same_v< MemorySpace2, ::MemorySpace::Default >, int >=0)
static void add_avpbw(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const Number a, const Number b, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &v_data, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &w_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void sadd_xav(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const Number x, const Number a, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void equ_au(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const Number a, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void scale(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static Number mean_value(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void add_factor(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, Number a, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void sadd_xv(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const Number x, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void norm_1(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, real_type &sum, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void copy(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const ::MemorySpace::MemorySpaceData< Number2, ::MemorySpace::Host > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void import_elements(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, VectorOperation::values operation, const ::MemorySpace::MemorySpaceData< Number, MemorySpace2 > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data, std::enable_if_t< std::is_same_v< MemorySpace2, ::MemorySpace::Host >, int >=0)
static void add_av(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const Number a, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void add_vector(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void sadd_xavbw(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const Number x, const Number a, const Number b, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &v_data, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &w_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void subtract_vector(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static Number add_and_dot(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const Number a, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &v_data, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &w_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static Number dot(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const ::MemorySpace::MemorySpaceData< Number2, ::MemorySpace::Host > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void equ_aubv(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const Number a, const Number b, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &v_data, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &w_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void multiply_factor(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, const Number factor, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Host > &data)
static void subtract_vector(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void sadd_xav(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const Number x, const Number a, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static Number dot(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void add_av(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const Number a, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void copy(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static Number add_and_dot(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const Number a, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &w_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void sadd_xavbw(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const Number x, const Number a, const Number b, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &w_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static Number mean_value(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void norm_p(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, real_type &sum, real_type exp, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void add_factor(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, Number a, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void add_vector(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void add_avpbw(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const Number a, const Number b, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &w_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void set(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const Number s, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void norm_2(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, real_type &sum, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void import_elements(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, VectorOperation::values operation, const ::MemorySpace::MemorySpaceData< Number, MemorySpace2 > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data, std::enable_if_t< std::is_same_v< MemorySpace2, ::MemorySpace::Host >, int >=0)
static void sadd_xv(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const Number x, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void multiply_factor(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const Number factor, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void scale(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void equ_aubv(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const Number a, const Number b, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &w_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void import_elements(const std::shared_ptr<::parallel::internal::TBBPartitioner > &thread_loop_partitioner, const size_type size, VectorOperation::values operation, const ::MemorySpace::MemorySpaceData< Number, MemorySpace2 > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data, std::enable_if_t< std::is_same_v< MemorySpace2, ::MemorySpace::Default >, int >=0)
static void norm_1(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, real_type &sum, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static void equ_au(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type size, const Number a, const ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &v_data, ::MemorySpace::MemorySpaceData< Number, ::MemorySpace::Default > &data)
static Number mean_value(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void equ_au(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const Number, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void add_avpbw(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const Number, const Number, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void sadd_xv(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const Number, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void add_factor(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, Number, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void norm_2(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, real_type &, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void add_vector(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void scale(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void subtract_vector(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void sadd_xavbw(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const Number, const Number, const Number, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static Number dot(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const ::MemorySpace::MemorySpaceData< Number2, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static Number add_and_dot(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const Number, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void sadd_xav(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const Number, const Number, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void import_elements(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, VectorOperation::values, const ::MemorySpace::MemorySpaceData< Number, MemorySpace2 > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void copy(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const ::MemorySpace::MemorySpaceData< Number2, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void norm_1(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, real_type &, Number *, Number *)
static void add_av(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const Number, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void multiply_factor(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const Number, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void norm_p(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, real_type &, real_type, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void equ_aubv(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const Number, const Number, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, const ::MemorySpace::MemorySpaceData< Number, MemorySpace > &, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static void set(const std::shared_ptr<::parallel::internal::TBBPartitioner > &, const size_type, const Number, ::MemorySpace::MemorySpaceData< Number, MemorySpace > &)
static real_type abs(const number &x)
Definition numbers.h:588
static constexpr real_type abs_square(const number &x)
Definition numbers.h:579