10#ifndef XTENSOR_STORAGE_HPP
11#define XTENSOR_STORAGE_HPP
16#include <initializer_list>
21#include "../core/xtensor_config.hpp"
22#include "../utils/xexception.hpp"
23#include "../utils/xtensor_simd.hpp"
24#include "../utils/xutils.hpp"
33 template <
class T,
class A = std::allocator<T>>
38 using allocator_type = A;
40 using value_type =
typename std::allocator_traits<A>::value_type;
41 using reference = value_type&;
42 using const_reference =
const value_type&;
43 using pointer =
typename std::allocator_traits<A>::pointer;
44 using const_pointer =
typename std::allocator_traits<A>::const_pointer;
46 using size_type =
typename std::allocator_traits<A>::size_type;
47 using difference_type =
typename std::allocator_traits<A>::difference_type;
49 using iterator = pointer;
50 using const_iterator = const_pointer;
51 using reverse_iterator = std::reverse_iterator<iterator>;
52 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
55 explicit uvector(
const allocator_type& alloc)
noexcept;
56 explicit uvector(size_type count,
const allocator_type& alloc = allocator_type());
57 uvector(size_type count, const_reference value,
const allocator_type& alloc = allocator_type());
59 template <std::input_iterator InputIt>
60 uvector(InputIt first, InputIt last,
const allocator_type& alloc = allocator_type());
62 uvector(std::initializer_list<T> init,
const allocator_type& alloc = allocator_type());
66 uvector(
const uvector& rhs);
67 uvector(
const uvector& rhs,
const allocator_type& alloc);
68 uvector& operator=(
const uvector&);
70 uvector(uvector&& rhs)
noexcept;
71 uvector(uvector&& rhs,
const allocator_type& alloc)
noexcept;
72 uvector& operator=(uvector&& rhs)
noexcept;
74 allocator_type get_allocator()
const noexcept;
76 bool empty()
const noexcept;
77 size_type size()
const noexcept;
78 void resize(size_type size);
79 size_type max_size()
const noexcept;
80 void reserve(size_type new_cap);
81 size_type capacity()
const noexcept;
85 reference operator[](size_type i);
86 const_reference operator[](size_type i)
const;
88 reference at(size_type i);
89 const_reference at(size_type i)
const;
92 const_reference front()
const;
95 const_reference back()
const;
97 pointer data()
noexcept;
98 const_pointer data()
const noexcept;
100 iterator begin()
noexcept;
101 iterator end()
noexcept;
103 const_iterator begin()
const noexcept;
104 const_iterator end()
const noexcept;
106 const_iterator cbegin()
const noexcept;
107 const_iterator cend()
const noexcept;
109 reverse_iterator rbegin()
noexcept;
110 reverse_iterator rend()
noexcept;
112 const_reverse_iterator rbegin()
const noexcept;
113 const_reverse_iterator rend()
const noexcept;
115 const_reverse_iterator crbegin()
const noexcept;
116 const_reverse_iterator crend()
const noexcept;
118 void swap(uvector& rhs)
noexcept;
123 void init_data(I first, I last);
125 void resize_impl(size_type new_size);
127 allocator_type m_allocator;
135 template <
class T,
class A>
138 template <
class T,
class A>
141 template <
class T,
class A>
144 template <
class T,
class A>
147 template <
class T,
class A>
150 template <
class T,
class A>
153 template <
class T,
class A>
163 inline typename std::allocator_traits<A>::pointer
164 safe_init_allocate(A& alloc,
typename std::allocator_traits<A>::size_type size)
166 using traits = std::allocator_traits<A>;
167 using pointer =
typename traits::pointer;
168 using value_type =
typename traits::value_type;
169 pointer res = alloc.allocate(size);
170 if (!std::is_trivially_default_constructible<value_type>::value)
172 for (pointer p = res; p != res + size; ++p)
174 traits::construct(alloc, p, value_type());
181 inline void safe_destroy_deallocate(
183 typename std::allocator_traits<A>::pointer ptr,
184 typename std::allocator_traits<A>::size_type size
187 using traits = std::allocator_traits<A>;
188 using pointer =
typename traits::pointer;
189 using value_type =
typename traits::value_type;
192 if (!std::is_trivially_default_constructible<value_type>::value)
194 for (pointer p = ptr; p != ptr + size; ++p)
196 traits::destroy(alloc, p);
199 traits::deallocate(alloc, ptr, size);
204 template <
class T,
class A>
206 inline void uvector<T, A>::init_data(I first, I last)
208 size_type size =
static_cast<size_type
>(std::distance(first, last));
209 if (size != size_type(0))
211 p_begin = m_allocator.allocate(size);
212 std::uninitialized_copy(first, last, p_begin);
213 p_end = p_begin + size;
217 template <
class T,
class A>
218 inline void uvector<T, A>::resize_impl(size_type new_size)
220 size_type old_size = size();
221 pointer old_begin = p_begin;
222 if (new_size != old_size)
224 p_begin = detail::safe_init_allocate(m_allocator, new_size);
225 p_end = p_begin + new_size;
226 detail::safe_destroy_deallocate(m_allocator, old_begin, old_size);
230 template <
class T,
class A>
231 inline uvector<T, A>::uvector() noexcept
236 template <
class T,
class A>
237 inline uvector<T, A>::uvector(
const allocator_type& alloc) noexcept
244 template <
class T,
class A>
245 inline uvector<T, A>::uvector(size_type count,
const allocator_type& alloc)
252 p_begin = detail::safe_init_allocate(m_allocator, count);
253 p_end = p_begin + count;
257 template <
class T,
class A>
258 inline uvector<T, A>::uvector(size_type count, const_reference value,
const allocator_type& alloc)
265 p_begin = m_allocator.allocate(count);
266 p_end = p_begin + count;
267 std::uninitialized_fill(p_begin, p_end, value);
271 template <
class T,
class A>
272 template <std::input_iterator InputIt>
273 inline uvector<T, A>::uvector(InputIt first, InputIt last,
const allocator_type& alloc)
278 init_data(first, last);
281 template <
class T,
class A>
282 inline uvector<T, A>::uvector(std::initializer_list<T> init,
const allocator_type& alloc)
287 init_data(init.begin(), init.end());
290 template <
class T,
class A>
291 inline uvector<T, A>::~uvector()
293 detail::safe_destroy_deallocate(m_allocator, p_begin, size());
298 template <
class T,
class A>
299 inline uvector<T, A>::uvector(
const uvector& rhs)
301 std::allocator_traits<allocator_type>::select_on_container_copy_construction(rhs.get_allocator())
306 init_data(rhs.p_begin, rhs.p_end);
309 template <
class T,
class A>
310 inline uvector<T, A>::uvector(
const uvector& rhs,
const allocator_type& alloc)
315 init_data(rhs.p_begin, rhs.p_end);
318 template <
class T,
class A>
324 m_allocator = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
327 resize_impl(rhs.size());
328 if (std::is_trivially_default_constructible<value_type>::value)
330 std::uninitialized_copy(rhs.p_begin, rhs.p_end, p_begin);
334 std::copy(rhs.p_begin, rhs.p_end, p_begin);
340 template <
class T,
class A>
341 inline uvector<T, A>::uvector(
uvector&& rhs) noexcept
342 : m_allocator(std::move(rhs.m_allocator))
343 , p_begin(rhs.p_begin)
346 rhs.p_begin =
nullptr;
350 template <
class T,
class A>
351 inline uvector<T, A>::uvector(
uvector&& rhs,
const allocator_type& alloc) noexcept
353 , p_begin(rhs.p_begin)
356 rhs.p_begin =
nullptr;
360 template <
class T,
class A>
365 swap(p_begin, tmp.p_begin);
366 swap(p_end, tmp.p_end);
370 template <
class T,
class A>
371 inline auto uvector<T, A>::get_allocator() const noexcept -> allocator_type
373 return allocator_type(m_allocator);
376 template <
class T,
class A>
377 inline bool uvector<T, A>::empty() const noexcept
379 return size() == size_type(0);
382 template <
class T,
class A>
383 inline auto uvector<T, A>::size() const noexcept -> size_type
385 return static_cast<size_type
>(p_end - p_begin);
388 template <
class T,
class A>
389 inline void uvector<T, A>::resize(size_type size)
394 template <
class T,
class A>
395 inline auto uvector<T, A>::max_size() const noexcept -> size_type
397 return m_allocator.max_size();
400 template <
class T,
class A>
401 inline void uvector<T, A>::reserve(size_type )
405 template <
class T,
class A>
406 inline auto uvector<T, A>::capacity() const noexcept -> size_type
411 template <
class T,
class A>
412 inline void uvector<T, A>::shrink_to_fit()
416 template <
class T,
class A>
417 inline void uvector<T, A>::clear()
419 resize(size_type(0));
422 template <
class T,
class A>
423 inline auto uvector<T, A>::operator[](size_type i) -> reference
428 template <
class T,
class A>
429 inline auto uvector<T, A>::operator[](size_type i)
const -> const_reference
434 template <
class T,
class A>
435 inline auto uvector<T, A>::at(size_type i) -> reference
439 XTENSOR_THROW(std::out_of_range,
"Out of range in uvector access");
441 return this->operator[](i);
444 template <
class T,
class A>
445 inline auto uvector<T, A>::at(size_type i)
const -> const_reference
449 XTENSOR_THROW(std::out_of_range,
"Out of range in uvector access");
451 return this->operator[](i);
454 template <
class T,
class A>
455 inline auto uvector<T, A>::front() -> reference
460 template <
class T,
class A>
461 inline auto uvector<T, A>::front() const -> const_reference
466 template <
class T,
class A>
467 inline auto uvector<T, A>::back() -> reference
472 template <
class T,
class A>
473 inline auto uvector<T, A>::back() const -> const_reference
478 template <
class T,
class A>
479 inline auto uvector<T, A>::data() noexcept -> pointer
484 template <
class T,
class A>
485 inline auto uvector<T, A>::data() const noexcept -> const_pointer
490 template <
class T,
class A>
491 inline auto uvector<T, A>::begin() noexcept -> iterator
496 template <
class T,
class A>
497 inline auto uvector<T, A>::end() noexcept -> iterator
502 template <
class T,
class A>
503 inline auto uvector<T, A>::begin() const noexcept -> const_iterator
508 template <
class T,
class A>
509 inline auto uvector<T, A>::end() const noexcept -> const_iterator
514 template <
class T,
class A>
515 inline auto uvector<T, A>::cbegin() const noexcept -> const_iterator
520 template <
class T,
class A>
521 inline auto uvector<T, A>::cend() const noexcept -> const_iterator
526 template <
class T,
class A>
527 inline auto uvector<T, A>::rbegin() noexcept -> reverse_iterator
529 return reverse_iterator(end());
532 template <
class T,
class A>
533 inline auto uvector<T, A>::rend() noexcept -> reverse_iterator
535 return reverse_iterator(begin());
538 template <
class T,
class A>
539 inline auto uvector<T, A>::rbegin() const noexcept -> const_reverse_iterator
541 return const_reverse_iterator(end());
544 template <
class T,
class A>
545 inline auto uvector<T, A>::rend() const noexcept -> const_reverse_iterator
547 return const_reverse_iterator(begin());
550 template <
class T,
class A>
551 inline auto uvector<T, A>::crbegin() const noexcept -> const_reverse_iterator
556 template <
class T,
class A>
557 inline auto uvector<T, A>::crend() const noexcept -> const_reverse_iterator
562 template <
class T,
class A>
566 swap(m_allocator, rhs.m_allocator);
567 swap(p_begin, rhs.p_begin);
568 swap(p_end, rhs.p_end);
571 template <
class T,
class A>
574 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
577 template <
class T,
class A>
580 return !(lhs == rhs);
583 template <
class T,
class A>
586 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
589 template <
class T,
class A>
595 template <
class T,
class A>
601 template <
class T,
class A>
607 template <
class T,
class A>
620 struct allocator_alignment
622 static constexpr std::size_t value = 0;
625 template <
class T, std::
size_t A>
626 struct allocator_alignment<xt_simd::aligned_allocator<T, A>>
628 static constexpr std::size_t value = A;
632 template <
class T, std::
size_t N = 4,
class A = std::allocator<T>,
bool Init = true>
637 using self_type = svector<T, N, A, Init>;
638 using allocator_type = A;
639 using size_type =
typename std::allocator_traits<A>::size_type;
640 using value_type =
typename std::allocator_traits<A>::value_type;
641 using pointer =
typename std::allocator_traits<A>::pointer;
642 using const_pointer =
typename std::allocator_traits<A>::const_pointer;
643 using reference = value_type&;
644 using const_reference =
const value_type&;
645 using difference_type =
typename std::allocator_traits<A>::difference_type;
647 using iterator = pointer;
648 using const_iterator = const_pointer;
649 using reverse_iterator = std::reverse_iterator<iterator>;
650 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
652 static constexpr std::size_t alignment = detail::allocator_alignment<A>::value != 0
653 ? detail::allocator_alignment<A>::value
659 explicit svector(
const allocator_type& alloc)
noexcept;
660 explicit svector(size_type n,
const allocator_type& alloc = allocator_type());
661 svector(size_type n,
const value_type& v,
const allocator_type& alloc = allocator_type());
662 svector(std::initializer_list<T> il,
const allocator_type& alloc = allocator_type());
664 svector(
const std::vector<T>& vec);
666 template <std::input_iterator IT>
667 svector(IT begin, IT end,
const allocator_type& alloc = allocator_type());
669 template <std::
size_t N2,
bool I2>
670 explicit svector(
const svector<T, N2, A, I2>& rhs)
673 svector& operator=(
const svector& rhs);
674 svector& operator=(svector&& rhs)
noexcept(std::is_nothrow_move_assignable<value_type>::value);
675 svector& operator=(
const std::vector<T>& rhs);
676 svector& operator=(std::initializer_list<T> il);
678 template <std::
size_t N2,
bool I2>
679 svector& operator=(
const svector<T, N2, A, I2>& rhs)
682 svector(
const svector& other);
683 svector(svector&& other)
noexcept(std::is_nothrow_move_constructible<value_type>::value);
685 void assign(size_type n,
const value_type& v);
688 void assign(std::initializer_list<V> il);
691 void assign(IT other_begin, IT other_end);
693 reference operator[](size_type idx);
694 const_reference operator[](size_type idx)
const;
696 reference at(size_type idx);
697 const_reference at(size_type idx)
const;
700 const_pointer data()
const;
702 void push_back(
const T& elt);
703 void push_back(T&& elt);
707 const_iterator begin()
const;
708 const_iterator cbegin()
const;
710 const_iterator end()
const;
711 const_iterator cend()
const;
713 reverse_iterator rbegin();
714 const_reverse_iterator rbegin()
const;
715 const_reverse_iterator crbegin()
const;
716 reverse_iterator rend();
717 const_reverse_iterator rend()
const;
718 const_reverse_iterator crend()
const;
721 size_type size()
const;
722 void resize(size_type n);
723 size_type max_size()
const noexcept;
724 size_type capacity()
const;
725 void reserve(size_type n);
726 void shrink_to_fit();
730 const_reference front()
const;
732 const_reference back()
const;
736 iterator erase(const_iterator cit);
737 iterator erase(const_iterator cfirst, const_iterator clast);
739 iterator insert(const_iterator it,
const T& elt);
742 iterator insert(const_iterator pos, It first, It last);
744 iterator insert(const_iterator pos, std::initializer_list<T> l);
746 template <std::
size_t ON,
class OA,
bool InitA>
747 void swap(svector<T, ON, OA, InitA>& rhs);
749 allocator_type get_allocator()
const noexcept;
755 T* m_begin = std::begin(m_data);
756 T* m_end = std::begin(m_data);
757 T* m_capacity = std::end(m_data);
760 alignas(alignment) T m_data[N > 0 ? N : 1];
762 void grow(size_type min_capacity = 0);
763 void destroy_range(T* begin, T* end);
766 template <
class T, std::
size_t N,
class A,
bool Init>
767 inline svector<T, N, A, Init>::~svector()
771 detail::safe_destroy_deallocate(m_allocator, m_begin,
static_cast<std::size_t
>(m_capacity - m_begin));
775 template <
class T, std::
size_t N,
class A,
bool Init>
776 inline svector<T, N, A, Init>::svector() noexcept
781 template <
class T, std::
size_t N,
class A,
bool Init>
782 inline svector<T, N, A, Init>::svector(
const allocator_type& alloc) noexcept
787 template <
class T, std::
size_t N,
class A,
bool Init>
788 inline svector<T, N, A, Init>::svector(size_type n,
const allocator_type& alloc)
801 template <
class T, std::
size_t N,
class A,
bool Init>
802 template <std::input_iterator IT>
803 inline svector<T, N, A, Init>::svector(IT begin, IT end,
const allocator_type& alloc)
809 template <
class T, std::
size_t N,
class A,
bool Init>
810 template <std::
size_t N2,
bool I2>
813 : m_allocator(rhs.get_allocator())
815 assign(rhs.begin(), rhs.end());
818 template <
class T, std::
size_t N,
class A,
bool Init>
819 inline svector<T, N, A, Init>::svector(
const std::vector<T>& vec)
821 assign(vec.begin(), vec.end());
824 template <
class T, std::
size_t N,
class A,
bool Init>
825 inline svector<T, N, A, Init>::svector(size_type n,
const value_type& v,
const allocator_type& alloc)
831 template <
class T, std::
size_t N,
class A,
bool Init>
832 inline svector<T, N, A, Init>::svector(std::initializer_list<T> il,
const allocator_type& alloc)
835 assign(il.begin(), il.end());
838 template <
class T, std::
size_t N,
class A,
bool Init>
841 assign(rhs.begin(), rhs.end());
845 template <
class T, std::
size_t N,
class A,
bool Init>
847 )
noexcept(std::is_nothrow_move_assignable<value_type>::value)
849 assign(rhs.begin(), rhs.end());
853 template <
class T, std::
size_t N,
class A,
bool Init>
856 m_allocator = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
859 assign(rhs.begin(), rhs.end());
863 template <
class T, std::
size_t N,
class A,
bool Init>
866 return operator=(self_type(il));
869 template <
class T, std::
size_t N,
class A,
bool Init>
870 template <std::
size_t N2,
bool I2>
874 m_allocator = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
877 assign(rhs.begin(), rhs.end());
881 template <
class T, std::
size_t N,
class A,
bool Init>
882 inline svector<T, N, A, Init>::svector(
const svector& rhs)
884 std::allocator_traits<allocator_type>::select_on_container_copy_construction(rhs.get_allocator())
887 assign(rhs.begin(), rhs.end());
890 template <
class T, std::
size_t N,
class A,
bool Init>
891 inline svector<T, N, A, Init>::svector(
svector&& rhs
892 )
noexcept(std::is_nothrow_move_constructible<value_type>::value)
897 template <
class T, std::
size_t N,
class A,
bool Init>
898 inline void svector<T, N, A, Init>::assign(size_type n,
const value_type& v)
900 if (n > N && n > capacity())
905 std::fill(begin(), end(), v);
908 template <
class T, std::
size_t N,
class A,
bool Init>
910 inline void svector<T, N, A, Init>::assign(std::initializer_list<V> il)
912 assign(il.begin(), il.end());
915 template <
class T, std::
size_t N,
class A,
bool Init>
917 inline void svector<T, N, A, Init>::assign(IT other_begin, IT other_end)
919 std::size_t size =
static_cast<std::size_t
>(other_end - other_begin);
920 if (size > N && size > capacity())
924 std::uninitialized_copy(other_begin, other_end, m_begin);
925 m_end = m_begin + size;
928 template <
class T, std::
size_t N,
class A,
bool Init>
929 inline auto svector<T, N, A, Init>::operator[](size_type idx) -> reference
934 template <
class T, std::
size_t N,
class A,
bool Init>
935 inline auto svector<T, N, A, Init>::operator[](size_type idx)
const -> const_reference
940 template <
class T, std::
size_t N,
class A,
bool Init>
941 inline auto svector<T, N, A, Init>::at(size_type idx) -> reference
945 XTENSOR_THROW(std::out_of_range,
"Out of range in svector access");
947 return this->operator[](idx);
950 template <
class T, std::
size_t N,
class A,
bool Init>
951 inline auto svector<T, N, A, Init>::at(size_type idx)
const -> const_reference
955 XTENSOR_THROW(std::out_of_range,
"Out of range in svector access");
957 return this->operator[](idx);
960 template <
class T, std::
size_t N,
class A,
bool Init>
961 inline auto svector<T, N, A, Init>::data() -> pointer
966 template <
class T, std::
size_t N,
class A,
bool Init>
967 inline auto svector<T, N, A, Init>::data() const -> const_pointer
972 template <
class T, std::
size_t N,
class A,
bool Init>
973 void svector<T, N, A, Init>::resize(size_type n)
975 if (n > N && n > capacity())
979 size_type old_size = size();
981 if (Init && old_size < size())
983 std::fill(begin() + old_size, end(), T());
987 template <
class T, std::
size_t N,
class A,
bool Init>
988 inline auto svector<T, N, A, Init>::max_size() const noexcept -> size_type
990 return m_allocator.max_size();
993 template <
class T, std::
size_t N,
class A,
bool Init>
994 inline auto svector<T, N, A, Init>::capacity() const -> size_type
996 return static_cast<std::size_t
>(m_capacity - m_begin);
999 template <
class T, std::
size_t N,
class A,
bool Init>
1000 inline void svector<T, N, A, Init>::reserve(size_type n)
1002 if (n > N && n > capacity())
1008 template <
class T, std::
size_t N,
class A,
bool Init>
1009 inline void svector<T, N, A, Init>::shrink_to_fit()
1014 template <
class T, std::
size_t N,
class A,
bool Init>
1015 inline void svector<T, N, A, Init>::clear()
1017 resize(size_type(0));
1020 template <
class T, std::
size_t N,
class A,
bool Init>
1021 void svector<T, N, A, Init>::push_back(
const T& elt)
1023 if (m_end >= m_capacity)
1030 template <
class T, std::
size_t N,
class A,
bool Init>
1031 void svector<T, N, A, Init>::push_back(T&& elt)
1033 if (m_end >= m_capacity)
1037 *(m_end++) = std::move(elt);
1040 template <
class T, std::
size_t N,
class A,
bool Init>
1041 void svector<T, N, A, Init>::pop_back()
1046 template <
class T, std::
size_t N,
class A,
bool Init>
1047 inline auto svector<T, N, A, Init>::begin() -> iterator
1052 template <
class T, std::
size_t N,
class A,
bool Init>
1053 inline auto svector<T, N, A, Init>::begin() const -> const_iterator
1058 template <
class T, std::
size_t N,
class A,
bool Init>
1059 inline auto svector<T, N, A, Init>::cbegin() const -> const_iterator
1064 template <
class T, std::
size_t N,
class A,
bool Init>
1065 inline auto svector<T, N, A, Init>::end() -> iterator
1070 template <
class T, std::
size_t N,
class A,
bool Init>
1071 inline auto svector<T, N, A, Init>::end() const -> const_iterator
1076 template <
class T, std::
size_t N,
class A,
bool Init>
1077 inline auto svector<T, N, A, Init>::cend() const -> const_iterator
1082 template <
class T, std::
size_t N,
class A,
bool Init>
1083 inline auto svector<T, N, A, Init>::rbegin() -> reverse_iterator
1085 return reverse_iterator(m_end);
1088 template <
class T, std::
size_t N,
class A,
bool Init>
1089 inline auto svector<T, N, A, Init>::rbegin() const -> const_reverse_iterator
1091 return const_reverse_iterator(m_end);
1094 template <
class T, std::
size_t N,
class A,
bool Init>
1095 inline auto svector<T, N, A, Init>::crbegin() const -> const_reverse_iterator
1097 return const_reverse_iterator(m_end);
1100 template <
class T, std::
size_t N,
class A,
bool Init>
1101 inline auto svector<T, N, A, Init>::rend() -> reverse_iterator
1103 return reverse_iterator(m_begin);
1106 template <
class T, std::
size_t N,
class A,
bool Init>
1107 inline auto svector<T, N, A, Init>::rend() const -> const_reverse_iterator
1109 return const_reverse_iterator(m_begin);
1112 template <
class T, std::
size_t N,
class A,
bool Init>
1113 inline auto svector<T, N, A, Init>::crend() const -> const_reverse_iterator
1115 return const_reverse_iterator(m_begin);
1118 template <
class T, std::
size_t N,
class A,
bool Init>
1119 inline auto svector<T, N, A, Init>::size() const -> size_type
1121 return static_cast<size_type
>(m_end - m_begin);
1124 template <
class T, std::
size_t N,
class A,
bool Init>
1125 inline auto svector<T, N, A, Init>::empty() const ->
bool
1127 return m_begin == m_end;
1130 template <
class T, std::
size_t N,
class A,
bool Init>
1131 inline auto svector<T, N, A, Init>::front() -> reference
1133 XTENSOR_ASSERT(!
empty());
1137 template <
class T, std::
size_t N,
class A,
bool Init>
1138 inline auto svector<T, N, A, Init>::front() const -> const_reference
1140 XTENSOR_ASSERT(!
empty());
1144 template <
class T, std::
size_t N,
class A,
bool Init>
1145 inline auto svector<T, N, A, Init>::back() -> reference
1147 XTENSOR_ASSERT(!
empty());
1151 template <
class T, std::
size_t N,
class A,
bool Init>
1152 inline auto svector<T, N, A, Init>::back() const -> const_reference
1154 XTENSOR_ASSERT(!
empty());
1158 template <
class T, std::
size_t N,
class A,
bool Init>
1159 inline auto svector<T, N, A, Init>::on_stack() ->
bool
1161 return m_begin == &m_data[0];
1164 template <
class T, std::
size_t N,
class A,
bool Init>
1165 inline auto svector<T, N, A, Init>::get_allocator() const noexcept -> allocator_type
1170 template <
class T, std::
size_t N,
class A,
bool Init>
1171 inline auto svector<T, N, A, Init>::erase(const_iterator cit) -> iterator
1173 auto it =
const_cast<pointer
>(cit);
1174 iterator ret_val = it;
1175 std::move(it + 1, m_end, it);
1180 template <
class T, std::
size_t N,
class A,
bool Init>
1181 inline auto svector<T, N, A, Init>::erase(const_iterator cfirst, const_iterator clast) -> iterator
1183 auto first =
const_cast<pointer
>(cfirst);
1184 auto last =
const_cast<pointer
>(clast);
1191 iterator new_end = std::move(last, m_end, first);
1196 template <
class T, std::
size_t N,
class A,
bool Init>
1197 inline auto svector<T, N, A, Init>::insert(const_iterator cit,
const T& elt) -> iterator
1199 auto it =
const_cast<pointer
>(cit);
1206 if (m_end >= m_capacity)
1208 std::ptrdiff_t elt_no = it - m_begin;
1210 it = m_begin + elt_no;
1214 std::move_backward(it, m_end - 1, m_end);
1218 const T* elt_ptr = &elt;
1219 bool cond = it <= elt_ptr && elt_ptr < m_end;
1222 const T* src_ptr = cond ? it + (elt_ptr - it) + std::ptrdiff_t(1) : elt_ptr;
1227 template <
class T, std::
size_t N,
class A,
bool Init>
1229 inline auto svector<T, N, A, Init>::insert(const_iterator pos, It first, It last) -> iterator
1231 auto it =
const_cast<pointer
>(pos);
1232 difference_type n = std::distance(first, last);
1235 if (n > m_capacity - m_end)
1237 std::ptrdiff_t elt_no = it - m_begin;
1238 grow(
static_cast<size_t>((m_capacity - m_begin) + n));
1239 it = m_begin + elt_no;
1242 std::move_backward(it, m_end, m_end + n);
1244 std::copy(first, last, it);
1249 template <
class T, std::
size_t N,
class A,
bool Init>
1250 inline auto svector<T, N, A, Init>::insert(const_iterator pos, std::initializer_list<T> l) -> iterator
1252 return insert(pos, l.begin(), l.end());
1255 template <
class T, std::
size_t N,
class A,
bool Init>
1256 inline void svector<T, N, A, Init>::destroy_range(T* begin, T* end)
1258 if (!std::is_trivially_default_constructible<T>::value)
1260 while (begin != end)
1268 template <
class T, std::
size_t N,
class A,
bool Init>
1269 template <std::
size_t ON,
class OA,
bool InitA>
1279 if (!this->on_stack() && !rhs.on_stack())
1281 swap(this->m_begin, rhs.m_begin);
1282 swap(this->m_end, rhs.m_end);
1283 swap(this->m_capacity, rhs.m_capacity);
1287 size_type rhs_old_size = rhs.size();
1288 size_type old_size = this->size();
1290 if (rhs_old_size > old_size)
1292 this->resize(rhs_old_size);
1294 else if (old_size > rhs_old_size)
1296 rhs.resize(old_size);
1300 size_type min_size = (std::min)(old_size, rhs_old_size);
1301 for (size_type i = 0; i < min_size; ++i)
1303 swap((*
this)[i], rhs[i]);
1307 if (old_size > rhs_old_size)
1309 std::copy(this->begin() + min_size, this->end(), rhs.begin() + min_size);
1310 this->destroy_range(this->begin() + min_size, this->end());
1311 this->m_end = this->begin() + min_size;
1313 else if (rhs_old_size > old_size)
1315 std::copy(rhs.begin() + min_size, rhs.end(), this->begin() + min_size);
1316 this->destroy_range(rhs.begin() + min_size, rhs.end());
1317 rhs.m_end = rhs.begin() + min_size;
1321 template <
class T, std::
size_t N,
class A,
bool Init>
1322 inline void svector<T, N, A, Init>::grow(size_type min_capacity)
1324 size_type current_size = size();
1325 size_type new_capacity = 2 * current_size + 1;
1326 if (new_capacity < min_capacity)
1328 new_capacity = min_capacity;
1333 if (m_begin == &m_data[0])
1335 new_alloc = m_allocator.allocate(new_capacity);
1336 std::uninitialized_copy(m_begin, m_end, new_alloc);
1341 new_alloc = m_allocator.allocate(new_capacity);
1342 std::uninitialized_copy(m_begin, m_end, new_alloc);
1343 m_allocator.deallocate(m_begin, std::size_t(m_capacity - m_begin));
1345 XTENSOR_ASSERT(new_alloc);
1347 m_end = new_alloc + current_size;
1348 m_begin = new_alloc;
1349 m_capacity = new_alloc + new_capacity;
1352 template <
class T, std::
size_t N,
class A,
bool Init>
1355 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1358 template <
class T, std::
size_t N,
class A,
bool Init>
1361 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1364 template <
class T, std::
size_t N,
class A,
bool Init>
1367 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1370 template <
class T, std::
size_t N,
class A,
bool Init>
1373 return !(lhs == rhs);
1376 template <
class T, std::
size_t N,
class A,
bool Init>
1379 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
1382 template <
class T, std::
size_t N,
class A,
bool Init>
1385 return !(lhs > rhs);
1388 template <
class T, std::
size_t N,
class A,
bool Init>
1394 template <
class T, std::
size_t N,
class A,
bool Init>
1397 return !(lhs < rhs);
1400 template <
class T, std::
size_t N,
class A,
bool Init>
1406 template <
class X,
class T, std::
size_t N,
class A,
bool B>
1409 using traits = std::allocator_traits<A>;
1410 using allocator =
typename traits::template rebind_alloc<X>;
1420 template <
class T, std::
size_t N, std::
size_t Align = XTENSOR_
SELECT_ALIGN(T)>
1427 using allocator_type = std::conditional_t<Align != 0, xt_simd::aligned_allocator<T, Align>, std::allocator<T>>;
1430#if defined(_MSC_VER)
1431#define XTENSOR_CONST
1433#define XTENSOR_CONST const
1440 template <
class T, std::
size_t N>
1443 using size_type = std::size_t;
1444 using value_type = T;
1445 using pointer = value_type*;
1446 using const_pointer =
const value_type*;
1447 using reference = value_type&;
1448 using const_reference =
const value_type&;
1449 using difference_type = std::ptrdiff_t;
1450 using iterator = pointer;
1451 using const_iterator = const_pointer;
1453 using reverse_iterator = std::reverse_iterator<const_iterator>;
1454 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1456 constexpr const_reference operator[](std::size_t idx)
const
1461 constexpr const_iterator begin()
const noexcept
1466 constexpr const_iterator end()
const noexcept
1471 constexpr const_iterator cbegin()
const noexcept
1476 constexpr const_iterator cend()
const noexcept
1482 reverse_iterator rbegin()
const noexcept
1487 reverse_iterator rend()
const noexcept
1492 const_reverse_iterator crbegin()
const noexcept
1494 return const_reverse_iterator(end());
1497 const_reverse_iterator crend()
const noexcept
1499 return const_reverse_iterator(begin());
1502 constexpr const_pointer data()
const noexcept
1507 constexpr const_reference front()
const noexcept
1512 constexpr const_reference back()
const noexcept
1514 return m_data[size() - 1];
1517 constexpr bool empty()
const noexcept
1519 return size() == size_type(0);
1522 constexpr size_type size()
const noexcept
1527 XTENSOR_CONST T m_data[N > 0 ? N : 1];
1530 template <
class T, std::
size_t N>
1533 return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
1536 template <
class T, std::
size_t N>
1537 inline bool operator!=(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1539 return !(lhs == rhs);
1542 template <
class T, std::
size_t N>
1543 inline bool operator<(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1545 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
1548 template <
class T, std::
size_t N>
1549 inline bool operator<=(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1551 return !(lhs > rhs);
1554 template <
class T, std::
size_t N>
1555 inline bool operator>(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1560 template <
class T, std::
size_t N>
1561 inline bool operator>=(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1563 return !(lhs < rhs);
1567#ifdef __cpp_template_template_args
1568 template <
class X,
class T, std::
size_t N>
1569 struct rebind_container<X, aligned_array<T, N>>
1571 using type = aligned_array<X, N>;
1574 template <
class X,
class T, std::
size_t N>
1575 struct rebind_container<X, const_array<T, N>>
1577 using type = const_array<X, N>;
1586 template <std::size_t... X>
1591 using cast_type =
const_array<std::size_t,
sizeof...(X)>;
1592 using value_type = std::size_t;
1593 using size_type = std::size_t;
1594 using const_iterator =
typename cast_type::const_iterator;
1596 static constexpr std::size_t size()
1598 return sizeof...(X);
1601 template <std::
size_t idx>
1602 static constexpr auto get()
1604 using tmp_cast_type = std::array<std::size_t,
sizeof...(X)>;
1605 return std::get<idx>(tmp_cast_type{X...});
1608 constexpr operator cast_type()
const
1610 return cast_type({X...});
1613 constexpr auto begin()
const
1615 return m_array.begin();
1618 constexpr auto end()
const
1620 return m_array.end();
1625 return m_array.rbegin();
1630 return m_array.rend();
1633 constexpr auto cbegin()
const
1635 return m_array.cbegin();
1638 constexpr auto cend()
const
1640 return m_array.cend();
1643 constexpr std::size_t operator[](std::size_t idx)
const
1645 return m_array[idx];
1648 constexpr bool empty()
const
1650 return sizeof...(X) == 0;
1655 XTENSOR_CONSTEXPR_ENHANCED_STATIC cast_type m_array = cast_type({X...});
1658 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End = -1>
1663 using value_type =
typename E::value_type;
1664 using reference =
typename E::reference;
1665 using const_reference =
typename E::const_reference;
1666 using pointer =
typename E::pointer;
1667 using const_pointer =
typename E::const_pointer;
1669 using size_type =
typename E::size_type;
1670 using difference_type =
typename E::difference_type;
1672 using iterator =
typename E::iterator;
1673 using const_iterator =
typename E::const_iterator;
1674 using reverse_iterator =
typename E::reverse_iterator;
1675 using const_reverse_iterator =
typename E::const_reverse_iterator;
1677 explicit sequence_view(
const E& container);
1679 template <std::ptrdiff_t OS, std::ptrdiff_t OE>
1680 explicit sequence_view(
const sequence_view<E, OS, OE>& other);
1682 template <class T, class R = decltype(std::declval<T>().begin())>
1686 size_type size()
const;
1687 const_reference operator[](std::size_t idx)
const;
1689 const_iterator end()
const;
1690 const_iterator begin()
const;
1691 const_iterator cend()
const;
1692 const_iterator cbegin()
const;
1694 const_reverse_iterator rend()
const;
1695 const_reverse_iterator rbegin()
const;
1696 const_reverse_iterator crend()
const;
1697 const_reverse_iterator crbegin()
const;
1699 const_reference front()
const;
1700 const_reference back()
const;
1702 const E& storage()
const;
1706 const E& m_sequence;
1709 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1710 sequence_view<E, Start, End>::sequence_view(
const E& container)
1711 : m_sequence(container)
1715 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1716 template <std::ptrdiff_t OS, std::ptrdiff_t OE>
1717 sequence_view<E, Start, End>::sequence_view(
const sequence_view<E, OS, OE>& other)
1718 : m_sequence(other.storage())
1722 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1723 template <
class T,
class R>
1726 T ret = xtl::make_sequence<T>(this->size());
1727 std::copy(this->cbegin(), this->cend(), ret.begin());
1731 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1732 bool sequence_view<E, Start, End>::empty()
const
1734 return size() == size_type(0);
1737 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1738 auto sequence_view<E, Start, End>::size() const -> size_type
1742 return m_sequence.size() -
static_cast<size_type
>(Start);
1746 return static_cast<size_type
>(End - Start);
1750 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1751 auto sequence_view<E, Start, End>::operator[](std::size_t idx)
const -> const_reference
1753 return m_sequence[idx +
static_cast<std::size_t
>(Start)];
1756 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1757 auto sequence_view<E, Start, End>::end() const -> const_iterator
1761 return m_sequence.begin() + End;
1765 return m_sequence.end();
1769 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1770 auto sequence_view<E, Start, End>::begin() const -> const_iterator
1772 return m_sequence.begin() + Start;
1775 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1776 auto sequence_view<E, Start, End>::cend() const -> const_iterator
1781 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1782 auto sequence_view<E, Start, End>::cbegin() const -> const_iterator
1787 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1788 auto sequence_view<E, Start, End>::rend() const -> const_reverse_iterator
1790 return const_reverse_iterator(begin());
1793 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1794 auto sequence_view<E, Start, End>::rbegin() const -> const_reverse_iterator
1796 return const_reverse_iterator(end());
1799 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1800 auto sequence_view<E, Start, End>::crend() const -> const_reverse_iterator
1805 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1806 auto sequence_view<E, Start, End>::crbegin() const -> const_reverse_iterator
1811 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1812 auto sequence_view<E, Start, End>::front() const -> const_reference
1814 return *(m_sequence.begin() + Start);
1817 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1818 auto sequence_view<E, Start, End>::back() const -> const_reference
1822 return m_sequence.back();
1826 return m_sequence[
static_cast<std::size_t
>(End - 1)];
1830 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1831 const E& sequence_view<E, Start, End>::storage()
const
1836 template <
class T, std::ptrdiff_t TB, std::ptrdiff_t TE>
1839 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1842 template <
class T, std::ptrdiff_t TB, std::ptrdiff_t TE>
1845 return !(lhs == rhs);
1859#if defined(__clang__)
1860 # pragma clang diagnostic push
1861 # pragma clang diagnostic ignored "-Wmismatched-tags"
1867 template <
class T, std::
size_t N>
1868 class tuple_size<
xt::const_array<T, N>> :
public integral_constant<std::size_t, N>
1872 template <std::size_t... N>
1873 class tuple_size<
xt::fixed_shape<N...>> :
public integral_constant<std::size_t, sizeof...(N)>
1877 template <
class T, std::ptrdiff_t Start, std::ptrdiff_t End>
1878 class tuple_size<
xt::sequence_view<T, Start, End>>
1879 :
public integral_constant<std::size_t, std::size_t(End - Start)>
1884 template <
class T, std::ptrdiff_t Start>
1885 class tuple_size<
xt::sequence_view<T, Start, -1>>;
1890#if defined(__clang__)
1891 # 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
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.