Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
2ab5b2d
Test files for parallel memory algorithms
frederick-vs-ja Oct 8, 2022
bb38f91
Add `P0040R3_parallel_memory_algorithms` to list
frederick-vs-ja Oct 8, 2022
dbcf1a4
Implement parallel memory algorithms
frederick-vs-ja Oct 8, 2022
df9f83e
Remove UTF-8 BOM
frederick-vs-ja Oct 8, 2022
03d5cbb
Fix `uninitialized_move_n` and `uninitialized_fill`
frederick-vs-ja Oct 8, 2022
f12b6be
Fix the test file
frederick-vs-ja Oct 8, 2022
c387462
Address @barcharcraz's review comments
frederick-vs-ja Nov 20, 2022
c48f9d7
Address @barcharcraz's review comments (`<execution>`)
frederick-vs-ja Nov 20, 2022
97c4f54
Add `memset` test cases and check the returned iterators
frederick-vs-ja Nov 20, 2022
aa22fc2
Merge branch 'microsoft:main' into parallel-memory-algorithms
frederick-vs-ja Nov 20, 2022
d96ccc3
Clang-format
frederick-vs-ja Nov 20, 2022
e963846
Clang-format
frederick-vs-ja Nov 20, 2022
4aa74a8
Use `usual_17_matrix.lst` for the test
frederick-vs-ja Nov 20, 2022
9294b4f
Fix missing `_REQUIRE_CPP17_MUTABLE_LVALUE_ITERATOR`
frederick-vs-ja Nov 20, 2022
c4d8a34
Remove DUPLICATED `destroy`!
frederick-vs-ja Nov 20, 2022
54404af
Merge branch 'microsoft:main' into parallel-memory-algorithms
frederick-vs-ja Dec 9, 2022
36fcf35
Address @CaseyCarter's review comments
frederick-vs-ja Dec 14, 2022
504b120
Clang-format: revert changes of unrelated lines
frederick-vs-ja Dec 14, 2022
a32de8b
Test coverage for more cases
frederick-vs-ja Dec 14, 2022
7c72ff7
Clang-format: remove additional spaces
frederick-vs-ja Dec 15, 2022
adcc243
Signedness issues
frederick-vs-ja Dec 15, 2022
9c80ffe
Complete addressing @CaseyCarter's review comments
frederick-vs-ja Dec 15, 2022
afb20a8
Use make_unique in a couple more places
CaseyCarter Dec 15, 2022
79ca246
Style changes per @StephanTLavavej's review comments
frederick-vs-ja Dec 16, 2022
a9895ff
Partially address @StephanTLavavej's review comments
frederick-vs-ja Dec 16, 2022
930a866
Revert unrelated bad changes (again!)
frederick-vs-ja Dec 16, 2022
c02455d
Drop `const` for parameter objects in forward declarations
frederick-vs-ja Dec 16, 2022
300d413
Revert Casey's reinterpret_cast suggestion
CaseyCarter Dec 16, 2022
f2ae6e7
Consistency pass
CaseyCarter Dec 16, 2022
9760926
Test coverage for wrapped iterators
frederick-vs-ja Dec 17, 2022
a8c8d54
Eliminate possibly problematic iterator arithmetic
frederick-vs-ja Dec 17, 2022
455223d
Merge branch 'main' into parallel-memory-algorithms
StephanTLavavej Jan 21, 2023
ca84b3f
Fix /clr.
StephanTLavavej Jan 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 162 additions & 1 deletion stl/inc/execution
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ namespace execution {
// indicates support by element access functions for weakly parallel forward progress guarantees, and for
// executing interleaved on the same thread, and requests termination on exceptions
//
// (at this time, equivalent to sequenced_policy except for the for_each family)
// (at this time, equivalent to sequenced_policy except for for_each(_n), destroy(_n),
// uninitialized_default_construct(_n), and uninitialized_value_construct(_n))
public:
using _Standard_execution_policy = int;
static constexpr bool _Parallelize = false;
Expand Down Expand Up @@ -5050,6 +5051,166 @@ _FwdIt2 adjacent_difference(_ExPo&&, const _FwdIt1 _First, const _FwdIt1 _Last,
_Get_unwrapped_n(_Dest, _Idl_distance<_FwdIt1>(_UFirst, _ULast)), _Pass_fn(_Diff_op)));
return _Dest;
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, _Enable_if_execution_policy_t<_ExPo> /* = 0 */>
void destroy(_ExPo&& _Exec, const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last) noexcept /* terminates */ {
// destroy all elements in [_First, _Last)
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);
_STD _Adl_verify_range(_First, _Last);
using _Ty = remove_reference_t<_Iter_ref_t<_NoThrowFwdIt>>;
Comment thread
frederick-vs-ja marked this conversation as resolved.
if constexpr (!is_trivially_destructible_v<_Ty>) {
_STD for_each(_STD forward<_ExPo>(_Exec), _First, _Last, [](_Ty& _Obj) { _STD _Destroy_in_place(_Obj); });
}
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, class _Diff, _Enable_if_execution_policy_t<_ExPo> /* = 0 */>
_NoThrowFwdIt destroy_n(_ExPo&& _Exec, _NoThrowFwdIt _First, const _Diff _Count_raw) noexcept /* terminates */ {
// destroy all elements in [_First, _First + _Count)
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);
_Algorithm_int_t<_Diff> _Count = _Count_raw;
if (_Count <= 0) {
return _First;
}

