Commit 0360f9ad by Thomas Rodgers Committed by Thomas Rodgers

Add PSTL internal namespace qualifications

	* include/pstl/algorithm_impl.h: Add namespace qualification.
	* include/pstl/execution_defs.h: Add namespace qualification.
	* include/pstl/execution_impl.h: Add namespace qualification.
	* include/pstl/numeric_impl.h: Add namespace qualification.
	* include/pstl/parallel_backend_tbb.h: Add namespace qualification.
	* include/pstl/unseq_backend_simd.h: Add namespace qualification.
	* include/pstl/parallel_backend_utils.h: Include <cassert>.

From-SVN: r270231
parent 8a22feb6
2019-04-09 Thomas Rodgers <trodgers@redhat.com>
* include/pstl/algorithm_impl.h: Add namespace qualification.
* include/pstl/execution_defs.h: Add namespace qualification.
* include/pstl/execution_impl.h: Add namespace qualification.
* include/pstl/numeric_impl.h: Add namespace qualification.
* include/pstl/parallel_backend_tbb.h: Add namespace qualification.
* include/pstl/unseq_backend_simd.h: Add namespace qualification.
* include/pstl/parallel_backend_utils.h: Include <cassert>.
2019-04-08 Ville Voutilainen <ville.voutilainen@gmail.com>
Fix visit<R> for variant.
......
......@@ -123,27 +123,27 @@ struct is_execution_policy : std::false_type
};
template <>
struct is_execution_policy<sequenced_policy> : std::true_type
struct is_execution_policy<__pstl::execution::sequenced_policy> : std::true_type
{
};
#if __PSTL_USE_PAR_POLICIES
template <>
struct is_execution_policy<parallel_policy> : std::true_type
struct is_execution_policy<__pstl::execution::parallel_policy> : std::true_type
{
};
template <>
struct is_execution_policy<parallel_unsequenced_policy> : std::true_type
struct is_execution_policy<__pstl::execution::parallel_unsequenced_policy> : std::true_type
{
};
#endif
template <>
struct is_execution_policy<unsequenced_policy> : std::true_type
struct is_execution_policy<__pstl::execution::unsequenced_policy> : std::true_type
{
};
#if __PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT
template <class T>
constexpr bool is_execution_policy_v = is_execution_policy<T>::value;
constexpr bool is_execution_policy_v = __pstl::execution::is_execution_policy<T>::value;
#endif
} // namespace v1
......
......@@ -55,7 +55,7 @@ template <typename _IteratorType, typename... _OtherIteratorTypes>
struct __is_random_access_iterator
{
static constexpr bool value =
__is_random_access_iterator<_IteratorType>::value && __is_random_access_iterator<_OtherIteratorTypes...>::value;
__internal::__is_random_access_iterator<_IteratorType>::value && __internal::__is_random_access_iterator<_OtherIteratorTypes...>::value;
typedef std::integral_constant<bool, value> type;
};
......@@ -106,38 +106,38 @@ struct __policy_traits<parallel_unsequenced_policy>
#endif
template <typename _ExecutionPolicy>
using __collector_t = typename __policy_traits<typename std::decay<_ExecutionPolicy>::type>::__collector_type;
using __collector_t = typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__collector_type;
template <typename _ExecutionPolicy>
using __allow_vector = typename __policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_vector;
using __allow_vector = typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_vector;
template <typename _ExecutionPolicy>
using __allow_unsequenced = typename __policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_unsequenced;
using __allow_unsequenced = typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_unsequenced;
template <typename _ExecutionPolicy>
using __allow_parallel = typename __policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_parallel;
using __allow_parallel = typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_parallel;
template <typename _ExecutionPolicy, typename... _IteratorTypes>
auto
__is_vectorization_preferred(_ExecutionPolicy&& __exec)
-> decltype(__lazy_and(__exec.__allow_vector(), typename __is_random_access_iterator<_IteratorTypes...>::type()))
-> decltype(__internal::__lazy_and(__exec.__allow_vector(), typename __internal::__is_random_access_iterator<_IteratorTypes...>::type()))
{
return __lazy_and(__exec.__allow_vector(), typename __is_random_access_iterator<_IteratorTypes...>::type());
return __internal::__lazy_and(__exec.__allow_vector(), typename __internal::__is_random_access_iterator<_IteratorTypes...>::type());
}
template <typename _ExecutionPolicy, typename... _IteratorTypes>
auto
__is_parallelization_preferred(_ExecutionPolicy&& __exec)
-> decltype(__lazy_and(__exec.__allow_parallel(), typename __is_random_access_iterator<_IteratorTypes...>::type()))
-> decltype(__internal::__lazy_and(__exec.__allow_parallel(), typename __internal::__is_random_access_iterator<_IteratorTypes...>::type()))
{
return __lazy_and(__exec.__allow_parallel(), typename __is_random_access_iterator<_IteratorTypes...>::type());
return __internal::__lazy_and(__exec.__allow_parallel(), typename __internal::__is_random_access_iterator<_IteratorTypes...>::type());
}
template <typename policy, typename... _IteratorTypes>
struct __prefer_unsequenced_tag
{
static constexpr bool value =
__allow_unsequenced<policy>::value && __is_random_access_iterator<_IteratorTypes...>::value;
__internal::__allow_unsequenced<policy>::value && __internal::__is_random_access_iterator<_IteratorTypes...>::value;
typedef std::integral_constant<bool, value> type;
};
......@@ -145,7 +145,7 @@ template <typename policy, typename... _IteratorTypes>
struct __prefer_parallel_tag
{
static constexpr bool value =
__allow_parallel<policy>::value && __is_random_access_iterator<_IteratorTypes...>::value;
__internal::__allow_parallel<policy>::value && __internal::__is_random_access_iterator<_IteratorTypes...>::value;
typedef std::integral_constant<bool, value> type;
};
......
......@@ -71,7 +71,7 @@ __pattern_transform_reduce(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __f
_RandomAccessIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1,
_BinaryOperation2 __binary_op2, _IsVector __is_vector, /*is_parallel=*/std::true_type)
{
return __except_handler([&]() {
return __internal::__except_handler([&]() {
return __par_backend::__parallel_transform_reduce(
std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
[__first1, __first2, __binary_op2](_RandomAccessIterator1 __i) mutable {
......@@ -81,7 +81,7 @@ __pattern_transform_reduce(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __f
__binary_op1, // Combine
[__first1, __first2, __binary_op1, __binary_op2,
__is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j, _Tp __init) -> _Tp {
return __brick_transform_reduce(__i, __j, __first2 + (__i - __first1), __init, __binary_op1,
return __internal::__brick_transform_reduce(__i, __j, __first2 + (__i - __first1), __init, __binary_op1,
__binary_op2, __is_vector);
});
});
......@@ -122,7 +122,7 @@ __pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator __first, _Forwar
_BinaryOperation __binary_op, _UnaryOperation __unary_op, _IsVector __is_vector,
/*is_parallel=*/std::false_type) noexcept
{
return __brick_transform_reduce(__first, __last, __init, __binary_op, __unary_op, __is_vector);
return __internal::__brick_transform_reduce(__first, __last, __init, __binary_op, __unary_op, __is_vector);
}
#if __PSTL_USE_PAR_POLICIES
......@@ -133,12 +133,12 @@ __pattern_transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first,
_BinaryOperation __binary_op, _UnaryOperation __unary_op, _IsVector __is_vector,
/*is_parallel=*/std::true_type)
{
return __except_handler([&]() {
return __internal::__except_handler([&]() {
return __par_backend::__parallel_transform_reduce(
std::forward<_ExecutionPolicy>(__exec), __first, __last,
[__unary_op](_ForwardIterator __i) mutable { return __unary_op(*__i); }, __init, __binary_op,
[__unary_op, __binary_op, __is_vector](_ForwardIterator __i, _ForwardIterator __j, _Tp __init) {
return __brick_transform_reduce(__i, __j, __init, __binary_op, __unary_op, __is_vector);
return __internal::__brick_transform_reduce(__i, __j, __init, __binary_op, __unary_op, __is_vector);
});
});
}
......@@ -201,7 +201,7 @@ __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _Outpu
_Inclusive());
#else
// We need to call serial brick here to call function for inclusive and exclusive scan that depends on _Inclusive() value
return __brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
/*is_vector=*/std::false_type());
#endif
}
......@@ -213,7 +213,7 @@ __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _Outpu
_UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, _Inclusive,
/*is_vector=*/std::true_type) noexcept
{
return __brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
/*is_vector=*/std::false_type());
}
......@@ -224,7 +224,7 @@ __pattern_transform_scan(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardI
_OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
_Inclusive, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
{
return __brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(), __is_vector)
return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(), __is_vector)
.first;
}
......@@ -238,19 +238,19 @@ __pattern_transform_scan(_ExecutionPolicy&& __exec, _RandomAccessIterator __firs
{
typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
return __except_handler([&]() {
return __internal::__except_handler([&]() {
__par_backend::__parallel_transform_scan(
std::forward<_ExecutionPolicy>(__exec), __last - __first,
[__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, __init,
__binary_op,
[__first, __unary_op, __binary_op](_DifferenceType __i, _DifferenceType __j, _Tp __init) {
// Execute serial __brick_transform_reduce, due to the explicit SIMD vectorization (reduction) requires a commutative operation for the guarantee of correct scan.
return __brick_transform_reduce(__first + __i, __first + __j, __init, __binary_op, __unary_op,
return __internal::__brick_transform_reduce(__first + __i, __first + __j, __init, __binary_op, __unary_op,
/*__is_vector*/ std::false_type());
},
[__first, __unary_op, __binary_op, __result, __is_vector](_DifferenceType __i, _DifferenceType __j,
_Tp __init) {
return __brick_transform_scan(__first + __i, __first + __j, __result + __i, __unary_op, __init,
return __internal::__brick_transform_scan(__first + __i, __first + __j, __result + __i, __unary_op, __init,
__binary_op, _Inclusive(), __is_vector)
.second;
});
......@@ -274,11 +274,11 @@ __pattern_transform_scan(_ExecutionPolicy&& __exec, _RandomAccessIterator __firs
{
return __result;
}
return __except_handler([&]() {
return __internal::__except_handler([&]() {
__par_backend::parallel_strict_scan(
std::forward<_ExecutionPolicy>(__exec), __n, __init,
[__first, __unary_op, __binary_op, __result, __is_vector](_DifferenceType __i, _DifferenceType __len) {
return __brick_transform_scan(__first + __i, __first + (__i + __len), __result + __i, __unary_op, _Tp{},
return __internal::__brick_transform_scan(__first + __i, __first + (__i + __len), __result + __i, __unary_op, _Tp{},
__binary_op, _Inclusive(), __is_vector)
.second;
},
......@@ -333,7 +333,7 @@ __pattern_adjacent_difference(_ExecutionPolicy&&, _ForwardIterator __first, _For
_OutputIterator __d_first, _BinaryOperation __op, _IsVector __is_vector,
/*is_parallel*/ std::false_type) noexcept
{
return __brick_adjacent_difference(__first, __last, __d_first, __op, __is_vector);
return __internal::__brick_adjacent_difference(__first, __last, __d_first, __op, __is_vector);
}
#if __PSTL_USE_PAR_POLICIES
......@@ -353,7 +353,7 @@ __pattern_adjacent_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __fir
std::forward<_ExecutionPolicy>(__exec), __first, __last - 1,
[&__op, __is_vector, __d_first, __first](_ForwardIterator1 __b, _ForwardIterator1 __e) {
_ForwardIterator2 __d_b = __d_first + (__b - __first);
__brick_walk3(
__internal::__brick_walk3(
__b, __e, __b + 1, __d_b + 1,
[&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) { __z = __op(__y, __x); },
__is_vector);
......
......@@ -190,7 +190,7 @@ _Tp
__parallel_transform_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, _Up __u, _Tp __init, _Cp __combine,
_Rp __brick_reduce)
{
__par_trans_red_body<_Index, _Up, _Tp, _Cp, _Rp> __body(__u, __init, __combine, __brick_reduce);
__par_backend::__par_trans_red_body<_Index, _Up, _Tp, _Cp, _Rp> __body(__u, __init, __combine, __brick_reduce);
// The grain size of 3 is used in order to provide mininum 2 elements for each body
tbb::this_task_arena::isolate(
[__first, __last, &__body]() { tbb::parallel_reduce(tbb::blocked_range<_Index>(__first, __last, 3), __body); });
......@@ -234,7 +234,7 @@ class __trans_scan_body
sum() const
{
__TBB_ASSERT(_M_has_sum, "sum expected");
return *(_Tp*)_M_sum_storage;
return *const_cast<_Tp*>(reinterpret_cast<_Tp const*>(_M_sum_storage));
}
void
......@@ -304,8 +304,8 @@ __upsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsize
{
_Index __k = __split(__m);
tbb::parallel_invoke(
[=] { __upsweep(__i, __k, __tilesize, __r, __tilesize, __reduce, __combine); },
[=] { __upsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize, __reduce, __combine); });
[=] { __par_backend::__upsweep(__i, __k, __tilesize, __r, __tilesize, __reduce, __combine); },
[=] { __par_backend::__upsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize, __reduce, __combine); });
if (__m == 2 * __k)
__r[__m - 1] = __combine(__r[__k - 1], __r[__m - 1]);
}
......@@ -321,11 +321,11 @@ __downsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsi
else
{
const _Index __k = __split(__m);
tbb::parallel_invoke([=] { __downsweep(__i, __k, __tilesize, __r, __tilesize, __initial, __combine, __scan); },
tbb::parallel_invoke([=] { __par_backend::__downsweep(__i, __k, __tilesize, __r, __tilesize, __initial, __combine, __scan); },
// Assumes that __combine never throws.
//TODO: Consider adding a requirement for user functors to be constant.
[=, &__combine] {
__downsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize,
__par_backend::__downsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize,
__combine(__initial, __r[__k - 1]), __combine, __scan);
});
}
......@@ -358,7 +358,8 @@ parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __reduce
_Index __m = (__n - 1) / __tilesize;
__buffer<_Tp> __buf(__m + 1);
_Tp* __r = __buf.get();
__upsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __reduce, __combine);
__par_backend::__upsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __reduce, __combine);
// When __apex is a no-op and __combine has no side effects, a good optimizer
// should be able to eliminate all code between here and __apex.
// Alternatively, provide a default value for __apex that can be
......@@ -368,7 +369,7 @@ parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __reduce
while ((__k &= __k - 1))
__t = __combine(__r[__k - 1], __t);
__apex(__combine(__initial, __t));
__downsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __initial, __combine,
__par_backend::__downsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __initial, __combine,
__scan);
return;
}
......@@ -522,7 +523,7 @@ __stable_sort_task<_RandomAccessIterator1, _RandomAccessIterator2, _Compare, _Le
{
_M_leaf_sort(_M_xs, _M_xe, _M_comp);
if (_M_inplace != 2)
__init_buf(_M_xs, _M_xe, _M_zs, _M_inplace == 0);
__par_backend::__init_buf(_M_xs, _M_xe, _M_zs, _M_inplace == 0);
return NULL;
}
else
......@@ -535,19 +536,19 @@ __stable_sort_task<_RandomAccessIterator1, _RandomAccessIterator2, _Compare, _Le
auto __move_sequences = [](_RandomAccessIterator2 __first1, _RandomAccessIterator2 __last1,
_RandomAccessIterator1 __first2) { return std::move(__first1, __last1, __first2); };
if (_M_inplace == 2)
__m = new (allocate_continuation())
__m = new (tbb::task::allocate_continuation())
__merge_task<_RandomAccessIterator2, _RandomAccessIterator2, _RandomAccessIterator1, _Compare,
__serial_destroy,
__serial_move_merge<decltype(__move_values), decltype(__move_sequences)>>(
__par_backend::__serial_move_merge<decltype(__move_values), decltype(__move_sequences)>>(
_M_zs, __zm, __zm, __ze, _M_xs, _M_comp, __serial_destroy(),
__serial_move_merge<decltype(__move_values), decltype(__move_sequences)>(__nmerge, __move_values,
__par_backend::__serial_move_merge<decltype(__move_values), decltype(__move_sequences)>(__nmerge, __move_values,
__move_sequences));
else if (_M_inplace)
__m = new (allocate_continuation())
__m = new (tbb::task::allocate_continuation())
__merge_task<_RandomAccessIterator2, _RandomAccessIterator2, _RandomAccessIterator1, _Compare,
__binary_no_op, __serial_move_merge<decltype(__move_values), decltype(__move_sequences)>>(
_M_zs, __zm, __zm, __ze, _M_xs, _M_comp, __binary_no_op(),
__serial_move_merge<decltype(__move_values), decltype(__move_sequences)>(__nmerge, __move_values,
__par_backend::__binary_no_op, __par_backend::__serial_move_merge<decltype(__move_values), decltype(__move_sequences)>>(
_M_zs, __zm, __zm, __ze, _M_xs, _M_comp, __par_backend::__binary_no_op(),
__par_backend::__serial_move_merge<decltype(__move_values), decltype(__move_sequences)>(__nmerge, __move_values,
__move_sequences));
else
{
......@@ -556,18 +557,18 @@ __stable_sort_task<_RandomAccessIterator1, _RandomAccessIterator2, _Compare, _Le
_RandomAccessIterator2 __first2) {
return std::move(__first1, __last1, __first2);
};
__m = new (allocate_continuation())
__m = new (tbb::task::allocate_continuation())
__merge_task<_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _Compare,
__binary_no_op, __serial_move_merge<decltype(__move_values), decltype(__move_sequences)>>(
_M_xs, __xm, __xm, _M_xe, _M_zs, _M_comp, __binary_no_op(),
__serial_move_merge<decltype(__move_values), decltype(__move_sequences)>(__nmerge, __move_values,
__par_backend::__binary_no_op, __par_backend::__serial_move_merge<decltype(__move_values), decltype(__move_sequences)>>(
_M_xs, __xm, __xm, _M_xe, _M_zs, _M_comp, __par_backend::__binary_no_op(),
__par_backend::__serial_move_merge<decltype(__move_values), decltype(__move_sequences)>(__nmerge, __move_values,
__move_sequences));
}
__m->set_ref_count(2);
task* __right = new (__m->allocate_child())
__stable_sort_task(__xm, _M_xe, __zm, !_M_inplace, _M_comp, _M_leaf_sort, __nmerge);
spawn(*__right);
recycle_as_child_of(*__m);
tbb::task::spawn(*__right);
tbb::task::recycle_as_child_of(*__m);
_M_xe = __xm;
_M_inplace = !_M_inplace;
}
......@@ -628,10 +629,10 @@ __parallel_merge(_ExecutionPolicy&&, _RandomAccessIterator1 __xs, _RandomAccessI
{
tbb::this_task_arena::isolate([=]() {
typedef __merge_task<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3, _Compare,
__binary_no_op, _LeafMerge>
__par_backend::__binary_no_op, _LeafMerge>
_TaskType;
tbb::task::spawn_root_and_wait(*new (tbb::task::allocate_root()) _TaskType(
__xs, __xe, __ys, __ye, __zs, __comp, __binary_no_op(), __leaf_merge));
__xs, __xe, __ys, __ye, __zs, __comp, __par_backend::__binary_no_op(), __leaf_merge));
});
}
}
......
......@@ -12,6 +12,7 @@
#include <iterator>
#include <utility>
#include <cassert>
#include "utils.h"
namespace __pstl
......
......@@ -456,7 +456,7 @@ template <typename _Size, typename _Tp, typename _BinaryOperation, typename _Una
typename std::enable_if<!is_arithmetic_plus<_Tp, _BinaryOperation>::value, _Tp>::type
__simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept
{
const std::size_t __block_size = __lane_size / sizeof(_Tp);
const _Size __block_size = __lane_size / sizeof(_Tp);
if (__n > 2 * __block_size && __block_size > 1)
{
alignas(__lane_size) char __lane_[__lane_size];
......@@ -796,7 +796,7 @@ __simd_find_first_of(_ForwardIterator1 __first, _ForwardIterator1 __last, _Forwa
{
for (; __first != __last; ++__first)
{
if (__simd_or(__s_first, __n2,
if (__unseq_backend::__simd_or(__s_first, __n2,
__internal::__equal_value_by_pred<decltype(*__first), _BinaryPredicate>(*__first, __pred)))
{
return __first;
......@@ -807,7 +807,7 @@ __simd_find_first_of(_ForwardIterator1 __first, _ForwardIterator1 __last, _Forwa
{
for (; __s_first != __s_last; ++__s_first)
{
const auto __result = __simd_first(__first, _DifferencType(0), __n1,
const auto __result = __unseq_backend::__simd_first(__first, _DifferencType(0), __n1,
[__s_first, &__pred](_ForwardIterator1 __it, _DifferencType __i) {
return __pred(__it[__i], *__s_first);
});
......@@ -826,7 +826,7 @@ __simd_remove_if(_RandomAccessIterator __first, _DifferenceType __n, _UnaryPredi
{
// find first element we need to remove
auto __current =
__simd_first(__first, _DifferenceType(0), __n,
__unseq_backend::__simd_first(__first, _DifferenceType(0), __n,
[&__pred](_RandomAccessIterator __it, _DifferenceType __i) { return __pred(__it[__i]); });
__n -= __current - __first;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment