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