10#ifndef XTENSOR_UTILS_HPP 
   11#define XTENSOR_UTILS_HPP 
   18#include <initializer_list> 
   26#include <xtl/xfunctional.hpp> 
   27#include <xtl/xmeta_utils.hpp> 
   28#include <xtl/xsequence.hpp> 
   29#include <xtl/xtype_traits.hpp> 
   31#include "../core/xtensor_config.hpp" 
   33#if (defined(_MSC_VER) && _MSC_VER >= 1910) 
   36#define NOEXCEPT(T) noexcept(T) 
   54    template <std::size_t I, 
class... Args>
 
   55    constexpr decltype(
auto) argument(Args&&... args) 
noexcept;
 
   57    template <
class R, 
class F, 
class... S>
 
   58    R apply(std::size_t index, F&& func, 
const std::tuple<S...>& s) NOEXCEPT(
noexcept(func(std::get<0>(s))));
 
   60    template <
class T, 
class S>
 
   61    void nested_copy(T&& iter, 
const S& s);
 
   63    template <
class T, 
class S>
 
   64    void nested_copy(T&& iter, std::initializer_list<S> s);
 
   67    bool resize_container(C& c, 
typename C::size_type size);
 
   69    template <
class T, std::
size_t N>
 
   70    bool resize_container(std::array<T, N>& a, 
typename std::array<T, N>::size_type size);
 
   72    template <std::size_t... I>
 
   75    template <std::size_t... I>
 
   78    template <
class X, 
class C>
 
   81    template <
class X, 
class C>
 
   84    std::size_t normalize_axis(std::size_t dim, std::ptrdiff_t axis);
 
   95    using void_t = 
typename make_void<T...>::type;
 
  103    template <
class... T>
 
  109    template <
class T, 
class R>
 
  110    using disable_integral_t = std::enable_if_t<!xtl::is_integral<T>::value, R>;
 
  126    template <
template <
class...> 
class TT, 
class T>
 
  131    template <
template <
class...> 
class TT, 
class... Ts>
 
  145    template <
class C, 
class R, 
class... Args>
 
  148        typedef R type(Args...);
 
 
  151    template <
class C, 
class R, 
class... Args>
 
  154        typedef R type(Args...);
 
 
  166        template <std::size_t I, 
class F, 
class... T>
 
  167        inline typename std::enable_if<I == 
sizeof...(T), 
void>::type
 
  168        for_each_impl(F&& , std::tuple<T...>& ) 
noexcept 
  172        template <std::size_t I, 
class F, 
class... T>
 
  173            inline typename std::enable_if < I<
sizeof...(T), 
void>::type
 
  174            for_each_impl(F&& f, std::tuple<T...>& t) 
noexcept(
noexcept(f(std::get<I>(t))))
 
  177            for_each_impl<I + 1, F, T...>(std::forward<F>(f), t);
 
  181    template <
class F, 
class... T>
 
  182    inline void for_each(F&& f, std::tuple<T...>& t) 