using _Ty = remove_reference_t<_Iter_ref_t<_NoThrowFwdIt>>;
if constexpr (is_trivially_destructible_v<_Ty>) {
_STD advance(_First, _Count);
return _First;
} else {
return _STD for_each_n(
_STD forward<_ExPo>(_Exec), _First, _Count, [](_Ty& _Obj) { _STD _Destroy_in_place(_Obj); });
}
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, _Enable_if_execution_policy_t<_ExPo> /* = 0 */>
void uninitialized_default_construct(_ExPo&& _Exec, const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last) noexcept
/* terminates */ {
// default-initialize all elements in [_First, _Last)
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);
_STD _Adl_verify_range(_First, _Last);
using _Ty = remove_reference_t<_Iter_ref_t<_NoThrowFwdIt>>;
if constexpr (!is_trivially_default_constructible_v<_Ty>) {
_STD for_each(
_STD forward<_ExPo>(_Exec), _First, _Last, [](_Ty& _Obj) { _STD _Default_construct_in_place(_Obj); });
Comment thread
frederick-vs-ja marked this conversation as resolved.
}
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, class _Diff, _Enable_if_execution_policy_t<_ExPo> /* = 0 */>
_NoThrowFwdIt uninitialized_default_construct_n(_ExPo&& _Exec, _NoThrowFwdIt _First, const _Diff _Count_raw) noexcept
/* terminates */ {
// default-initialize all elements in [_First, _First + _Count_raw)
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);
_Algorithm_int_t<_Diff> _Count = _Count_raw;
if (_Count <= 0) {
return _First;
}

using _Ty = remove_reference_t<_Iter_ref_t<_NoThrowFwdIt>>;
if constexpr (is_trivially_default_constructible_v<_Ty>) {
_STD advance(_First, _Count);
return _First;
} else {
return _STD for_each_n(
_STD forward<_ExPo>(_Exec), _First, _Count, [](_Ty& _Obj) { _STD _Default_construct_in_place(_Obj); });
}
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, _Enable_if_execution_policy_t<_ExPo> /* = 0 */>
void uninitialized_value_construct(_ExPo&&, _NoThrowFwdIt _First, _NoThrowFwdIt _Last) noexcept /* terminates */ {
// value-initialize all elements in [_First, _Last)
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);

if constexpr (_Use_memset_value_construct_v<decltype(_UFirst)>) {
_STD _Zero_range(_UFirst, _ULast);
} else if constexpr (remove_reference_t<_ExPo>::_Parallelize) {
const size_t _Hw_threads = _CSTD __std_parallel_algorithms_hw_threads();
if (_Hw_threads > 1) { // parallelize on multiprocessor machines...
auto _Count = _STD distance(_UFirst, _ULast);
if (_Count >= 2) { // ... with at least 2 elements
_TRY_BEGIN
using _Ty = remove_reference_t<_Iter_ref_t<_NoThrowFwdIt>>;
auto _Ctor_fn = [](_Ty& _Obj) { _STD _Construct_in_place(_Obj); };
_Static_partitioned_for_each2<decltype(_UFirst), decltype(_Count), decltype(_Ctor_fn)> _Operation{
_Hw_threads, _Count, _Ctor_fn};
_Operation._Basis._Populate(_Operation._Team, _UFirst);
_STD _Run_chunked_parallel_work(_Hw_threads, _Operation);
return;
_CATCH(const _Parallelism_resources_exhausted&)
// fall through to serial case below
_CATCH_END
}
}

#pragma loop(ivdep)
for (; _UFirst != _ULast; ++_UFirst) {
_STD _Construct_in_place(*_UFirst);
}
} else if constexpr (remove_reference_t<_ExPo>::_Ivdep) {
#pragma loop(ivdep)
for (; _UFirst != _ULast; ++_UFirst) {
_STD _Construct_in_place(*_UFirst);
}
} else {
for (; _UFirst != _ULast; ++_UFirst) {
_STD _Construct_in_place(*_UFirst);
}
}
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, class _Diff, _Enable_if_execution_policy_t<_ExPo> /* = 0 */>
_NoThrowFwdIt uninitialized_value_construct_n(_ExPo&&, _NoThrowFwdIt _First, const _Diff _Count_raw) noexcept
/* terminates */ {
// value-initialize all elements in [_First, _First + _Count_raw)
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);
_Algorithm_int_t<_Diff> _Count = _Count_raw;

