#ifndef PYTHONIC_INCLUDE_NUMPY_ARANGE_HPP #define PYTHONIC_INCLUDE_NUMPY_ARANGE_HPP #include "pythonic/include/utils/functor.hpp" #include "pythonic/include/operator_/pos.hpp" #include "pythonic/include/types/ndarray.hpp" PYTHONIC_NS_BEGIN namespace numpy { namespace details { #ifdef USE_XSIMD template struct arange_simd_iterator { using vector_type = xsimd::simd_type; vector_type curr_; vector_type step_; long index_; arange_simd_iterator(T start, T step, long n) : curr_{}, step_{static_cast(vector_type::size * step)}, index_{static_cast(n / vector_type::size)} { T from[vector_type::size]; for (size_t i = 0; i < vector_type::size; ++i) from[i] = start + i * step; curr_ = xsimd::load_unaligned(from); } vector_type operator*() const { return curr_; } arange_simd_iterator &operator++() { curr_ += step_; ++index_; return *this; } arange_simd_iterator &operator+=(long n) { curr_ += n * step_; index_ += n; return *this; } arange_simd_iterator operator+(long n) const { arange_simd_iterator other{*this}; return other += n; } arange_simd_iterator &operator--() { curr_ -= step_; --index_; return *this; } long operator-(arange_simd_iterator const &other) const { return index_ - other.index_; } bool operator!=(arange_simd_iterator const &other) const { return index_ != other.index_; } bool operator==(arange_simd_iterator const &other) const { return index_ == other.index_; } bool operator<(arange_simd_iterator const &other) const { return index_ < other.index_; } arange_simd_iterator & operator=(arange_simd_iterator const &other) = default; }; #endif template struct arange_index { T start, step; long size; using iterator = types::nditerator; using const_iterator = types::const_nditerator; using dtype = T; using value_type = dtype; using shape_t = types::pshape; #ifdef USE_XSIMD using simd_iterator = arange_simd_iterator; using simd_iterator_nobroadcast = simd_iterator; template simd_iterator vbegin(vectorizer) const { return {start, step, 0}; } template simd_iterator vend(vectorizer) const { return {static_cast(start + size * step), step, size}; } #endif static constexpr size_t value = 1; static constexpr bool is_strided = false; static constexpr bool is_vectorizable = types::is_vectorizable::value; T fast(long i) const { return start + i * step; } dtype load(long i) const { return fast(i); } template long shape() const { return size; } types::ndarray operator[](types::slice s) const { auto ns = s.normalize(size); arange_index r{start + s.lower * step, step * ns.step, ns.size()}; return { types::numpy_expr{ r}}; } types::ndarray operator()(types::slice s) const { return operator[](s); } types::ndarray operator[](types::contiguous_slice s) const { auto ns = s.normalize(size); arange_index r{start + s.lower * step, step, ns.size()}; return { types::numpy_expr{ r}}; } types::ndarray operator()(types::contiguous_slice s) const { return operator[](s); } template auto operator()(S const &... s) const -> typename std::enable_if< (sizeof...(S) > 1), decltype(std::declval>()(s...))>::type { return types::ndarray{ types::numpy_expr{ *this}}(s...); } const_iterator begin() const { return {*this, 0}; } const_iterator end() const { return {*this, size}; } iterator begin() { return {*this, 0}; } iterator end() { return {*this, size}; } }; } template ::type>> types::numpy_expr> arange(T begin, U end, S step = S(1), dtype d = dtype()); template types::numpy_expr::type>> arange(T end); DEFINE_FUNCTOR(pythonic::numpy, arange); } PYTHONIC_NS_END #endif