10#ifndef XTENSOR_XSHAPE_HPP 
   11#define XTENSOR_XSHAPE_HPP 
   18#include <initializer_list> 
   22#include "../containers/xstorage.hpp" 
   23#include "../core/xlayout.hpp" 
   24#include "../core/xtensor_forward.hpp" 
   31    template <
class T, std::
size_t N>
 
   32    using static_shape = std::array<T, N>;
 
   34    template <std::size_t... X>
 
   37    using xindex = dynamic_shape<std::size_t>;
 
   39    template <
class S1, 
class S2>
 
   40    bool same_shape(
const S1& s1, 
const S2& s2) 
noexcept;
 
   45    template <
class R, 
class T>
 
   46    constexpr R shape(T t);
 
   48    template <
class R = std::
size_t, 
class T, std::
size_t N>
 
   49    xt::static_shape<R, N> shape(
const T (&aList)[N]);
 
   54    template <layout_type L, 
class S>
 
   72        struct sequence_builder;
 
   74        template <std::size_t... I>
 
   75        struct sequence_builder<xt::fixed_shape<I...>>
 
   77            using sequence_type = xt::fixed_shape<I...>;
 
   78            using value_type = 
typename sequence_type::value_type;
 
   80            inline static sequence_type make(std::size_t )
 
   82                return sequence_type{};
 
   85            inline static sequence_type make(std::size_t , value_type )
 
   87                return sequence_type{};
 
  111    template <
class S1, 
class S2>
 
  114        return s1.size() == s2.size() && std::equal(s1.begin(), s1.end(), s2.begin());
 
 
  129    template <
class E, 
class S>
 
  130    inline bool has_shape(
const E& e, std::initializer_list<S> shape) 
noexcept 
  132        return e.shape().size() == shape.size()
 
  133               && std::equal(e.shape().cbegin(), e.shape().cend(), shape.begin());
 
 
  144    template <class E, class S, class = typename std::enable_if_t<has_iterator_interface<S>::value>>
 
  147        return e.shape().size() == shape.size()
 
  148               && std::equal(e.shape().cbegin(), e.shape().cend(), shape.begin());
 
 
  158        struct initializer_depth_impl
 
  160            static constexpr std::size_t value = 0;
 
  164        struct initializer_depth_impl<std::initializer_list<T>>
 
  166            static constexpr std::size_t value = 1 + initializer_depth_impl<T>::value;
 
  173        static constexpr std::size_t value = detail::initializer_depth_impl<U>::value;
 
 
  182        template <std::
size_t I>
 
  183        struct initializer_shape_impl
 
  186            static constexpr std::size_t value(T t)
 
  188                return t.size() == 0 ? 0 : initializer_shape_impl<I - 1>::value(*t.begin());
 
  193        struct initializer_shape_impl<0>
 
  196            static constexpr std::size_t value(T t)
 
  202        template <
class R, 
class U, std::size_t... I>
 
  203        constexpr R initializer_shape(U t, std::index_sequence<I...>)
 
  205            using size_type = 
typename R::value_type;
 
  206            return {size_type(initializer_shape_impl<I>::value(t))...};
 
  210    template <
