| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991 |
- /***************************************************************************
- * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
- * Copyright (c) QuantStack *
- * *
- * Distributed under the terms of the BSD 3-Clause License. *
- * *
- * The full license is in the file LICENSE, distributed with this software. *
- ****************************************************************************/
- #ifndef XTENSOR_FIXED_HPP
- #define XTENSOR_FIXED_HPP
- #include <algorithm>
- #include <array>
- #include <cstddef>
- #include <utility>
- #include <vector>
- #include <xtl/xsequence.hpp>
- #include "xcontainer.hpp"
- #include "xsemantic.hpp"
- #include "xstorage.hpp"
- #include "xstrides.hpp"
- #include "xtensor_config.hpp"
- namespace xtl
- {
- namespace detail
- {
- template <class T, std::size_t N>
- struct sequence_builder<xt::const_array<T, N>>
- {
- using sequence_type = xt::const_array<T, N>;
- using value_type = typename sequence_type::value_type;
- using size_type = typename sequence_type::size_type;
- inline static sequence_type make(size_type /*size*/, value_type /*v*/)
- {
- return sequence_type();
- }
- };
- }
- }
- namespace xt
- {
- /**********************
- * xfixed declaration *
- **********************/
- template <class ET, class S, layout_type L, bool SH, class Tag>
- class xfixed_container;
- namespace detail
- {
- /**************************************************************************************
- The following is something we can currently only dream about -- for when we drop
- support for a lot of the old compilers (e.g. GCC 4.9, MSVC 2017 ;)
- template <class T>
- constexpr std::size_t calculate_stride(T& shape, std::size_t idx, layout_type L)
- {
- if (shape[idx] == 1)
- {
- return std::size_t(0);
- }
- std::size_t data_size = 1;
- std::size_t stride = 1;
- if (L == layout_type::row_major)
- {
- // because we have a integer sequence that counts
- // from 0 to sz - 1, we need to "invert" idx here
- idx = shape.size() - idx;
- for (std::size_t i = idx; i != 0; --i)
- {
- stride = data_size;
- data_size = stride * shape[i - 1];
- }
- }
- else
- {
- for (std::size_t i = 0; i < idx + 1; ++i)
- {
- stride = data_size;
- data_size = stride * shape[i];
- }
- }
- return stride;
- }
- *****************************************************************************************/
- template <layout_type L, std::size_t I, std::size_t... X>
- struct calculate_stride;
- template <std::size_t I, std::size_t Y, std::size_t... X>
- struct calculate_stride<layout_type::column_major, I, Y, X...>
- {
- static constexpr std::ptrdiff_t value = Y
- * calculate_stride<layout_type::column_major, I - 1, X...>::value;
- };
- template <std::size_t Y, std::size_t... X>
- struct calculate_stride<layout_type::column_major, 0, Y, X...>
- {
- static constexpr std::ptrdiff_t value = 1;
- };
- template <std::size_t I, std::size_t... X>
- struct calculate_stride_row_major
- {
- static constexpr std::ptrdiff_t value = at<sizeof...(X) - I, X...>::value
- * calculate_stride_row_major<I - 1, X...>::value;
- };
- template <std::size_t... X>
- struct calculate_stride_row_major<0, X...>
- {
- static constexpr std::ptrdiff_t value = 1;
- };
- template <std::size_t I, std::size_t... X>
- struct calculate_stride<layout_type::row_major, I, X...>
- {
- static constexpr std::ptrdiff_t value = calculate_stride_row_major<sizeof...(X) - I - 1, X...>::value;
- };
- namespace workaround
- {
- template <layout_type L, size_t I, class SEQ>
- struct computed_strides;
- template <layout_type L, size_t I, size_t... X>
- struct computed_strides<L, I, std::index_sequence<X...>>
- {
- static constexpr std::ptrdiff_t value = calculate_stride<L, I, X...>::value;
- };
- template <layout_type L, size_t I, class SEQ>
- constexpr std::ptrdiff_t get_computed_strides(bool cond)
- {
- return cond ? 0 : computed_strides<L, I, SEQ>::value;
- }
- }
- template <layout_type L, class R, std::size_t... X, std::size_t... I>
- constexpr R get_strides_impl(const xt::fixed_shape<X...>& shape, std::index_sequence<I...>)
- {
- static_assert(
- (L == layout_type::row_major) || (L == layout_type::column_major),
- "Layout not supported for fixed array"
- );
- #if (_MSC_VER >= 1910)
- using temp_type = std::index_sequence<X...>;
- return R({workaround::get_computed_strides<L, I, temp_type>(shape[I] == 1)...});
- #else
- return R({shape[I] == 1 ? 0 : calculate_stride<L, I, X...>::value...});
- #endif
- }
- template <class S, class T, std::size_t... I>
- constexpr T get_backstrides_impl(const S& shape, const T& strides, std::index_sequence<I...>)
- {
- return T({(strides[I] * std::ptrdiff_t(shape[I] - 1))...});
- }
- template <std::size_t... X>
- struct fixed_compute_size_impl;
- template <std::size_t Y, std::size_t... X>
- struct fixed_compute_size_impl<Y, X...>
- {
- static constexpr std::size_t value = Y * fixed_compute_size_impl<X...>::value;
- };
- template <std::size_t X>
- struct fixed_compute_size_impl<X>
- {
- static constexpr std::size_t value = X;
- };
- template <>
- struct fixed_compute_size_impl<>
- {
- // support for 0D xtensor fixed (empty shape = xshape<>)
- static constexpr std::size_t value = 1;
- };
- // TODO unify with constexpr compute_size when dropping MSVC 2015
- template <class T>
- struct fixed_compute_size;
- template <std::size_t... X>
- struct fixed_compute_size<xt::fixed_shape<X...>>
- {
- static constexpr std::size_t value = fixed_compute_size_impl<X...>::value;
- };
- template <class V, std::size_t... X>
- struct get_init_type_impl;
- template <class V, std::size_t Y>
- struct get_init_type_impl<V, Y>
- {
- using type = V[Y];
- };
- template <class V>
- struct get_init_type_impl<V>
- {
- using type = V[1];
- };
- template <class V, std::size_t Y, std::size_t... X>
- struct get_init_type_impl<V, Y, X...>
- {
- using tmp_type = typename get_init_type_impl<V, X...>::type;
- using type = tmp_type[Y];
- };
- }
- template <layout_type L, class R, std::size_t... X>
- constexpr R get_strides(const fixed_shape<X...>& shape) noexcept
- {
- return detail::get_strides_impl<L, R>(shape, std::make_index_sequence<sizeof...(X)>{});
- }
- template <class S, class T>
- constexpr T get_backstrides(const S& shape, const T& strides) noexcept
- {
- return detail::get_backstrides_impl(shape, strides, std::make_index_sequence<std::tuple_size<T>::value>{});
- }
- template <class V, class S>
- struct get_init_type;
- template <class V, std::size_t... X>
- struct get_init_type<V, fixed_shape<X...>>
- {
- using type = typename detail::get_init_type_impl<V, X...>::type;
- };
- template <class V, class S>
- using get_init_type_t = typename get_init_type<V, S>::type;
- template <class ET, class S, layout_type L, bool SH, class Tag>
- struct xcontainer_inner_types<xfixed_container<ET, S, L, SH, Tag>>
- {
- using shape_type = S;
- using inner_shape_type = typename S::cast_type;
- using strides_type = get_strides_t<inner_shape_type>;
- using inner_strides_type = strides_type;
- using backstrides_type = inner_strides_type;
- using inner_backstrides_type = backstrides_type;
- // NOTE: 0D (S::size() == 0) results in storage for 1 element (scalar)
- #if defined(_MSC_VER) && _MSC_VER < 1910 && !defined(_WIN64)
- // WORKAROUND FOR MSVC 2015 32 bit, fallback to unaligned container for 0D scalar case
- using storage_type = std::array<ET, detail::fixed_compute_size<S>::value>;
- #else
- using storage_type = aligned_array<ET, detail::fixed_compute_size<S>::value>;
- #endif
- using reference = typename storage_type::reference;
- using const_reference = typename storage_type::const_reference;
- using size_type = typename storage_type::size_type;
- using temporary_type = xfixed_container<ET, S, L, SH, Tag>;
- static constexpr layout_type layout = L;
- };
- template <class ET, class S, layout_type L, bool SH, class Tag>
- struct xiterable_inner_types<xfixed_container<ET, S, L, SH, Tag>>
- : xcontainer_iterable_types<xfixed_container<ET, S, L, SH, Tag>>
- {
- };
- /**
- * @class xfixed_container
- * @brief Dense multidimensional container with tensor semantic and fixed
- * dimension.
- *
- * The xfixed_container class implements a dense multidimensional container
- * with tensor semantic and fixed dimension
- *
- * @tparam ET The type of the elements.
- * @tparam S The xshape template paramter of the container.
- * @tparam L The layout_type of the tensor.
- * @tparam SH Wether the tensor can be used as a shared expression.
- * @tparam Tag The expression tag.
- * @sa xtensor_fixed
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- class xfixed_container : public xcontainer<xfixed_container<ET, S, L, SH, Tag>>,
- public xcontainer_semantic<xfixed_container<ET, S, L, SH, Tag>>
- {
- public:
- using self_type = xfixed_container<ET, S, L, SH, Tag>;
- using base_type = xcontainer<self_type>;
- using semantic_base = xcontainer_semantic<self_type>;
- using storage_type = typename base_type::storage_type;
- using value_type = typename base_type::value_type;
- using reference = typename base_type::reference;
- using const_reference = typename base_type::const_reference;
- using pointer = typename base_type::pointer;
- using const_pointer = typename base_type::const_pointer;
- using shape_type = typename base_type::shape_type;
- using inner_shape_type = typename base_type::inner_shape_type;
- using strides_type = typename base_type::strides_type;
- using backstrides_type = typename base_type::backstrides_type;
- using inner_backstrides_type = typename base_type::inner_backstrides_type;
- using inner_strides_type = typename base_type::inner_strides_type;
- using temporary_type = typename semantic_base::temporary_type;
- using expression_tag = Tag;
- static constexpr std::size_t N = std::tuple_size<shape_type>::value;
- static constexpr std::size_t rank = N;
- xfixed_container() = default;
- xfixed_container(const value_type& v);
- explicit xfixed_container(const inner_shape_type& shape, layout_type l = L);
- explicit xfixed_container(const inner_shape_type& shape, value_type v, layout_type l = L);
- // remove this enable_if when removing the other value_type constructor
- template <class IX = std::integral_constant<std::size_t, N>, class EN = std::enable_if_t<IX::value != 0, int>>
- xfixed_container(nested_initializer_list_t<value_type, N> t);
- ~xfixed_container() = default;
- xfixed_container(const xfixed_container&) = default;
- xfixed_container& operator=(const xfixed_container&) = default;
- xfixed_container(xfixed_container&&) = default;
- xfixed_container& operator=(xfixed_container&&) = default;
- template <class E>
- xfixed_container(const xexpression<E>& e);
- template <class E>
- xfixed_container& operator=(const xexpression<E>& e);
- template <class ST = std::array<std::size_t, N>>
- static xfixed_container from_shape(ST&& /*s*/);
- template <class ST = std::array<std::size_t, N>>
- void resize(ST&& shape, bool force = false) const;
- template <class ST = shape_type>
- void resize(ST&& shape, layout_type l) const;
- template <class ST = shape_type>
- void resize(ST&& shape, const strides_type& strides) const;
- template <class ST = std::array<std::size_t, N>>
- const auto& reshape(ST&& shape, layout_type layout = L) const;
- template <class ST>
- bool broadcast_shape(ST& s, bool reuse_cache = false) const;
- constexpr layout_type layout() const noexcept;
- bool is_contiguous() const noexcept;
- private:
- storage_type m_storage;
- XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
- XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L, inner_strides_type>(S());
- XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type
- m_backstrides = get_backstrides(m_shape, m_strides);
- storage_type& storage_impl() noexcept;
- const storage_type& storage_impl() const noexcept;
- XTENSOR_CONSTEXPR_RETURN const inner_shape_type& shape_impl() const noexcept;
- XTENSOR_CONSTEXPR_RETURN const inner_strides_type& strides_impl() const noexcept;
- XTENSOR_CONSTEXPR_RETURN const inner_backstrides_type& backstrides_impl() const noexcept;
- friend class xcontainer<xfixed_container<ET, S, L, SH, Tag>>;
- };
- #ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED
- // Out of line definitions to prevent linker errors prior to C++17
- template <class ET, class S, layout_type L, bool SH, class Tag>
- constexpr
- typename xfixed_container<ET, S, L, SH, Tag>::inner_shape_type xfixed_container<ET, S, L, SH, Tag>::m_shape;
- template <class ET, class S, layout_type L, bool SH, class Tag>
- constexpr
- typename xfixed_container<ET, S, L, SH, Tag>::inner_strides_type xfixed_container<ET, S, L, SH, Tag>::m_strides;
- template <class ET, class S, layout_type L, bool SH, class Tag>
- constexpr typename xfixed_container<ET, S, L, SH, Tag>::inner_backstrides_type
- xfixed_container<ET, S, L, SH, Tag>::m_backstrides;
- #endif
- /****************************************
- * xfixed_container_adaptor declaration *
- ****************************************/
- template <class EC, class S, layout_type L, bool SH, class Tag>
- class xfixed_adaptor;
- template <class EC, class S, layout_type L, bool SH, class Tag>
- struct xcontainer_inner_types<xfixed_adaptor<EC, S, L, SH, Tag>>
- {
- using storage_type = std::remove_reference_t<EC>;
- using reference = typename storage_type::reference;
- using const_reference = typename storage_type::const_reference;
- using size_type = typename storage_type::size_type;
- using shape_type = S;
- using inner_shape_type = typename S::cast_type;
- using strides_type = get_strides_t<inner_shape_type>;
- using backstrides_type = strides_type;
- using inner_strides_type = strides_type;
- using inner_backstrides_type = backstrides_type;
- using temporary_type = xfixed_container<typename storage_type::value_type, S, L, SH, Tag>;
- static constexpr layout_type layout = L;
- };
- template <class EC, class S, layout_type L, bool SH, class Tag>
- struct xiterable_inner_types<xfixed_adaptor<EC, S, L, SH, Tag>>
- : xcontainer_iterable_types<xfixed_adaptor<EC, S, L, SH, Tag>>
- {
- };
- /**
- * @class xfixed_adaptor
- * @brief Dense multidimensional container adaptor with tensor semantic
- * and fixed dimension.
- *
- * The xfixed_adaptor class implements a dense multidimensional
- * container adaptor with tensor semantic and fixed dimension. It
- * is used to provide a multidimensional container semantic and a
- * tensor semantic to stl-like containers.
- *
- * @tparam EC The closure for the container type to adapt.
- * @tparam S The xshape template parameter for the fixed shape of the adaptor
- * @tparam L The layout_type of the adaptor.
- * @tparam SH Wether the adaptor can be used as a shared expression.
- * @tparam Tag The expression tag.
- */
- template <class EC, class S, layout_type L, bool SH, class Tag>
- class xfixed_adaptor : public xcontainer<xfixed_adaptor<EC, S, L, SH, Tag>>,
- public xcontainer_semantic<xfixed_adaptor<EC, S, L, SH, Tag>>
- {
- public:
- using container_closure_type = EC;
- using self_type = xfixed_adaptor<EC, S, L, SH, Tag>;
- using base_type = xcontainer<self_type>;
- using semantic_base = xcontainer_semantic<self_type>;
- using storage_type = typename base_type::storage_type;
- using shape_type = typename base_type::shape_type;
- using strides_type = typename base_type::strides_type;
- using backstrides_type = typename base_type::backstrides_type;
- using inner_shape_type = typename base_type::inner_shape_type;
- using inner_strides_type = typename base_type::inner_strides_type;
- using inner_backstrides_type = typename base_type::inner_backstrides_type;
- using temporary_type = typename semantic_base::temporary_type;
- using expression_tag = Tag;
- static constexpr std::size_t N = S::size();
- xfixed_adaptor(storage_type&& data);
- xfixed_adaptor(const storage_type& data);
- template <class D>
- xfixed_adaptor(D&& data);
- ~xfixed_adaptor() = default;
- xfixed_adaptor(const xfixed_adaptor&) = default;
- xfixed_adaptor& operator=(const xfixed_adaptor&);
- xfixed_adaptor(xfixed_adaptor&&) = default;
- xfixed_adaptor& operator=(xfixed_adaptor&&);
- xfixed_adaptor& operator=(temporary_type&&);
- template <class E>
- xfixed_adaptor& operator=(const xexpression<E>& e);
- template <class ST = std::array<std::size_t, N>>
- void resize(ST&& shape, bool force = false) const;
- template <class ST = shape_type>
- void resize(ST&& shape, layout_type l) const;
- template <class ST = shape_type>
- void resize(ST&& shape, const strides_type& strides) const;
- template <class ST = std::array<std::size_t, N>>
- const auto& reshape(ST&& shape, layout_type layout = L) const;
- template <class ST>
- bool broadcast_shape(ST& s, bool reuse_cache = false) const;
- constexpr layout_type layout() const noexcept;
- bool is_contiguous() const noexcept;
- private:
- container_closure_type m_storage;
- XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
- XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L, inner_strides_type>(S());
- XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type
- m_backstrides = get_backstrides(m_shape, m_strides);
- storage_type& storage_impl() noexcept;
- const storage_type& storage_impl() const noexcept;
- XTENSOR_CONSTEXPR_RETURN const inner_shape_type& shape_impl() const noexcept;
- XTENSOR_CONSTEXPR_RETURN const inner_strides_type& strides_impl() const noexcept;
- XTENSOR_CONSTEXPR_RETURN const inner_backstrides_type& backstrides_impl() const noexcept;
- friend class xcontainer<xfixed_adaptor<EC, S, L, SH, Tag>>;
- };
- #ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED
- // Out of line definitions to prevent linker errors prior to C++17
- template <class EC, class S, layout_type L, bool SH, class Tag>
- constexpr
- typename xfixed_adaptor<EC, S, L, SH, Tag>::inner_shape_type xfixed_adaptor<EC, S, L, SH, Tag>::m_shape;
- template <class EC, class S, layout_type L, bool SH, class Tag>
- constexpr
- typename xfixed_adaptor<EC, S, L, SH, Tag>::inner_strides_type xfixed_adaptor<EC, S, L, SH, Tag>::m_strides;
- template <class EC, class S, layout_type L, bool SH, class Tag>
- constexpr typename xfixed_adaptor<EC, S, L, SH, Tag>::inner_backstrides_type
- xfixed_adaptor<EC, S, L, SH, Tag>::m_backstrides;
- #endif
- /************************************
- * xfixed_container implementation *
- ************************************/
- /**
- * @name Constructors
- */
- //@{
- /**
- * Create an uninitialized xfixed_container.
- * Note this function is only provided for homogeneity, and the shape & layout argument is
- * disregarded (the template shape is always used).
- *
- * @param shape the shape of the xfixed_container (unused!)
- * @param l the layout_type of the xfixed_container (unused!)
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const inner_shape_type& shape, layout_type l)
- {
- (void) (shape);
- (void) (l);
- XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), m_shape.begin()));
- XTENSOR_ASSERT(L == l);
- }
- template <class ET, class S, layout_type L, bool SH, class Tag>
- inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const value_type& v)
- {
- if (this->size() != 1)
- {
- XTENSOR_THROW(std::runtime_error, "wrong shape for scalar assignment (has to be xshape<>).");
- }
- m_storage[0] = v;
- }
- /**
- * Create an xfixed_container, and initialize with the value of v.
- * Note, the shape argument to this function is only provided for homogeneity,
- * and the shape argument is disregarded (the template shape is always used).
- *
- * @param shape the shape of the xfixed_container (unused!)
- * @param v the fill value
- * @param l the layout_type of the xfixed_container (unused!)
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(
- const inner_shape_type& shape,
- value_type v,
- layout_type l
- )
- {
- (void) (shape);
- (void) (l);
- XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), m_shape.begin()));
- XTENSOR_ASSERT(L == l);
- std::fill(m_storage.begin(), m_storage.end(), v);
- }
- namespace detail
- {
- template <std::size_t X>
- struct check_initializer_list_shape
- {
- template <class T, class S>
- static bool run(const T& t, const S& shape)
- {
- std::size_t IX = shape.size() - X;
- bool result = (shape[IX] == t.size());
- for (std::size_t i = 0; i < shape[IX]; ++i)
- {
- result = result && check_initializer_list_shape<X - 1>::run(t.begin()[i], shape);
- }
- return result;
- }
- };
- template <>
- struct check_initializer_list_shape<0>
- {
- template <class T, class S>
- static bool run(const T& /*t*/, const S& /*shape*/)
- {
- return true;
- }
- };
- }
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class ST>
- inline xfixed_container<ET, S, L, SH, Tag> xfixed_container<ET, S, L, SH, Tag>::from_shape(ST&& shape)
- {
- (void) shape;
- self_type tmp;
- XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), tmp.shape().begin()));
- return tmp;
- }
- /**
- * Allocates an xfixed_container with shape S with values from a C array.
- * The type returned by get_init_type_t is raw C array ``value_type[X][Y][Z]`` for
- * ``xt::xshape<X, Y, Z>``. C arrays can be initialized with the initializer list syntax,
- * but the size is checked at compile time to prevent errors.
- * Note: for clang < 3.8 this is an initializer_list and the size is not checked at compile-or runtime.
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class IX, class EN>
- inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(nested_initializer_list_t<value_type, N> t)
- {
- XTENSOR_ASSERT_MSG(
- detail::check_initializer_list_shape<N>::run(t, this->shape()) == true,
- "initializer list shape does not match fixed shape"
- );
- constexpr auto tmp = layout_type::row_major;
- L == tmp ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin<tmp>(), t);
- }
- //@}
- /**
- * @name Extended copy semantic
- */
- //@{
- /**
- * The extended copy constructor.
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class E>
- inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const xexpression<E>& e)
- {
- semantic_base::assign(e);
- }
- /**
- * The extended assignment operator.
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class E>
- inline auto xfixed_container<ET, S, L, SH, Tag>::operator=(const xexpression<E>& e) -> self_type&
- {
- return semantic_base::operator=(e);
- }
- //@}
- /**
- * Note that the xfixed_container **cannot** be resized. Attempting to resize with a different
- * size throws an assert in debug mode.
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class ST>
- inline void xfixed_container<ET, S, L, SH, Tag>::resize(ST&& shape, bool) const
- {
- (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
- XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
- }
- /**
- * Note that the xfixed_container **cannot** be resized. Attempting to resize with a different
- * size throws an assert in debug mode.
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class ST>
- inline void xfixed_container<ET, S, L, SH, Tag>::resize(ST&& shape, layout_type l) const
- {
- (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
- (void) (l);
- XTENSOR_ASSERT(
- std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size() && L == l
- );
- }
- /**
- * Note that the xfixed_container **cannot** be resized. Attempting to resize with a different
- * size throws an assert in debug mode.
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class ST>
- inline void xfixed_container<ET, S, L, SH, Tag>::resize(ST&& shape, const strides_type& strides) const
- {
- (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
- (void) (strides);
- XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
- XTENSOR_ASSERT(
- std::equal(strides.begin(), strides.end(), m_strides.begin()) && strides.size() == m_strides.size()
- );
- }
- /**
- * Note that the xfixed_container **cannot** be reshaped to a shape different from ``S``.
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class ST>
- inline const auto& xfixed_container<ET, S, L, SH, Tag>::reshape(ST&& shape, layout_type layout) const
- {
- if (!(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size()
- && layout == L))
- {
- XTENSOR_THROW(std::runtime_error, "Trying to reshape xtensor_fixed with different shape or layout.");
- }
- return *this;
- }
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class ST>
- inline bool xfixed_container<ET, S, L, SH, Tag>::broadcast_shape(ST& shape, bool) const
- {
- return xt::broadcast_shape(m_shape, shape);
- }
- template <class ET, class S, layout_type L, bool SH, class Tag>
- constexpr layout_type xfixed_container<ET, S, L, SH, Tag>::layout() const noexcept
- {
- return base_type::static_layout;
- }
- template <class ET, class S, layout_type L, bool SH, class Tag>
- inline bool xfixed_container<ET, S, L, SH, Tag>::is_contiguous() const noexcept
- {
- using str_type = typename inner_strides_type::value_type;
- return m_strides.empty() || (layout() == layout_type::row_major && m_strides.back() == str_type(1))
- || (layout() == layout_type::column_major && m_strides.front() == str_type(1));
- }
- template <class ET, class S, layout_type L, bool SH, class Tag>
- inline auto xfixed_container<ET, S, L, SH, Tag>::storage_impl() noexcept -> storage_type&
- {
- return m_storage;
- }
- template <class ET, class S, layout_type L, bool SH, class Tag>
- inline auto xfixed_container<ET, S, L, SH, Tag>::storage_impl() const noexcept -> const storage_type&
- {
- return m_storage;
- }
- template <class ET, class S, layout_type L, bool SH, class Tag>
- XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, SH, Tag>::shape_impl() const noexcept
- -> const inner_shape_type&
- {
- return m_shape;
- }
- template <class ET, class S, layout_type L, bool SH, class Tag>
- XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, SH, Tag>::strides_impl() const noexcept
- -> const inner_strides_type&
- {
- return m_strides;
- }
- template <class ET, class S, layout_type L, bool SH, class Tag>
- XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, SH, Tag>::backstrides_impl() const noexcept
- -> const inner_backstrides_type&
- {
- return m_backstrides;
- }
- /*******************
- * xfixed_adaptor *
- *******************/
- /**
- * @name Constructors
- */
- //@{
- /**
- * Constructs an xfixed_adaptor of the given stl-like container.
- * @param data the container to adapt
- */
- template <class EC, class S, layout_type L, bool SH, class Tag>
- inline xfixed_adaptor<EC, S, L, SH, Tag>::xfixed_adaptor(storage_type&& data)
- : base_type()
- , m_storage(std::move(data))
- {
- }
- /**
- * Constructs an xfixed_adaptor of the given stl-like container.
- * @param data the container to adapt
- */
- template <class EC, class S, layout_type L, bool SH, class Tag>
- inline xfixed_adaptor<EC, S, L, SH, Tag>::xfixed_adaptor(const storage_type& data)
- : base_type()
- , m_storage(data)
- {
- }
- /**
- * Constructs an xfixed_adaptor of the given stl-like container,
- * with the specified shape and layout_type.
- * @param data the container to adapt
- */
- template <class EC, class S, layout_type L, bool SH, class Tag>
- template <class D>
- inline xfixed_adaptor<EC, S, L, SH, Tag>::xfixed_adaptor(D&& data)
- : base_type()
- , m_storage(std::forward<D>(data))
- {
- }
- //@}
- template <class EC, class S, layout_type L, bool SH, class Tag>
- inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(const xfixed_adaptor& rhs) -> self_type&
- {
- base_type::operator=(rhs);
- m_storage = rhs.m_storage;
- return *this;
- }
- template <class EC, class S, layout_type L, bool SH, class Tag>
- inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(xfixed_adaptor&& rhs) -> self_type&
- {
- base_type::operator=(std::move(rhs));
- m_storage = rhs.m_storage;
- return *this;
- }
- template <class EC, class S, layout_type L, bool SH, class Tag>
- inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(temporary_type&& rhs) -> self_type&
- {
- m_storage.resize(rhs.storage().size());
- std::copy(rhs.storage().cbegin(), rhs.storage().cend(), m_storage.begin());
- return *this;
- }
- /**
- * @name Extended copy semantic
- */
- //@{
- /**
- * The extended assignment operator.
- */
- template <class EC, class S, layout_type L, bool SH, class Tag>
- template <class E>
- inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(const xexpression<E>& e) -> self_type&
- {
- return semantic_base::operator=(e);
- }
- //@}
- /**
- * Note that the xfixed_adaptor **cannot** be resized. Attempting to resize with a different
- * size throws an assert in debug mode.
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class ST>
- inline void xfixed_adaptor<ET, S, L, SH, Tag>::resize(ST&& shape, bool) const
- {
- (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
- XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
- }
- /**
- * Note that the xfixed_adaptor **cannot** be resized. Attempting to resize with a different
- * size throws an assert in debug mode.
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class ST>
- inline void xfixed_adaptor<ET, S, L, SH, Tag>::resize(ST&& shape, layout_type l) const
- {
- (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
- (void) (l);
- XTENSOR_ASSERT(
- std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size() && L == l
- );
- }
- /**
- * Note that the xfixed_adaptor **cannot** be resized. Attempting to resize with a different
- * size throws an assert in debug mode.
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class ST>
- inline void xfixed_adaptor<ET, S, L, SH, Tag>::resize(ST&& shape, const strides_type& strides) const
- {
- (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
- (void) (strides);
- XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
- XTENSOR_ASSERT(
- std::equal(strides.begin(), strides.end(), m_strides.begin()) && strides.size() == m_strides.size()
- );
- }
- /**
- * Note that the xfixed_container **cannot** be reshaped to a shape different from ``S``.
- */
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class ST>
- inline const auto& xfixed_adaptor<ET, S, L, SH, Tag>::reshape(ST&& shape, layout_type layout) const
- {
- if (!(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size()
- && layout == L))
- {
- XTENSOR_THROW(std::runtime_error, "Trying to reshape xtensor_fixed with different shape or layout.");
- }
- return *this;
- }
- template <class ET, class S, layout_type L, bool SH, class Tag>
- template <class ST>
- inline bool xfixed_adaptor<ET, S, L, SH, Tag>::broadcast_shape(ST& shape, bool) const
- {
- return xt::broadcast_shape(m_shape, shape);
- }
- template <class EC, class S, layout_type L, bool SH, class Tag>
- inline auto xfixed_adaptor<EC, S, L, SH, Tag>::storage_impl() noexcept -> storage_type&
- {
- return m_storage;
- }
- template <class EC, class S, layout_type L, bool SH, class Tag>
- inline auto xfixed_adaptor<EC, S, L, SH, Tag>::storage_impl() const noexcept -> const storage_type&
- {
- return m_storage;
- }
- template <class EC, class S, layout_type L, bool SH, class Tag>
- constexpr layout_type xfixed_adaptor<EC, S, L, SH, Tag>::layout() const noexcept
- {
- return base_type::static_layout;
- }
- template <class EC, class S, layout_type L, bool SH, class Tag>
- inline bool xfixed_adaptor<EC, S, L, SH, Tag>::is_contiguous() const noexcept
- {
- using str_type = typename inner_strides_type::value_type;
- return m_strides.empty() || (layout() == layout_type::row_major && m_strides.back() == str_type(1))
- || (layout() == layout_type::column_major && m_strides.front() == str_type(1));
- }
- template <class EC, class S, layout_type L, bool SH, class Tag>
- XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, SH, Tag>::shape_impl() const noexcept
- -> const inner_shape_type&
- {
- return m_shape;
- }
- template <class EC, class S, layout_type L, bool SH, class Tag>
- XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, SH, Tag>::strides_impl() const noexcept
- -> const inner_strides_type&
- {
- return m_strides;
- }
- template <class EC, class S, layout_type L, bool SH, class Tag>
- XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, SH, Tag>::backstrides_impl() const noexcept
- -> const inner_backstrides_type&
- {
- return m_backstrides;
- }
- }
- #endif
|