| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671 |
- /***************************************************************************
- * 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_SLICE_HPP
- #define XTENSOR_SLICE_HPP
- #include <cstddef>
- #include <map>
- #include <type_traits>
- #include <utility>
- #include <xtl/xtype_traits.hpp>
- #include "xstorage.hpp"
- #include "xtensor_config.hpp"
- #include "xutils.hpp"
- #ifndef XTENSOR_CONSTEXPR
- #if (defined(_MSC_VER) || __GNUC__ < 8)
- #define XTENSOR_CONSTEXPR inline
- #define XTENSOR_GLOBAL_CONSTEXPR static const
- #else
- #define XTENSOR_CONSTEXPR constexpr
- #define XTENSOR_GLOBAL_CONSTEXPR constexpr
- #endif
- #endif
- namespace xt
- {
- /**********************
- * xslice declaration *
- **********************/
- template <class D>
- class xslice
- {
- public:
- using derived_type = D;
- derived_type& derived_cast() noexcept;
- const derived_type& derived_cast() const noexcept;
- protected:
- xslice() = default;
- ~xslice() = default;
- xslice(const xslice&) = default;
- xslice& operator=(const xslice&) = default;
- xslice(xslice&&) = default;
- xslice& operator=(xslice&&) = default;
- };
- template <class S>
- using is_xslice = std::is_base_of<xslice<S>, S>;
- template <class E, class R = void>
- using disable_xslice = typename std::enable_if<!is_xslice<E>::value, R>::type;
- template <class... E>
- using has_xslice = xtl::disjunction<is_xslice<E>...>;
- /**************
- * slice tags *
- **************/
- #define DEFINE_TAG_CONVERSION(NAME) \
- template <class T> \
- XTENSOR_CONSTEXPR NAME convert() const noexcept \
- { \
- return NAME(); \
- }
- struct xall_tag
- {
- DEFINE_TAG_CONVERSION(xall_tag)
- };
- struct xnewaxis_tag
- {
- DEFINE_TAG_CONVERSION(xnewaxis_tag)
- };
- struct xellipsis_tag
- {
- DEFINE_TAG_CONVERSION(xellipsis_tag)
- };
- #undef DEFINE_TAG_CONVERSION
- /**********************
- * xrange declaration *
- **********************/
- template <class T>
- class xrange : public xslice<xrange<T>>
- {
- public:
- using size_type = T;
- using self_type = xrange<T>;
- xrange() = default;
- xrange(size_type start_val, size_type stop_val) noexcept;
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- operator xrange<S>() const noexcept;
- // Same as implicit conversion operator but more convenient to call
- // from a variant visitor
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- xrange<S> convert() const noexcept;
- size_type operator()(size_type i) const noexcept;
- size_type size() const noexcept;
- size_type step_size() const noexcept;
- size_type step_size(std::size_t i, std::size_t n = 1) const noexcept;
- size_type revert_index(std::size_t i) const noexcept;
- bool contains(size_type i) const noexcept;
- bool operator==(const self_type& rhs) const noexcept;
- bool operator!=(const self_type& rhs) const noexcept;
- private:
- size_type m_start;
- size_type m_size;
- template <class S>
- friend class xrange;
- };
- /******************************
- * xstepped_range declaration *
- ******************************/
- template <class T>
- class xstepped_range : public xslice<xstepped_range<T>>
- {
- public:
- using size_type = T;
- using self_type = xstepped_range<T>;
- xstepped_range() = default;
- xstepped_range(size_type start_val, size_type stop_val, size_type step) noexcept;
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- operator xstepped_range<S>() const noexcept;
- // Same as implicit conversion operator but more convenient to call
- // from a variant visitor
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- xstepped_range<S> convert() const noexcept;
- size_type operator()(size_type i) const noexcept;
- size_type size() const noexcept;
- size_type step_size() const noexcept;
- size_type step_size(std::size_t i, std::size_t n = 1) const noexcept;
- size_type revert_index(std::size_t i) const noexcept;
- bool contains(size_type i) const noexcept;
- bool operator==(const self_type& rhs) const noexcept;
- bool operator!=(const self_type& rhs) const noexcept;
- private:
- size_type m_start;
- size_type m_size;
- size_type m_step;
- template <class S>
- friend class xstepped_range;
- };
- /********************
- * xall declaration *
- ********************/
- template <class T>
- class xall : public xslice<xall<T>>
- {
- public:
- using size_type = T;
- using self_type = xall<T>;
- xall() = default;
- explicit xall(size_type size) noexcept;
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- operator xall<S>() const noexcept;
- // Same as implicit conversion operator but more convenient to call
- // from a variant visitor
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- xall<S> convert() const noexcept;
- size_type operator()(size_type i) const noexcept;
- size_type size() const noexcept;
- size_type step_size() const noexcept;
- size_type step_size(std::size_t i, std::size_t n = 1) const noexcept;
- size_type revert_index(std::size_t i) const noexcept;
- bool contains(size_type i) const noexcept;
- bool operator==(const self_type& rhs) const noexcept;
- bool operator!=(const self_type& rhs) const noexcept;
- private:
- size_type m_size;
- };
- /**
- * Returns a slice representing a full dimension,
- * to be used as an argument of view function.
- * @sa view, strided_view
- */
- inline auto all() noexcept
- {
- return xall_tag();
- }
- /**
- * Returns a slice representing all remaining dimensions,
- * and selecting all in these dimensions. Ellipsis will expand
- * to a series of `all()` slices, until the number of slices is
- * equal to the number of dimensions of the source array.
- *
- * Note: ellipsis can only be used in strided_view!
- *
- * @code{.cpp}
- * xarray<double> a = xarray<double>::from_shape({5, 5, 1, 1, 5});
- * auto v = xt::strided_view(a, {2, xt::ellipsis(), 2});
- * // equivalent to using {2, xt::all(), xt::all(), xt::all(), 2};
- * @endcode
- *
- * @sa strided_view
- */
- inline auto ellipsis() noexcept
- {
- return xellipsis_tag();
- }
- /************************
- * xnewaxis declaration *
- ************************/
- template <class T>
- class xnewaxis : public xslice<xnewaxis<T>>
- {
- public:
- using size_type = T;
- using self_type = xnewaxis<T>;
- xnewaxis() = default;
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- operator xnewaxis<S>() const noexcept;
- // Same as implicit conversion operator but more convenient to call
- // from a variant visitor
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- xnewaxis<S> convert() const noexcept;
- size_type operator()(size_type i) const noexcept;
- size_type size() const noexcept;
- size_type step_size() const noexcept;
- size_type step_size(std::size_t i, std::size_t n = 1) const noexcept;
- size_type revert_index(std::size_t i) const noexcept;
- bool contains(size_type i) const noexcept;
- bool operator==(const self_type& rhs) const noexcept;
- bool operator!=(const self_type& rhs) const noexcept;
- };
- /**
- * Returns a slice representing a new axis of length one,
- * to be used as an argument of view function.
- * @sa view, strided_view
- */
- inline auto newaxis() noexcept
- {
- return xnewaxis_tag();
- }
- /***************************
- * xkeep_slice declaration *
- ***************************/
- template <class T>
- class xkeep_slice;
- namespace detail
- {
- template <class T>
- struct is_xkeep_slice : std::false_type
- {
- };
- template <class T>
- struct is_xkeep_slice<xkeep_slice<T>> : std::true_type
- {
- };
- template <class T>
- using disable_xkeep_slice_t = std::enable_if_t<!is_xkeep_slice<std::decay_t<T>>::value, void>;
- template <class T>
- using enable_xkeep_slice_t = std::enable_if_t<is_xkeep_slice<std::decay_t<T>>::value, void>;
- }
- template <class T>
- class xkeep_slice : public xslice<xkeep_slice<T>>
- {
- public:
- using container_type = svector<T>;
- using size_type = typename container_type::value_type;
- using self_type = xkeep_slice<T>;
- template <class C, typename = detail::disable_xkeep_slice_t<C>>
- explicit xkeep_slice(C& cont);
- explicit xkeep_slice(container_type&& cont);
- template <class S>
- xkeep_slice(std::initializer_list<S> t);
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- operator xkeep_slice<S>() const noexcept;
- // Same as implicit conversion operator but more convenient to call
- // from a variant visitor
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- xkeep_slice<S> convert() const noexcept;
- size_type operator()(size_type i) const noexcept;
- size_type size() const noexcept;
- void normalize(std::size_t s);
- size_type step_size(std::size_t i, std::size_t n = 1) const noexcept;
- size_type revert_index(std::size_t i) const;
- bool contains(size_type i) const noexcept;
- bool operator==(const self_type& rhs) const noexcept;
- bool operator!=(const self_type& rhs) const noexcept;
- private:
- xkeep_slice() = default;
- container_type m_indices;
- container_type m_raw_indices;
- template <class S>
- friend class xkeep_slice;
- };
- namespace detail
- {
- template <class T>
- using disable_integral_keep = std::enable_if_t<
- !xtl::is_integral<std::decay_t<T>>::value,
- xkeep_slice<typename std::decay_t<T>::value_type>>;
- template <class T, class R>
- using enable_integral_keep = std::enable_if_t<xtl::is_integral<T>::value, xkeep_slice<R>>;
- }
- /**
- * Create a non-contigous slice from a container of indices to keep.
- * Note: this slice cannot be used in the xstrided_view!
- *
- * @code{.cpp}
- * xt::xarray<double> a = xt::arange(9);
- * a.reshape({3, 3});
- * xt::view(a, xt::keep(0, 2); // => {{0, 1, 2}, {6, 7, 8}}
- * xt::view(a, xt::keep(1, 1, 1); // => {{3, 4, 5}, {3, 4, 5}, {3, 4, 5}}
- * @endcode
- *
- * @param indices The indices container
- * @return instance of xkeep_slice
- */
- template <class T>
- inline detail::disable_integral_keep<T> keep(T&& indices)
- {
- return xkeep_slice<typename std::decay_t<T>::value_type>(std::forward<T>(indices));
- }
- template <class R = std::ptrdiff_t, class T>
- inline detail::enable_integral_keep<T, R> keep(T i)
- {
- using slice_type = xkeep_slice<R>;
- using container_type = typename slice_type::container_type;
- container_type tmp = {static_cast<R>(i)};
- return slice_type(std::move(tmp));
- }
- template <class R = std::ptrdiff_t, class Arg0, class Arg1, class... Args>
- inline xkeep_slice<R> keep(Arg0 i0, Arg1 i1, Args... args)
- {
- using slice_type = xkeep_slice<R>;
- using container_type = typename slice_type::container_type;
- container_type tmp = {static_cast<R>(i0), static_cast<R>(i1), static_cast<R>(args)...};
- return slice_type(std::move(tmp));
- }
- /***************************
- * xdrop_slice declaration *
- ***************************/
- template <class T>
- class xdrop_slice;
- namespace detail
- {
- template <class T>
- struct is_xdrop_slice : std::false_type
- {
- };
- template <class T>
- struct is_xdrop_slice<xdrop_slice<T>> : std::true_type
- {
- };
- template <class T>
- using disable_xdrop_slice_t = std::enable_if_t<!is_xdrop_slice<std::decay_t<T>>::value, void>;
- template <class T>
- using enable_xdrop_slice_t = std::enable_if_t<is_xdrop_slice<std::decay_t<T>>::value, void>;
- }
- template <class T>
- class xdrop_slice : public xslice<xdrop_slice<T>>
- {
- public:
- using container_type = svector<T>;
- using size_type = typename container_type::value_type;
- using self_type = xdrop_slice<T>;
- template <class C, typename = detail::disable_xdrop_slice_t<C>>
- explicit xdrop_slice(C& cont);
- explicit xdrop_slice(container_type&& cont);
- template <class S>
- xdrop_slice(std::initializer_list<S> t);
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- operator xdrop_slice<S>() const noexcept;
- // Same as implicit conversion operator but more convenient to call
- // from a variant visitor
- template <class S, typename = std::enable_if_t<std::is_convertible<S, T>::value, void>>
- xdrop_slice<S> convert() const noexcept;
- size_type operator()(size_type i) const noexcept;
- size_type size() const noexcept;
- void normalize(std::size_t s);
- size_type step_size(std::size_t i, std::size_t n = 1) const noexcept;
- size_type revert_index(std::size_t i) const;
- bool contains(size_type i) const noexcept;
- bool operator==(const self_type& rhs) const noexcept;
- bool operator!=(const self_type& rhs) const noexcept;
- private:
- xdrop_slice() = default;
- container_type m_indices;
- container_type m_raw_indices;
- std::map<size_type, size_type> m_inc;
- size_type m_size;
- template <class S>
- friend class xdrop_slice;
- };
- namespace detail
- {
- template <class T>
- using disable_integral_drop = std::enable_if_t<
- !xtl::is_integral<std::decay_t<T>>::value,
- xdrop_slice<typename std::decay_t<T>::value_type>>;
- template <class T, class R>
- using enable_integral_drop = std::enable_if_t<xtl::is_integral<T>::value, xdrop_slice<R>>;
- }
- /**
- * Create a non-contigous slice from a container of indices to drop.
- * Note: this slice cannot be used in the xstrided_view!
- *
- * @code{.cpp}
- * xt::xarray<double> a = xt::arange(9);
- * a.reshape({3, 3});
- * xt::view(a, xt::drop(0, 2); // => {{3, 4, 5}}
- * @endcode
- *
- * @param indices The container of indices to drop
- * @return instance of xdrop_slice
- */
- template <class T>
- inline detail::disable_integral_drop<T> drop(T&& indices)
- {
- return xdrop_slice<typename std::decay_t<T>::value_type>(std::forward<T>(indices));
- }
- template <class R = std::ptrdiff_t, class T>
- inline detail::enable_integral_drop<T, R> drop(T i)
- {
- using slice_type = xdrop_slice<R>;
- using container_type = typename slice_type::container_type;
- container_type tmp = {static_cast<R>(i)};
- return slice_type(std::move(tmp));
- }
- template <class R = std::ptrdiff_t, class Arg0, class Arg1, class... Args>
- inline xdrop_slice<R> drop(Arg0 i0, Arg1 i1, Args... args)
- {
- using slice_type = xdrop_slice<R>;
- using container_type = typename slice_type::container_type;
- container_type tmp = {static_cast<R>(i0), static_cast<R>(i1), static_cast<R>(args)...};
- return slice_type(std::move(tmp));
- }
- /******************************
- * xrange_adaptor declaration *
- ******************************/
- template <class A, class B = A, class C = A>
- struct xrange_adaptor
- {
- xrange_adaptor(A start_val, B stop_val, C step)
- : m_start(start_val)
- , m_stop(stop_val)
- , m_step(step)
- {
- }
- template <class MI = A, class MA = B, class STEP = C>
- inline std::enable_if_t<
- xtl::is_integral<MI>::value && xtl::is_integral<MA>::value && xtl::is_integral<STEP>::value,
- xstepped_range<std::ptrdiff_t>>
- get(std::size_t size) const
- {
- return get_stepped_range(m_start, m_stop, m_step, size);
- }
- template <class MI = A, class MA = B, class STEP = C>
- inline std::enable_if_t<
- !xtl::is_integral<MI>::value && xtl::is_integral<MA>::value && xtl::is_integral<STEP>::value,
- xstepped_range<std::ptrdiff_t>>
- get(std::size_t size) const
- {
- return get_stepped_range(m_step > 0 ? 0 : static_cast<std::ptrdiff_t>(size) - 1, m_stop, m_step, size);
- }
- template <class MI = A, class MA = B, class STEP = C>
- inline std::enable_if_t<
- xtl::is_integral<MI>::value && !xtl::is_integral<MA>::value && xtl::is_integral<STEP>::value,
- xstepped_range<std::ptrdiff_t>>
- get(std::size_t size) const
- {
- auto sz = static_cast<std::ptrdiff_t>(size);
- return get_stepped_range(m_start, m_step > 0 ? sz : -(sz + 1), m_step, size);
- }
- template <class MI = A, class MA = B, class STEP = C>
- inline std::enable_if_t<
- xtl::is_integral<MI>::value && xtl::is_integral<MA>::value && !xtl::is_integral<STEP>::value,
- xrange<std::ptrdiff_t>>
- get(std::size_t size) const
- {
- return xrange<std::ptrdiff_t>(normalize(m_start, size), normalize(m_stop, size));
- }
- template <class MI = A, class MA = B, class STEP = C>
- inline std::enable_if_t<
- !xtl::is_integral<MI>::value && !xtl::is_integral<MA>::value && xtl::is_integral<STEP>::value,
- xstepped_range<std::ptrdiff_t>>
- get(std::size_t size) const
- {
- std::ptrdiff_t start = m_step >= 0 ? 0 : static_cast<std::ptrdiff_t>(size) - 1;
- std::ptrdiff_t stop = m_step >= 0 ? static_cast<std::ptrdiff_t>(size) : -1;
- return xstepped_range<std::ptrdiff_t>(start, stop, m_step);
- }
- template <class MI = A, class MA = B, class STEP = C>
- inline std::enable_if_t<
- xtl::is_integral<MI>::value && !xtl::is_integral<MA>::value && !xtl::is_integral<STEP>::value,
- xrange<std::ptrdiff_t>>
- get(std::size_t size) const
- {
- return xrange<std::ptrdiff_t>(normalize(m_start, size), static_cast<std::ptrdiff_t>(size));
- }
- template <class MI = A, class MA = B, class STEP = C>
- inline std::enable_if_t<
- !xtl::is_integral<MI>::value && xtl::is_integral<MA>::value && !xtl::is_integral<STEP>::value,
- xrange<std::ptrdiff_t>>
- get(std::size_t size) const
- {
- return xrange<std::ptrdiff_t>(0, normalize(m_stop, size));
- }
- template <class MI = A, class MA = B, class STEP = C>
- inline std::enable_if_t<
- !xtl::is_integral<MI>::value && !xtl::is_integral<MA>::value && !xtl::is_integral<STEP>::value,
- xall<std::ptrdiff_t>>
- get(std::size_t size) const
- {
- return xall<std::ptrdiff_t>(static_cast<std::ptrdiff_t>(size));
- }
- A start() const
- {
- return m_start;
- }
- B stop() const
- {
- return m_stop;
- }
- C step() const
- {
- return m_step;
- }
- private:
- static auto normalize(std::ptrdiff_t val, std::size_t ssize)
- {
- std::ptrdiff_t size = static_cast<std::ptrdiff_t>(ssize);
- val = (val >= 0) ? val : val + size;
- return (std::max)(std::ptrdiff_t(0), (std::min)(size, val));
- }
- static auto
- get_stepped_range(std::ptrdiff_t start, std::ptrdiff_t stop, std::ptrdiff_t step, std::size_t ssize)
- {
- std::ptrdiff_t size = static_cast<std::ptrdiff_t>(ssize);
- start = (start >= 0) ? start : start + size;
- stop = (stop >= 0) ? stop : stop + size;
- if (step > 0)
- {
- start = (std::max)(std::ptrdiff_t(0), (std::min)(size, start));
- stop = (std::max)(std::ptrdiff_t(0), (std::min)(size, stop));
- }
- else
- {
- start = (std::max)(std::ptrdiff_t(-1), (std::min)(size - 1, start));
- stop = (std::max)(std::ptrdiff_t(-1), (std::min)(size - 1, stop));
- }
- return xstepped_range<std::ptrdiff_t>(start, stop, step);
- }
- A m_start;
- B m_stop;
- C m_step;
- };
- /*******************************
- * Placeholders and rangemaker *
- *******************************/
- namespace placeholders
- {
- // xtensor universal placeholder
- struct xtuph
- {
- };
- template <class... Args>
- struct rangemaker
- {
- std::ptrdiff_t rng[3]; // = { 0, 0, 0 };
- };
- XTENSOR_CONSTEXPR xtuph get_tuph_or_val(std::ptrdiff_t /*val*/, std::true_type)
- {
- return xtuph();
- }
- XTENSOR_CONSTEXPR std::ptrdiff_t get_tuph_or_val(std::ptrdiff_t val, std::false_type)
- {
- return val;
- }
- template <class A, class B, class C>
- struct rangemaker<A, B, C>
- {
- XTENSOR_CONSTEXPR operator xrange_adaptor<A, B, C>()
- {
- return xrange_adaptor<A, B, C>(
- {get_tuph_or_val(rng[0], std::is_same<A, xtuph>()),
- get_tuph_or_val(rng[1], std::is_same<B, xtuph>()),
- get_tuph_or_val(rng[2], std::is_same<C, xtuph>())}
- );
- }
- std::ptrdiff_t rng[3]; // = { 0, 0, 0 };
- };
- template <class A, class B>
- struct rangemaker<A, B>
- {
- XTENSOR_CONSTEXPR operator xrange_adaptor<A, B, xt::placeholders::xtuph>()
- {
- return xrange_adaptor<A, B, xt::placeholders::xtuph>(
- {get_tuph_or_val(rng[0], std::is_same<A, xtuph>()),
- get_tuph_or_val(rng[1], std::is_same<B, xtuph>()),
- xtuph()}
- );
- }
- std::ptrdiff_t rng[3]; // = { 0, 0, 0 };
- };
- template <class... OA>
- XTENSOR_CONSTEXPR auto operator|(const rangemaker<OA...>& rng, const std::ptrdiff_t& t)
- {
- auto nrng = rangemaker<OA..., std::ptrdiff_t>({rng.rng[0], rng.rng[1], rng.rng[2]});
- nrng.rng[sizeof...(OA)] = t;
- return nrng;
- }
- template <class... OA>
- XTENSOR_CONSTEXPR auto operator|(const rangemaker<OA...>& rng, const xt::placeholders::xtuph& /*t*/)
- {
- auto nrng = rangemaker<OA..., xt::placeholders::xtuph>({rng.rng[0], rng.rng[1], rng.rng[2]});
- return nrng;
- }
- XTENSOR_GLOBAL_CONSTEXPR xtuph _{};
- XTENSOR_GLOBAL_CONSTEXPR rangemaker<> _r = rangemaker<>({0, 0, 0});
- XTENSOR_GLOBAL_CONSTEXPR xall_tag _a{};
- XTENSOR_GLOBAL_CONSTEXPR xnewaxis_tag _n{};
- XTENSOR_GLOBAL_CONSTEXPR xellipsis_tag _e{};
- }
- inline auto xnone()
- {
- return placeholders::xtuph();
- }
- namespace detail
- {
- template <class T, class E = void>
- struct cast_if_integer
- {
- using type = T;
- type operator()(T t)
- {
- return t;
- }
- };
- template <class T>
- struct cast_if_integer<T, std::enable_if_t<xtl::is_integral<T>::value>>
- {
- using type = std::ptrdiff_t;
- type operator()(T t)
- {
- return static_cast<type>(t);
- }
- };
- template <class T>
- using cast_if_integer_t = typename cast_if_integer<T>::type;
- }
- /**
- * Select a range from start_val to stop_val (excluded).
- * You can use the shorthand `_` syntax to select from the start or until the end.
- *
- * @code{.cpp}
- * using namespace xt::placeholders; // to enable _ syntax
- *
- * range(3, _) // select from index 3 to the end
- * range(_, 5) // select from index 0 to 5 (excluded)
- * range(_, _) // equivalent to `all()`
- * @endcode
- *
- * @sa view, strided_view
- */
- template <class A, class B>
- inline auto range(A start_val, B stop_val)
- {
- return xrange_adaptor<detail::cast_if_integer_t<A>, detail::cast_if_integer_t<B>, placeholders::xtuph>(
- detail::cast_if_integer<A>{}(start_val),
- detail::cast_if_integer<B>{}(stop_val),
- placeholders::xtuph()
- );
- }
- /**
- * Select a range from start_val to stop_val (excluded) with step
- * You can use the shorthand `_` syntax to select from the start or until the end.
- *
- * @code{.cpp}
- * using namespace xt::placeholders; // to enable _ syntax
- * range(3, _, 5) // select from index 3 to the end with stepsize 5
- * @endcode
- *
- * @sa view, strided_view
- */
- template <class A, class B, class C>
- inline auto range(A start_val, B stop_val, C step)
- {
- return xrange_adaptor<detail::cast_if_integer_t<A>, detail::cast_if_integer_t<B>, detail::cast_if_integer_t<C>>(
- detail::cast_if_integer<A>{}(start_val),
- detail::cast_if_integer<B>{}(stop_val),
- detail::cast_if_integer<C>{}(step)
- );
- }
- /******************************************************
- * homogeneous get_size for integral types and slices *
- ******************************************************/
- template <class S>
- inline disable_xslice<S, std::size_t> get_size(const S&) noexcept
- {
- return 1;
- }
- template <class S>
- inline auto get_size(const xslice<S>& slice) noexcept
- {
- return slice.derived_cast().size();
- }
- /*******************************************************
- * homogeneous step_size for integral types and slices *
- *******************************************************/
- template <class S>
- inline disable_xslice<S, std::size_t> step_size(const S&, std::size_t) noexcept
- {
- return 0;
- }
- template <class S>
- inline disable_xslice<S, std::size_t> step_size(const S&, std::size_t, std::size_t) noexcept
- {
- return 0;
- }
- template <class S>
- inline auto step_size(const xslice<S>& slice, std::size_t idx) noexcept
- {
- return slice.derived_cast().step_size(idx);
- }
- template <class S>
- inline auto step_size(const xslice<S>& slice, std::size_t idx, std::size_t n) noexcept
- {
- return slice.derived_cast().step_size(idx, n);
- }
- /*********************************************
- * homogeneous value for integral and slices *
- *********************************************/
- template <class S, class I>
- inline disable_xslice<S, std::size_t> value(const S& s, I) noexcept
- {
- return static_cast<std::size_t>(s);
- }
- template <class S, class I>
- inline auto value(const xslice<S>& slice, I i) noexcept
- {
- using ST = typename S::size_type;
- return slice.derived_cast()(static_cast<ST>(i));
- }
- /****************************************
- * homogeneous get_slice_implementation *
- ****************************************/
- namespace detail
- {
- template <class T>
- struct slice_implementation_getter
- {
- template <class E, class SL>
- inline decltype(auto) operator()(E& e, SL&& slice, std::size_t index) const
- {
- return get_slice(e, std::forward<SL>(slice), index, xtl::is_signed<std::decay_t<SL>>());
- }
- private:
- template <class E, class SL>
- inline decltype(auto) get_slice(E&, SL&& slice, std::size_t, std::false_type) const
- {
- return std::forward<SL>(slice);
- }
- template <class E, class SL>
- inline decltype(auto) get_slice(E& e, SL&& slice, std::size_t index, std::true_type) const
- {
- using int_type = std::decay_t<SL>;
- return slice < int_type(0) ? slice + static_cast<std::ptrdiff_t>(e.shape(index))
- : std::ptrdiff_t(slice);
- }
- };
- struct keep_drop_getter
- {
- template <class E, class SL>
- inline decltype(auto) operator()(E& e, SL&& slice, std::size_t index) const
- {
- slice.normalize(e.shape()[index]);
- return std::forward<SL>(slice);
- }
- template <class E, class SL>
- inline auto operator()(E& e, const SL& slice, std::size_t index) const
- {
- return this->operator()(e, SL(slice), index);
- }
- };
- template <class T>
- struct slice_implementation_getter<xkeep_slice<T>> : keep_drop_getter
- {
- };
- template <class T>
- struct slice_implementation_getter<xdrop_slice<T>> : keep_drop_getter
- {
- };
- template <>
- struct slice_implementation_getter<xall_tag>
- {
- template <class E, class SL>
- inline auto operator()(E& e, SL&&, std::size_t index) const
- {
- return xall<typename E::size_type>(e.shape()[index]);
- }
- };
- template <>
- struct slice_implementation_getter<xnewaxis_tag>
- {
- template <class E, class SL>
- inline auto operator()(E&, SL&&, std::size_t) const
- {
- return xnewaxis<typename E::size_type>();
- }
- };
- template <class A, class B, class C>
- struct slice_implementation_getter<xrange_adaptor<A, B, C>>
- {
- template <class E, class SL>
- inline auto operator()(E& e, SL&& adaptor, std::size_t index) const
- {
- return adaptor.get(e.shape()[index]);
- }
- };
- }
- template <class E, class SL>
- inline auto get_slice_implementation(E& e, SL&& slice, std::size_t index)
- {
- detail::slice_implementation_getter<std::decay_t<SL>> getter;
- return getter(e, std::forward<SL>(slice), index);
- }
- /******************************
- * homogeneous get_slice_type *
- ******************************/
- namespace detail
- {
- template <class E, class SL>
- struct get_slice_type_impl
- {
- using type = SL;
- };
- template <class E>
- struct get_slice_type_impl<E, xall_tag>
- {
- using type = xall<typename E::size_type>;
- };
- template <class E>
- struct get_slice_type_impl<E, xnewaxis_tag>
- {
- using type = xnewaxis<typename E::size_type>;
- };
- template <class E, class A, class B, class C>
- struct get_slice_type_impl<E, xrange_adaptor<A, B, C>>
- {
- using type = decltype(xrange_adaptor<A, B, C>(A(), B(), C()).get(0));
- };
- }
- template <class E, class SL>
- using get_slice_type = typename detail::get_slice_type_impl<E, std::remove_reference_t<SL>>::type;
- /*************************
- * xslice implementation *
- *************************/
- template <class D>
- inline auto xslice<D>::derived_cast() noexcept -> derived_type&
- {
- return *static_cast<derived_type*>(this);
- }
- template <class D>
- inline auto xslice<D>::derived_cast() const noexcept -> const derived_type&
- {
- return *static_cast<const derived_type*>(this);
- }
- /*************************
- * xrange implementation *
- *************************/
- template <class T>
- inline xrange<T>::xrange(size_type start_val, size_type stop_val) noexcept
- : m_start(start_val)
- , m_size(stop_val > start_val ? stop_val - start_val : 0)
- {
- }
- template <class T>
- template <class S, typename>
- inline xrange<T>::operator xrange<S>() const noexcept
- {
- xrange<S> ret;
- ret.m_start = static_cast<S>(m_start);
- ret.m_size = static_cast<S>(m_size);
- return ret;
- }
- template <class T>
- template <class S, typename>
- inline xrange<S> xrange<T>::convert() const noexcept
- {
- return xrange<S>(*this);
- }
- template <class T>
- inline auto xrange<T>::operator()(size_type i) const noexcept -> size_type
- {
- return m_start + i;
- }
- template <class T>
- inline auto xrange<T>::size() const noexcept -> size_type
- {
- return m_size;
- }
- template <class T>
- inline auto xrange<T>::step_size() const noexcept -> size_type
- {
- return 1;
- }
- template <class T>
- inline auto xrange<T>::step_size(std::size_t /*i*/, std::size_t n) const noexcept -> size_type
- {
- return static_cast<size_type>(n);
- }
- template <class T>
- inline auto xrange<T>::revert_index(std::size_t i) const noexcept -> size_type
- {
- return i - m_start;
- }
- template <class T>
- inline bool xrange<T>::contains(size_type i) const noexcept
- {
- return i >= m_start && i < m_start + m_size;
- }
- template <class T>
- inline bool xrange<T>::operator==(const self_type& rhs) const noexcept
- {
- return (m_start == rhs.m_start) && (m_size == rhs.m_size);
- }
- template <class T>
- inline bool xrange<T>::operator!=(const self_type& rhs) const noexcept
- {
- return !(*this == rhs);
- }
- /********************************
- * xtepped_range implementation *
- ********************************/
- template <class T>
- inline xstepped_range<T>::xstepped_range(size_type start_val, size_type stop_val, size_type step) noexcept
- : m_start(start_val)
- , m_size(size_type(0))
- , m_step(step)
- {
- size_type n = stop_val - start_val;
- m_size = n / step + (((n < 0) ^ (step > 0)) && (n % step));
- }
- template <class T>
- template <class S, typename>
- inline xstepped_range<T>::operator xstepped_range<S>() const noexcept
- {
- xstepped_range<S> ret;
- ret.m_start = static_cast<S>(m_start);
- ret.m_size = static_cast<S>(m_size);
- ret.m_step = static_cast<S>(m_step);
- return ret;
- }
- template <class T>
- template <class S, typename>
- inline xstepped_range<S> xstepped_range<T>::convert() const noexcept
- {
- return xstepped_range<S>(*this);
- }
- template <class T>
- inline auto xstepped_range<T>::operator()(size_type i) const noexcept -> size_type
- {
- return m_start + i * m_step;
- }
- template <class T>
- inline auto xstepped_range<T>::size() const noexcept -> size_type
- {
- return m_size;
- }
- template <class T>
- inline auto xstepped_range<T>::step_size() const noexcept -> size_type
- {
- return m_step;
- }
- template <class T>
- inline auto xstepped_range<T>::step_size(std::size_t /*i*/, std::size_t n) const noexcept -> size_type
- {
- return m_step * static_cast<size_type>(n);
- }
- template <class T>
- inline auto xstepped_range<T>::revert_index(std::size_t i) const noexcept -> size_type
- {
- return (i - m_start) / m_step;
- }
- template <class T>
- inline bool xstepped_range<T>::contains(size_type i) const noexcept
- {
- return i >= m_start && i < m_start + m_size * m_step && ((i - m_start) % m_step == 0);
- }
- template <class T>
- inline bool xstepped_range<T>::operator==(const self_type& rhs) const noexcept
- {
- return (m_start == rhs.m_start) && (m_size == rhs.m_size) && (m_step == rhs.m_step);
- }
- template <class T>
- inline bool xstepped_range<T>::operator!=(const self_type& rhs) const noexcept
- {
- return !(*this == rhs);
- }
- /***********************
- * xall implementation *
- ***********************/
- template <class T>
- inline xall<T>::xall(size_type size) noexcept
- : m_size(size)
- {
- }
- template <class T>
- template <class S, typename>
- inline xall<T>::operator xall<S>() const noexcept
- {
- return xall<S>(static_cast<S>(m_size));
- }
- template <class T>
- template <class S, typename>
- inline xall<S> xall<T>::convert() const noexcept
- {
- return xall<S>(*this);
- }
- template <class T>
- inline auto xall<T>::operator()(size_type i) const noexcept -> size_type
- {
- return i;
- }
- template <class T>
- inline auto xall<T>::size() const noexcept -> size_type
- {
- return m_size;
- }
- template <class T>
- inline auto xall<T>::step_size() const noexcept -> size_type
- {
- return 1;
- }
- template <class T>
- inline auto xall<T>::step_size(std::size_t /*i*/, std::size_t n) const noexcept -> size_type
- {
- return static_cast<size_type>(n);
- }
- template <class T>
- inline auto xall<T>::revert_index(std::size_t i) const noexcept -> size_type
- {
- return i;
- }
- template <class T>
- inline bool xall<T>::contains(size_type i) const noexcept
- {
- return i < m_size;
- }
- template <class T>
- inline bool xall<T>::operator==(const self_type& rhs) const noexcept
- {
- return m_size == rhs.m_size;
- }
- template <class T>
- inline bool xall<T>::operator!=(const self_type& rhs) const noexcept
- {
- return !(*this == rhs);
- }
- /***************************
- * xnewaxis implementation *
- ***************************/
- template <class T>
- template <class S, typename>
- inline xnewaxis<T>::operator xnewaxis<S>() const noexcept
- {
- return xnewaxis<S>();
- }
- template <class T>
- template <class S, typename>
- inline xnewaxis<S> xnewaxis<T>::convert() const noexcept
- {
- return xnewaxis<S>(*this);
- }
- template <class T>
- inline auto xnewaxis<T>::operator()(size_type) const noexcept -> size_type
- {
- return 0;
- }
- template <class T>
- inline auto xnewaxis<T>::size() const noexcept -> size_type
- {
- return 1;
- }
- template <class T>
- inline auto xnewaxis<T>::step_size() const noexcept -> size_type
- {
- return 0;
- }
- template <class T>
- inline auto xnewaxis<T>::step_size(std::size_t /*i*/, std::size_t /*n*/) const noexcept -> size_type
- {
- return 0;
- }
- template <class T>
- inline auto xnewaxis<T>::revert_index(std::size_t i) const noexcept -> size_type
- {
- return i;
- }
- template <class T>
- inline bool xnewaxis<T>::contains(size_type i) const noexcept
- {
- return i == 0;
- }
- template <class T>
- inline bool xnewaxis<T>::operator==(const self_type& /*rhs*/) const noexcept
- {
- return true;
- }
- template <class T>
- inline bool xnewaxis<T>::operator!=(const self_type& /*rhs*/) const noexcept
- {
- return true;
- }
- /******************************
- * xkeep_slice implementation *
- ******************************/
- template <class T>
- template <class C, typename>
- inline xkeep_slice<T>::xkeep_slice(C& cont)
- : m_raw_indices(cont.begin(), cont.end())
- {
- }
- template <class T>
- inline xkeep_slice<T>::xkeep_slice(container_type&& cont)
- : m_raw_indices(std::move(cont))
- {
- }
- template <class T>
- template <class S>
- inline xkeep_slice<T>::xkeep_slice(std::initializer_list<S> t)
- : m_raw_indices(t.size())
- {
- std::transform(
- t.begin(),
- t.end(),
- m_raw_indices.begin(),
- [](auto t)
- {
- return static_cast<size_type>(t);
- }
- );
- }
- template <class T>
- template <class S, typename>
- inline xkeep_slice<T>::operator xkeep_slice<S>() const noexcept
- {
- xkeep_slice<S> ret;
- using us_type = typename container_type::size_type;
- us_type sz = static_cast<us_type>(size());
- ret.m_raw_indices.resize(sz);
- ret.m_indices.resize(sz);
- std::transform(
- m_raw_indices.cbegin(),
- m_raw_indices.cend(),
- ret.m_raw_indices.begin(),
- [](const T& val)
- {
- return static_cast<S>(val);
- }
- );
- std::transform(
- m_indices.cbegin(),
- m_indices.cend(),
- ret.m_indices.begin(),
- [](const T& val)
- {
- return static_cast<S>(val);
- }
- );
- return ret;
- }
- template <class T>
- template <class S, typename>
- inline xkeep_slice<S> xkeep_slice<T>::convert() const noexcept
- {
- return xkeep_slice<S>(*this);
- }
- template <class T>
- inline void xkeep_slice<T>::normalize(std::size_t shape)
- {
- m_indices.resize(m_raw_indices.size());
- std::size_t sz = m_indices.size();
- for (std::size_t i = 0; i < sz; ++i)
- {
- m_indices[i] = m_raw_indices[i] < 0 ? static_cast<size_type>(shape) + m_raw_indices[i]
- : m_raw_indices[i];
- }
- }
- template <class T>
- inline auto xkeep_slice<T>::operator()(size_type i) const noexcept -> size_type
- {
- return m_indices.size() == size_type(1) ? m_indices.front() : m_indices[static_cast<std::size_t>(i)];
- }
- template <class T>
- inline auto xkeep_slice<T>::size() const noexcept -> size_type
- {
- return static_cast<size_type>(m_raw_indices.size());
- }
- template <class T>
- inline auto xkeep_slice<T>::step_size(std::size_t i, std::size_t n) const noexcept -> size_type
- {
- if (m_indices.size() == 1)
- {
- return 0;
- }
- if (i + n >= m_indices.size())
- {
- return m_indices.back() - m_indices[i] + 1;
- }
- else
- {
- return m_indices[i + n] - m_indices[i];
- }
- }
- template <class T>
- inline auto xkeep_slice<T>::revert_index(std::size_t i) const -> size_type
- {
- auto it = std::find(m_indices.begin(), m_indices.end(), i);
- if (it != m_indices.end())
- {
- return std::distance(m_indices.begin(), it);
- }
- else
- {
- XTENSOR_THROW(std::runtime_error, "Index i (" + std::to_string(i) + ") not in indices of islice.");
- }
- }
- template <class T>
- inline bool xkeep_slice<T>::contains(size_type i) const noexcept
- {
- return (std::find(m_indices.begin(), m_indices.end(), i) == m_indices.end()) ? false : true;
- }
- template <class T>
- inline bool xkeep_slice<T>::operator==(const self_type& rhs) const noexcept
- {
- return m_indices == rhs.m_indices;
- }
- template <class T>
- inline bool xkeep_slice<T>::operator!=(const self_type& rhs) const noexcept
- {
- return !(*this == rhs);
- }
- /******************************
- * xdrop_slice implementation *
- ******************************/
- template <class T>
- template <class C, typename>
- inline xdrop_slice<T>::xdrop_slice(C& cont)
- : m_raw_indices(cont.begin(), cont.end())
- {
- }
- template <class T>
- inline xdrop_slice<T>::xdrop_slice(container_type&& cont)
- : m_raw_indices(std::move(cont))
- {
- }
- template <class T>
- template <class S>
- inline xdrop_slice<T>::xdrop_slice(std::initializer_list<S> t)
- : m_raw_indices(t.size())
- {
- std::transform(
- t.begin(),
- t.end(),
- m_raw_indices.begin(),
- [](auto t)
- {
- return static_cast<size_type>(t);
- }
- );
- }
- template <class T>
- template <class S, typename>
- inline xdrop_slice<T>::operator xdrop_slice<S>() const noexcept
- {
- xdrop_slice<S> ret;
- ret.m_raw_indices.resize(m_raw_indices.size());
- ret.m_indices.resize(m_indices.size());
- std::transform(
- m_raw_indices.cbegin(),
- m_raw_indices.cend(),
- ret.m_raw_indices.begin(),
- [](const T& val)
- {
- return static_cast<S>(val);
- }
- );
- std::transform(
- m_indices.cbegin(),
- m_indices.cend(),
- ret.m_indices.begin(),
- [](const T& val)
- {
- return static_cast<S>(val);
- }
- );
- std::transform(
- m_inc.cbegin(),
- m_inc.cend(),
- std::inserter(ret.m_inc, ret.m_inc.begin()),
- [](const auto& val)
- {
- return std::make_pair(static_cast<S>(val.first), static_cast<S>(val.second));
- }
- );
- ret.m_size = static_cast<S>(m_size);
- return ret;
- }
- template <class T>
- template <class S, typename>
- inline xdrop_slice<S> xdrop_slice<T>::convert() const noexcept
- {
- return xdrop_slice<S>(*this);
- }
- template <class T>
- inline void xdrop_slice<T>::normalize(std::size_t shape)
- {
- m_size = static_cast<size_type>(shape - m_raw_indices.size());
- m_indices.resize(m_raw_indices.size());
- std::size_t sz = m_indices.size();
- for (std::size_t i = 0; i < sz; ++i)
- {
- m_indices[i] = m_raw_indices[i] < 0 ? static_cast<size_type>(shape) + m_raw_indices[i]
- : m_raw_indices[i];
- }
- size_type cum = size_type(0);
- size_type prev_cum = cum;
- for (std::size_t i = 0; i < sz; ++i)
- {
- std::size_t ind = i;
- size_type d = m_indices[i];
- while (i + 1 < sz && m_indices[i + 1] == m_indices[i] + 1)
- {
- ++i;
- }
- cum += (static_cast<size_type>(i) - static_cast<size_type>(ind)) + 1;
- m_inc[d - prev_cum] = cum;
- prev_cum = cum;
- }
- }
- template <class T>
- inline auto xdrop_slice<T>::operator()(size_type i) const noexcept -> size_type
- {
- if (m_inc.empty() || i < m_inc.begin()->first)
- {
- return i;
- }
- else
- {
- auto iter = --m_inc.upper_bound(i);
- return i + iter->second;
- }
- }
- template <class T>
- inline auto xdrop_slice<T>::size() const noexcept -> size_type
- {
- return m_size;
- }
- template <class T>
- inline auto xdrop_slice<T>::step_size(std::size_t i, std::size_t n) const noexcept -> size_type
- {
- if (i + n >= static_cast<std::size_t>(m_size))
- {
- return (*this)(static_cast<size_type>(m_size - 1)) - (*this)(static_cast<size_type>(i)) + 1;
- }
- else
- {
- return (*this)(static_cast<size_type>(i + n)) - (*this)(static_cast<size_type>(i));
- }
- }
- template <class T>
- inline auto xdrop_slice<T>::revert_index(std::size_t i) const -> size_type
- {
- if (i < m_inc.begin()->first)
- {
- return i;
- }
- else
- {
- auto iter = --m_inc.lower_bound(i);
- auto check = iter->first + iter->second;
- if (check > i)
- {
- --iter;
- }
- return i - iter->second;
- }
- }
- template <class T>
- inline bool xdrop_slice<T>::contains(size_type i) const noexcept
- {
- return (std::find(m_indices.begin(), m_indices.end(), i) == m_indices.end()) ? true : false;
- }
- template <class T>
- inline bool xdrop_slice<T>::operator==(const self_type& rhs) const noexcept
- {
- return m_indices == rhs.m_indices;
- }
- template <class T>
- inline bool xdrop_slice<T>::operator!=(const self_type& rhs) const noexcept
- {
- return !(*this == rhs);
- }
- }
- #undef XTENSOR_CONSTEXPR
- #endif
|