13 #ifndef VC_COMMON_SPAN_H_    14 #define VC_COMMON_SPAN_H_    20 #include <type_traits>      21 #include "subscript.h"      23 namespace Vc_VERSIONED_NAMESPACE
    25 #ifdef __cpp_inline_variables    28     constexpr ptrdiff_t dynamic_extent = -1;
    31 template <
typename T, ptrdiff_t Extent = dynamic_extent> 
class span;
    33 template <
typename T, ptrdiff_t Extent>
    34 constexpr 
auto begin(
const span<T, Extent>& s) noexcept -> decltype(s.begin())
    38 template <
typename T, ptrdiff_t Extent>
    39 constexpr 
auto end(
const span<T, Extent>& s) noexcept -> decltype(s.end())
    44 template <
class T> 
struct _is_span_impl : 
public std::false_type {
    47 template <
class T, ptrdiff_t Extent>
    48 struct _is_span_impl<
span<T, Extent>> : 
public std::true_type {
    52 struct _is_span : 
public _is_span_impl<typename std::remove_cv<T>::type> {
    55 template <
class T> 
struct _is_std_array_impl : 
public std::false_type {
    58 template <
class T, 
size_t Sz>
    59 struct _is_std_array_impl<array<T, Sz>> : 
public std::true_type {
    63 struct _is_std_array : 
public _is_std_array_impl<typename std::remove_cv<T>::type> {
    66 template <
class T, 
class ElementType, 
class = 
void>
    67 struct _is_span_compatible_container : 
public std::false_type {
    70 template <
class... Ts> 
using _void_t = void;
    72 template <
class C> constexpr 
auto _std_data(C& c) -> decltype(c.data())
    76 template <
class C> constexpr 
auto _std_data(
const C& c) -> decltype(c.data())
    80 template <
class T, std::
size_t N> constexpr T* _std_data(T (&array)[N]) noexcept
    84 template <
class E> constexpr 
const E* _std_data(std::initializer_list<E> il) noexcept
    89 template <
class C> constexpr 
auto _std_size(
const C& c) -> decltype(c.size())
    93 template <
class T, std::
size_t N>
    94 constexpr std::size_t _std_size(
const T (&array)[N]) noexcept
    99 template <
class T, 
class ElementType>
   100 struct _is_span_compatible_container<
   104         typename 
std::enable_if<!_is_span<T>::value, std::nullptr_t>::type,
   106         typename std::enable_if<!_is_std_array<T>::value, std::nullptr_t>::type,
   108         typename std::enable_if<!std::is_array<T>::value, std::nullptr_t>::type,
   110         decltype(data(std::declval<T>())), decltype(size(std::declval<T>())),
   112         typename std::enable_if<
   113             std::is_convertible<typename std::remove_pointer<decltype(
   114                                     data(std::declval<T&>()))>::type (*)[],
   115                                 ElementType (*)[]>::value,
   116             std::nullptr_t>::type>> : 
public std::true_type {
   119 #if defined Vc_MSVC || (defined Vc_GCC && Vc_GCC < 0x50100) || defined Vc_ICC   122 #define Vc_CONSTEXPR constexpr   125 template <
typename T, ptrdiff_t Extent> 
class span   129     using element_type = T;
   130     using value_type = 
typename std::remove_cv<T>::type;
   131     using index_type = ptrdiff_t;
   132     using difference_type = ptrdiff_t;
   134     using const_pointer = 
const T*;  
   135     using reference = T&;
   136     using const_reference = 
const T&;  
   137     using iterator = pointer;
   138     using const_iterator = const_pointer;
   139     using reverse_iterator = std::reverse_iterator<iterator>;
   140     using const_reverse_iterator = std::reverse_iterator<const_iterator>;
   142     static constexpr index_type extent = Extent;
   143     static_assert(Extent >= 0, 
"Can't have a span with an extent < 0");
   146     Vc_CONSTEXPR 
span() noexcept : data_{
nullptr}
   148         static_assert(Extent == 0,
   149                       "Can't default construct a statically sized span with size > 0");
   152     Vc_CONSTEXPR 
span(
const span&) noexcept = default;
   153     Vc_CONSTEXPR 
span& operator=(const 
span&) noexcept = default;
   155     Vc_CONSTEXPR 
span(pointer _ptr, index_type _count) : data_{_ptr}
   158         Vc_ASSERT((
"size mismatch in span's constructor (ptr, len)", Extent == _count));
   160     Vc_CONSTEXPR 
span(pointer _f, pointer _l) : data_{_f}
   163         Vc_ASSERT((
"size mismatch in span's constructor (ptr, ptr)",
   164                    Extent == distance(_f, _l)));
   167     Vc_CONSTEXPR 
span(element_type (&_arr)[Extent]) noexcept : data_{_arr} {}
   168     Vc_CONSTEXPR 
span(array<value_type, Extent>& _arr) noexcept : data_{_arr.data()} {}
   169     Vc_CONSTEXPR 
span(
const array<value_type, Extent>& _arr) noexcept : data_{_arr.data()} {}
   171     template <
class Container>
   172     inline Vc_CONSTEXPR 
span(
   174         typename std::enable_if<_is_span_compatible_container<Container, T>::value,
   175                                 std::nullptr_t>::type = 
nullptr)
   176         : data_{_std_data(_c)}
   178         Vc_ASSERT((
"size mismatch in span's constructor (container))",
   179                    Extent == _std_size(_c)));
   182     template <
class Container>
   183     inline Vc_CONSTEXPR 
span(
   185         typename std::enable_if<_is_span_compatible_container<const Container, T>::value,
   186                                 std::nullptr_t>::type = 
nullptr)
   187         : data_{_std_data(_c)}
   189         Vc_ASSERT((
"size mismatch in span's constructor (const container)",
   190                    Extent == _std_size(_c)));
   193     template <
class OtherElementType>
   194     inline Vc_CONSTEXPR 
span(
   195         const span<OtherElementType, Extent>& _other,
   196         typename std::enable_if<
   197             std::is_convertible<OtherElementType (*)[], element_type (*)[]>::value,
   198             std::nullptr_t>::type = 
nullptr)
   199         : data_{_other.data()}
   203     template <
class OtherElementType>
   204     inline Vc_CONSTEXPR 
span(
   205         const span<OtherElementType, dynamic_extent>& _other,
   206         typename std::enable_if<
   207             std::is_convertible<OtherElementType (*)[], element_type (*)[]>::value,
   208             std::nullptr_t>::type = 
nullptr) noexcept
   209         : data_{_other.data()}
   211         Vc_ASSERT((
"size mismatch in span's constructor (other span)",
   212                    Extent == _other.size()));
   217     template <ptrdiff_t Count>
   218     inline Vc_CONSTEXPR span<element_type, Count> first() const noexcept
   220         static_assert(Count >= 0, 
"Count must be >= 0 in span::first()");
   221         static_assert(Count <= Extent, 
"Count out of range in span::first()");
   222         return {data(), Count};
   225     template <ptrdiff_t Count>
   226     inline Vc_CONSTEXPR span<element_type, Count> last() const noexcept
   228         static_assert(Count >= 0, 
"Count must be >= 0 in span::last()");
   229         static_assert(Count <= Extent, 
"Count out of range in span::last()");
   230         return {data() + size() - Count, Count};
   233     Vc_CONSTEXPR span<element_type, dynamic_extent> first(index_type _count) 
const noexcept
   235         Vc_ASSERT((
"Count out of range in span::first(count)",
   236                    _count >= 0 && _count <= size()));
   237         return {data(), _count};
   240     Vc_CONSTEXPR span<element_type, dynamic_extent> last(index_type _count) 
const noexcept
   243             (
"Count out of range in span::last(count)", _count >= 0 && _count <= size()));
   244         return {data() + size() - _count, _count};
   251     template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent>
   252     inline Vc_CONSTEXPR 
auto subspan() const noexcept
   253         -> span<element_type, Count != dynamic_extent ? Count : Extent - Offset>
   256             (
"Offset out of range in span::subspan()", Offset >= 0 && Offset <= size()));
   257         return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
   260     inline Vc_CONSTEXPR span<element_type, dynamic_extent> subspan(
   261         index_type offset, index_type count = dynamic_extent) const noexcept
   263         Vc_ASSERT((
"Offset out of range in span::subspan(offset, count)",
   264                    offset >= 0 && offset <= size()));
   265         Vc_ASSERT((
"Count out of range in span::subspan(offset, count)",
   266                    (count >= 0 && count <= size()) || count == dynamic_extent));
   267         if (count == dynamic_extent) {
   268             return {data() + offset, size() - offset};
   270         Vc_ASSERT((
"count + offset out of range in span::subspan(offset, count)",
   271                    offset + count <= size()));
   272         return {data() + offset, count};
   276     Vc_CONSTEXPR index_type size() const noexcept { 
return Extent; }
   277     Vc_CONSTEXPR index_type size_bytes() const noexcept
   279         return Extent * 
sizeof(element_type);
   281     Vc_CONSTEXPR 
bool empty() const noexcept { 
return Extent == 0; }
   283     Vc_CONSTEXPR reference operator[](index_type _idx) 
const noexcept
   285         Vc_ASSERT((
"span<T,N>[] index out of bounds", _idx >= 0 && _idx < size()));
   289     Vc_CONSTEXPR reference operator()(index_type _idx) 
const noexcept
   291         Vc_ASSERT((
"span<T,N>() index out of bounds", _idx >= 0 && _idx < size()));
   295     Vc_CONSTEXPR pointer data() const noexcept { 
return data_; }
   298     Vc_CONSTEXPR iterator begin() const noexcept { 
return iterator(data()); }
   299     Vc_CONSTEXPR iterator end() const noexcept { 
return iterator(data() + size()); }
   300     Vc_CONSTEXPR const_iterator cbegin() const noexcept { 
return const_iterator(data()); }
   301     Vc_CONSTEXPR const_iterator cend() const noexcept
   303         return const_iterator(data() + size());
   305     Vc_CONSTEXPR reverse_iterator rbegin() const noexcept { 
return reverse_iterator(end()); }
   306     Vc_CONSTEXPR reverse_iterator rend() const noexcept { 
return reverse_iterator(begin()); }
   307     Vc_CONSTEXPR const_reverse_iterator crbegin() const noexcept
   309         return const_reverse_iterator(cend());
   311     Vc_CONSTEXPR const_reverse_iterator crend() const noexcept
   313         return const_reverse_iterator(cbegin());
   316     Vc_CONSTEXPR 
void swap(span& _other) noexcept
   319         data_ = _other.data_;
   323 #ifdef __cpp_lib_byte   324     span<const std::byte, Extent * sizeof(element_type)> _as_bytes() const noexcept
   326         return {
reinterpret_cast<const std::byte*
>(data()), size_bytes()};
   329     span<std::byte, Extent * sizeof(element_type)> _as_writeable_bytes() const noexcept
   331         return {
reinterpret_cast<std::byte*
>(data()), size_bytes()};
   333 #endif  // __cpp_lib_byte   339 template <
typename T> 
class span<T, dynamic_extent>
   344     using element_type = T;
   345     using value_type = 
typename std::remove_cv<T>::type;
   346     using index_type = ptrdiff_t;
   347     using difference_type = ptrdiff_t;
   349     using const_pointer = 
const T*;  
   350     using reference = T&;
   351     using const_reference = 
const T&;  
   352     using iterator = pointer;
   353     using const_iterator = const_pointer;
   354     using reverse_iterator = std::reverse_iterator<iterator>;
   355     using const_reverse_iterator = std::reverse_iterator<const_iterator>;
   357     static constexpr index_type extent = dynamic_extent;
   360     Vc_CONSTEXPR 
span() noexcept : data_{
nullptr}, size_{0} {}
   362     Vc_CONSTEXPR 
span(
const span&) noexcept = default;
   363     Vc_CONSTEXPR span& operator=(const span&) noexcept = default;
   365     Vc_CONSTEXPR span(pointer _ptr, index_type _count) : data_{_ptr}, size_{_count} {}
   366     Vc_CONSTEXPR 
span(pointer _f, pointer _l) : data_{_f}, size_{distance(_f, _l)} {}
   369     inline Vc_CONSTEXPR 
span(element_type (&_arr)[Sz]) noexcept : data_{_arr}, size_{Sz}
   374     inline Vc_CONSTEXPR 
span(array<value_type, Sz>& _arr) noexcept
   375         : data_{_arr.data()}, size_{Sz}
   380     inline Vc_CONSTEXPR 
span(
const array<value_type, Sz>& _arr) noexcept
   381         : data_{_arr.data()}, size_{Sz}
   385     template <
class Container>
   386     inline Vc_CONSTEXPR 
span(
   388         typename std::enable_if<_is_span_compatible_container<Container, T>::value,
   389                                 std::nullptr_t>::type = 
nullptr)
   390         : data_{_std_data(_c)}, size_{index_type(_std_size(_c))}
   394     template <
class Container>
   395     inline Vc_CONSTEXPR 
span(
   397         typename std::enable_if<_is_span_compatible_container<const Container, T>::value,
   398                                 std::nullptr_t>::type = 
nullptr)
   399         : data_{_std_data(_c)}, size_{index_type(_std_size(_c))}
   403     template <
class OtherElementType, ptrdiff_t OtherExtent>
   404     inline Vc_CONSTEXPR 
span(
   405         const span<OtherElementType, OtherExtent>& _other,
   406         typename std::enable_if<
   407             std::is_convertible<OtherElementType (*)[], element_type (*)[]>::value,
   408             std::nullptr_t>::type = 
nullptr) noexcept
   409         : data_{_other.data()}, size_{_other.size()}
   415     template <ptrdiff_t Count>
   416     inline Vc_CONSTEXPR span<element_type, Count> first() const noexcept
   418         static_assert(Count >= 0, 
"");
   419         Vc_ASSERT((
"Count out of range in span::first()", Count <= size()));
   420         return {data(), Count};
   423     template <ptrdiff_t Count>
   424     inline Vc_CONSTEXPR span<element_type, Count> last() const noexcept
   426         static_assert(Count >= 0, 
"");
   427         Vc_ASSERT((
"Count out of range in span::last()", Count <= size()));
   428         return {data() + size() - Count, Count};
   431     Vc_CONSTEXPR span<element_type, dynamic_extent> first(index_type _count) 
const noexcept
   433         Vc_ASSERT((
"Count out of range in span::first(count)",
   434                    _count >= 0 && _count <= size()));
   435         return {data(), _count};
   438     Vc_CONSTEXPR span<element_type, dynamic_extent> last(index_type _count) 
const noexcept
   441             (
"Count out of range in span::last(count)", _count >= 0 && _count <= size()));
   442         return {data() + size() - _count, _count};
   445     template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent>
   446     inline Vc_CONSTEXPR span<T, dynamic_extent> subspan() const noexcept
   449             (
"Offset out of range in span::subspan()", Offset >= 0 && Offset <= size()));
   450         Vc_ASSERT((
"Count out of range in span::subspan()",
   451                    Count == dynamic_extent || Offset + Count <= size()));
   452         return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
   455     Vc_CONSTEXPR span<element_type, dynamic_extent> 
inline subspan(
   456         index_type _offset, index_type _count = dynamic_extent) const noexcept
   458         Vc_ASSERT((
"Offset out of range in span::subspan(offset, count)",
   459                    _offset >= 0 && _offset <= size()));
   460         Vc_ASSERT((
"count out of range in span::subspan(offset, count)",
   461                    (_count >= 0 && _count <= size()) || _count == dynamic_extent));
   462         if (_count == dynamic_extent)
   463             return {data() + _offset, size() - _offset};
   464         Vc_ASSERT((
"Offset + count out of range in span::subspan(offset, count)",
   465                    _offset + _count <= size()));
   466         return {data() + _offset, _count};
   469     Vc_CONSTEXPR index_type size() const noexcept { 
return size_; }
   470     Vc_CONSTEXPR index_type size_bytes() const noexcept
   472         return size_ * 
sizeof(element_type);
   474     Vc_CONSTEXPR 
bool empty() const noexcept { 
return size_ == 0; }
   476     Vc_CONSTEXPR reference operator[](index_type _idx) 
const noexcept
   478         Vc_ASSERT((
"span<T>[] index out of bounds", _idx >= 0 && _idx < size()));
   482     Vc_CONSTEXPR reference operator()(index_type _idx) 
const noexcept
   484         Vc_ASSERT((
"span<T>() index out of bounds", _idx >= 0 && _idx < size()));
   488     Vc_CONSTEXPR pointer data() const noexcept { 
return data_; }
   491     Vc_CONSTEXPR iterator begin() const noexcept { 
return iterator(data()); }
   492     Vc_CONSTEXPR iterator end() const noexcept { 
return iterator(data() + size()); }
   493     Vc_CONSTEXPR const_iterator cbegin() const noexcept { 
return const_iterator(data()); }
   494     Vc_CONSTEXPR const_iterator cend() const noexcept
   496         return const_iterator(data() + size());
   498     Vc_CONSTEXPR reverse_iterator rbegin() const noexcept { 
return reverse_iterator(end()); }
   499     Vc_CONSTEXPR reverse_iterator rend() const noexcept { 
return reverse_iterator(begin()); }
   500     Vc_CONSTEXPR const_reverse_iterator crbegin() const noexcept
   502         return const_reverse_iterator(cend());
   504     Vc_CONSTEXPR const_reverse_iterator crend() const noexcept
   506         return const_reverse_iterator(cbegin());
   509     Vc_CONSTEXPR 
void swap(span& _other) noexcept
   512         data_ = _other.data_;
   515         index_type _sz = size_;
   516         size_ = _other.size_;
   520 #ifdef __cpp_lib_byte   521     span<const std::byte, dynamic_extent> _as_bytes() const noexcept
   523         return {
reinterpret_cast<const std::byte*
>(data()), size_bytes()};
   526     span<std::byte, dynamic_extent> _as_writeable_bytes() const noexcept
   528         return {
reinterpret_cast<std::byte*
>(data()), size_bytes()};
   530 #endif  // __cpp_lib_byte   537 template <
class T1, ptrdiff_t Extent1, 
class T2, ptrdiff_t Extent2>
   538 Vc_CONSTEXPR 
bool operator==(
const span<T1, Extent1>& lhs, 
const span<T2, Extent2>& rhs)
   540     return equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
   543 template <
class T1, ptrdiff_t Extent1, 
class T2, ptrdiff_t Extent2>
   544 Vc_CONSTEXPR 
bool operator!=(
const span<T1, Extent1>& lhs, 
const span<T2, Extent2>& rhs)
   546     return !(rhs == lhs);
   549 template <
class T1, ptrdiff_t Extent1, 
class T2, ptrdiff_t Extent2>
   550 Vc_CONSTEXPR 
bool operator<(const span<T1, Extent1>& lhs, 
const span<T2, Extent2>& rhs)
   552     return lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
   555 template <
class T1, ptrdiff_t Extent1, 
class T2, ptrdiff_t Extent2>
   556 Vc_CONSTEXPR 
bool operator<=(const span<T1, Extent1>& lhs, 
const span<T2, Extent2>& rhs)
   561 template <
class T1, ptrdiff_t Extent1, 
class T2, ptrdiff_t Extent2>
   562 Vc_CONSTEXPR 
bool operator>(
const span<T1, Extent1>& lhs, 
const span<T2, Extent2>& rhs)
   567 template <
class T1, ptrdiff_t Extent1, 
class T2, ptrdiff_t Extent2>
   568 Vc_CONSTEXPR 
bool operator>=(
const span<T1, Extent1>& lhs, 
const span<T2, Extent2>& rhs)
   574 template <
class T, ptrdiff_t Extent>
   575 auto as_bytes(span<T, Extent> _s) noexcept -> decltype(_s._as_bytes())
   577     return _s._as_bytes();
   580 template <
class T, ptrdiff_t Extent>
   581 auto as_writeable_bytes(span<T, Extent> _s) noexcept ->
   582     typename std::enable_if<!std::is_const<T>::value,
   583                             decltype(_s._as_writeable_bytes())>::type
   585     return _s._as_writeable_bytes();
   588 template <
class T, ptrdiff_t Extent>
   589 Vc_CONSTEXPR 
void swap(span<T, Extent>& lhs, span<T, Extent>& rhs) noexcept
   597 #ifdef __cpp_deduction_guides   598 template <
class T, 
size_t Sz> 
span(T (&)[Sz])->span<T, Sz>;
   600 template <
class T, 
size_t Sz> 
span(array<T, Sz>&)->span<T, Sz>;
   602 template <
class T, 
size_t Sz> 
span(
const array<T, Sz>&)->span<
const T, Sz>;
   604 template <
class Container> 
span(Container&)->span<
typename Container::value_type>;
   606 template <
class Container>
   607 span(
const Container&)->span<
const typename Container::value_type>;
   608 #endif  // __cpp_deduction_guides   634 template <
typename T, ptrdiff_t Extent>
   635 using span = Common::AdaptSubscriptOperator<Common::span<T, Extent>>;
   639 template <
typename T, ptrdiff_t Extent>
   640 struct has_contiguous_storage_impl<Vc::span<T, Extent>> : 
public std::true_type {
   642 template <
typename T, ptrdiff_t Extent>
   643 struct has_contiguous_storage_impl<Vc::
Common::span<T, Extent>> : 
public std::true_type {
   649 #endif  // VC_COMMON_SPAN_H_ void swap(Adapter< S, T, N > &a, std::size_t i, S &x)
Swaps one scalar object x with a SIMD slot at offset i in the simdized object a. 
Common::AdaptSubscriptOperator< Common::span< T, Extent >> span
An adapted std::span with additional subscript operators supporting gather and scatter operations...
result_vector_type< L, R >::mask_type operator!=(L &&lhs, R &&rhs)
Applies != component-wise and concurrently. 
result_vector_type< L, R >::mask_type operator==(L &&lhs, R &&rhs)
Applies == component-wise and concurrently. 
result_vector_type< L, R >::mask_type operator>=(L &&lhs, R &&rhs)
Applies >= component-wise and concurrently. 
result_vector_type< L, R >::mask_type operator>(L &&lhs, R &&rhs)
Applies > component-wise and concurrently.