-
Notifications
You must be signed in to change notification settings - Fork 755
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libc++][PSTL] Implement std::fill{,_n}
Reviewed By: ldionne, #libc Spies: libcxx-commits Differential Revision: https://reviews.llvm.org/D149540
- Loading branch information
1 parent
cb3cb41
commit ade9c3b
Showing
8 changed files
with
237 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef _LIBCPP___ALGORITHM_PSTL_FILL_H | ||
#define _LIBCPP___ALGORITHM_PSTL_FILL_H | ||
|
||
#include <__algorithm/fill.h> | ||
#include <__config> | ||
#include <__iterator/iterator_traits.h> | ||
#include <__pstl/internal/parallel_impl.h> | ||
#include <__pstl/internal/unseq_backend_simd.h> | ||
#include <__type_traits/is_execution_policy.h> | ||
#include <__utility/terminate_on_exception.h> | ||
|
||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
# pragma GCC system_header | ||
#endif | ||
|
||
#if _LIBCPP_STD_VER >= 17 | ||
|
||
_LIBCPP_BEGIN_NAMESPACE_STD | ||
|
||
template <class _ExecutionPolicy, | ||
class _ForwardIterator, | ||
class _Tp, | ||
enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI void | ||
fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { | ||
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && | ||
__is_cpp17_random_access_iterator<_ForwardIterator>::value) { | ||
std::__terminate_on_exception([&] { | ||
__pstl::__par_backend::__parallel_for( | ||
__pstl::__internal::__par_backend_tag{}, | ||
__policy, | ||
__first, | ||
__last, | ||
[&__policy, &__value](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { | ||
std::fill(std::__remove_parallel_policy(__policy), __brick_first, __brick_last, __value); | ||
}); | ||
}); | ||
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && | ||
__is_cpp17_random_access_iterator<_ForwardIterator>::value) { | ||
__pstl::__unseq_backend::__simd_fill_n(__first, __last - __first, __value); | ||
} else { | ||
std::fill(__first, __last, __value); | ||
} | ||
} | ||
|
||
template <class _ExecutionPolicy, | ||
class _ForwardIterator, | ||
class _SizeT, | ||
class _Tp, | ||
enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI void | ||
fill_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _SizeT __n, const _Tp& __value) { | ||
if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) | ||
std::fill(__policy, __first, __first + __n, __value); | ||
else | ||
std::fill_n(__first, __n, __value); | ||
} | ||
|
||
_LIBCPP_END_NAMESPACE_STD | ||
|
||
#endif // _LIBCPP_STD_VER >= 17 | ||
|
||
#endif // _LIBCPP___ALGORITHM_PSTL_FILL_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// <algorithm> | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14 | ||
|
||
// REQUIRES: with-pstl | ||
|
||
// template<class ExecutionPolicy, class ForwardIterator, class T> | ||
// void fill(ExecutionPolicy&& exec, | ||
// ForwardIterator first, ForwardIterator last, const T& value); | ||
|
||
#include <algorithm> | ||
#include <cassert> | ||
#include <vector> | ||
|
||
#include "test_macros.h" | ||
#include "test_execution_policies.h" | ||
#include "test_iterators.h" | ||
|
||
EXECUTION_POLICY_SFINAE_TEST(fill); | ||
|
||
static_assert(sfinae_test_fill<int, int*, int*, bool (*)(int)>); | ||
static_assert(!sfinae_test_fill<std::execution::parallel_policy, int*, int*, int>); | ||
|
||
template <class Iter> | ||
struct Test { | ||
template <class Policy> | ||
void operator()(Policy&& policy) { | ||
{ // simple test | ||
int a[4]; | ||
std::fill(policy, Iter(std::begin(a)), Iter(std::end(a)), 33); | ||
assert(std::all_of(std::begin(a), std::end(a), [](int i) { return i == 33; })); | ||
} | ||
{ // check that an empty range works | ||
int a[1] = {2}; | ||
std::fill(policy, Iter(std::begin(a)), Iter(std::begin(a)), 33); | ||
assert(a[0] == 2); | ||
} | ||
{ // check that a one-element range works | ||
int a[1]; | ||
std::fill(policy, Iter(std::begin(a)), Iter(std::end(a)), 33); | ||
assert(std::all_of(std::begin(a), std::end(a), [](int i) { return i == 33; })); | ||
} | ||
{ // check that a two-element range works | ||
int a[2]; | ||
std::fill(policy, Iter(std::begin(a)), Iter(std::end(a)), 33); | ||
assert(std::all_of(std::begin(a), std::end(a), [](int i) { return i == 33; })); | ||
} | ||
{ // check that a large range works | ||
std::vector<int> a(234, 2); | ||
std::fill(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 33); | ||
assert(std::all_of(std::begin(a), std::end(a), [](int i) { return i == 33; })); | ||
} | ||
} | ||
}; | ||
|
||
struct ThrowOnCopy { | ||
ThrowOnCopy& operator=(const ThrowOnCopy&) { throw int{}; } | ||
}; | ||
|
||
int main(int, char**) { | ||
types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<Test>{}); | ||
|
||
#ifndef TEST_HAS_NO_EXCEPTIONS | ||
std::set_terminate(terminate_successful); | ||
ThrowOnCopy a[2]; | ||
try { | ||
(void)std::fill(std::execution::par, std::begin(a), std::end(a), ThrowOnCopy{}); | ||
} catch (int) { | ||
assert(false); | ||
} | ||
#endif | ||
|
||
return 0; | ||
} |
82 changes: 82 additions & 0 deletions
82
libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/pstl.fill_n.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// <algorithm> | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14 | ||
|
||
// REQUIRES: with-pstl | ||
|
||
// template<class ExecutionPolicy, class ForwardIterator, class Size, class T> | ||
// ForwardIterator fill_n(ExecutionPolicy&& exec, | ||
// ForwardIterator first, Size n, const T& value); | ||
|
||
#include <algorithm> | ||
#include <cassert> | ||
#include <vector> | ||
|
||
#include "test_macros.h" | ||
#include "test_execution_policies.h" | ||
#include "test_iterators.h" | ||
|
||
EXECUTION_POLICY_SFINAE_TEST(fill_n); | ||
|
||
static_assert(sfinae_test_fill_n<int, int*, int*, bool (*)(int)>); | ||
static_assert(!sfinae_test_fill_n<std::execution::parallel_policy, int*, int*, int>); | ||
|
||
template <class Iter> | ||
struct Test { | ||
template <class Policy> | ||
void operator()(Policy&& policy) { | ||
{ // simple test | ||
int a[4]; | ||
std::fill_n(policy, Iter(std::begin(a)), std::size(a), 33); | ||
assert(std::all_of(std::begin(a), std::end(a), [](int i) { return i == 33; })); | ||
} | ||
{ // check that an empty range works | ||
int a[1] = {2}; | ||
std::fill_n(policy, Iter(std::begin(a)), 0, 33); | ||
assert(a[0] == 2); | ||
} | ||
{ // check that a one-element range works | ||
int a[1]; | ||
std::fill_n(policy, Iter(std::begin(a)), std::size(a), 33); | ||
assert(std::all_of(std::begin(a), std::end(a), [](int i) { return i == 33; })); | ||
} | ||
{ // check that a two-element range works | ||
int a[2]; | ||
std::fill_n(policy, Iter(std::begin(a)), std::size(a), 33); | ||
assert(std::all_of(std::begin(a), std::end(a), [](int i) { return i == 33; })); | ||
} | ||
{ // check that a large range works | ||
std::vector<int> a(234, 2); | ||
std::fill_n(policy, Iter(std::data(a)), std::size(a), 33); | ||
assert(std::all_of(std::begin(a), std::end(a), [](int i) { return i == 33; })); | ||
} | ||
} | ||
}; | ||
|
||
struct ThrowOnCopy { | ||
ThrowOnCopy& operator=(const ThrowOnCopy&) { throw int{}; } | ||
}; | ||
|
||
int main(int, char**) { | ||
types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<Test>{}); | ||
|
||
#ifndef TEST_HAS_NO_EXCEPTIONS | ||
std::set_terminate(terminate_successful); | ||
ThrowOnCopy a[2]; | ||
try { | ||
(void)std::fill_n(std::execution::par, std::begin(a), std::size(a), ThrowOnCopy{}); | ||
} catch (int) { | ||
assert(false); | ||
} | ||
#endif | ||
|
||
return 0; | ||
} |