if (_Count <= 0) {
return _First;
}

auto _UFirst = _STD _Get_unwrapped_n(_First, _Count);
if constexpr (_Use_memset_value_construct_v<decltype(_UFirst)>) {
_STD _Zero_range(_UFirst, _UFirst + _Count);
_STD _Seek_wrapped(_First, _UFirst + _Count);
} else if constexpr (remove_reference_t<_ExPo>::_Parallelize) {
const size_t _Hw_threads = _CSTD __std_parallel_algorithms_hw_threads();
if (_Hw_threads > 1 && _Count >= 2) { // parallelize on multiprocessor machines with at least 2 elements
_TRY_BEGIN
using _Ty = remove_reference_t<_Iter_ref_t<_NoThrowFwdIt>>;
auto _Ctor_fn = [](_Ty& _Obj) { _STD _Construct_in_place(_Obj); };
_Static_partitioned_for_each2<decltype(_UFirst), decltype(_Count), decltype(_Ctor_fn)> _Operation{
_Hw_threads, _Count, _Ctor_fn};
_STD _Seek_wrapped(_First, _Operation._Basis._Populate(_Operation._Team, _UFirst));
_STD _Run_chunked_parallel_work(_Hw_threads, _Operation);
return _First;
_CATCH(const _Parallelism_resources_exhausted&)
// fall through to serial case below
_CATCH_END
}

#pragma loop(ivdep)
for (; _Count > 0; --_Count, (void) ++_UFirst) {
_STD _Construct_in_place(*_UFirst);
}
_STD _Seek_wrapped(_First, _UFirst);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No change requested: I observe that we could _STD _Seek_wrapped(_First, _Operation._Basis._Populate(_Operation._Team, _UFirst)); above (right line 5186), then exhaust parallelism resources and fall through to here, where we _Seek_wrapped again. However, this is correct because _Seek_wrapped is a "seek to"/assignment, not a "seek by", and there are no other uses of _First that could be damaged by it having been unexpectedly updated.

} else if constexpr (remove_reference_t<_ExPo>::_Ivdep) {
#pragma loop(ivdep)
for (; _Count > 0; --_Count, (void) ++_UFirst) {
_STD _Construct_in_place(*_UFirst);
}
_STD _Seek_wrapped(_First, _UFirst);
} else {
for (; _Count > 0; --_Count, (void) ++_UFirst) {
_STD _Construct_in_place(*_UFirst);
}
_STD _Seek_wrapped(_First, _UFirst);
}

return _First;
}
_STD_END
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
Expand Down
103 changes: 102 additions & 1 deletion stl/inc/memory
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,24 @@ _STL_DISABLE_CLANG_WARNINGS
#undef new

_STD_BEGIN
#if _HAS_CXX17
#define _REQUIRE_PARALLEL_LVALUE_ITERATOR(_Iter) \
static_assert(_Is_ranges_fwd_iter_v<_Iter> && is_lvalue_reference_v<_Iter_ref_t<_Iter>>, \
"Parallel specialized <memory> algorithms require the iterator type to be forward iterator and dereference " \
"to lvalues.")

_EXPORT_STD template <class _ExPo, class _FwdIt, class _NoThrowFwdIt, _Enable_if_execution_policy_t<_ExPo> = 0>
_NoThrowFwdIt uninitialized_copy(_ExPo&&, const _FwdIt _First, const _FwdIt _Last, _NoThrowFwdIt _Dest) noexcept
/* terminates */ {
// copy [_First, _Last) to raw [_Dest, ...)
// not parallelized at present
_REQUIRE_PARALLEL_ITERATOR(_FwdIt);
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);

