10#ifndef XTENSOR_GENERATOR_HPP 
   11#define XTENSOR_GENERATOR_HPP 
   20#include <xtl/xsequence.hpp> 
   22#include "../core/xaccessible.hpp" 
   23#include "../core/xexpression.hpp" 
   24#include "../core/xiterable.hpp" 
   25#include "../core/xstrides.hpp" 
   26#include "../utils/xutils.hpp" 
   27#include "../views/xstrided_view.hpp" 
   38        template <
class Tag, 
class F, 
class R, 
class S>
 
   41        template <
class F, 
class R, 
class S>
 
   47        template <
class F, 
class R, 
class S>
 
   52        template <
class F, 
class R, 
class S>
 
   60    template <
class F, 
class R, 
class S>
 
   66    template <
class C, 
class R, 
class S>
 
   69        using inner_shape_type = S;
 
   71        using stepper = const_stepper;
 
 
   74    template <
class C, 
class R, 
class S>
 
   78        using const_reference = R;
 
   79        using size_type = std::size_t;
 
 
   86    template <xgenerator_concept E>
 
  107    template <
class F, 
class R, 
class S>
 
  108    class xgenerator : 
public xsharable_expression<xgenerator<F, R, S>>,
 
  110                       public xconst_accessible<xgenerator<F, R, S>>,
 
  111                       public extension::xgenerator_base_t<F, R, S>
 
  116        using functor_type = 
typename std::remove_reference<F>::type;
 
  118        using accessible_base = xconst_accessible<self_type>;
 
  119        using extension_base = extension::xgenerator_base_t<F, R, S>;
 
  120        using expression_tag = 
typename extension_base::expression_tag;
 
  123        using value_type = R;
 
  124        using reference = 
typename inner_types::reference;
 
  125        using const_reference = 
typename inner_types::const_reference;
 
  126        using pointer = value_type*;
 
  127        using const_pointer = 
const value_type*;
 
  128        using size_type = 
typename inner_types::size_type;
 
  129        using difference_type = std::ptrdiff_t;
 
  132        using inner_shape_type = 
typename iterable_base::inner_shape_type;
 
  133        using shape_type = inner_shape_type;
 
  135        using stepper = 
typename iterable_base::stepper;
 
  136        using const_stepper = 
typename iterable_base::const_stepper;
 
  138        using bool_load_type = xt::bool_load_type<R>;
 
  141        static constexpr bool contiguous_layout = 
false;
 
  143        template <
class Func>
 
  146        const inner_shape_type& 
shape() const noexcept;
 
  148        bool is_contiguous() const noexcept;
 
  149        using accessible_base::
shape;
 
  151        template <class... Args>
 
  152        const_reference operator()(Args... args) const;
 
  153        template <class... Args>
 
  154        const_reference unchecked(Args... args) const;
 
  157        const_reference element(It first, It last) const;
 
  166        const_stepper stepper_begin(const O& 
shape) const noexcept;
 
  170        template <class E, class FE = F>
 
  172            requires(has_assign_to_v<E, FE>);
 
  174        const functor_type& functor() const noexcept;
 
  176        template <class OR, class OF>
 
  179        template <class OR, class OF>
 
  180        rebind_t<OR, OF> build_generator(OF&& func) const;
 
  182        template <class O = 
xt::dynamic_shape<typename shape_type::value_type>>
 
  185        template <class O = 
xt::dynamic_shape<typename shape_type::value_type>>
 
  197        decltype(auto) compute_shape(O&& 
shape, std::false_type ) const;
 
  200        auto compute_shape(O&& 
shape, std::true_type ) const;
 
  203        auto compute_shape(std::initializer_list<T> 
shape) const;
 
  205        template <std::
size_t dim>
 
  206        void adapt_index() const;
 
  208        template <std::
size_t dim, class I, class... Args>
 
  209        void adapt_index(I& 
arg, Args&... args) const;
 
  212        inner_shape_type m_shape;
 
 
  229    template <class F, class R, class S>
 
  230    template <class Func>
 
  232        : m_f(std::forward<Func>(f))
 
 
  246    template <
class F, 
class R, 
class S>
 
  252    template <
class F, 
class R, 
class S>
 
  253    inline layout_type xgenerator<F, R, S>::layout() const noexcept
 
  255        return static_layout;
 
  258    template <
class F, 
class R, 
class S>
 
  259    inline bool xgenerator<F, R, S>::is_contiguous() const noexcept
 
  276    template <
class F, 
class R, 
class S>
 
  277    template <
class... Args>
 
  278    inline auto xgenerator<F, R, S>::operator()(Args... args) 
const -> const_reference
 
  280        XTENSOR_TRY(check_index(
shape(), args...));
 
  281        adapt_index<0>(args...);
 
 
  304    template <
class F, 
class R, 
class S>
 
  305    template <
class... Args>
 
  306    inline auto xgenerator<F, R, S>::unchecked(Args... args) 
const -> const_reference
 
 
  318    template <
class F, 
class R, 
class S>
 
  320    inline auto xgenerator<F, R, S>::element(It first, It last) 
const -> const_reference
 
  323        XTENSOR_TRY(check_element_index(
shape(), first, last));
 
  324        return m_f.element(bounded_iterator(first, 
shape().
cbegin()), bounded_iterator(last, 
shape().
cend()));
 
 
  339    template <
