NOTE: All wording is relative to [N4744], the Proposed Draft Technical Specification for version 2 of the C++ Parallelism Technical Specification (ISO/IEC PTDS 19750).
NOTE: Paragraph references are relative to [N4744] and do not take paragraph renumbering into account. In the places where this would be ambiguous, descriptions of the location are provided instead of paragraph numbers.
NOTE: The changes should be applied in order.
1. CA 15, CA 16, CA 17, US 11, US 12, CH 35
Modify [parallel.simd.whereexpr] paragraph 12 as follows:
If the template parameterFlagsisvector_aligned_tag,memshall point to storage aligned bymemory_alignment_v<T, U>. If the template parameterFlagsisoveraligned_tag<N>,memshall point to storage aligned byN. If the template parameterFlagsiselement_aligned_tag,memshall point to storage aligned byalignof(U). IfMis notbool, the largest i ∊[0, M::size())wheremask[i]istrueselected index is less than the number of values pointed to bymem.
In [parallel.simd.reductions] replace all occurrences of:
for all i ∊ {j ∊ ℕ0 ∣ j <M::size()⋀mask[j]}
with:
for all selected indices i
Replace all occurrences of ∊ preceding a half-open range with in the range of.
Replace all remaining occurrences of ∊ with ∈.
Replace all occurrences of ℕ0 with ℕ.
Replace all occurrences of -th to th.
Replace all occurrences of i and j (code font) with i and j (math font) respectively.
2. US 37
Move paragraphs 4 and 5 of [parallel.simd.overview] into a new subsection after [parallel.simd.overview]:
9.3.2 simd width [parallel.simd.width]
static constexpr size_t size() noexcept;Returns: The width of
simd<T, Abi>.
Move paragraphs 4 and 5 of [parallel.simd.mask.overview] into a new subsection after [parallel.simd.mask.overview]:
9.5.2 simd_mask width [parallel.simd.mask.width]
static constexpr size_t size() noexcept;Returns: The width of
simd<T, Abi>.
3. US 44
Modify [parallel.references] paragraph 2 as follows:
ISO/IEC 14882:2017 is herein called the C++ Standard. References to clauses within the C++ Standard are written as "C++17 §3.2". The library described in ISO/IEC 14882:2017 clauses 20-33 is herein called the C++ Standard Library. The C++ Standard Library components described in ISO/IEC 14882:2017 clauses 28, 29.8 and 23.10.10 are herein called the C++ Standard Algorithms Library.
Replace all references to the C++ Standard with references in the style "C++17 §3.2":
Modify [parallel.simd.ctor] paragraph 7 as follows:
if both U and value_type are integral, the integer conversion rank [conv.rank](C++17 §7.15) of value_type is greater than the integer conversion rank of U.
Modify [parallel.simd.ctor] paragraph 11 as follows:
Vectorization-unsafe standard library functions may not be invoked by gen ([algorithms.parallel.exec]C++17 §28.4.3).
Modify [parallel.simd.reductions] paragraph 4 as follows:
template<class T, class Abi, class BinaryOperation = plus<>> T reduce(const simd<T, Abi>& x, BinaryOperation binary_op = {});Requires:
binary_opshall be callable with two arguments of typeTreturningT, or callable with two arguments of typesimd<T, A1>returningsimd<T, A1>for everyA1that is an ABI tag type.Returns:
GENERALIZED_SUM(binary_op, x.data[i], ...)for all i ∈[0, size())(C++17 §29.2).
4. US 53
Modify [parallel.scope] paragraph 3 as follows:
The goal of this Technical Specification is to build widespread existing practice for parallelism in the C++ programming languagestandard algorithms library. It gives advice on extensions to those vendors who wish to provide them.
5. US 3
Insert a new paragraph after [parallel.general.namespaces] p1:
Each header described in this technical specification shall import the contents ofstd::experimental::parallelism_v2intostd::experimentalas if bynamespace std::experimental { inline namespace parallelism_v2 {} }
6. US 7
Modify [parallel.alg.ops.synopsis] as follows:
// Exposition only: Suppress template argument deduction.
template<class T> struct no_deducetype_identity { using type = T; };
template<class T> using no_deduce_ttype_identity_t = typename no_deducetype_identity<T>::type;
In [parallel.alg], replace all occurrences of:
no_deduce_t
with:
type_identity_t
In [parallel.simd], replace all occurrences of:
nodeduce_t
with:
type_identity_t
7. CA 4
Remove the column titled "Doc. No." from [parallel.general.features] Table 1.
8. CA 8
Modify [parallel.alg.reductions] paragraph 3 as follows:
Modifications to the accumulator by the application of element access functions accrue as
partial results.
At some point before the algorithm returns, the partial results are combined, two at a time, using the reduction object’s combiner operation until a single value remains, which is then assigned back to the live-out object.
[ Note: inIn order to produce useful results, modifications to the accumulator should be limited to commutative operations closely related to the combiner operation.
For example if the combiner is plus<T>, incrementing the accumulator would be consistent with the combiner but doubling it or assigning to it would not.
— end note ]
9. CA 5
Modify [parallel.exceptions.synopsis] p2 as follows:
The typeexception_list::iteratorfulfills the requirements ofForwardIterator.exception_list::iteratoris an iterator which meets the forward iterator requirements and has a value type ofexception_ptr.
10. DE 19, DE 48
Modify the array-returning declarations of split in [parallel.simd.synopsis]:
template<size_t... Sizes, class T, class Abi> tuple<simd<T, simd_abi::deduce_t<T, Sizes>>...> split(const simd<T, Abi>&); template<size_t... Sizes, class T, class Abi> tuple<simd_mask<T, simd_mask_abi::deduce_t<T, Sizes>>...> split(const simd_mask<T, Abi>&); template<class V, class Abi> array<V, simd_size_v<typename V::value_type, Abi> / V::size()> split(const simd<typename V::value_type, Abi>&); template<class V, class Abi> array<V, simd_size_v<typename V::simd_type::value_type, Abi> / V::size()> split(const simd_mask<typename V::simd_type::value_type, Abi>&);
Modify the array-returning definitions of split in [parallel.simd.casts]:
template<class V, class Abi> array<V, simd_size_v<typename V::value_type, Abi> / V::size()> split(const simd<typename V::value_type, Abi>& x); template<class V, class Abi> array<V, simd_size_v<typename V::simd_type::value_type, Abi> / V::size()> split(const simd_mask<typename V::simd_type::value_type, Abi>& x);Returns: An array of data-parallel objects with the
i-thsimd/simd_maskelement of thej-th element initialized to the value of the element inxwith indexi + j * V::size().Remarks: These functions shall not participate in overload resolution unless either:
simd_size_v<typename V::value_type, Abi>is an integral multiple ofV::size(), andfor the overload with a
simdparameteris_simd_v<V>istrue, for the overload with asimd_maskparameteris_simd_mask_v<V>istrue.
is_simd_v<V>istrueandsimd_size_v<typename V::value_type, Abi>is an integral multiple ofV::size(), or
is_simd_mask_v<V>istrueandsimd_size_v<typename V::simd_type::value_type, Abi>is an integral multiple ofV::size().
11. CH 21
Modify the synopsis for namespace simd_abi in [parallel.simd.abi] as follows:
namespace simd_abi { struct scalar {}; template<int N> struct fixed_size {}; template<class T> inline constexpr int max_fixed_size = implementation-defined; template<class T> using compatible = implementation-defined; template<class T> using native = implementation-defined; }
12. CH 23
Modify [parallel.simd.abi] paragraph 9 as follows:
compatible<T>is an implementation-defined alias for an ABI tag. [ Note: The intent is to use the ABI tag producing the most efficient data-parallel execution for the element typeTthat ensures ABI compatibility between translation units on the target architecture. — end note ][ Example: Consider a target architecture supporting the extended ABI tags
__simd128and__simd256, where the__simd256type requires an optional ISA extension on said architecture. Also, the target architecture does not support long double with either ABI tag. The implementation therefore definescompatible<T>as an alias for:
compatible<T>is an alias for __simd128 for all vectorizable T, exceptlong double, and
compatible<long double>as an alias for scalar.
scalarifTis the same type aslong double, and
__simd128otherwise. — end example ]
13. US 42, US 43
Modify [parallel.simd.binary] as follows:
friend simd operator+(const simd& lhs, const simd& rhs); friend simd operator-(const simd& lhs, const simd& rhs); friend simd operator*(const simd& lhs, const simd& rhs); friend simd operator/(const simd& lhs, const simd& rhs); friend simd operator%(const simd& lhs, const simd& rhs); friend simd operator&(const simd& lhs, const simd& rhs); friend simd operator|(const simd& lhs, const simd& rhs); friend simd operator^(const simd& lhs, const simd& rhs); friend simd operator<<(const simd& lhs, const simd& rhs); friend simd operator>>(const simd& lhs, const simd& rhs);Returns: A
simdobject initialized with the results of the element-wise application of the indicated operator.applying the indicated operator tolhsandrhsas a binary element-wise operation.Throws: Nothing.
Remarks: Each of these operators shall not participate in overload resolution unless the indicated operator can be applied to objects of type
value_type.
Modify [parallel.simd.cassign] as follows:
friend simd& operator+=(simd& lhs, const simd& rhs); friend simd& operator-=(simd& lhs, const simd& rhs); friend simd& operator*=(simd& lhs, const simd& rhs); friend simd& operator/=(simd& lhs, const simd& rhs); friend simd& operator%=(simd& lhs, const simd& rhs); friend simd& operator&=(simd& lhs, const simd& rhs); friend simd& operator|=(simd& lhs, const simd& rhs); friend simd& operator^=(simd& lhs, const simd& rhs); friend simd& operator<<=(simd& lhs, const simd& rhs); friend simd& operator>>=(simd& lhs, const simd& rhs); friend simd& operator<<=(simd& lhs, int n); friend simd& operator>>=(simd& lhs, int n);Effects: These operators perform the indicated binary element-wise operation.apply the indicated operator to
lhsandrhsas an element-wise operation.Returns:
lhs.Throws: Nothing.
Remarks: These operators shall not participate in overload resolution unless the indicated operator can be applied to objects of type
value_type.friend simd& operator<<=(simd& lhs, int n); friend simd& operator>>=(simd& lhs, int n);Effects: Equivalent to:
return operator@=(lhs, simd(n));Remarks: These operators shall not participate in overload resolution unless the indicated operator can be applied to objects of type
value_type.
Modify [parallel.simd.comparison] as follows:
friend mask_type operator==(const simd& lhs, const simd& rhs); friend mask_type operator!=(const simd& lhs, const simd& rhs); friend mask_type operator>=(const simd& lhs, const simd& rhs); friend mask_type operator<=(const simd& lhs, const simd& rhs); friend mask_type operator>(const simd& lhs, const simd& rhs); friend mask_type operator<(const simd& lhs, const simd& rhs);Returns: A
simd_maskobject initialized with the results of the element-wise application of the indicated operator.applying the indicated operator tolhsandrhsas a binary element-wise operation.Throws: Nothing.
Modify [parallel.simd.mask.binary] as follows:
friend simd_mask operator&&(const simd_mask& lhs, const simd_mask& rhs) noexcept; friend simd_mask operator||(const simd_mask& lhs, const simd_mask& rhs) noexcept; friend simd_mask operator& (const simd_mask& lhs, const simd_mask& rhs) noexcept; friend simd_mask operator| (const simd_mask& lhs, const simd_mask& rhs) noexcept; friend simd_mask operator^ (const simd_mask& lhs, const simd_mask& rhs) noexcept;Returns: A
simd_maskobject initialized with the results of the element-wise appliation of the indicated operator.applying the indicated operator tolhsandrhsas a binary element-wise operation.
Modify [parallel.simd.mask.cassign] as follows:
friend simd_mask& operator&=(simd_mask& lhs, const simd_mask& rhs) noexcept; friend simd_mask& operator|=(simd_mask& lhs, const simd_mask& rhs) noexcept; friend simd_mask& operator^=(simd_mask& lhs, const simd_mask& rhs) noexcept;Effects: These operators perform the indicated binary element-wise operation.apply the indicated operator to
lhsandrhsas a binary element-wise operation.Returns:
lhs.
Modify [parallel.simd.mask.comparison] as follows:
friend simd_mask operator==(const simd_mask& lhs, const simd_mask& rhs) noexcept; friend simd_mask operator!=(const simd_mask& lhs, const simd_mask& rhs) noexcept;Returns: An object initialized with the results of the element-wise application of the indicated operator.applying the indicated operator to
lhsandrhsas a binary element-wise operation.
14. CH 30, CH 33
Add noexcept to the following functions in [parallel.simd]:
-
simd_cast -
static_simd_cast -
split -
concat -
reduce(const const_where_expression<M, V>& x, plus<> binary_op) -
reduce(const const_where_expression<M, V>& x, multiplies<> binary_op) -
reduce(const const_where_expression<M, V>& x, bit_and<> binary_op) -
reduce(const const_where_expression<M, V>& x, bit_or<> binary_op) -
reduce(const const_where_expression<M, V>& x, bit_xor<> binary_op) -
hmin -
hmax -
All members of
const_where_expressionandwhere_expression -
All
simdconstructors, exceptsimd(const U* mem, Flags f) -
All
simdmember and non-member operators, exceptoperator[] -
All
referencemember functions -
simd_mask()
Remove noexcept from the following functions in [parallel.simd]:
-
find_first_set(only the non-simd overload) -
find_last_set(only the non-simd overload) -
clamp(only in the synopsis)
Remove the following Throws: paragraphs:
-
[parallel.simd.whereexpr] paragraph 10
-
[parallel.simd.ctor] paragraph 3
-
[parallel.simd.unary] paragraph 5, paragraph 9, paragraph 13, paragraph 17, paragraph 20, paragraph 23, paragraph 27, and paragraph 30
-
[parallel.simd.binary] paragraph 3 and paragraph 7
-
[parallel.simd.cassign] paragraph 4
-
[parallel.simd.comparison] paragraph 3
-
[parallel.simd.reductions] paragraph 12, paragraph 15, paragraph 19, paragraph 23, paragraph 26, paragraph 29, paragraph 32, paragraph 35
-
[parallel.simd.casts] paragraph 4 and paragraph 10
Modify [parallel.simd.overview] paragraph 2 as follows:
Every specialization ofsimdshall be a complete type. The specializationsimd<T, Abi>is supported ifTis a vectorizable type and
Abiissimd_abi::scalar, or
Abiissimd_abi::fixed_size<N>, withNis constrained as defined in 9.2.1.If
Abiis an extended ABI tag, it is implementation-defined whethersimd<T, Abi>is supported. [ Note: The intent is for implementations to decide on the basis of the currently targeted system. — end note ]If
simd<T, Abi>is not supported, the specialization shall have a deleted default constructor, deleted destructor, deleted copy constructor, and deleted copy assignment. Otherwise, the following aretrue:
is_nothrow_move_constructible_v<simd<T, Abi>>, and
is_nothrow_move_assignable_v<simd<T, Abi>>, and
is_nothrow_default_constructible_v<simd<T, Abi>>.
Modify [parallel.simd.mask.overview] paragraph 2 as follows:
Every specialization ofsimd_maskshall be a complete type. The specializationsimd_mask<T, Abi>is supported ifTis a vectorizable type and
Abiissimd_abi::scalar, orAbiissimd_abi::fixed_size<N>, withNconstrained as defined in (9.2.1).If
Abiis an extended ABI tag, it is implementation-defined whethersimd_mask<T, Abi>is supported. [ Note: The intent is for implementations to decide on the basis of the currently targeted system. — end note ]If
simd_mask<T, Abi>is not supported, the specialization shall have a deleted default constructor, deleted destructor, deleted copy constructor, and deleted copy assignment. Otherwise, the following aretrue:
is_nothrow_move_constructible_v<simd_mask<T, Abi>>, and
is_nothrow_move_assignable_v<simd_mask<T, Abi>>, and
is_nothrow_default_constructible_v<simd_mask<T, Abi>>.
After [parallel.simd.mask.ctor] paragraph 8 add a new paragraph:
Throws: Nothing.
After [parallel.simd.mask.copy] paragraph 3 and paragraph 7 add a new paragraph:
Throws: Nothing.
After [parallel.simd.mask.reductions] paragraph 13, paragraph 16, and paragraph 22 add a new paragraph:
Throws: Nothing.
15. CH 38
Modify [parallel.simd.overview] as follows:
template<class T, class Abi> class simd { public: using value_type = T; using reference = see below; using mask_type = simd_mask<T, Abi>; using abi_type = Abi;
16. US 41, US 45, CH 46, CH 47
Modify the definition of simd's U&& constructor in [parallel.simd.ctor] as follows:
template<class U> simd(U&&);Effects: Constructs an object with each element initialized to the value of the argument after conversion to
value_type.Throws: Any exception thrown while converting the argument to
value_type.Remarks: Let
Fromdenoteidentify the typeremove_cv_t<remove_reference_t<U>>. This constructor shall not participate in overload resolution unless:
Fromis a vectorizable type and every possibly value ofFromcan be represented withvalue_type, or
Fromis not an arithmetic type and is implicitly convertible tovalue_type, or
Fromis int, orFrom is
unsigned intandvalue_typeis an unsigned integral type.
Modify the definition of simd_cast in [parallel.simd.casts] as follows:
template<class T, class U, class Abi> see below simd_cast(const simd<U, Abi>& x);Let
TodenoteidentifyT::value_typeifis_simd_v<T>istrue, orTotherwise.Returns: A
simdobject with the ith element initialized tostatic_cast<To>(x[i])for all i ∈[0, size()).Throws: Nothing.
Remarks: The function shall not participate in overload resolution unless
every possible value of type
Ucan be represented with typeTo, andeither
is_simd_v<T>isfalse, or
T::size() == simd<U, Abi>::size()istrue.The return type is
Tifis_simd_v<T>istrue, otherwise;otherwise,
simd<T, Abi>isifUis the same type asT, otherwise;otherwise,
simd<T, simd_abi::fixed_size<simd<U, Abi>::size()>>
Modify the definition of static_simd_cast in [parallel.simd.casts] as follows:
template<class T, class U, class Abi> see below static_simd_cast(const simd<U, Abi>& x);Let
TodenoteidentifyT::value_typeifis_simd_v<T>is true orTotherwise.Returns: A
simdobject with the ith element initialized tostatic_cast<To>(x[i])for all i ∈[0, size()).Throws: Nothing.
Remarks: The function shall not participate in overload resolution unless either:
is_simd_v<T>isfalse, or
T::size() == simd<U, Abi>::size()istrue.The return type is:
Tifis_simd_v<T>istrue, otherwise;otherwise,
simd<T, Abi>if eitherUis the same type asTorUandTare integral types that only differ in signedness, otherwisemake_signed_t<U>is the same type asmake_signed_t<T>;otherwise,
simd<T, simd_abi::fixed_size<simd<U, Abi>::size()>>.
17. US 50
Modify [parallel.simd.math] paragraph 2 as follows:
Each function overload produced by the above rules applies the indicated <cmath> function element-wise. The results per element are not required to be bitwiseFor the mathematical functions, the results per element only need to be approximately equal to the application of the function which is overloaded for the element type.
18. US 51
Modify [parallel.simd.synopsis] as follows:
bool all_of (see belowT) noexcept;
bool any_of (see belowT) noexcept;
bool none_of (see belowT) noexcept;
bool some_of (see belowT) noexcept;
int popcount (see belowT) noexcept;
int find_first_set(see belowT) noexcept;
int find_last_set (see belowT) noexcept;
Modify [parallel.simd.mask.reductions] as follows:
bool all_of (see belowT) noexcept;
bool any_of (see belowT) noexcept;
bool none_of (see belowT) noexcept;
bool some_of (see belowT) noexcept;
int popcount (see belowT) noexcept;
Returns:
all_ofandany_ofreturn their arguments;none_ofreturns the negation of its argument;some_ofreturnsfalse;popcountreturns the integral representation of its argument.Remarks: The functions shall not participate in overload resolution unless the argument is of type
bool.The parameter typeTis an unspecified type that is only constructible via implicit conversion frombool.
int find_first_set(see belowT) noexcept;
int find_last_set (see belowT) noexcept;Requires: The value of the argument is
true.Returns:
0.Remarks: The functions shall not participate in overload resolution unless the argument is of type
bool.The parameter typeTis an unspecified type that is only constructible via implicit conversion frombool.