return _STD uninitialized_copy(_First, _Last, _Dest);
}
#endif // _HAS_CXX17

#ifdef __cpp_lib_concepts
namespace ranges {
_EXPORT_STD template <class _In, class _Out>
Expand Down Expand Up @@ -129,6 +147,21 @@ _NoThrowFwdIt uninitialized_copy_n(const _InIt _First, const _Diff _Count_raw, _
return _Dest;
}

#if _HAS_CXX17
_EXPORT_STD template <class _ExPo, class _FwdIt, class _Diff, class _NoThrowFwdIt,
_Enable_if_execution_policy_t<_ExPo> = 0>
_NoThrowFwdIt uninitialized_copy_n(_ExPo&&, const _FwdIt _First, const _Diff _Count_raw, _NoThrowFwdIt _Dest) noexcept
/* terminates */ {
// copy [_First, _First + _Count) to raw [_Dest, ...)
// not parallelized at present
_REQUIRE_PARALLEL_ITERATOR(_FwdIt);
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);

_Algorithm_int_t<_Diff> _Count = _Count_raw;
return _STD uninitialized_copy_n(_First, _Count, _Dest);
}
#endif // _HAS_CXX17

#ifdef __cpp_lib_concepts
namespace ranges {
_EXPORT_STD template <class _In, class _Out>
Expand Down Expand Up @@ -194,6 +227,17 @@ _NoThrowFwdIt uninitialized_move(const _InIt _First, const _InIt _Last, _NoThrow
return _Dest;
}

_EXPORT_STD template <class _ExPo, class _FwdIt, class _NoThrowFwdIt, _Enable_if_execution_policy_t<_ExPo> = 0>
_NoThrowFwdIt uninitialized_move(_ExPo&&, const _FwdIt _First, const _FwdIt _Last, _NoThrowFwdIt _Dest) noexcept
/* terminates */ {
// move [_First, _Last) to raw [_Dest, ...)
// not parallelized at present
_REQUIRE_PARALLEL_ITERATOR(_FwdIt);
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);

return _STD uninitialized_move(_First, _Last, _Dest);
}