noexcept(
 
  183        noexcept(detail::for_each_impl<0, F, T...>(std::forward<F>(f), t))
 
  186        detail::for_each_impl<0, F, T...>(std::forward<F>(f), t);
 
  191        template <std::size_t I, 
class F, 
class... T>
 
  192        inline typename std::enable_if<I == 
sizeof...(T), 
void>::type
 
  193        for_each_impl(F&& , 
const std::tuple<T...>& ) 
noexcept 
  197        template <std::size_t I, 
class F, 
class... T>
 
  198            inline typename std::enable_if < I<
sizeof...(T), 
void>::type
 
  199            for_each_impl(F&& f, 
const std::tuple<T...>& t) 
noexcept(
noexcept(f(std::get<I>(t))))
 
  202            for_each_impl<I + 1, F, T...>(std::forward<F>(f), t);
 
  206    template <
class F, 
class... T>
 
  207    inline void for_each(F&& f, 
const std::tuple<T...>& t) 
noexcept(
 
  208        noexcept(detail::for_each_impl<0, F, T...>(std::forward<F>(f), t))
 
  211        detail::for_each_impl<0, F, T...>(std::forward<F>(f), t);
 
  222        template <std::size_t I, 
class F, 
class R, 
class... T>
 
  223        inline std::enable_if_t<I == 
sizeof...(T), R>
 
  224        accumulate_impl(F&& , R init, 
const std::tuple<T...>& ) 
noexcept 
  229        template <std::size_t I, 
class F, 
class R, 
class... T>
 
  230            inline std::enable_if_t < I<
sizeof...(T), R>
 
  231            accumulate_impl(F&& f, R init, 
const std::tuple<T...>& t) 
noexcept(
noexcept(f(init, std::get<I>(t))))
 
  233            R res = f(init, std::get<I>(t));
 
  234            return accumulate_impl<I + 1, F, R, T...>(std::forward<F>(f), res, t);
 
  238    template <
class F, 
class R, 
class... T>
 
  239    inline R 
accumulate(F&& f, R init, 
const std::tuple<T...>& t) 
noexcept(
 
  240        noexcept(detail::accumulate_impl<0, F, R, T...>(std::forward<F>(f), init, t))
 
  243        return detail::accumulate_impl<0, F, R, T...>(std::forward<F>(f), init, t);
 
  254        template <std::
size_t I>
 
  257            template <
class Arg, 
class... Args>
 
  258            static constexpr decltype(
auto) get(Arg&& , Args&&... args) 
noexcept 
  260                return getter<I - 1>::get(std::forward<Args>(args)...);
 
  267            template <
class Arg, 
class... Args>
 
  268            static constexpr Arg&& get(Arg&& 
arg, Args&&... ) noexcept
 
  270                return std::forward<Arg>(
arg);
 
  275    template <std::size_t I, 
class... Args>
 
  276    constexpr decltype(
auto) argument(Args&&... args) 
noexcept 
  278        static_assert(I < 
sizeof...(Args), 
"I should be lesser than sizeof...(Args)");
 
  279        return detail::getter<I>::get(std::forward<Args>(args)...);
 
  286    template <
class R, 
class F, 
class... S>
 
  287    inline R apply(std::size_t index, F&& func, 
const std::tuple<S...>& s)
 
  288        NOEXCEPT(
noexcept(func(std::get<0>(s))))
 
  290        XTENSOR_ASSERT(
sizeof...(S) > index);
 
  292            [&](
const S&... args) -> R
 
  294                auto f_impl = [&](
auto&& self, 
auto&& i, 
auto&& h, 
auto&&... t) -> R
 
  298                        return static_cast<R
>(func(h));
 
  300                    if constexpr (
sizeof...(t) > 0)
 
  302                        return self(self, std::size_t{i + 1}, t...);
 
  306                return f_impl(f_impl, std::size_t{0}, args...);
 
  316    template <
class T, std::
size_t I>
 
  328    template <
class T, std::
size_t I>
 
  329    using nested_initializer_list_t = 
typename nested_initializer_list<T, I>::type;
 
  335    template <
class T, 
class S>
 
  336    inline void nested_copy(T&& iter, 
const S& s)
 
  341    template <
class T, 
class S>
 
  342    inline void nested_copy(T&& iter, std::initializer_list<S> s)
 
  344        for (
auto it = s.begin(); it != s.end(); ++it)
 
  346            nested_copy(std::forward<T>(iter), *it);
 
  354    inline bool resize_container(C& c, 
typename C::size_type size)
 
  360    template <
class T, std::
size_t N>
 
  361    inline bool resize_container(std::array<T, N>& , 
typename std::array<T, N>::size_type size)
 
  366    template <std::size_t... I>
 
  367    inline bool resize_container(xt::fixed_shape<I...>&, std::size_t size)
 
  369        return sizeof...(I) == size;
 
  377    inline std::size_t normalize_axis(std::size_t dim, std::ptrdiff_t axis)
 
  379        return axis < 0 ? static_cast<std::size_t>(
static_cast<std::ptrdiff_t
>(dim) + axis)
 
  380                        : static_cast<std::size_t>(axis);
 
  383    template <
class E, 
class C>
 
  384    inline std::enable_if_t<
 
  385        !xtl::is_integral<std::decay_t<C>>::value && xtl::is_signed<typename std::decay_t<C>::value_type>::value,
 
  386        rebind_container_t<std::size_t, std::decay_t<C>>>
 
  387    normalize_axis(E& expr, C&& axes)
 
  389        rebind_container_t<std::size_t, std::decay_t<C>> res;
 
  390        resize_container(res, axes.size());
 
  392        for (std::size_t i = 0; i < axes.size(); ++i)
 
  394            res[i] = normalize_axis(expr.dimension(), axes[i]);
 
  397        XTENSOR_ASSERT(std::all_of(
 
  402                return ax_el < expr.dimension();
 
  409    template <
class C, 
class E>
 
  410    inline std::enable_if_t<
 
  411        !xtl::is_integral<std::decay_t<C>>::value && std::is_unsigned<typename std::decay_t<C>::value_type>::value,
 
  413    normalize_axis(E& expr, C&& axes)
 
  415        static_cast<void>(expr);
 
  416        XTENSOR_ASSERT(std::all_of(
 
  421                return ax_el < expr.dimension();
 
  424        return std::forward<C>(axes);
 
  427    template <
class R, 
class E, 
class C>
 
  428    inline auto forward_normalize(E& expr, C&& axes)
 
  429        -> std::enable_if_t<xtl::is_signed<std::decay_t<
decltype(*std::begin(axes))>>::value, R>
 
  432        xt::resize_container(res, std::size(axes));
 
  433        auto dim = expr.dimension();
 
  440                return normalize_axis(dim, ax_el);
 
  444        XTENSOR_ASSERT(std::all_of(
 
  449                return ax_el < expr.dimension();
 
  456    template <
class R, 
class E, 
class C>
 
  457    inline auto forward_normalize(E& expr, C&& axes) -> std::enable_if_t<
 
  458        !xtl::is_signed<std::decay_t<
decltype(*std::begin(axes))>>::value && !std::is_same<R, std::decay_t<C>>::value,
 
  461        static_cast<void>(expr);
 
  464        xt::resize_container(res, std::size(axes));
 
  465        std::copy(std::begin(axes), std::end(axes), std::begin(res));
 
  466        XTENSOR_ASSERT(std::all_of(
 
  471                return ax_el < expr.dimension();
 
  477    template <
class R, 
class E, 
class C>
 
  478    inline auto forward_normalize(E& expr, C&& axes) -> std::enable_if_t<
 
  479        !xtl::is_signed<std::decay_t<
decltype(*std::begin(axes))>>::value && std::is_same<R, std::decay_t<C>>::value,
 
  482        static_cast<void>(expr);
 
  483        XTENSOR_ASSERT(std::all_of(
 
  488                return ax_el < expr.dimension();
 
  491        return std::move(axes);
 
  498    template <
class T, 
class = 
void_t<>>
 
  507        using type = 
typename T::value_type;
 
 
  511    using get_value_type_t = 
typename get_value_type<T>::type;
 
  519    template <std::size_t I, 
template <
typename... Args> 
class T, typename... Args>
 
  520    decltype(auto) get(T<Args...>&& v)
 
  522        return std::get<I>(
static_cast<std::tuple<Args...
>&&>(v));
 
  525    template <std::size_t I, 
template <
typename... Args> 
class T, typename... Args>
 
  526    decltype(auto) get(T<Args...>& v)
 
  528        return std::get<I>(
static_cast<std::tuple<Args...
>&>(v));
 
  531    template <std::size_t I, 
template <
typename... Args> 
class T, typename... Args>
 
  532    decltype(auto) get(const T<Args...>& v)
 
  534        return std::get<I>(
static_cast<const std::tuple<Args...
>&>(v));
 
  543        template <
class T, std::size_t N, std::size_t... I>
 
  544        constexpr std::array<std::remove_cv_t<T>, N> to_array_impl(T (&a)[N], std::index_sequence<I...>)
 
  550    template <
class T, std::
size_t N>
 
  551    constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N])
 
  553        return detail::to_array_impl(a, std::make_index_sequence<N>{});
 
  560    template <
class T, 
class = 
void>
 
  571              std::is_same<typename std::remove_cv<typename xcontainer_inner_types<T>::storage_type>::type, invalid_type>>
 
 
  579    template <
class E, 
class = 
void>
 
  592    template <
class E, 
class = 
void>
 
  602    template <
class E, 
class = 
void>
 
  619    template <
class E, 
class = 
void>
 
  628            decltype(*std::declval<const E>(), std::declval<const E>() == std::declval<const E>(), std::declval<const E>() != std::declval<const E>(), ++(*std::declval<E*>()), (*std::declval<E*>())++, std::true_type())>>
 
 
  633    template <
typename E>
 
  640#if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7 
  642#define XTENSOR_GLIBCXX_USE_CXX11_ABI 1 
  644#if defined(_GLIBCXX_USE_CXX11_ABI) 
  645#if _GLIBCXX_USE_CXX11_ABI || (defined(_GLIBCXX_USE_DUAL_ABI) && !_GLIBCXX_USE_DUAL_ABI) 
  646#define XTENSOR_GLIBCXX_USE_CXX11_ABI 1 
  651#if !defined(__GNUG__) || defined(_LIBCPP_VERSION) || defined(XTENSOR_GLIBCXX_USE_CXX11_ABI) 
  654    using xtrivially_default_constructible = std::is_trivially_default_constructible<T>;
 
  659    using xtrivially_default_constructible = std::has_trivial_default_constructor<T>;
 
  662#undef XTENSOR_GLIBCXX_USE_CXX11_ABI 
  668    template <
bool condition, 
class T>
 
  680        inline auto operator()(U&& u)
 const 
  682            return static_cast<T
>(std::forward<U>(u));
 
 
  694    template <
bool condition, 
class T, 
class U>
 
  704    namespace alloc_tracking
 
  706        inline bool& enabled()
 
  717        inline void disable()
 
  729    template <
class T, 
class A, alloc_tracking::policy P>
 
  730    struct tracking_allocator : 
private A
 
  733        using value_type = 
typename A::value_type;
 
  734        using reference = value_type&;
 
  735        using const_reference = 
const value_type&;
 
  736        using pointer = 
typename std::allocator_traits<A>::pointer;
 
  737        using const_pointer = 
typename std::allocator_traits<A>::const_pointer;
 
  738        using size_type = 
typename std::allocator_traits<A>::size_type;
 
  739        using difference_type = 
typename std::allocator_traits<A>::difference_type;
 
  741        tracking_allocator() = 
default;
 
  743        T* allocate(std::size_t n)
 
  745            if (alloc_tracking::enabled())
 
  747                if (P == alloc_tracking::print)
 
  749                    std::cout << 
"xtensor allocating: " << n << 
"" << std::endl;
 
  751                else if (P == alloc_tracking::assert)
 
  755                        "xtensor allocation of " + std::to_string(n) + 
" elements detected" 
  759            return base_type::allocate(n);
 
  762        using base_type::deallocate;
 
  765#if ((defined(__cplusplus) && __cplusplus < 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG < 202002L)) 
  766        using base_type::construct;
 
  767        using base_type::destroy;
 
  773            using traits = std::allocator_traits<A>;
 
  774            using other = tracking_allocator<U, typename traits::template rebind_alloc<U>, P>;
 
 
 
  778    template <
class T, 
class AT, alloc_tracking::policy PT, 
class U, 
class AU, alloc_tracking::policy PU>
 
  781        return std::is_same<AT, AU>::value;
 
  784    template <
class T, 
class AT, alloc_tracking::policy PT, 
class U, 
class AU, alloc_tracking::policy PU>
 
  785    inline bool operator!=(
const tracking_allocator<T, AT, PT>& a, 
const tracking_allocator<U, AU, PU>& b)
 
  794    template <
class E1, 
class E2, 
class = 
void>
 
  799    template <
class E1, 
class E2>
 
  800    struct has_assign_to<E1, E2, void_t<decltype(std::declval<const E2&>().assign_to(std::declval<E1&>()))>>
 
 
  805    template <
class E1, 
class E2>
 
  812    template <
class T, 
class Enable = 
void>
 
  818    struct has_memory_address<T, void_t<decltype(std::addressof(*std::declval<T>().begin()))>> : std::true_type
 
 
  822    template <
typename T>
 
  824    template <
typename T>
 
  831        const uintptr_t m_first = 0;
 
  832        const uintptr_t m_last = 0;
 
  834        explicit memory_range() = 
default;
 
  837        explicit memory_range(T* first, T* last)
 
  838            : m_first(
reinterpret_cast<uintptr_t
>(last < first ? last : first))
 
  839            , m_last(
reinterpret_cast<uintptr_t
>(last < first ? first : last))
 
  844        bool overlaps(T* first, T* last)
 const 
  848                return reinterpret_cast<uintptr_t
>(first) <= m_last
 
  849                       && 
reinterpret_cast<uintptr_t
>(last) >= m_first;
 
  853                return reinterpret_cast<uintptr_t
>(last) <= m_last
 
  854                       && 
reinterpret_cast<uintptr_t
>(first) >= m_first;
 
 
  859    template <
class E, 
class Enable = 
void>
 
  862        static bool check_overlap(
const E&, 
const memory_range&)
 
 
  871        static bool check_overlap(
const E& expr, 
const memory_range& dst_range)
 
  873            if (expr.size() == 0)
 
  879                return dst_range.overlaps(std::addressof(*expr.begin()), std::addressof(*expr.rbegin()));
 
 
  884    struct overlapping_memory_checker_base
 
  888        explicit overlapping_memory_checker_base() = 
default;
 
  890        explicit overlapping_memory_checker_base(
memory_range dst_memory_range)
 
  891            : m_dst_range(std::move(dst_memory_range))
 
  896        bool check_overlap(
const E& expr)
 const 
  898            if (!m_dst_range.m_first || !m_dst_range.m_last)
 
  904                return overlapping_memory_checker_traits<E>::check_overlap(expr, m_dst_range);
 
 
  909    template <
class Dst, 
class Enable = 
void>
 
  910    struct overlapping_memory_checker : overlapping_memory_checker_base
 
  912        explicit overlapping_memory_checker(
const Dst&)
 
  913            : overlapping_memory_checker_base()
 
 
  919    struct overlapping_memory_checker<Dst, std::enable_if_t<has_memory_address<Dst>::value>>
 
  920        : overlapping_memory_checker_base
 
  922        explicit overlapping_memory_checker(
const Dst& aDst)
 
  923            : overlapping_memory_checker_base(
 
  926                    if (aDst.size() == 0)
 
  932                        return memory_range(std::addressof(*aDst.begin()), std::addressof(*aDst.rbegin()));
 
 
  941    auto make_overlapping_memory_checker(
const Dst& a_dst)
 
  950    template <
class X, 
template <
class, 
class> 
class C, 
class T, 
class A>
 
  953        using traits = std::allocator_traits<A>;
 
  954        using allocator = 
typename traits::template rebind_alloc<X>;
 
  955        using type = C<X, allocator>;
 
 
  959#ifdef __cpp_template_template_args 
  960    template <
class X, 
class T, std::
size_t N>
 
  963        using type = std::array<X, N>;
 
  966    template <
class X, 
template <
class, std::
size_t> 
class C, 
class T, std::size_t N>
 
  969        using type = C<X, N>;
 
 
  983    template <std::size_t... I>
 
  989        using type = std::array<std::ptrdiff_t, 
sizeof...(I)>;
 
 
  992    template <
class CP, 
class O, 
class A>
 
  995    template <
class CP, 
class O, 
class A>
 
 1001        using type = std::vector<
 
 1002            typename xbuffer_adaptor<CP, O, A>::value_type,
 
 1003            typename xbuffer_adaptor<CP, O, A>::allocator_type>;
 
 
 1008    using get_strides_t = 
typename get_strides_type<C>::type;
 
 1017        using storage_type = std::decay_t<ST>;
 
 1018        using type = std::conditional_t<
 
 1019            std::is_const<std::remove_reference_t<ST>>::value,
 
 1020            typename storage_type::const_reference,
 
 1021            typename storage_type::reference>;
 
 
 1025    using inner_reference_t = 
typename inner_reference<ST>::type;
 
 1031    template <
class E, 
typename = 
void>
 
 1034        static constexpr std::size_t value = SIZE_MAX;
 
 
 1040        static constexpr std::size_t value = E::rank;
 
 
 1050        using type = std::integral_constant<bool, get_rank<std::decay_t<E>>::value != SIZE_MAX>;
 
 
 1060    template <
class E, 
size_t N>
 
 1063        using type = std::integral_constant<bool, get_rank<std::decay_t<E>>::value == N>;
 
 
 1066    template <
class E, 
size_t N>
 
Fixed shape implementation for compile time defined arrays.
auto arg(E &&e) noexcept
Calculates the phase angle (in radians) elementwise for the complex numbers in e.
auto strides(const E &e, stride_type type=stride_type::normal) noexcept
Get strides of an object.
standard mathematical functions for xexpressions
auto accumulate(F &&f, E &&e, EVS evaluation_strategy=EVS())
Accumulate and flatten array NOTE This function is not lazy!
auto conditional_cast(U &&u)
Perform a type cast when a condition is true.