1. Motivation
The
function takes a
object and breaks it down
into a tuple of as many objects of type
that it can, and maybe one
remainder object. An example illustrates this:
simd < float , 19 > x ; using IntoType = simd < float , 8 > ; auto t = simd_split < IntoType > ( x ); // get<0>(t) will be of type simd<float, 8> // get<1>(t) will be of type simd<float, 8> // get<2>(t) will be of type simd<float, 3> - the remainder
If the original type is perfectly divisible into type
then an
is
returned instead of a tuple of different sized
objects.
The behaviour
is virtually identical to that of
and
. They take a view and
a number n and produce a range of views (the chunks) of the original view, such
that each chunk, except maybe the last one, has the size n.
In contrast, the more closely named
has a different
behaviour to
. The ranges version of
takes an input range
and a delimiter value, and generates a range of views split on the delimiter. For
example, the string "This,is,a,list", when split by the comma value would
generate a range containing 4 views: "This", "is", "a", "list".
We propose that the
function is renamed to
to make
its behaviour consistant with the existing range/view counterparts.
Note that a common use case for
/
is to break a larger
object into smaller native-sized pieces to call target-specific
intrinsics. In this case the size of the chunk is known, but the user has to
supply a complete type as the first template parameter to
:
simd < float , 19 > x ; // Break into AVX2-sized pieces: auto t = simd_chunk < simd < float , 8 >> ( x );
In addition to this style we also propose that an overload is provided that
takes the size of the chunk, rather than a complete
type, which makes the
most common use case more readable:
simd < float , 19 > x ; // Break into AVX2-sized pieces: auto t = simd_chunk < 8 > ( x );
2. Wording
2.1. Rename split to chunk in overview
�// [simd.creation], basic_simd and basic_simd_mask creation template < class V , class Abi > constexpr auto simd_split simd_chunk ( const basic_simd < typename V :: value_type , Abi >& x ) noexcept ; template < class M , class Abi > constexpr auto simd_split simd_chunk ( const basic_simd_mask < mask - element - size < M > , Abi >& x ) noexcept ;
2.2. Add simd_chunk
integer overload to overview
�// [simd.creation], basic_simd and basic_simd_mask creation template < size_t N , class T , class Abi > constexpr auto simd_chunk ( const basic_simd < T , Abi >& x ) noexcept ; template < size_t N , size_t Bytes , class Abi > constexpr auto simd_chunk ( const basic_simd_mask < Bytes , Abi >& x ) noexcept ;
2.3. Add description of basic_simd
and basic_simd_mask
creation [simd.creation]
�
and
basic_simd creation [simd.creation]
basic_simd_mask template < class T , class Abi > constexpr auto simd_split simd_chunk ( const basic_simd < typename T :: value_type , Abi >& x ) noexcept ; template < class T , class Abi > constexpr auto simd_split simd_chunk ( const basic_simd_mask < mask - element - size < T > , Abi >& x ) noexcept ;
template < size_t N , class T , class Abi > constexpr auto simd_chunk ( const basic_simd < T , Abi >& x ) noexcept ; Effects:
Equivalent to
return simd_chunk < resize_simd_t < N , basic_simd < T , Abi >>> ( x ) template < size_t N , size_t Bytes , class Abi > constexpr auto simd_chunk ( const basic_simd_mask < Bytes , Abi >& x ) noexcept ; Equivalent to
return simd_chunk < resize_simd_t < N , basic_simd_mask < Bytes , Abi >>> ( x )