10#ifndef XTENSOR_STORAGE_HPP
11#define XTENSOR_STORAGE_HPP
16#include <initializer_list>
21#include "xexception.hpp"
22#include "xtensor_config.hpp"
23#include "xtensor_simd.hpp"
32 using require_input_iter =
typename std::enable_if<
33 std::is_convertible<typename std::iterator_traits<It>::iterator_category, std::input_iterator_tag>::value>::type;
41 template <
class T,
class A = std::allocator<T>>
46 using allocator_type = A;
48 using value_type =
typename std::allocator_traits<A>::value_type;
49 using reference = value_type&;
50 using const_reference =
const value_type&;
51 using pointer =
typename std::allocator_traits<A>::pointer;
52 using const_pointer =
typename std::allocator_traits<A>::const_pointer;
54 using size_type =
typename std::allocator_traits<A>::size_type;
55 using difference_type =
typename std::allocator_traits<A>::difference_type;
57 using iterator = pointer;
58 using const_iterator = const_pointer;
59 using reverse_iterator = std::reverse_iterator<iterator>;
60 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
64 explicit uvector(size_type count,
const allocator_type&
alloc = allocator_type());
65 uvector(size_type count, const_reference value,
const allocator_type&
alloc = allocator_type());
67 template <
class InputIt,
class = detail::require_input_iter<InputIt>>
70 uvector(std::initializer_list<T> init,
const allocator_type&
alloc = allocator_type());
82 allocator_type get_allocator()
const noexcept;
84 bool empty()
const noexcept;
85 size_type size()
const noexcept;
86 void resize(size_type size);
87 size_type max_size()
const noexcept;
88 void reserve(size_type
new_cap);
89 size_type capacity()
const noexcept;
93 reference operator[](size_type
i);
94 const_reference operator[](size_type
i)
const;
96 reference at(size_type
i);
97 const_reference at(size_type
i)
const;
100 const_reference front()
const;
103 const_reference back()
const;
105 pointer data()
noexcept;
106 const_pointer data()
const noexcept;
108 iterator begin()
noexcept;
109 iterator end()
noexcept;
111 const_iterator begin()
const noexcept;
112 const_iterator end()
const noexcept;
114 const_iterator cbegin()
const noexcept;
115 const_iterator cend()
const noexcept;
117 reverse_iterator rbegin()
noexcept;
118 reverse_iterator rend()
noexcept;
120 const_reverse_iterator rbegin()
const noexcept;
121 const_reverse_iterator rend()
const noexcept;
123 const_reverse_iterator crbegin()
const noexcept;
124 const_reverse_iterator crend()
const noexcept;
133 void resize_impl(size_type
new_size);
135 allocator_type m_allocator;
143 template <
class T,
class A>
146 template <
class T,
class A>
149 template <
class T,
class A>
152 template <
class T,
class A>
155 template <
class T,
class A>
158 template <
class T,
class A>
161 template <
class T,
class A>
171 inline typename std::allocator_traits<A>::pointer
172 safe_init_allocate(A&
alloc,
typename std::allocator_traits<A>::size_type size)
174 using traits = std::allocator_traits<A>;
175 using pointer =
typename traits::pointer;
176 using value_type =
typename traits::value_type;
178 if (!xtrivially_default_constructible<value_type>::value)
180 for (pointer
p =
res;
p !=
res + size; ++
p)
182 traits::construct(
alloc,
p, value_type());
189 inline void safe_destroy_deallocate(
191 typename std::allocator_traits<A>::pointer ptr,
192 typename std::allocator_traits<A>::size_type size
195 using traits = std::allocator_traits<A>;
196 using pointer =
typename traits::pointer;
197 using value_type =
typename traits::value_type;
200 if (!xtrivially_default_constructible<value_type>::value)
202 for (pointer p = ptr; p != ptr + size; ++p)
204 traits::destroy(alloc, p);
207 traits::deallocate(alloc, ptr, size);
212 template <
class T,
class A>
214 inline void uvector<T, A>::init_data(I first, I last)
216 size_type size =
static_cast<size_type
>(std::distance(first, last));
217 if (size != size_type(0))
219 p_begin = m_allocator.allocate(size);
220 std::uninitialized_copy(first, last, p_begin);
221 p_end = p_begin + size;
225 template <
class T,
class A>
226 inline void uvector<T, A>::resize_impl(size_type new_size)
228 size_type old_size = size();
229 pointer old_begin = p_begin;
230 if (new_size != old_size)
232 p_begin = detail::safe_init_allocate(m_allocator, new_size);
233 p_end = p_begin + new_size;
234 detail::safe_destroy_deallocate(m_allocator, old_begin, old_size);
238 template <
class T,
class A>
239 inline uvector<T, A>::uvector() noexcept
240 : uvector(allocator_type())
244 template <
class T,
class A>
245 inline uvector<T, A>::uvector(
const allocator_type& alloc) noexcept
252 template <
class T,
class A>
253 inline uvector<T, A>::uvector(size_type count,
const allocator_type& alloc)
260 p_begin = detail::safe_init_allocate(m_allocator, count);
261 p_end = p_begin + count;
265 template <
class T,
class A>
266 inline uvector<T, A>::uvector(size_type count, const_reference value,
const allocator_type& alloc)
273 p_begin = m_allocator.allocate(count);
274 p_end = p_begin + count;
275 std::uninitialized_fill(p_begin, p_end, value);
279 template <
class T,
class A>
280 template <
class InputIt,
class>
281 inline uvector<T, A>::uvector(InputIt first, InputIt last,
const allocator_type& alloc)
286 init_data(first, last);
289 template <
class T,
class A>
290 inline uvector<T, A>::uvector(std::initializer_list<T> init,
const allocator_type& alloc)
295 init_data(init.begin(), init.end());
298 template <
class T,
class A>
299 inline uvector<T, A>::~uvector()
301 detail::safe_destroy_deallocate(m_allocator, p_begin, size());
306 template <
class T,
class A>
307 inline uvector<T, A>::uvector(
const uvector& rhs)
309 std::allocator_traits<allocator_type>::select_on_container_copy_construction(rhs.get_allocator())
314 init_data(rhs.p_begin, rhs.p_end);
317 template <
class T,
class A>
318 inline uvector<T, A>::uvector(
const uvector& rhs,
const allocator_type& alloc)
323 init_data(rhs.p_begin, rhs.p_end);
326 template <
class T,
class A>
327 inline uvector<T, A>& uvector<T, A>::operator=(
const uvector& rhs)
332 m_allocator = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
335 resize_impl(rhs.size());
336 if (xtrivially_default_constructible<value_type>::value)
338 std::uninitialized_copy(rhs.p_begin, rhs.p_end, p_begin);
342 std::copy(rhs.p_begin, rhs.p_end, p_begin);
348 template <
class T,
class A>
349 inline uvector<T, A>::uvector(uvector&& rhs) noexcept
350 : m_allocator(std::move(rhs.m_allocator))
351 , p_begin(rhs.p_begin)
354 rhs.p_begin =
nullptr;
358 template <
class T,
class A>
359 inline uvector<T, A>::uvector(uvector&& rhs,
const allocator_type& alloc) noexcept
361 , p_begin(rhs.p_begin)
364 rhs.p_begin =
nullptr;
368 template <
class T,
class A>
369 inline uvector<T, A>& uvector<T, A>::operator=(uvector&& rhs)
noexcept
372 uvector tmp(std::move(rhs));
373 swap(p_begin, tmp.p_begin);
374 swap(p_end, tmp.p_end);
378 template <
class T,
class A>
379 inline auto uvector<T, A>::get_allocator() const noexcept -> allocator_type
381 return allocator_type(m_allocator);
384 template <
class T,
class A>
385 inline bool uvector<T, A>::empty() const noexcept
387 return size() == size_type(0);
390 template <
class T,
class A>
391 inline auto uvector<T, A>::size() const noexcept -> size_type
393 return static_cast<size_type
>(p_end - p_begin);
396 template <
class T,
class A>
397 inline void uvector<T, A>::resize(size_type size)
402 template <
class T,
class A>
403 inline auto uvector<T, A>::max_size() const noexcept -> size_type
405 return m_allocator.max_size();
408 template <
class T,
class A>
409 inline void uvector<T, A>::reserve(size_type )
413 template <
class T,
class A>
414 inline auto uvector<T, A>::capacity() const noexcept -> size_type
419 template <
class T,
class A>
420 inline void uvector<T, A>::shrink_to_fit()
424 template <
class T,
class A>
425 inline void uvector<T, A>::clear()
427 resize(size_type(0));
430 template <
class T,
class A>
431 inline auto uvector<T, A>::operator[](size_type i) -> reference
436 template <
class T,
class A>
437 inline auto uvector<T, A>::operator[](size_type i)
const -> const_reference
442 template <
class T,
class A>
443 inline auto uvector<T, A>::at(size_type i) -> reference
447 XTENSOR_THROW(std::out_of_range,
"Out of range in uvector access");
449 return this->operator[](i);
452 template <
class T,
class A>
453 inline auto uvector<T, A>::at(size_type i)
const -> const_reference
457 XTENSOR_THROW(std::out_of_range,
"Out of range in uvector access");
459 return this->operator[](i);
462 template <
class T,
class A>
463 inline auto uvector<T, A>::front() -> reference
468 template <
class T,
class A>
469 inline auto uvector<T, A>::front() const -> const_reference
474 template <
class T,
class A>
475 inline auto uvector<T, A>::back() -> reference
480 template <
class T,
class A>
481 inline auto uvector<T, A>::back() const -> const_reference
486 template <
class T,
class A>
487 inline auto uvector<T, A>::data() noexcept -> pointer
492 template <
class T,
class A>
493 inline auto uvector<T, A>::data() const noexcept -> const_pointer
498 template <
class T,
class A>
499 inline auto uvector<T, A>::begin() noexcept -> iterator
504 template <
class T,
class A>
505 inline auto uvector<T, A>::end() noexcept -> iterator
510 template <
class T,
class A>
511 inline auto uvector<T, A>::begin() const noexcept -> const_iterator
516 template <
class T,
class A>
517 inline auto uvector<T, A>::end() const noexcept -> const_iterator
522 template <
class T,
class A>
523 inline auto uvector<T, A>::cbegin() const noexcept -> const_iterator
528 template <
class T,
class A>
529 inline auto uvector<T, A>::cend() const noexcept -> const_iterator
534 template <
class T,
class A>
535 inline auto uvector<T, A>::rbegin() noexcept -> reverse_iterator
537 return reverse_iterator(end());
540 template <
class T,
class A>
541 inline auto uvector<T, A>::rend() noexcept -> reverse_iterator
543 return reverse_iterator(begin());
546 template <
class T,
class A>
547 inline auto uvector<T, A>::rbegin() const noexcept -> const_reverse_iterator
549 return const_reverse_iterator(end());
552 template <
class T,
class A>
553 inline auto uvector<T, A>::rend() const noexcept -> const_reverse_iterator
555 return const_reverse_iterator(begin());
558 template <
class T,
class A>
559 inline auto uvector<T, A>::crbegin() const noexcept -> const_reverse_iterator
564 template <
class T,
class A>
565 inline auto uvector<T, A>::crend() const noexcept -> const_reverse_iterator
570 template <
class T,
class A>
571 inline void uvector<T, A>::swap(uvector<T, A>& rhs)
noexcept
574 swap(m_allocator, rhs.m_allocator);
575 swap(p_begin, rhs.p_begin);
576 swap(p_end, rhs.p_end);
579 template <
class T,
class A>
580 inline bool operator==(
const uvector<T, A>& lhs,
const uvector<T, A>& rhs)
582 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
585 template <
class T,
class A>
586 inline bool operator!=(
const uvector<T, A>& lhs,
const uvector<T, A>& rhs)
588 return !(lhs == rhs);
591 template <
class T,
class A>
592 inline bool operator<(
const uvector<T, A>& lhs,
const uvector<T, A>& rhs)
594 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
597 template <
class T,
class A>
598 inline bool operator<=(
const uvector<T, A>& lhs,
const uvector<T, A>& rhs)
603 template <
class T,
class A>
604 inline bool operator>(
const uvector<T, A>& lhs,
const uvector<T, A>& rhs)
609 template <
class T,
class A>
610 inline bool operator>=(
const uvector<T, A>& lhs,
const uvector<T, A>& rhs)
615 template <
class T,
class A>
616 inline void swap(uvector<T, A>& lhs, uvector<T, A>& rhs)
noexcept
628 struct allocator_alignment
630 static constexpr std::size_t value = 0;
633 template <
class T, std::
size_t A>
634 struct allocator_alignment<xt_simd::aligned_allocator<T, A>>
636 static constexpr std::size_t value = A;
640 template <
class T, std::
size_t N = 4,
class A = std::allocator<T>,
bool Init = true>
646 using allocator_type = A;
647 using size_type =
typename std::allocator_traits<A>::size_type;
648 using value_type =
typename std::allocator_traits<A>::value_type;
649 using pointer =
typename std::allocator_traits<A>::pointer;
650 using const_pointer =
typename std::allocator_traits<A>::const_pointer;
651 using reference = value_type&;
652 using const_reference =
const value_type&;
653 using difference_type =
typename std::allocator_traits<A>::difference_type;
655 using iterator = pointer;
656 using const_iterator = const_pointer;
657 using reverse_iterator = std::reverse_iterator<iterator>;
658 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
660#if defined(_MSC_VER) && _MSC_VER < 1910
661 static constexpr std::size_t alignment = detail::allocator_alignment<A>::value;
663 static constexpr std::size_t alignment = detail::allocator_alignment<A>::value != 0
664 ? detail::allocator_alignment<A>::value
672 explicit svector(size_type
n,
const allocator_type&
alloc = allocator_type());
673 svector(size_type
n,
const value_type&
v,
const allocator_type&
alloc = allocator_type());
674 svector(std::initializer_list<T>
il,
const allocator_type&
alloc = allocator_type());
678 template <
class IT,
class = detail::require_input_iter<IT>>
681 template <std::
size_t N2,
bool I2,
class = std::enable_if_t<N != N2,
void>>
685 svector& operator=(
svector&&
rhs)
noexcept(std::is_nothrow_move_assignable<value_type>::value);
686 svector& operator=(
const std::vector<T>&
rhs);
687 svector& operator=(std::initializer_list<T>
il);
689 template <std::
size_t N2,
bool I2,
class = std::enable_if_t<N != N2,
void>>
693 svector(
svector&& other)
noexcept(std::is_nothrow_move_constructible<value_type>::value);
695 void assign(size_type
n,
const value_type&
v);
698 void assign(std::initializer_list<V>
il);
703 reference operator[](size_type idx);
704 const_reference operator[](size_type idx)
const;
706 reference at(size_type idx);
707 const_reference at(size_type idx)
const;
710 const_pointer data()
const;
712 void push_back(
const T&
elt);
713 void push_back(T&&
elt);
717 const_iterator begin()
const;
718 const_iterator cbegin()
const;
720 const_iterator end()
const;
721 const_iterator cend()
const;
723 reverse_iterator rbegin();
724 const_reverse_iterator rbegin()
const;
725 const_reverse_iterator crbegin()
const;
726 reverse_iterator rend();
727 const_reverse_iterator rend()
const;
728 const_reverse_iterator crend()
const;
731 size_type size()
const;
732 void resize(size_type
n);
733 size_type max_size()
const noexcept;
734 size_type capacity()
const;
735 void reserve(size_type
n);
736 void shrink_to_fit();
740 const_reference front()
const;
742 const_reference back()
const;
746 iterator erase(const_iterator
cit);
747 iterator erase(const_iterator
cfirst, const_iterator
clast);
749 iterator insert(const_iterator
it,
const T&
elt);
754 iterator insert(const_iterator
pos, std::initializer_list<T>
l);
756 template <std::
size_t ON,
class OA,
bool InitA>
759 allocator_type get_allocator()
const noexcept;
765 T* m_begin = std::begin(m_data);
766 T* m_end = std::begin(m_data);
767 T* m_capacity = std::end(m_data);
770 alignas(alignment) T m_data[N > 0 ? N : 1];
773 void destroy_range(T* begin, T* end);
776 template <
class T, std::
size_t N,
class A,
bool Init>
781 detail::safe_destroy_deallocate(m_allocator, m_begin,
static_cast<std::size_t
>(m_capacity - m_begin));
785 template <
class T, std::
size_t N,
class A,
bool Init>
786 inline svector<T, N, A, Init>::svector() noexcept
787 : svector(allocator_type())
791 template <
class T, std::
size_t N,
class A,
bool Init>
792 inline svector<T, N, A, Init>::svector(
const allocator_type& alloc) noexcept
797 template <
class T, std::
size_t N,
class A,
bool Init>
798 inline svector<T, N, A, Init>::svector(size_type n,
const allocator_type& alloc)
811 template <
class T, std::
size_t N,
class A,
bool Init>
812 template <
class IT,
class>
813 inline svector<T, N, A, Init>::svector(IT begin, IT end,
const allocator_type& alloc)
819 template <
class T, std::
size_t N,
class A,
bool Init>
820 template <std::
size_t N2,
bool I2,
class>
821 inline svector<T, N, A, Init>::svector(
const svector<T, N2, A, I2>& rhs)
822 : m_allocator(rhs.get_allocator())
824 assign(rhs.begin(), rhs.end());
827 template <
class T, std::
size_t N,
class A,
bool Init>
828 inline svector<T, N, A, Init>::svector(
const std::vector<T>& vec)
830 assign(vec.begin(), vec.end());
833 template <
class T, std::
size_t N,
class A,
bool Init>
834 inline svector<T, N, A, Init>::svector(size_type n,
const value_type& v,
const allocator_type& alloc)
840 template <
class T, std::
size_t N,
class A,
bool Init>
841 inline svector<T, N, A, Init>::svector(std::initializer_list<T> il,
const allocator_type& alloc)
844 assign(il.begin(), il.end());
847 template <
class T, std::
size_t N,
class A,
bool Init>
848 inline svector<T, N, A, Init>& svector<T, N, A, Init>::operator=(
const svector& rhs)
850 assign(rhs.begin(), rhs.end());
854 template <
class T, std::
size_t N,
class A,
bool Init>
855 inline svector<T, N, A, Init>& svector<T, N, A, Init>::operator=(svector&& rhs
856 )
noexcept(std::is_nothrow_move_assignable<value_type>::value)
858 assign(rhs.begin(), rhs.end());
862 template <
class T, std::
size_t N,
class A,
bool Init>
863 inline svector<T, N, A, Init>& svector<T, N, A, Init>::operator=(
const std::vector<T>& rhs)
865 m_allocator = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
868 assign(rhs.begin(), rhs.end());
872 template <
class T, std::
size_t N,
class A,
bool Init>
873 inline svector<T, N, A, Init>& svector<T, N, A, Init>::operator=(std::initializer_list<T> il)
875 return operator=(self_type(il));
878 template <
class T, std::
size_t N,
class A,
bool Init>
879 template <std::
size_t N2,
bool I2,
class>
880 inline svector<T, N, A, Init>& svector<T, N, A, Init>::operator=(
const svector<T, N2, A, I2>& rhs)
882 m_allocator = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
885 assign(rhs.begin(), rhs.end());
889 template <
class T, std::
size_t N,
class A,
bool Init>
890 inline svector<T, N, A, Init>::svector(
const svector& rhs)
892 std::allocator_traits<allocator_type>::select_on_container_copy_construction(rhs.get_allocator())
895 assign(rhs.begin(), rhs.end());
898 template <
class T, std::
size_t N,
class A,
bool Init>
899 inline svector<T, N, A, Init>::svector(svector&& rhs
900 )
noexcept(std::is_nothrow_move_constructible<value_type>::value)
905 template <
class T, std::
size_t N,
class A,
bool Init>
906 inline void svector<T, N, A, Init>::assign(size_type n,
const value_type& v)
908 if (n > N && n > capacity())
913 std::fill(begin(), end(), v);
916 template <
class T, std::
size_t N,
class A,
bool Init>
918 inline void svector<T, N, A, Init>::assign(std::initializer_list<V> il)
920 assign(il.begin(), il.end());
923 template <
class T, std::
size_t N,
class A,
bool Init>
925 inline void svector<T, N, A, Init>::assign(IT other_begin, IT other_end)
927 std::size_t size =
static_cast<std::size_t
>(other_end - other_begin);
928 if (size > N && size > capacity())
932 std::uninitialized_copy(other_begin, other_end, m_begin);
933 m_end = m_begin + size;
936 template <
class T, std::
size_t N,
class A,
bool Init>
937 inline auto svector<T, N, A, Init>::operator[](size_type idx) -> reference
942 template <
class T, std::
size_t N,
class A,
bool Init>
943 inline auto svector<T, N, A, Init>::operator[](size_type idx)
const -> const_reference
948 template <
class T, std::
size_t N,
class A,
bool Init>
949 inline auto svector<T, N, A, Init>::at(size_type idx) -> reference
953 XTENSOR_THROW(std::out_of_range,
"Out of range in svector access");
955 return this->operator[](idx);
958 template <
class T, std::
size_t N,
class A,
bool Init>
959 inline auto svector<T, N, A, Init>::at(size_type idx)
const -> const_reference
963 XTENSOR_THROW(std::out_of_range,
"Out of range in svector access");
965 return this->operator[](idx);
968 template <
class T, std::
size_t N,
class A,
bool Init>
969 inline auto svector<T, N, A, Init>::data() -> pointer
974 template <
class T, std::
size_t N,
class A,
bool Init>
975 inline auto svector<T, N, A, Init>::data() const -> const_pointer
980 template <
class T, std::
size_t N,
class A,
bool Init>
981 void svector<T, N, A, Init>::resize(size_type n)
983 if (n > N && n > capacity())
987 size_type old_size = size();
989 if (Init && old_size < size())
991 std::fill(begin() + old_size, end(), T());
995 template <
class T, std::
size_t N,
class A,
bool Init>
996 inline auto svector<T, N, A, Init>::max_size() const noexcept -> size_type
998 return m_allocator.max_size();
1001 template <
class T, std::
size_t N,
class A,
bool Init>
1002 inline auto svector<T, N, A, Init>::capacity() const -> size_type
1004 return static_cast<std::size_t
>(m_capacity - m_begin);
1007 template <
class T, std::
size_t N,
class A,
bool Init>
1008 inline void svector<T, N, A, Init>::reserve(size_type n)
1010 if (n > N && n > capacity())
1016 template <
class T, std::
size_t N,
class A,
bool Init>
1017 inline void svector<T, N, A, Init>::shrink_to_fit()
1022 template <
class T, std::
size_t N,
class A,
bool Init>
1023 inline void svector<T, N, A, Init>::clear()
1025 resize(size_type(0));
1028 template <
class T, std::
size_t N,
class A,
bool Init>
1029 void svector<T, N, A, Init>::push_back(
const T& elt)
1031 if (m_end >= m_capacity)
1038 template <
class T, std::
size_t N,
class A,
bool Init>
1039 void svector<T, N, A, Init>::push_back(T&& elt)
1041 if (m_end >= m_capacity)
1045 *(m_end++) = std::move(elt);
1048 template <
class T, std::
size_t N,
class A,
bool Init>
1049 void svector<T, N, A, Init>::pop_back()
1054 template <
class T, std::
size_t N,
class A,
bool Init>
1055 inline auto svector<T, N, A, Init>::begin() -> iterator
1060 template <
class T, std::
size_t N,
class A,
bool Init>
1061 inline auto svector<T, N, A, Init>::begin() const -> const_iterator
1066 template <
class T, std::
size_t N,
class A,
bool Init>
1067 inline auto svector<T, N, A, Init>::cbegin() const -> const_iterator
1072 template <
class T, std::
size_t N,
class A,
bool Init>
1073 inline auto svector<T, N, A, Init>::end() -> iterator
1078 template <
class T, std::
size_t N,
class A,
bool Init>
1079 inline auto svector<T, N, A, Init>::end() const -> const_iterator
1084 template <
class T, std::
size_t N,
class A,
bool Init>
1085 inline auto svector<T, N, A, Init>::cend() const -> const_iterator
1090 template <
class T, std::
size_t N,
class A,
bool Init>
1091 inline auto svector<T, N, A, Init>::rbegin() -> reverse_iterator
1093 return reverse_iterator(m_end);
1096 template <
class T, std::
size_t N,
class A,
bool Init>
1097 inline auto svector<T, N, A, Init>::rbegin() const -> const_reverse_iterator
1099 return const_reverse_iterator(m_end);
1102 template <
class T, std::
size_t N,
class A,
bool Init>
1103 inline auto svector<T, N, A, Init>::crbegin() const -> const_reverse_iterator
1105 return const_reverse_iterator(m_end);
1108 template <
class T, std::
size_t N,
class A,
bool Init>
1109 inline auto svector<T, N, A, Init>::rend() -> reverse_iterator
1111 return reverse_iterator(m_begin);
1114 template <
class T, std::
size_t N,
class A,
bool Init>
1115 inline auto svector<T, N, A, Init>::rend() const -> const_reverse_iterator
1117 return const_reverse_iterator(m_begin);
1120 template <
class T, std::
size_t N,
class A,
bool Init>
1121 inline auto svector<T, N, A, Init>::crend() const -> const_reverse_iterator
1123 return const_reverse_iterator(m_begin);
1126 template <
class T, std::
size_t N,
class A,
bool Init>
1127 inline auto svector<T, N, A, Init>::size() const -> size_type
1129 return static_cast<size_type
>(m_end - m_begin);
1132 template <
class T, std::
size_t N,
class A,
bool Init>
1133 inline auto svector<T, N, A, Init>::empty() const ->
bool
1135 return m_begin == m_end;
1138 template <
class T, std::
size_t N,
class A,
bool Init>
1139 inline auto svector<T, N, A, Init>::front() -> reference
1141 XTENSOR_ASSERT(!
empty());
1145 template <
class T, std::
size_t N,
class A,
bool Init>
1146 inline auto svector<T, N, A, Init>::front() const -> const_reference
1148 XTENSOR_ASSERT(!
empty());
1152 template <
class T, std::
size_t N,
class A,
bool Init>
1153 inline auto svector<T, N, A, Init>::back() -> reference
1155 XTENSOR_ASSERT(!
empty());
1159 template <
class T, std::
size_t N,
class A,
bool Init>
1160 inline auto svector<T, N, A, Init>::back() const -> const_reference
1162 XTENSOR_ASSERT(!
empty());
1166 template <
class T, std::
size_t N,
class A,
bool Init>
1167 inline auto svector<T, N, A, Init>::on_stack() ->
bool
1169 return m_begin == &m_data[0];
1172 template <
class T, std::
size_t N,
class A,
bool Init>
1173 inline auto svector<T, N, A, Init>::get_allocator() const noexcept -> allocator_type
1178 template <
class T, std::
size_t N,
class A,
bool Init>
1179 inline auto svector<T, N, A, Init>::erase(const_iterator cit) -> iterator
1181 auto it =
const_cast<pointer
>(cit);
1182 iterator ret_val = it;
1183 std::move(it + 1, m_end, it);
1188 template <
class T, std::
size_t N,
class A,
bool Init>
1189 inline auto svector<T, N, A, Init>::erase(const_iterator cfirst, const_iterator clast) -> iterator
1191 auto first =
const_cast<pointer
>(cfirst);
1192 auto last =
const_cast<pointer
>(clast);
1199 iterator new_end = std::move(last, m_end, first);
1204 template <
class T, std::
size_t N,
class A,
bool Init>
1205 inline auto svector<T, N, A, Init>::insert(const_iterator cit,
const T& elt) -> iterator
1207 auto it =
const_cast<pointer
>(cit);
1214 if (m_end >= m_capacity)
1216 std::ptrdiff_t elt_no = it - m_begin;
1218 it = m_begin + elt_no;
1222 std::move_backward(it, m_end - 1, m_end);
1226 const T* elt_ptr = &elt;
1227 bool cond = it <= elt_ptr && elt_ptr < m_end;
1230 const T* src_ptr = cond ? it + (elt_ptr - it) + std::ptrdiff_t(1) : elt_ptr;
1235 template <
class T, std::
size_t N,
class A,
bool Init>
1237 inline auto svector<T, N, A, Init>::insert(const_iterator pos, It first, It last) -> iterator
1239 auto it =
const_cast<pointer
>(pos);
1240 difference_type n = std::distance(first, last);
1243 if (n > m_capacity - m_end)
1245 std::ptrdiff_t elt_no = it - m_begin;
1246 grow(
static_cast<size_t>((m_capacity - m_begin) + n));
1247 it = m_begin + elt_no;
1250 std::move_backward(it, m_end, m_end + n);
1252 std::copy(first, last, it);
1257 template <
class T, std::
size_t N,
class A,
bool Init>
1258 inline auto svector<T, N, A, Init>::insert(const_iterator pos, std::initializer_list<T> l) -> iterator
1260 return insert(pos, l.begin(), l.end());
1263 template <
class T, std::
size_t N,
class A,
bool Init>
1264 inline void svector<T, N, A, Init>::destroy_range(T* begin, T* end)
1266 if (!xtrivially_default_constructible<T>::value)
1268 while (begin != end)
1276 template <
class T, std::
size_t N,
class A,
bool Init>
1277 template <std::
size_t ON,
class OA,
bool InitA>
1278 inline void svector<T, N, A, Init>::swap(svector<T, ON, OA, InitA>& rhs)
1287 if (!this->on_stack() && !rhs.on_stack())
1289 swap(this->m_begin, rhs.m_begin);
1290 swap(this->m_end, rhs.m_end);
1291 swap(this->m_capacity, rhs.m_capacity);
1295 size_type rhs_old_size = rhs.size();
1296 size_type old_size = this->size();
1298 if (rhs_old_size > old_size)
1300 this->resize(rhs_old_size);
1302 else if (old_size > rhs_old_size)
1304 rhs.resize(old_size);
1308 size_type min_size = (std::min)(old_size, rhs_old_size);
1309 for (size_type i = 0; i < min_size; ++i)
1311 swap((*
this)[i], rhs[i]);
1315 if (old_size > rhs_old_size)
1317 std::copy(this->begin() + min_size, this->end(), rhs.begin() + min_size);
1318 this->destroy_range(this->begin() + min_size, this->end());
1319 this->m_end = this->begin() + min_size;
1321 else if (rhs_old_size > old_size)
1323 std::copy(rhs.begin() + min_size, rhs.end(), this->begin() + min_size);
1324 this->destroy_range(rhs.begin() + min_size, rhs.end());
1325 rhs.m_end = rhs.begin() + min_size;
1329 template <
class T, std::
size_t N,
class A,
bool Init>
1330 inline void svector<T, N, A, Init>::grow(size_type min_capacity)
1332 size_type current_size = size();
1333 size_type new_capacity = 2 * current_size + 1;
1334 if (new_capacity < min_capacity)
1336 new_capacity = min_capacity;
1341 if (m_begin == &m_data[0])
1343 new_alloc = m_allocator.allocate(new_capacity);
1344 std::uninitialized_copy(m_begin, m_end, new_alloc);
1349 new_alloc = m_allocator.allocate(new_capacity);
1350 std::uninitialized_copy(m_begin, m_end, new_alloc);
1351 m_allocator.deallocate(m_begin, std::size_t(m_capacity - m_begin));
1353 XTENSOR_ASSERT(new_alloc);
1355 m_end = new_alloc + current_size;
1356 m_begin = new_alloc;
1357 m_capacity = new_alloc + new_capacity;
1360 template <
class T, std::
size_t N,
class A,
bool Init>
1361 inline bool operator==(
const std::vector<T>& lhs,
const svector<T, N, A, Init>& rhs)
1363 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1366 template <
class T, std::
size_t N,
class A,
bool Init>
1367 inline bool operator==(
const svector<T, N, A, Init>& lhs,
const std::vector<T>& rhs)
1369 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1372 template <
class T, std::
size_t N,
class A,
bool Init>
1373 inline bool operator==(
const svector<T, N, A, Init>& lhs,
const svector<T, N, A, Init>& rhs)
1375 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1378 template <
class T, std::
size_t N,
class A,
bool Init>
1379 inline bool operator!=(
const svector<T, N, A, Init>& lhs,
const svector<T, N, A, Init>& rhs)
1381 return !(lhs == rhs);
1384 template <
class T, std::
size_t N,
class A,
bool Init>
1385 inline bool operator<(
const svector<T, N, A, Init>& lhs,
const svector<T, N, A, Init>& rhs)
1387 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
1390 template <
class T, std::
size_t N,
class A,
bool Init>
1391 inline bool operator<=(
const svector<T, N, A, Init>& lhs,
const svector<T, N, A, Init>& rhs)
1393 return !(lhs > rhs);
1396 template <
class T, std::
size_t N,
class A,
bool Init>
1397 inline bool operator>(
const svector<T, N, A, Init>& lhs,
const svector<T, N, A, Init>& rhs)
1402 template <
class T, std::
size_t N,
class A,
bool Init>
1403 inline bool operator>=(
const svector<T, N, A, Init>& lhs,
const svector<T, N, A, Init>& rhs)
1405 return !(lhs < rhs);
1408 template <
class T, std::
size_t N,
class A,
bool Init>
1409 inline void swap(svector<T, N, A, Init>& lhs, svector<T, N, A, Init>& rhs)
noexcept
1414 template <
class X,
class T, std::
size_t N,
class A,
bool B>
1417 using traits = std::allocator_traits<A>;
1428 template <
class T, std::
size_t N, std::
size_t Align = XTENSOR_
SELECT_ALIGN(T)>
1435 using allocator_type = std::conditional_t<Align != 0, xt_simd::aligned_allocator<T, Align>, std::allocator<T>>;
1438#if defined(_MSC_VER)
1439#define XTENSOR_CONST
1441#define XTENSOR_CONST const
1444#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
1445#define GCC4_FALLBACK
1449 template <
class T, std::
size_t N>
1452 using storage_type = T[N];
1454 static constexpr T&
ref(
const storage_type&
t, std::size_t
n)
noexcept
1456 return const_cast<T&
>(
t[
n]);
1459 static constexpr T* ptr(
const storage_type& t)
noexcept
1461 return const_cast<T*
>(t);
1466 struct array_traits<T, 0>
1472 using storage_type =
empty;
1474 static constexpr T& ref(
const storage_type& , std::size_t )
noexcept
1476 return *
static_cast<T*
>(
nullptr);
1479 static constexpr T* ptr(
const storage_type& )
noexcept
1491 template <
class T, std::
size_t N>
1494 using size_type = std::size_t;
1495 using value_type = T;
1496 using pointer = value_type*;
1497 using const_pointer =
const value_type*;
1498 using reference = value_type&;
1499 using const_reference =
const value_type&;
1500 using difference_type = std::ptrdiff_t;
1501 using iterator = pointer;
1502 using const_iterator = const_pointer;
1504 using reverse_iterator = std::reverse_iterator<const_iterator>;
1505 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1507 constexpr const_reference operator[](std::size_t idx)
const
1510 return const_array_detail::array_traits<T, N>::ref(m_data, idx);
1516 constexpr const_iterator begin()
const noexcept
1521 constexpr const_iterator end()
const noexcept
1526 constexpr const_iterator cbegin()
const noexcept
1531 constexpr const_iterator cend()
const noexcept
1537 reverse_iterator rbegin()
const noexcept
1542 reverse_iterator rend()
const noexcept
1547 const_reverse_iterator crbegin()
const noexcept
1549 return const_reverse_iterator(end());
1552 const_reverse_iterator crend()
const noexcept
1554 return const_reverse_iterator(begin());
1557 constexpr const_pointer data()
const noexcept
1560 return const_array_detail::array_traits<T, N>::ptr(m_data);
1566 constexpr const_reference front()
const noexcept
1569 return const_array_detail::array_traits<T, N>::ref(m_data, 0);
1575 constexpr const_reference back()
const noexcept
1578 return N ? const_array_detail::array_traits<T, N>::ref(m_data, N - 1)
1579 : const_array_detail::array_traits<T, N>::ref(m_data, 0);
1581 return m_data[size() - 1];
1585 constexpr bool empty()
const noexcept
1587 return size() == size_type(0);
1590 constexpr size_type size()
const noexcept
1596 XTENSOR_CONST
typename const_array_detail::array_traits<T, N>::storage_type m_data;
1598 XTENSOR_CONST T m_data[N > 0 ? N : 1];
1604 template <
class T, std::
size_t N>
1607 return std::equal(
lhs.cbegin(),
lhs.cend(),
rhs.cbegin());
1610 template <
class T, std::
size_t N>
1611 inline bool operator!=(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1613 return !(lhs == rhs);
1616 template <
class T, std::
size_t N>
1617 inline bool operator<(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1619 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
1622 template <
class T, std::
size_t N>
1623 inline bool operator<=(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1625 return !(lhs > rhs);
1628 template <
class T, std::
size_t N>
1629 inline bool operator>(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1634 template <
class T, std::
size_t N>
1635 inline bool operator>=(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1637 return !(lhs < rhs);
1641#if defined(__GNUC__) && __GNUC__ > 6 && !defined(__clang__) && __cplusplus >= 201703L
1642 template <
class X,
class T, std::
size_t N>
1643 struct rebind_container<X, aligned_array<T, N>>
1645 using type = aligned_array<X, N>;
1648 template <
class X,
class T, std::
size_t N>
1649 struct rebind_container<X, const_array<T, N>>
1651 using type = const_array<X, N>;
1660 template <std::size_t... X>
1665#if defined(_MSC_VER)
1666 using cast_type = std::array<std::size_t,
sizeof...(X)>;
1667#define XTENSOR_FIXED_SHAPE_CONSTEXPR inline
1670#define XTENSOR_FIXED_SHAPE_CONSTEXPR constexpr
1672 using value_type = std::size_t;
1673 using size_type = std::size_t;
1674 using const_iterator =
typename cast_type::const_iterator;
1676 static constexpr std::size_t size()
1678 return sizeof...(X);
1681 template <std::
size_t idx>
1682 static constexpr auto get()
1684 using tmp_cast_type = std::array<std::size_t,
sizeof...(X)>;
1688 XTENSOR_FIXED_SHAPE_CONSTEXPR
operator cast_type()
const
1693 XTENSOR_FIXED_SHAPE_CONSTEXPR
auto begin()
const
1695 return m_array.begin();
1698 XTENSOR_FIXED_SHAPE_CONSTEXPR
auto end()
const
1700 return m_array.end();
1705 return m_array.rbegin();
1710 return m_array.rend();
1713 XTENSOR_FIXED_SHAPE_CONSTEXPR
auto cbegin()
const
1715 return m_array.cbegin();
1718 XTENSOR_FIXED_SHAPE_CONSTEXPR
auto cend()
const
1720 return m_array.cend();
1723 XTENSOR_FIXED_SHAPE_CONSTEXPR std::size_t operator[](std::size_t idx)
const
1725 return m_array[idx];
1728 XTENSOR_FIXED_SHAPE_CONSTEXPR
bool empty()
const
1730 return sizeof...(X) == 0;
1738#ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED
1739 template <std::size_t...
X>
1743#undef XTENSOR_FIXED_SHAPE_CONSTEXPR
1745 template <
class E, std::ptrdiff_t
Start, std::ptrdiff_t
End = -1>
1750 using value_type =
typename E::value_type;
1751 using reference =
typename E::reference;
1752 using const_reference =
typename E::const_reference;
1753 using pointer =
typename E::pointer;
1754 using const_pointer =
typename E::const_pointer;
1756 using size_type =
typename E::size_type;
1757 using difference_type =
typename E::difference_type;
1759 using iterator =
typename E::iterator;
1760 using const_iterator =
typename E::const_iterator;
1761 using reverse_iterator =
typename E::reverse_iterator;
1762 using const_reverse_iterator =
typename E::const_reverse_iterator;
1766 template <std::ptrdiff_t OS, std::ptrdiff_t OE>
1773 size_type size()
const;
1774 const_reference operator[](std::size_t idx)
const;
1776 const_iterator end()
const;
1777 const_iterator begin()
const;
1778 const_iterator cend()
const;
1779 const_iterator cbegin()
const;
1781 const_reverse_iterator rend()
const;
1782 const_reverse_iterator rbegin()
const;
1783 const_reverse_iterator crend()
const;
1784 const_reverse_iterator crbegin()
const;
1786 const_reference front()
const;
1787 const_reference back()
const;
1789 const E& storage()
const;
1793 const E& m_sequence;
1796 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1802 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1803 template <std::ptrdiff_t OS, std::ptrdiff_t OE>
1804 sequence_view<E, Start, End>::sequence_view(
const sequence_view<E, OS, OE>& other)
1805 : m_sequence(other.storage())
1809 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1810 template <
class T,
class R>
1811 sequence_view<E, Start, End>::operator T()
const
1813 T ret = xtl::make_sequence<T>(this->size());
1814 std::copy(this->cbegin(), this->cend(), ret.begin());
1818 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1819 bool sequence_view<E, Start, End>::empty()
const
1821 return size() == size_type(0);
1824 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1825 auto sequence_view<E, Start, End>::size() const -> size_type
1829 return m_sequence.size() -
static_cast<size_type
>(Start);
1833 return static_cast<size_type
>(End - Start);
1837 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1838 auto sequence_view<E, Start, End>::operator[](std::size_t idx)
const -> const_reference
1840 return m_sequence[idx +
static_cast<std::size_t
>(Start)];
1843 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1844 auto sequence_view<E, Start, End>::end() const -> const_iterator
1848 return m_sequence.begin() + End;
1852 return m_sequence.end();
1856 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1857 auto sequence_view<E, Start, End>::begin() const -> const_iterator
1859 return m_sequence.begin() + Start;
1862 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1863 auto sequence_view<E, Start, End>::cend() const -> const_iterator
1868 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1869 auto sequence_view<E, Start, End>::cbegin() const -> const_iterator
1874 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1875 auto sequence_view<E, Start, End>::rend() const -> const_reverse_iterator
1877 return const_reverse_iterator(begin());
1880 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1881 auto sequence_view<E, Start, End>::rbegin() const -> const_reverse_iterator
1883 return const_reverse_iterator(end());
1886 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1887 auto sequence_view<E, Start, End>::crend() const -> const_reverse_iterator
1892 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1893 auto sequence_view<E, Start, End>::crbegin() const -> const_reverse_iterator
1898 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1899 auto sequence_view<E, Start, End>::front() const -> const_reference
1901 return *(m_sequence.begin() + Start);
1904 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1905 auto sequence_view<E, Start, End>::back() const -> const_reference
1909 return m_sequence.back();
1913 return m_sequence[
static_cast<std::size_t
>(End - 1)];
1917 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1918 const E& sequence_view<E, Start, End>::storage()
const
1923 template <
class T, std::ptrdiff_t TB, std::ptrdiff_t TE>
1924 inline bool operator==(
const sequence_view<T, TB, TE>& lhs,
const sequence_view<T, TB, TE>& rhs)
1926 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1929 template <
class T, std::ptrdiff_t TB, std::ptrdiff_t TE>
1930 inline bool operator!=(
const sequence_view<T, TB, TE>& lhs,
const sequence_view<T, TB, TE>& rhs)
1932 return !(lhs == rhs);
1946#if defined(__clang__)
1947 # pragma clang diagnostic push
1948 # pragma clang diagnostic ignored "-Wmismatched-tags"
1954 template <
class T, std::
size_t N>
1955 class tuple_size<
xt::const_array<T, N>> :
public integral_constant<std::size_t, N>
1959 template <std::size_t... N>
1960 class tuple_size<
xt::fixed_shape<N...>> :
public integral_constant<std::size_t, sizeof...(N)>
1964 template <
class T, std::ptrdiff_t Start, std::ptrdiff_t End>
1965 class tuple_size<
xt::sequence_view<T, Start, End>>
1966 :
public integral_constant<std::size_t, std::size_t(End - Start)>
1971 template <
class T, std::ptrdiff_t Start>
1972 class tuple_size<
xt::sequence_view<T, Start, -1>>;
1977#if defined(__clang__)
1978 # pragma clang diagnostic pop
This array class is modeled after std::array but adds optional alignment through a template parameter...
Fixed shape implementation for compile time defined arrays.
standard mathematical functions for xexpressions
bool operator==(const xaxis_iterator< CT > &lhs, const xaxis_iterator< CT > &rhs)
Checks equality of the iterators.
bool operator!=(const xaxis_iterator< CT > &lhs, const xaxis_iterator< CT > &rhs)
Checks inequality of the iterators.
xarray< T, L > empty(const S &shape)
Create a xcontainer (xarray, xtensor or xtensor_fixed) with uninitialized values of with value_type T...
A std::array like class with all member function (except reverse iterators) as constexpr.