class R, 
class T>
 
  211    constexpr R shape(T t)
 
  213        return detail::initializer_shape<R, decltype(t)>(
 
  220    template <
class R, 
class T, std::
size_t N>
 
  221    xt::static_shape<R, N> shape(
const T (&list)[N])
 
  223        xt::static_shape<R, N> shape;
 
  224        std::copy(std::begin(list), std::end(list), std::begin(shape));
 
 
  234        template <
class T, 
class E = 
void>
 
  235        struct static_dimension_impl
 
  237            static constexpr std::ptrdiff_t value = -1;
 
  241        struct static_dimension_impl<T, void_t<decltype(std::tuple_size<T>::value)>>
 
  243            static constexpr std::ptrdiff_t value = 
static_cast<std::ptrdiff_t
>(std::tuple_size<T>::value);
 
  250        static constexpr std::ptrdiff_t value = detail::static_dimension_impl<S>::value;
 
 
  262    template <layout_type L, 
class S>
 
  265        static constexpr std::ptrdiff_t static_dimension = xt::static_dimension<S>::value;
 
  266        static constexpr bool is_any = static_dimension != -1 && static_dimension <= 1
 
 
  277        template <
class T1, 
class T2>
 
  278        constexpr std::common_type_t<T1, T2> imax(
const T1& a, 
const T2& b)
 
  280            return a > b ? a : b;
 
  284        template <
class... T>
 
  285        struct max_array_size;
 
  288        struct max_array_size<>
 
  290            static constexpr std::size_t value = 0;
 
  293        template <
class T, 
class... Ts>
 
  294        struct max_array_size<T, Ts...>
 
  295            : std::integral_constant<std::size_t, imax(std::tuple_size<T>::value, max_array_size<Ts...>::value)>
 
  300        template <std::size_t IDX, std::size_t... X>
 
  303            static constexpr std::size_t arr[
sizeof...(X)] = {X...};
 
  304            static constexpr std::size_t value = (IDX < 
sizeof...(X)) ? arr[IDX] : 0;
 
  307        template <
class S1, 
class S2>
 
  308        struct broadcast_fixed_shape;
 
  310        template <
class IX, 
class A, 
class B>
 
  311        struct broadcast_fixed_shape_impl;
 
  313        template <std::
size_t IX, 
class A, 
class B>
 
  314        struct broadcast_fixed_shape_cmp_impl;
 
  316        template <std::size_t JX, std::size_t... I, std::size_t... J>
 
  317        struct broadcast_fixed_shape_cmp_impl<JX, fixed_shape<I...>, fixed_shape<J...>>
 
  321            static constexpr std::size_t IX = JX - (
sizeof...(J) - 
sizeof...(I));
 
  324            static constexpr std::size_t I_v = at<IX, I...>::value;
 
  325            static constexpr std::size_t J_v = at<JX, J...>::value;
 
  328            static_assert(!I_v || I_v == 1 || J_v == 1 || J_v == I_v, 
"broadcast shapes do not match.");
 
  330            static constexpr std::size_t ordinate = (I_v > J_v) ? I_v : J_v;
 
  331            static constexpr bool value = (I_v == J_v);
 
  334        template <std::size_t... JX, std::size_t... I, std::size_t... J>
 
  335        struct broadcast_fixed_shape_impl<std::index_sequence<JX...>, fixed_shape<I...>, fixed_shape<J...>>
 
  337            static_assert(
sizeof...(J) >= 
sizeof...(I), 
"broadcast shapes do not match.");
 
  339            using type = xt::fixed_shape<
 
  340                broadcast_fixed_shape_cmp_impl<JX, fixed_shape<I...>, fixed_shape<J...>>::ordinate...>;
 
  341            static constexpr bool value = std::conjunction<
 
  342                broadcast_fixed_shape_cmp_impl<JX, fixed_shape<I...>, fixed_shape<J...>>...>::value;
 
  351        template <std::size_t... I, std::size_t... J>
 
  352        struct broadcast_fixed_shape<fixed_shape<I...>, fixed_shape<J...>>
 
  353            : broadcast_fixed_shape_impl<std::make_index_sequence<sizeof...(J)>, fixed_shape<I...>, fixed_shape<J...>>
 
  361            static constexpr bool value = 
false;
 
  364        template <
class T, std::
size_t N>
 
  365        struct is_array<std::array<T, N>>
 
  367            static constexpr bool value = 
true;
 
  371        struct is_fixed : std::false_type
 
  375        template <std::size_t... N>
 
  376        struct is_fixed<fixed_shape<N...>> : std::true_type
 
  381        struct is_scalar_shape
 
  383            static constexpr bool value = 
false;
 
  387        struct is_scalar_shape<std::array<T, 0>>
 
  389            static constexpr bool value = 
true;
 
  392        template <
class... S>
 
  393        using only_array = std::conjunction<std::disjunction<is_array<S>, is_fixed<S>>...>;
 
  397        template <
class... S>
 
  398        using only_fixed = std::integral_constant<
 
  400            std::disjunction<is_fixed<S>...>::value
 
  401                && std::conjunction<std::disjunction<is_fixed<S>, is_scalar_shape<S>>...>::value>;
 
  403        template <
class... S>
 
  404        using all_fixed = std::conjunction<is_fixed<S>...>;
 
  410        template <
class... S>
 
  414                array<
typename std::common_type<
typename S::value_type...>::type, max_array_size<S...>::value>;
 
  418        struct promote_array<>
 
  420            using type = std::array<std::size_t, 0>;
 
  430        struct filter_scalar<std::array<T, 0>>
 
  432            using type = fixed_shape<1>;
 
  436        using filter_scalar_t = 
typename filter_scalar<S>::type;
 
  438        template <
class... S>
 
  439        struct promote_fixed : promote_fixed<filter_scalar_t<S>...>
 
  443        template <std::size_t... I>
 
  444        struct promote_fixed<fixed_shape<I...>>
 
  446            using type = fixed_shape<I...>;
 
  447            static constexpr bool value = 
true;
 
  450        template <std::size_t... I, std::size_t... J, 
class... S>
 
  451        struct promote_fixed<fixed_shape<I...>, fixed_shape<J...>, S...>
 
  455            using intermediate = std::conditional_t<
 
  456                (
sizeof...(I) > 
sizeof...(J)),
 
  457                broadcast_fixed_shape<fixed_shape<J...>, fixed_shape<I...>>,
 
  458                broadcast_fixed_shape<fixed_shape<I...>, fixed_shape<J...>>>;
 
  459            using result = promote_fixed<
typename intermediate::type, S...>;
 
  463            using type = 
typename result::type;
 
  464            static constexpr bool value = std::conjunction<intermediate, result>::value;
 
  467        template <
bool all_index, 
bool all_array, 
class... S>
 
  468        struct select_promote_index;
 
  470        template <
class... S>
 
  471        struct select_promote_index<true, true, S...> : promote_fixed<S...>
 
  476        struct select_promote_index<true, true>
 
  479            using type = dynamic_shape<std::size_t>;
 
  482        template <
class... S>
 
  483        struct select_promote_index<false, true, S...> : promote_array<S...>
 
  487        template <
class... S>
 
  488        struct select_promote_index<false, false, S...>
 
  490            using type = dynamic_shape<
typename std::common_type<
typename S::value_type...>::type>;
 
  493        template <
class... S>
 
  494        struct promote_index : select_promote_index<only_fixed<S...>::value, only_array<S...>::value, S...>
 
  499        struct index_from_shape_impl
 
  504        template <std::size_t... N>
 
  505        struct index_from_shape_impl<fixed_shape<N...>>
 
  507            using type = std::array<std::size_t, 
sizeof...(N)>;
 
  511    template <
typename T>
 
  514    template <
class... S>
 
  517        using type = 
typename detail::promote_index<S...>::type;
 
 
  523    template <
class... S>
 
  526    template <
class... S>
 
  529        using type = 
typename detail::promote_index<S...>::type;
 
 
  535    template <
class... S>
 
  541        using type = 
typename detail::index_from_shape_impl<S>::type;
 
 
  548    using index_from_shape_t = 
typename index_from_shape<S>::type;
 
  557        struct filter_fixed_shape_impl
 
  562        template <std::size_t... N>
 
  563        struct filter_fixed_shape_impl<fixed_shape<N...>>
 
  565            using type = std::array<std::size_t, 
sizeof...(N)>;
 
  578    using filter_fixed_shape_t = 
typename filter_fixed_shape<S>::type;
 
Fixed shape implementation for compile time defined arrays.
bool same_shape(const S1 &s1, const S2 &s2) noexcept
Check if two objects have the same shape.
bool has_shape(const E &e, std::initializer_list< S > shape) noexcept
Check if an object has a certain shape.
standard mathematical functions for xexpressions
Compute a layout based on a layout and a shape type.