#ifdef __cpp_lib_concepts
namespace ranges {
class _Uninitialized_move_fn : private _Not_quite_object {
Expand Down Expand Up @@ -259,8 +303,30 @@ pair<_InIt, _NoThrowFwdIt> uninitialized_move_n(_InIt _First, const _Diff _Count
_Seek_wrapped(_First, _UFirst);
return {_First, _Dest};
}
#endif // _HAS_CXX17

_EXPORT_STD template <class _ExPo, class _FwdIt, class _Diff, class _NoThrowFwdIt,
_Enable_if_execution_policy_t<_ExPo> = 0>
pair<_FwdIt, _NoThrowFwdIt> uninitialized_move_n(
_ExPo&&, const _FwdIt _First, const _Diff _Count_raw, _NoThrowFwdIt _Dest) noexcept /* terminates */ {
// move [_First, _First + _Count) to raw [_Dest, ...)
// not parallelized at present
_REQUIRE_PARALLEL_ITERATOR(_FwdIt);
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);

_Algorithm_int_t<_Diff> _Count = _Count_raw;
return _STD uninitialized_move_n(_First, _Count, _Dest);
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, class _Tval, _Enable_if_execution_policy_t<_ExPo> = 0>
void uninitialized_fill(_ExPo&&, const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, const _Tval& _Val) noexcept
/* terminates */ {
// copy _Val throughout raw [_First, _Last)
// not parallelized at present
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);

_STD uninitialized_fill(_First, _Last, _Val);
}
#endif // _HAS_CXX17

#ifdef __cpp_lib_concepts
namespace ranges {
Expand Down Expand Up @@ -403,6 +469,21 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw,
return _First;
}

#if _HAS_CXX17
_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, class _Diff, class _Tval,
_Enable_if_execution_policy_t<_ExPo> = 0>
_NoThrowFwdIt uninitialized_fill_n(
_ExPo&&, const _NoThrowFwdIt _First, const _Diff _Count_raw, const _Tval& _Val) noexcept
/* terminates */ {
// copy _Count copies of _Val to raw _First
// not parallelized at present
_REQUIRE_PARALLEL_LVALUE_ITERATOR(_NoThrowFwdIt);

_Algorithm_int_t<_Diff> _Count = _Count_raw;
return _STD uninitialized_fill_n(_First, _Count, _Val);
}
#endif // _HAS_CXX17

#ifdef __cpp_lib_concepts
namespace ranges {
class _Uninitialized_fill_n_fn : private _Not_quite_object {
Expand Down Expand Up @@ -493,6 +574,9 @@ _CONSTEXPR20 void destroy(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last)
_Destroy_range(_Get_unwrapped(_First), _Get_unwrapped(_Last));
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, _Enable_if_execution_policy_t<_ExPo> = 0>
void destroy(_ExPo&& _Exec, _NoThrowFwdIt _First, _NoThrowFwdIt _Last) noexcept; // terminates

#ifdef __cpp_lib_concepts
namespace ranges {
template <_No_throw_input_iterator _It, _No_throw_sentinel_for<_It> _Se>
Expand Down Expand Up @@ -557,6 +641,9 @@ _CONSTEXPR20 _NoThrowFwdIt destroy_n(_NoThrowFwdIt _First, const _Diff _Count_ra
return _First;
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, class _Diff, _Enable_if_execution_policy_t<_ExPo> = 0>
_NoThrowFwdIt destroy_n(_ExPo&& _Exec, _NoThrowFwdIt _First, _Diff _Count_raw) noexcept; // terminates

#ifdef __cpp_lib_concepts
namespace ranges {
class _Destroy_n_fn : private _Not_quite_object {
Expand Down Expand Up @@ -607,6 +694,9 @@ void uninitialized_default_construct(const _NoThrowFwdIt _First, const _NoThrowF
}
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, _Enable_if_execution_policy_t<_ExPo> = 0>
void uninitialized_default_construct(_ExPo&& _Exec, _NoThrowFwdIt _First, _NoThrowFwdIt _Last) noexcept; // terminates

#ifdef __cpp_lib_concepts
namespace ranges {
class _Uninitialized_default_construct_fn : private _Not_quite_object {
Expand Down Expand Up @@ -683,6 +773,10 @@ _NoThrowFwdIt uninitialized_default_construct_n(_NoThrowFwdIt _First, const _Dif
return _First;
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, class _Diff, _Enable_if_execution_policy_t<_ExPo> = 0>
_NoThrowFwdIt uninitialized_default_construct_n(
_ExPo&& _Exec, _NoThrowFwdIt _First, _Diff _Count_raw) noexcept; // terminates

#ifdef __cpp_lib_concepts
namespace ranges {
class _Uninitialized_default_construct_n_fn : private _Not_quite_object {
Expand Down Expand Up @@ -736,6 +830,9 @@ void uninitialized_value_construct(const _NoThrowFwdIt _First, const _NoThrowFwd
}
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, _Enable_if_execution_policy_t<_ExPo> = 0>
void uninitialized_value_construct(_ExPo&& _Exec, _NoThrowFwdIt _First, _NoThrowFwdIt _Last) noexcept; // terminates

#ifdef __cpp_lib_concepts
namespace ranges {
class _Uninitialized_value_construct_fn : private _Not_quite_object {
Expand Down Expand Up @@ -799,6 +896,10 @@ _NoThrowFwdIt uninitialized_value_construct_n(_NoThrowFwdIt _First, const _Diff
return _First;
}

_EXPORT_STD template <class _ExPo, class _NoThrowFwdIt, class _Diff, _Enable_if_execution_policy_t<_ExPo> = 0>
_NoThrowFwdIt uninitialized_value_construct_n(
_ExPo&& _Exec, _NoThrowFwdIt _First, const _Diff _Count_raw) noexcept; // terminates

#ifdef __cpp_lib_concepts
namespace ranges {
class _Uninitialized_value_construct_n_fn : private _Not_quite_object {
Expand Down
14 changes: 14 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@
// * any_of
// * count
// * count_if
// * destroy
// * destroy_n
// * equal
// * exclusive_scan
// * find
Expand Down Expand Up @@ -396,6 +398,10 @@
// * transform_exclusive_scan
// * transform_inclusive_scan
// * transform_reduce
// * uninitialized_default_construct
// * uninitialized_default_construct_n
// * uninitialized_value_construct
// * uninitialized_value_construct_n
//
// The following are not presently parallelized:
//
Expand All @@ -414,6 +420,14 @@
// * shift_right
// * swap_ranges
//
// Possibly same as above, but not yet tested.
// * uninitialized_copy
// * uninitialized_copy_n
// * uninitialized_fill
// * uninitialized_fill_n
// * uninitialized_move
// * uninitialized_move_n
//
// Confusion over user parallelism requirements exists; likely in the above category anyway.
// * generate
// * generate_n
Expand Down
Loading