14 #ifndef ROOT_RHYSD_SPAN_H
15 #define ROOT_RHYSD_SPAN_H
18 #if __cplusplus >= 201402L
19 #define R__CONSTEXPR_IF_CXX14 constexpr
21 #define R__CONSTEXPR_IF_CXX14
32 #include <type_traits>
33 #include <initializer_list>
41 struct is_array_class {
42 static bool const value =
false;
44 template<
class T,
size_t N>
45 struct is_array_class<std::array<T, N>> {
46 static bool const value =
true;
49 struct is_array_class<std::vector<T>> {
50 static bool const value =
true;
53 struct is_array_class<std::initializer_list<T>> {
54 static bool const value =
true;
59 template<
size_t... Indices >
61 static constexpr
size_t value[
sizeof...(Indices)] = {Indices...};
64 template<
class IndicesType,
size_t Next>
65 struct make_indices_next;
67 template<
size_t... Indices,
size_t Next>
68 struct make_indices_next<indices<Indices...>, Next> {
69 typedef indices<Indices..., (Indices + Next)...> type;
72 template<
class IndicesType,
size_t Next,
size_t Tail>
73 struct make_indices_next2;
75 template<
size_t... Indices,
size_t Next,
size_t Tail>
76 struct make_indices_next2<indices<Indices...>, Next, Tail> {
77 typedef indices<Indices..., (Indices + Next)..., Tail> type;
80 template<
size_t First,
size_t Step,
size_t N,
class =
void>
81 struct make_indices_impl;
83 template<
size_t First,
size_t Step,
size_t N>
84 struct make_indices_impl<
88 typename std::enable_if<(N == 0)>::type
90 typedef indices<> type;
93 template<
size_t First,
size_t Step,
size_t N>
94 struct make_indices_impl<
98 typename std::enable_if<(N == 1)>::type
100 typedef indices<First> type;
103 template<
size_t First,
size_t Step,
size_t N>
104 struct make_indices_impl<
108 typename std::enable_if<(N > 1 && N % 2 == 0)>::type
110 : ROOT::Detail::make_indices_next<
111 typename ROOT::Detail::make_indices_impl<First, Step, N / 2>::type,
116 template<
size_t First,
size_t Step,
size_t N>
117 struct make_indices_impl<
121 typename std::enable_if<(N > 1 && N % 2 == 1)>::type
123 : ROOT::Detail::make_indices_next2<
124 typename ROOT::Detail::make_indices_impl<First, Step, N / 2>::type,
125 First + N / 2 * Step,
126 First + (N - 1) * Step
130 template<
size_t First,
size_t Last,
size_t Step = 1>
132 : ROOT::Detail::make_indices_impl<
135 ((Last - First) + (Step - 1)) / Step
139 template <
size_t Start,
size_t Last,
size_t Step = 1 >
140 using make_indices =
typename make_indices_< Start, Last, Step >::type;
147 inline namespace __ROOT {
151 struct check_bound_t {};
152 static constexpr check_bound_t check_bound{};
160 typedef T element_type;
161 typedef std::remove_cv<T> value_type;
162 typedef element_type * pointer;
163 typedef element_type
const* const_pointer;
164 typedef element_type & reference;
165 typedef element_type
const& const_reference;
166 typedef element_type * iterator;
167 typedef element_type
const* const_iterator;
168 typedef ptrdiff_t difference_type;
169 typedef std::size_t index_type;
170 typedef std::reverse_iterator<iterator> reverse_iterator;
171 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
176 constexpr span() noexcept
177 : length_(0), data_(
nullptr)
180 constexpr span(span
const&) noexcept = default;
181 constexpr span(span &&) noexcept = default;
185 template<index_type N>
186 span(std::array<T, N> & a) noexcept
187 : length_(N), data_(N > 0 ? a.data() :
nullptr)
192 template<index_type N>
193 span(T(& a)[N]) noexcept
194 : length_(N), data_(N > 0 ? std::addressof(a[0]) :
nullptr)
196 static_assert(N > 0,
"Zero-length array is not permitted in ISO C++.");
199 span(std::vector<
typename std::remove_cv<T>::type>
const& v) noexcept
200 : length_(v.size()), data_(v.empty() ?
nullptr : v.data())
203 span(std::vector<
typename std::remove_cv<T>::type> & v) noexcept
204 : length_(v.size()), data_(v.empty() ?
nullptr : v.data())
207 constexpr span(pointer a, index_type
const n) noexcept
208 : length_(n), data_(a)
213 class =
typename std::enable_if<
215 typename std::remove_cv<T>::type,
216 typename std::iterator_traits<InputIterator>::value_type
220 span(InputIterator start, InputIterator last)
221 : length_(std::distance(start, last)), data_(&*start)
224 span(std::initializer_list<T>
const& l)
225 : length_(l.size()), data_(std::begin(l))
228 span& operator=(span
const&) noexcept = default;
229 span& operator=(span &&) noexcept = delete;
234 constexpr iterator begin() const noexcept
238 constexpr iterator end() const noexcept
240 return data_ + length_;
242 constexpr const_iterator cbegin() const noexcept
246 constexpr const_iterator cend() const noexcept
250 reverse_iterator rbegin()
const
254 reverse_iterator rend()
const
258 const_reverse_iterator crbegin()
const
262 const_reverse_iterator crend()
const
270 constexpr index_type size() const noexcept
274 constexpr index_type length() const noexcept
278 constexpr index_type max_size() const noexcept
282 constexpr
bool empty() const noexcept
286 constexpr reference operator[](index_type
const n)
const noexcept
290 constexpr reference at(index_type
const n)
const
295 return n >= length_ ?
throw std::out_of_range(
"span::at()") : *(data_ + n);
297 constexpr pointer data() const noexcept
301 constexpr const_reference front() const noexcept
305 constexpr const_reference back() const noexcept
307 return *(data_ + length_ - 1);
315 constexpr span<T> slice(check_bound_t, index_type
const pos, index_type
const slicelen)
const
322 return pos >= length_ || pos + slicelen >= length_ ?
throw std::out_of_range(
"span::slice()") : span<T>{begin() + pos, begin() + pos + slicelen};
324 constexpr span<T> slice_before(check_bound_t, index_type
const pos)
const
331 return pos >= length_ ? std::out_of_range(
"span::slice()") : span<T>{begin(), begin() + pos};
333 constexpr span<T> slice_after(check_bound_t, index_type
const pos)
const
340 return pos >= length_ ? std::out_of_range(
"span::slice()") : span<T>{begin() + pos, end()};
344 constexpr span<T> slice(index_type
const pos, index_type
const slicelen)
const
346 return span<T>{begin() + pos, begin() + pos + slicelen};
348 constexpr span<T> slice_before(index_type
const pos)
const
350 return span<T>{begin(), begin() + pos};
352 constexpr span<T> slice_after(index_type
const pos)
const
354 return span<T>{begin() + pos, end()};
360 constexpr span<T> slice(check_bound_t, iterator start, iterator last)
const
370 return ( start >= end() ||
373 static_cast<size_t>(std::distance(start, last > end() ? end() : last)) > length_ - std::distance(begin(), start) ) ?
throw std::out_of_range(
"span::slice()") : span<T>{start, last > end() ? end() : last};
375 constexpr span<T> slice_before(check_bound_t, iterator
const pos)
const
382 return pos < begin() || pos > end() ?
throw std::out_of_range(
"span::slice()") : span<T>{begin(), pos > end() ? end() : pos};
384 constexpr span<T> slice_after(check_bound_t, iterator
const pos)
const
391 return pos < begin() || pos > end() ?
throw std::out_of_range(
"span::slice()") : span<T>{pos < begin() ? begin() : pos, end()};
395 constexpr span<T> slice(iterator start, iterator last)
const
397 return span<T>{start, last};
399 constexpr span<T> slice_before(iterator
const pos)
const
401 return span<T>{begin(), pos};
403 constexpr span<T> slice_after(iterator
const pos)
const
405 return span<T>{pos, end()};
413 template<class Allocator = std::allocator<typename std::remove_cv<T>::type>>
414 auto to_vector(Allocator
const& alloc = Allocator{})
const
415 -> std::vector<
typename std::remove_cv<T>::type, Allocator>
417 return {begin(), end(), alloc};
421 auto to_array() const
424 return to_array_impl(ROOT::Detail::make_indices<0, N>{});
427 template<
size_t... I>
428 auto to_array_impl(ROOT::Detail::indices<I...>) const
429 -> std::array<T, sizeof...(I)>
431 return {{(I < length_ ? *(data_ + I) : T{} )...}};
446 template<
class ArrayL,
class ArrayR >
447 inline R__CONSTEXPR_IF_CXX14
448 bool operator_equal_impl(ArrayL
const& lhs,
size_t const lhs_size, ArrayR
const& rhs,
size_t const rhs_size)
450 if (lhs_size != rhs_size) {
454 auto litr = std::begin(lhs);
455 auto ritr = std::begin(rhs);
456 for (; litr != std::end(lhs); ++litr, ++ritr) {
457 if (!(*litr == *ritr)) {
468 inline namespace __ROOT {
470 template<
class T1,
class T2>
472 bool operator==(span<T1>
const& lhs, span<T2>
const& rhs)
474 return ROOT::Detail::operator_equal_impl(lhs, lhs.length(), rhs, rhs.length());
480 class =
typename std::enable_if<
481 ROOT::Detail::is_array_class<Array>::value
485 bool operator==(span<T>
const& lhs, Array
const& rhs)
487 return ROOT::Detail::operator_equal_impl(lhs, lhs.length(), rhs, rhs.size());
490 template<
class T1,
class T2,
size_t N>
492 bool operator==(span<T1>
const& lhs, T2
const (& rhs)[N])
494 return ROOT::Detail::operator_equal_impl(lhs, lhs.length(), rhs, N);
500 class =
typename std::enable_if<
501 is_array<Array>::value
505 bool operator!=(span<T>
const& lhs, Array
const& rhs)
507 return !(lhs == rhs);
513 class =
typename std::enable_if<
514 is_array<Array>::value
518 bool operator==(Array
const& lhs, span<T>
const& rhs)
526 class =
typename std::enable_if<
527 is_array<Array>::value,
532 bool operator!=(Array
const& lhs, span<T>
const& rhs)
534 return !(rhs == lhs);
541 class =
typename std::enable_if<
542 ROOT::Detail::is_array_class<Array>::value
546 auto make_view(Array
const& a)
547 -> span<typename Array::value_type>
552 template<
class T,
size_t N>
554 span<T> make_view(T
const (&a)[N])
561 span<T> make_view(T
const* p,
typename span<T>::index_type
const n)
563 return span<T>{p, n};
566 template<class InputIterator, class Result = span<typename std::iterator_traits<InputIterator>::value_type>>
568 Result make_view(InputIterator begin, InputIterator end)
570 return Result{begin, end};
575 span<T> make_view(std::initializer_list<T>
const& l)
593 #include <type_traits>
605 static constexpr
int rank = Rank;
606 using reference = ptrdiff_t &;
607 using const_reference =
const ptrdiff_t &;
608 using size_type = size_t;
609 using value_type = ptrdiff_t;
612 std::array<value_type, Rank> m_B;
615 constexpr bounds() noexcept;
617 constexpr bounds(value_type b) noexcept: m_B{{b}} { };
622 reference operator[](size_type i) noexcept {
return m_B[i]; }
624 constexpr const_reference operator[](
625 size_type i)
const noexcept {
return m_B[i]; };
628 bool operator==(
const bounds &rhs)
const noexcept;
630 bool operator!=(
const bounds &rhs)
const noexcept;
632 bounds operator+(
const index<rank> &rhs)
const noexcept;
634 bounds operator-(
const index<rank> &rhs)
const noexcept;
636 bounds &operator+=(
const index<rank> &rhs) noexcept;
638 bounds &operator-=(
const index<rank> &rhs) noexcept;
640 constexpr size_type size() const noexcept;
642 bool contains(const index<rank> &idx) const noexcept;
653 static constexpr
int rank = Rank;
654 using reference = ptrdiff_t &;
655 using const_reference =
const ptrdiff_t &;
656 using size_type = size_t;
657 using value_type = ptrdiff_t;
660 constexpr index() noexcept;
662 constexpr index(value_type) noexcept;
664 constexpr index(const initializer_list<value_type> &) noexcept;
666 constexpr index(const index &) noexcept;
668 index &operator=(const index &) noexcept;
670 reference operator[](size_type component_idx) noexcept;
672 constexpr const_reference operator[](size_type component_idx) const noexcept;
674 bool operator==(const index &rhs) const noexcept;
676 bool operator!=(const index &rhs) const noexcept;
678 index operator+(const index &rhs) const noexcept;
680 index operator-(const index &rhs) const noexcept;
682 index &operator+=(const index &rhs) noexcept;
684 index &operator-=(const index &rhs) noexcept;
686 index &operator++() noexcept;
688 index operator++(
int) noexcept;
690 index &operator--() noexcept;
692 index operator--(
int) noexcept;
694 index operator+() const noexcept;
696 index operator-() const noexcept;
701 template<typename ValueType,
int Rank = 1>
704 static constexpr
int rank = Rank;
705 using index_type = index<rank>;
706 using bounds_type = bounds<rank>;
707 using size_type =
typename bounds_type::size_type;
708 using value_type = ValueType;
709 using pointer =
typename std::add_pointer_t<value_type>;
710 using reference =
typename std::add_lvalue_reference_t<value_type>;
712 constexpr span() noexcept;
714 constexpr explicit span(std::vector<ValueType> &cont) noexcept;
716 template<typename ArrayType>
717 constexpr explicit span(ArrayType &data) noexcept;
719 template<typename ViewValueType>
720 constexpr span(const span<ViewValueType, rank> &rhs) noexcept;
722 template<typename Container>
723 constexpr span(bounds_type bounds, Container &cont) noexcept;
725 constexpr span(bounds_type bounds, pointer data) noexcept;
727 template<typename ViewValueType>
728 span &operator=(const span<ViewValueType, rank> &rhs) noexcept;
730 constexpr bounds_type bounds() const noexcept;
731 constexpr size_type size() const noexcept;
732 constexpr index_type stride() const noexcept;
734 constexpr pointer data() const noexcept;
735 constexpr reference operator[](const index_type& idx) const noexcept;
739 #endif // too complex!