10#ifndef XTENSOR_FIXED_HPP
11#define XTENSOR_FIXED_HPP
18#include <xtl/xsequence.hpp>
20#include "../containers/xcontainer.hpp"
21#include "../containers/xstorage.hpp"
22#include "../core/xsemantic.hpp"
23#include "../core/xstrides.hpp"
24#include "../core/xtensor_config.hpp"
30 template <
class T, std::
size_t N>
31 struct sequence_builder<xt::const_array<T, N>>
33 using sequence_type = xt::const_array<T, N>;
34 using value_type =
typename sequence_type::value_type;
35 using size_type =
typename sequence_type::size_type;
37 inline static sequence_type make(size_type , value_type )
39 return sequence_type();
52 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
95 template <
layout_type L, std::size_t I, std::size_t... X>
96 struct calculate_stride;
98 template <std::size_t I, std::size_t Y, std::size_t... X>
101 static constexpr std::ptrdiff_t value = Y
105 template <std::size_t Y, std::size_t... X>
108 static constexpr std::ptrdiff_t value = 1;
111 template <std::size_t I, std::size_t... X>
112 struct calculate_stride_row_major
114 static constexpr std::ptrdiff_t value = at<
sizeof...(X) - I, X...>::value
115 * calculate_stride_row_major<I - 1, X...>::value;
118 template <std::size_t... X>
119 struct calculate_stride_row_major<0, X...>
121 static constexpr std::ptrdiff_t value = 1;
124 template <std::size_t I, std::size_t... X>
127 static constexpr std::ptrdiff_t value = calculate_stride_row_major<
sizeof...(X) - I - 1, X...>::value;
132 template <layout_type L,
size_t I,
class SEQ>
133 struct computed_strides;
136 struct computed_strides<L, I, std::index_sequence<X...>>
138 static constexpr std::ptrdiff_t value = calculate_stride<L, I, X...>::value;
141 template <layout_type L,
size_t I,
class SEQ>
142 constexpr std::ptrdiff_t get_computed_strides(
bool cond)
144 return cond ? 0 : computed_strides<L, I, SEQ>::value;
148 template <
layout_type L,
class R, std::size_t... X, std::size_t... I>
149 constexpr R get_strides_impl(
const xt::fixed_shape<X...>& shape, std::index_sequence<I...>)
153 "Layout not supported for fixed array"
155#if (_MSC_VER >= 1910)
156 using temp_type = std::index_sequence<X...>;
157 return R({workaround::get_computed_strides<L, I, temp_type>(shape[I] == 1)...});
159 return R({shape[I] == 1 ? 0 : calculate_stride<L, I, X...>::value...});
163 template <
class S,
class T, std::size_t... I>
164 constexpr T get_backstrides_impl(
const S& shape,
const T&
strides, std::index_sequence<I...>)
166 return T({(
strides[I] * std::ptrdiff_t(shape[I] - 1))...});
169 template <std::size_t... X>
170 struct fixed_compute_size_impl;
172 template <std::size_t Y, std::size_t... X>
173 struct fixed_compute_size_impl<Y, X...>
175 static constexpr std::size_t value = Y * fixed_compute_size_impl<X...>::value;
178 template <std::
size_t X>
179 struct fixed_compute_size_impl<X>
181 static constexpr std::size_t value = X;
185 struct fixed_compute_size_impl<>
188 static constexpr std::size_t value = 1;
193 struct fixed_compute_size;
195 template <std::size_t... X>
196 struct fixed_compute_size<xt::fixed_shape<X...>>
198 static constexpr std::size_t value = fixed_compute_size_impl<X...>::value;
201 template <
class V, std::size_t... X>
202 struct get_init_type_impl;
204 template <
class V, std::
size_t Y>
205 struct get_init_type_impl<V, Y>
211 struct get_init_type_impl<V>
216 template <
class V, std::size_t Y, std::size_t... X>
217 struct get_init_type_impl<V, Y, X...>
219 using tmp_type =
typename get_init_type_impl<V, X...>::type;
220 using type = tmp_type[Y];
224 template <
layout_type L,
class R, std::size_t... X>
227 return detail::get_strides_impl<L, R>(shape, std::make_index_sequence<
sizeof...(X)>{});
230 template <
class S,
class T>
231 constexpr T get_backstrides(
const S& shape,
const T&
strides)
noexcept
233 return detail::get_backstrides_impl(shape,
strides, std::make_index_sequence<std::tuple_size<T>::value>{});
236 template <
class V,
class S>
239 template <
class V, std::size_t... X>
242 using type =
typename detail::get_init_type_impl<V, X...>::type;
245 template <
class V,
class S>
248 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
251 using shape_type = S;
252 using inner_shape_type =
typename S::cast_type;
253 using strides_type = get_strides_t<inner_shape_type>;
254 using inner_strides_type = strides_type;
255 using backstrides_type = inner_strides_type;
256 using inner_backstrides_type = backstrides_type;
261 using reference =
typename storage_type::reference;
262 using const_reference =
typename storage_type::const_reference;
263 using size_type =
typename storage_type::size_type;
268 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
289 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
290 class xfixed_container :
public xcontainer<xfixed_container<ET, S, L, SH, Tag>>,
291 public xcontainer_semantic<xfixed_container<ET, S, L, SH, Tag>>
295 using self_type = xfixed_container<ET, S, L, SH, Tag>;
296 using base_type = xcontainer<self_type>;
297 using semantic_base = xcontainer_semantic<self_type>;
299 using storage_type =
typename base_type::storage_type;
300 using value_type =
typename base_type::value_type;
301 using reference =
typename base_type::reference;
302 using const_reference =
typename base_type::const_reference;
303 using pointer =
typename base_type::pointer;
304 using const_pointer =
typename base_type::const_pointer;
305 using shape_type =
typename base_type::shape_type;
306 using inner_shape_type =
typename base_type::inner_shape_type;
307 using strides_type =
typename base_type::strides_type;
308 using backstrides_type =
typename base_type::backstrides_type;
309 using inner_backstrides_type =
typename base_type::inner_backstrides_type;
310 using inner_strides_type =
typename base_type::inner_strides_type;
311 using temporary_type =
typename semantic_base::temporary_type;
312 using expression_tag = Tag;
314 static constexpr std::size_t N = std::tuple_size<shape_type>::value;
315 static constexpr std::size_t rank = N;
317 xfixed_container() =
default;
318 xfixed_container(
const value_type& v);
322 template <
class IX = std::
integral_constant<std::
size_t, N>>
324 requires(IX::value != 0);
326 ~xfixed_container() =
default;
328 xfixed_container(
const xfixed_container&) =
default;
329 xfixed_container& operator=(
const xfixed_container&) =
default;
331 xfixed_container(xfixed_container&&) =
default;
332 xfixed_container& operator=(xfixed_container&&) =
default;
340 template <
class ST = std::array<std::
size_t, N>>
341 static xfixed_container from_shape(ST&& );
343 template <
class ST = std::array<std::
size_t, N>>
345 template <
class ST = shape_type>
347 template <
class ST = shape_type>
350 template <
class ST = std::array<std::
size_t, N>>
354 bool broadcast_shape(ST& s,
bool reuse_cache =
false)
const;
357 bool is_contiguous() const noexcept;
361 storage_type m_storage;
363 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
364 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L, inner_strides_type>(S());
365 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type
366 m_backstrides = get_backstrides(m_shape, m_strides);
368 storage_type& storage_impl() noexcept;
369 const storage_type& storage_impl() const noexcept;
371 constexpr const inner_shape_type& shape_impl() const noexcept;
372 constexpr const inner_strides_type& strides_impl() const noexcept;
373 constexpr const inner_backstrides_type& backstrides_impl() const noexcept;
375 friend class xcontainer<xfixed_container<ET, S, L, SH, Tag>>;
382 template <class EC, class S,
layout_type L,
bool SH, class Tag>
385 template <class EC, class S,
layout_type L,
bool SH, class Tag>
388 using storage_type = std::remove_reference_t<EC>;
389 using reference =
typename storage_type::reference;
390 using const_reference =
typename storage_type::const_reference;
391 using size_type =
typename storage_type::size_type;
392 using shape_type = S;
393 using inner_shape_type =
typename S::cast_type;
394 using strides_type = get_strides_t<inner_shape_type>;
395 using backstrides_type = strides_type;
396 using inner_strides_type = strides_type;
397 using inner_backstrides_type = backstrides_type;
402 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
424 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
426 public xcontainer_semantic<xfixed_adaptor<EC, S, L, SH, Tag>>
430 using container_closure_type = EC;
433 using base_type = xcontainer<self_type>;
434 using semantic_base = xcontainer_semantic<self_type>;
435 using storage_type =
typename base_type::storage_type;
436 using shape_type =
typename base_type::shape_type;
437 using strides_type =
typename base_type::strides_type;
438 using backstrides_type =
typename base_type::backstrides_type;
439 using inner_shape_type =
typename base_type::inner_shape_type;
440 using inner_strides_type =
typename base_type::inner_strides_type;
441 using inner_backstrides_type =
typename base_type::inner_backstrides_type;
442 using temporary_type =
typename semantic_base::temporary_type;
443 using expression_tag = Tag;
445 static constexpr std::size_t N = S::size();
465 template <
class ST = std::array<std::
size_t, N>>
467 template <
class ST = shape_type>
469 template <
class ST = shape_type>
472 template <
class ST = std::array<std::
size_t, N>>
476 bool broadcast_shape(ST& s,
bool reuse_cache =
false)
const;
479 bool is_contiguous()
const noexcept;
483 container_closure_type m_storage;
485 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
486 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L, inner_strides_type>(S());
487 XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type
488 m_backstrides = get_backstrides(m_shape, m_strides);
490 storage_type& storage_impl()
noexcept;
491 const storage_type& storage_impl()
const noexcept;
493 constexpr const inner_shape_type& shape_impl()
const noexcept;
494 constexpr const inner_strides_type& strides_impl()
const noexcept;
495 constexpr const inner_backstrides_type& backstrides_impl()
const noexcept;
517 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
518 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(
const inner_shape_type&
shape,
layout_type l)
522 XTENSOR_ASSERT(
shape.size() == N && std::equal(
shape.begin(),
shape.end(), m_shape.begin()));
523 XTENSOR_ASSERT(L == l);
526 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
527 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(
const value_type& v)
529 if (this->
size() != 1)
531 XTENSOR_THROW(std::runtime_error,
"wrong shape for scalar assignment (has to be xshape<>).");
545 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
546 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(
547 const inner_shape_type&
shape,
554 XTENSOR_ASSERT(
shape.size() == N && std::equal(
shape.begin(),
shape.end(), m_shape.begin()));
555 XTENSOR_ASSERT(L == l);
556 std::fill(m_storage.begin(), m_storage.end(), v);
561 template <std::
size_t X>
562 struct check_initializer_list_shape
564 template <
class T,
class S>
565 static bool run(
const T& t,
const S& shape)
567 std::size_t IX = shape.size() - X;
568 bool result = (shape[IX] == t.size());
569 for (std::size_t i = 0; i < shape[IX]; ++i)
571 result = result && check_initializer_list_shape<X - 1>::run(t.begin()[i], shape);
578 struct check_initializer_list_shape<0>
580 template <
class T,
class S>
581 static bool run(
const T& ,
const S& )
588 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
590 inline xfixed_container<ET, S, L, SH, Tag> xfixed_container<ET, S, L, SH, Tag>::from_shape(ST&&
shape)
594 XTENSOR_ASSERT(
shape.size() == N && std::equal(
shape.begin(),
shape.end(), tmp.shape().begin()));
605 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
607 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(nested_initializer_list_t<value_type, N> t)
608 requires(IX::value != 0)
611 detail::check_initializer_list_shape<N>::run(t, this->
shape()) ==
true,
612 "initializer list shape does not match fixed shape"
615 L == tmp ? nested_copy(m_storage.begin(), t) : nested_copy(this->
template begin<tmp>(), t);
627 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
629 inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(
const xexpression<E>& e)
631 semantic_base::assign(e);
637 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
639 inline auto xfixed_container<ET, S, L, SH, Tag>::operator=(
const xexpression<E>& e) -> self_type&
641 return semantic_base::operator=(e);
650 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
655 XTENSOR_ASSERT(std::equal(
shape.begin(),
shape.end(), m_shape.begin()) &&
shape.size() == m_shape.size());
662 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
669 std::equal(
shape.begin(),
shape.end(), m_shape.begin()) &&
shape.size() == m_shape.size() && L == l
677 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
683 XTENSOR_ASSERT(std::equal(
shape.begin(),
shape.end(), m_shape.begin()) &&
shape.size() == m_shape.size());
692 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
696 if (!(std::equal(
shape.begin(),
shape.end(), m_shape.begin()) &&
shape.size() == m_shape.size()
699 XTENSOR_THROW(std::runtime_error,
"Trying to reshape xtensor_fixed with different shape or layout.");
704 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
706 inline bool xfixed_container<ET, S, L, SH, Tag>::broadcast_shape(ST& shape,
bool)
const
708 return xt::broadcast_shape(m_shape, shape);
711 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
712 constexpr layout_type xfixed_container<ET, S, L, SH, Tag>::layout() const noexcept
714 return base_type::static_layout;
717 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
718 inline bool xfixed_container<ET, S, L, SH, Tag>::is_contiguous() const noexcept
720 using str_type =
typename inner_strides_type::value_type;
725 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
726 inline auto xfixed_container<ET, S, L, SH, Tag>::storage_impl() noexcept -> storage_type&
731 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
732 inline auto xfixed_container<ET, S, L, SH, Tag>::storage_impl() const noexcept -> const storage_type&
737 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
738 constexpr auto xfixed_container<ET, S, L, SH, Tag>::shape_impl() const noexcept -> const inner_shape_type&
743 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
744 constexpr auto xfixed_container<ET, S, L, SH, Tag>::strides_impl() const noexcept
745 -> const inner_strides_type&
750 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
751 constexpr auto xfixed_container<ET, S, L, SH, Tag>::backstrides_impl() const noexcept
752 -> const inner_backstrides_type&
754 return m_backstrides;
769 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
772 , m_storage(std::move(
data))
780 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
792 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
796 , m_storage(std::forward<D>(
data))
802 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
803 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(
const xfixed_adaptor& rhs) -> self_type&
805 base_type::operator=(rhs);
806 m_storage = rhs.m_storage;
810 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
811 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(xfixed_adaptor&& rhs) -> self_type&
813 base_type::operator=(std::move(rhs));
814 m_storage = rhs.m_storage;
818 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
819 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(
temporary_type&& rhs) -> self_type&
821 m_storage.resize(rhs.storage().size());
822 std::copy(rhs.storage().cbegin(), rhs.storage().cend(), m_storage.begin());
833 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
835 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(
const xexpression<E>& e) -> self_type&
837 return semantic_base::operator=(e);
846 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
851 XTENSOR_ASSERT(std::equal(
shape.begin(),
shape.end(), m_shape.begin()) &&
shape.size() == m_shape.size());
858 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
865 std::equal(
shape.begin(),
shape.end(), m_shape.begin()) &&
shape.size() == m_shape.size() && L == l
873 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
879 XTENSOR_ASSERT(std::equal(
shape.begin(),
shape.end(), m_shape.begin()) &&
shape.size() == m_shape.size());
888 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
892 if (!(std::equal(
shape.begin(),
shape.end(), m_shape.begin()) &&
shape.size() == m_shape.size()
895 XTENSOR_THROW(std::runtime_error,
"Trying to reshape xtensor_fixed with different shape or layout.");
900 template <
class ET,
class S, layout_type L,
bool SH,
class Tag>
902 inline bool xfixed_adaptor<ET, S, L, SH, Tag>::broadcast_shape(ST& shape,
bool)
const
904 return xt::broadcast_shape(m_shape, shape);
907 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
908 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::storage_impl() noexcept -> storage_type&
913 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
914 inline auto xfixed_adaptor<EC, S, L, SH, Tag>::storage_impl() const noexcept -> const storage_type&
919 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
920 constexpr layout_type xfixed_adaptor<EC, S, L, SH, Tag>::layout() const noexcept
922 return base_type::static_layout;
925 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
926 inline bool xfixed_adaptor<EC, S, L, SH, Tag>::is_contiguous() const noexcept
928 using str_type =
typename inner_strides_type::value_type;
933 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
934 constexpr auto xfixed_adaptor<EC, S, L, SH, Tag>::shape_impl() const noexcept -> const inner_shape_type&
939 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
940 constexpr auto xfixed_adaptor<EC, S, L, SH, Tag>::strides_impl() const noexcept
941 -> const inner_strides_type&
946 template <
class EC,
class S, layout_type L,
bool SH,
class Tag>
947 constexpr auto xfixed_adaptor<EC, S, L, SH, Tag>::backstrides_impl() const noexcept
948 -> const inner_backstrides_type&
950 return m_backstrides;
This array class is modeled after std::array but adds optional alignment through a template parameter...
Fixed shape implementation for compile time defined arrays.
size_type size() const noexcept
constexpr const inner_strides_type & strides() const noexcept
Returns the strides of the container.
constexpr const inner_shape_type & shape() const noexcept
Returns the shape of the container.
auto begin() noexcept -> select_iterator< L >
Base class for xexpressions.
Dense multidimensional container adaptor with tensor semantic and fixed dimension.
xfixed_adaptor(storage_type &&data)
Constructs an xfixed_adaptor of the given stl-like container.
const auto & reshape(ST &&shape, layout_type layout=L) const
Note that the xfixed_container cannot be reshaped to a shape different from S.
void resize(ST &&shape, bool force=false) const
Note that the xfixed_adaptor cannot be resized.
Dense multidimensional container with tensor semantic and fixed dimension.
xfixed_container(const inner_shape_type &shape, layout_type l=L)
Create an uninitialized xfixed_container.
xfixed_container(const xexpression< E > &e)
The extended copy constructor.
void resize(ST &&shape, bool force=false) const
Note that the xfixed_container cannot be resized.
void resize(ST &&shape, const strides_type &strides) const
Note that the xfixed_container cannot be resized.
xfixed_container(const inner_shape_type &shape, value_type v, layout_type l=L)
Create an xfixed_container, and initialize with the value of v.
void resize(ST &&shape, layout_type l) const
Note that the xfixed_container cannot be resized.
xfixed_container(nested_initializer_list_t< value_type, N > t)
Allocates an xfixed_container with shape S with values from a C array.
const auto & reshape(ST &&shape, layout_type layout=L) const
Note that the xfixed_container cannot be reshaped to a shape different from S.
auto strides(const E &e, stride_type type=stride_type::normal) noexcept
Get strides of an object.
standard mathematical functions for xexpressions