class F, 
class R, 
class S>
 
  343        return xt::broadcast_shape(m_shape, 
shape);
 
 
  351    template <
class F, 
class R, 
class S>
 
  360    template <
class F, 
class R, 
class S>
 
  362    inline auto xgenerator<F, R, S>::stepper_begin(
const O& shape) 
const noexcept -> const_stepper
 
  364        size_type offset = shape.size() - this->
dimension();
 
  365        return const_stepper(
this, offset);
 
  368    template <
class F, 
class R, 
class S>
 
  370    inline auto xgenerator<F, R, S>::stepper_end(
const O& 
shape, 
layout_type) 
const noexcept -> const_stepper
 
  373        return const_stepper(
this, offset, 
true);
 
  376    template <
class F, 
class R, 
class S>
 
  377    template <
class E, 
class FE>
 
  379        requires(has_assign_to_v<E, FE>)
 
  381        e.derived_cast().resize(m_shape);
 
  385    template <
class F, 
class R, 
class S>
 
  391    template <
class F, 
class R, 
class S>
 
  392    template <
class OR, 
class OF>
 
  395        return rebind_t<OR, OF>(std::move(func), shape_type(m_shape));
 
  408    template <
class F, 
class R, 
class S>
 
  412        return reshape_view(*
this, compute_shape(
shape, xtl::is_signed<
typename std::decay_t<O>::value_type>()));
 
 
  415    template <
class F, 
class R, 
class S>
 
  421            compute_shape(shape, xtl::is_signed<
typename std::decay_t<O>::value_type>())
 
  425    template <
class F, 
class R, 
class S>
 
  429        return reshape_view(*
this, compute_shape(
shape));
 
  432    template <
class F, 
class R, 
class S>
 
  436        return reshape_view(std::move(*
this), compute_shape(
shape));
 
  439    template <
class F, 
class R, 
class S>
 
  443        return xtl::forward_sequence<xt::dynamic_shape<typename shape_type::value_type>, O>(
shape);
 
  446    template <
class F, 
class R, 
class S>
 
  450        using vtype = 
typename shape_type::value_type;
 
  451        xt::dynamic_shape<vtype> sh(
shape.size());
 
  452        using int_type = 
typename std::decay_t<O>::value_type;
 
  453        int_type accumulator(1);
 
  454        std::size_t neg_idx = 0;
 
  456        for (std::size_t j = 0; j != 
shape.size(); ++j, ++i)
 
  461                XTENSOR_ASSERT(dim == -1 && !neg_idx);
 
  466                sh[j] = 
static_cast<vtype
>(dim);
 
  472            sh[neg_idx] = this->
size()
 
  473                          / 
static_cast<size_type
>(std::make_unsigned_t<int_type>(std::abs(accumulator)));
 
  478    template <
class F, 
class R, 
class S>
 
  482        using sh_type = xt::dynamic_shape<T>;
 
  483        sh_type sh = xtl::make_sequence<sh_type>(
shape.size());
 
  484        std::copy(
shape.begin(), 
shape.end(), sh.begin());
 
  485        return compute_shape(std::move(sh), xtl::is_signed<T>());
 
  488    template <
class F, 
class R, 
class S>
 
  489    template <std::
size_t dim>
 
  494    template <
class F, 
class R, 
class S>
 
  495    template <std::size_t dim, 
class I, 
class... Args>
 
  498        using tmp_value_type = 
typename decltype(m_shape)::value_type;
 
  499        if (
sizeof...(Args) + 1 > m_shape.size())
 
  501            adapt_index<dim>(args...);
 
  505            if (
static_cast<tmp_value_type
>(
arg) >= m_shape[dim] && m_shape[dim] == 1)
 
  509            adapt_index<dim + 1>(args...);
 
  515        template <
class Functor, 
class I, std::
size_t L>
 
  516        inline auto make_xgenerator(Functor&& f, 
const I (&shape)[L]) 
noexcept 
  518            using shape_type = std::array<std::size_t, L>;
 
  519            using type = xgenerator<Functor, typename Functor::value_type, shape_type>;
 
  520            return type(std::forward<Functor>(f), xtl::forward_sequence<shape_type, 
decltype(shape)>(shape));
 
  523        template <
class Functor, 
class S>
 
  524        inline auto make_xgenerator(Functor&& f, S&& shape) 
noexcept 
  526            using type = xgenerator<Functor, typename Functor::value_type, std::decay_t<S>>;
 
  527            return type(std::forward<Functor>(f), std::forward<S>(shape));
 
size_type size() const noexcept(noexcept(derived_cast().shape()))
size_type dimension() const noexcept
Base class for multidimensional iterable constant expressions.
auto cend() const noexcept -> const_layout_iterator< L >
auto cbegin() const noexcept -> const_layout_iterator< L >
Base class for xexpressions.
Multidimensional function operating on indices.
xgenerator(Func &&f, const S &shape) noexcept
Constructs an xgenerator applying the specified function over the given shape.
const inner_shape_type & shape() const noexcept
auto reshape(O &&shape) const &
bool has_linear_assign(const O &) const noexcept
bool broadcast_shape(O &shape, bool reuse_cache=false) const
auto arg(E &&e) noexcept
Calculates the phase angle (in radians) elementwise for the complex numbers in e.
standard mathematical functions for xexpressions