diff --git a/pythran/pythonic/builtins/slice.hpp b/pythran/pythonic/builtins/slice.hpp index f7652961a..3a96dc792 100644 --- a/pythran/pythonic/builtins/slice.hpp +++ b/pythran/pythonic/builtins/slice.hpp @@ -11,11 +11,11 @@ namespace builtins namespace anonymous { - inline types::contiguous_slice slice(types::none stop) + inline types::cstride_slice<1> slice(types::none stop) { return {types::none(), stop}; } - inline types::contiguous_slice slice(types::none start, + inline types::cstride_slice<1> slice(types::none start, types::none stop) { return {start, stop}; diff --git a/pythran/pythonic/include/builtins/slice.hpp b/pythran/pythonic/include/builtins/slice.hpp index 760ba05db..e8437d11a 100644 --- a/pythran/pythonic/include/builtins/slice.hpp +++ b/pythran/pythonic/include/builtins/slice.hpp @@ -11,15 +11,15 @@ namespace builtins namespace anonymous { - types::contiguous_slice slice(types::none stop); - types::contiguous_slice slice(types::none start, + types::cstride_slice<1> slice(types::none stop); + types::cstride_slice<1> slice(types::none start, types::none stop); types::slice slice(types::none start, types::none stop, types::none step); - } + } // namespace anonymous DEFINE_FUNCTOR(pythonic::builtins::anonymous, slice); -} +} // namespace builtins PYTHONIC_NS_END #endif diff --git a/pythran/pythonic/include/numpy/arange.hpp b/pythran/pythonic/include/numpy/arange.hpp index ddcb11262..0b6cb1bcb 100644 --- a/pythran/pythonic/include/numpy/arange.hpp +++ b/pythran/pythonic/include/numpy/arange.hpp @@ -1,9 +1,9 @@ #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" +#include "pythonic/include/utils/functor.hpp" PYTHONIC_NS_BEGIN @@ -128,20 +128,27 @@ namespace numpy { return operator[](s); } - types::ndarray operator[](types::contiguous_slice s) const + + template + types::ndarray + operator[](types::cstride_slice s) const { auto ns = s.normalize(size); - arange_index r{start + s.lower * step, step, ns.size()}; + arange_index r{start + s.lower * step, step * stride, ns.size()}; return { types::numpy_expr{ r}}; } - types::ndarray operator()(types::contiguous_slice s) const + + template + types::ndarray + operator()(types::cstride_slice s) const { return operator[](s); } + template - auto operator()(S const &... s) const -> typename std::enable_if< + auto operator()(S const &...s) const -> typename std::enable_if< (sizeof...(S) > 1), decltype(std::declval>()(s...))>::type { @@ -167,7 +174,7 @@ namespace numpy return {*this, size}; } }; - } + } // namespace details template ::type>> @@ -181,7 +188,7 @@ namespace numpy arange(T end); DEFINE_FUNCTOR(pythonic::numpy, arange); -} +} // namespace numpy PYTHONIC_NS_END #endif diff --git a/pythran/pythonic/include/numpy/fliplr.hpp b/pythran/pythonic/include/numpy/fliplr.hpp index 380f9b5ea..c2738a93e 100644 --- a/pythran/pythonic/include/numpy/fliplr.hpp +++ b/pythran/pythonic/include/numpy/fliplr.hpp @@ -1,8 +1,8 @@ #ifndef PYTHONIC_INCLUDE_NUMPY_FLIPLR_HPP #define PYTHONIC_INCLUDE_NUMPY_FLIPLR_HPP -#include "pythonic/include/utils/functor.hpp" #include "pythonic/include/types/ndarray.hpp" +#include "pythonic/include/utils/functor.hpp" PYTHONIC_NS_BEGIN @@ -10,11 +10,11 @@ namespace numpy { template auto fliplr(E &&expr) -> decltype(std::forward(expr)( - types::contiguous_slice{builtins::None, builtins::None}, + types::cstride_slice<1>{builtins::None, builtins::None}, types::slice{builtins::None, builtins::None, -1})); DEFINE_FUNCTOR(pythonic::numpy, fliplr); -} +} // namespace numpy PYTHONIC_NS_END #endif diff --git a/pythran/pythonic/include/numpy/trim_zeros.hpp b/pythran/pythonic/include/numpy/trim_zeros.hpp index b1543c268..21489f32b 100644 --- a/pythran/pythonic/include/numpy/trim_zeros.hpp +++ b/pythran/pythonic/include/numpy/trim_zeros.hpp @@ -1,8 +1,8 @@ #ifndef PYTHONIC_INCLUDE_NUMPY_TRIMZEROS_HPP #define PYTHONIC_INCLUDE_NUMPY_TRIMZEROS_HPP -#include "pythonic/include/utils/functor.hpp" #include "pythonic/include/types/numpy_gexpr.hpp" +#include "pythonic/include/utils/functor.hpp" PYTHONIC_NS_BEGIN @@ -10,11 +10,11 @@ namespace numpy { template - types::numpy_gexpr + types::numpy_gexpr> trim_zeros(T const &expr, types::str const &trim = "fb"); DEFINE_FUNCTOR(pythonic::numpy, trim_zeros) -} +} // namespace numpy PYTHONIC_NS_END #endif diff --git a/pythran/pythonic/include/types/dynamic_tuple.hpp b/pythran/pythonic/include/types/dynamic_tuple.hpp index 2b55ef753..99e477621 100644 --- a/pythran/pythonic/include/types/dynamic_tuple.hpp +++ b/pythran/pythonic/include/types/dynamic_tuple.hpp @@ -2,13 +2,13 @@ #define PYTHONIC_INCLUDE_TYPES_DYNAMIC_TUPLE_HPP #include "pythonic/include/types/assignable.hpp" -#include "pythonic/include/types/traits.hpp" #include "pythonic/include/types/nditerator.hpp" +#include "pythonic/include/types/traits.hpp" #include "pythonic/include/types/tuple.hpp" #include "pythonic/include/utils/int_.hpp" +#include "pythonic/include/utils/nested_container.hpp" #include "pythonic/include/utils/seq.hpp" #include "pythonic/include/utils/shared_ref.hpp" -#include "pythonic/include/utils/nested_container.hpp" #include @@ -58,8 +58,7 @@ namespace types dynamic_tuple &operator=(dynamic_tuple const &other) = default; template - dynamic_tuple(Iter start, Iter end) - : data(start, end) + dynamic_tuple(Iter start, Iter end) : data(start, end) { } @@ -148,10 +147,21 @@ namespace types return res; } - dynamic_tuple operator[](contiguous_slice const &s) const + template + dynamic_tuple operator[](cstride_slice const &s) const { auto ns = s.normalize(size()); - return {begin() + ns.lower, begin() + ns.upper}; + if (stride == 1) + return {begin() + ns.lower, begin() + ns.upper}; + else { + dynamic_tuple res; + res.data->reserve(ns.size()); + for (auto i = ns.lower, step = ns.step, n = ns.upper; i != n; + i += step) { + res.data->emplace_back(fast(i)); + } + return res; + } } dynamic_tuple operator[](fast_contiguous_slice const &s) const @@ -191,7 +201,7 @@ namespace types } return os << ')'; } -} +} // namespace types PYTHONIC_NS_END @@ -223,7 +233,7 @@ namespace std struct tuple_element> { using type = typename pythonic::types::dynamic_tuple::value_type; }; -} +} // namespace std /* specialize std::hash */ namespace std @@ -232,12 +242,12 @@ namespace std struct hash> { size_t operator()(pythonic::types::dynamic_tuple const &l) const; }; -} +} // namespace std #ifdef ENABLE_PYTHON_MODULE -#include "pythonic/include/utils/seq.hpp" #include "pythonic/include/utils/fwd.hpp" +#include "pythonic/include/utils/seq.hpp" #include "pythonic/python/core.hpp" PYTHONIC_NS_BEGIN diff --git a/pythran/pythonic/include/types/ndarray.hpp b/pythran/pythonic/include/types/ndarray.hpp index f6779f783..17a561afc 100644 --- a/pythran/pythonic/include/types/ndarray.hpp +++ b/pythran/pythonic/include/types/ndarray.hpp @@ -607,7 +607,7 @@ namespace types const & -> decltype((*this)(std::get(indices)...)) { return (*this)((indices.size() > Is ? std::get(indices) - : contiguous_slice())...); + : cstride_slice<1>())...); } template auto operator()(E const &a, S const &...slices) - -> decltype(_build_gexpr{}(a, types::contiguous_slice(), + -> decltype(_build_gexpr{}(a, types::cstride_slice<1>(), slices...)); }; diff --git a/pythran/pythonic/include/types/numpy_gexpr.hpp b/pythran/pythonic/include/types/numpy_gexpr.hpp index 8c5f0b332..ae7081903 100644 --- a/pythran/pythonic/include/types/numpy_gexpr.hpp +++ b/pythran/pythonic/include/types/numpy_gexpr.hpp @@ -59,8 +59,8 @@ namespace types template <> struct to_normalized_slice { - using type = contiguous_normalized_slice; - contiguous_normalized_slice operator()(none_type); + using type = cstride_normalized_slice<1>; + type operator()(none_type); }; /* helper to build a new shape out of a shape and a slice with new axis @@ -131,7 +131,7 @@ namespace types !is_slice::value, numpy_gexpr::type::dtype, array::type::value>>, - contiguous_normalized_slice, normalize_t...>>::type + cstride_normalized_slice<1>, normalize_t...>>::type operator()(E &&expr, F const &s0, S const &...s) { return numpy_vexpr::type::dtype, @@ -156,11 +156,6 @@ namespace types static constexpr size_t value = 0; }; - template <> - struct count_long { - static constexpr size_t value = 0; - }; - template struct count_long> { static constexpr size_t value = 0; @@ -198,7 +193,7 @@ namespace types }; template - struct is_contiguous { + struct is_contiguous, S...> { static const bool value = true; }; @@ -509,13 +504,6 @@ namespace types : gexpr_shape, array> { }; - template - struct gexpr_shape, - pshape, oTys...>, - contiguous_normalized_slice, S...> - : gexpr_shape>, - pshape, S...> { - }; template struct gexpr_shape, pshape, oTys...>, @@ -595,15 +583,15 @@ namespace types static const bool is_vectorizable = std::remove_reference::type::is_vectorizable && (sizeof...(S) < std::remove_reference::type::value || - std::is_same::value); + std::is_same, last_slice_t>::value); static const bool is_flat = std::remove_reference::type::is_flat && value == 1 && utils::all_of< - std::is_same::value...>::value; + std::is_same, S>::value...>::value; static const bool is_strided = std::remove_reference::type::is_strided || (((sizeof...(S) - count_long::value) == value) && - !std::is_same::value); + !std::is_same, last_slice_t>::value); using value_type = typename std::decay::get( @@ -627,11 +615,11 @@ namespace types shape_t _shape; dtype *buffer; + static constexpr types::pshape> + last_stride(cstride_normalized_slice<1>); template static constexpr types::pshape> last_stride(cstride_normalized_slice); - static constexpr types::pshape> - last_stride(contiguous_normalized_slice); static constexpr types::array last_stride(...); sutils::concat_t, diff --git a/pythran/pythonic/include/types/numpy_texpr.hpp b/pythran/pythonic/include/types/numpy_texpr.hpp index d076a0a0e..82c17b4cd 100644 --- a/pythran/pythonic/include/types/numpy_texpr.hpp +++ b/pythran/pythonic/include/types/numpy_texpr.hpp @@ -1,9 +1,9 @@ #ifndef PYTHONIC_INCLUDE_TYPES_NUMPY_TEXPR_HPP #define PYTHONIC_INCLUDE_TYPES_NUMPY_TEXPR_HPP -#include "pythonic/include/types/ndarray.hpp" #include "pythonic/include/builtins/None.hpp" #include "pythonic/include/numpy/transpose.hpp" +#include "pythonic/include/types/ndarray.hpp" PYTHONIC_NS_BEGIN @@ -36,7 +36,7 @@ namespace types using const_iterator = const_nditerator>; static constexpr size_t value = Arg::value; - using value_type = numpy_gexpr; + using value_type = numpy_gexpr, long>; using dtype = typename E::dtype; Arg arg; @@ -169,16 +169,18 @@ namespace types return arg[array{{indices[1], indices[0]}}]; } template - auto operator[](std::tuple const &indices) -> decltype( - arg[std::tuple{std::get<1>(indices), std::get<0>(indices)}]) + auto operator[](std::tuple const &indices) + -> decltype(arg[std::tuple{std::get<1>(indices), + std::get<0>(indices)}]) { return arg[std::tuple{std::get<1>(indices), std::get<0>(indices)}]; } template - auto operator[](std::tuple const &indices) const -> decltype( - arg[std::tuple{std::get<1>(indices), std::get<0>(indices)}]) + auto operator[](std::tuple const &indices) const + -> decltype(arg[std::tuple{std::get<1>(indices), + std::get<0>(indices)}]) { return arg[std::tuple{std::get<1>(indices), @@ -210,14 +212,14 @@ namespace types template auto - operator()(S0 const &s0, S const &... s) const -> typename std::enable_if< + operator()(S0 const &s0, S const &...s) const -> typename std::enable_if< !is_numexpr_arg::value, decltype(this->_reverse_index( std::tuple{s0, s...}, utils::make_reversed_index_sequence<1 + sizeof...(S)>()))>::type; template - auto operator()(S0 const &s0, S const &... s) const -> + auto operator()(S0 const &s0, S const &...s) const -> typename std::enable_if::value, decltype(this->copy()(s0, s...))>::type; @@ -366,7 +368,7 @@ namespace types return {*this, shape<0>()}; } }; -} +} // namespace types template struct assignable_noescape> { diff --git a/pythran/pythonic/include/types/slice.hpp b/pythran/pythonic/include/types/slice.hpp index b987a39c2..75de78d4f 100644 --- a/pythran/pythonic/include/types/slice.hpp +++ b/pythran/pythonic/include/types/slice.hpp @@ -53,9 +53,7 @@ namespace types struct cstride_slice; template struct cstride_normalized_slice; - struct contiguous_slice; struct fast_contiguous_slice; - struct contiguous_normalized_slice; struct normalized_slice { long lower, upper, step; @@ -63,14 +61,12 @@ namespace types normalized_slice(long lower, long upper, long step = 1); normalized_slice operator*(normalized_slice const &other) const; - normalized_slice operator*(contiguous_normalized_slice const &other) const; template normalized_slice operator*(cstride_normalized_slice const &other) const; normalized_slice operator*(slice const &other) const; template normalized_slice operator*(cstride_slice const &other) const; - normalized_slice operator*(contiguous_slice const &other) const; normalized_slice operator*(fast_contiguous_slice const &other) const; long size() const; @@ -89,8 +85,6 @@ namespace types template slice operator*(cstride_slice const &other) const; - slice operator*(contiguous_slice const &other) const; - slice operator*(fast_contiguous_slice const &other) const; /* @@ -113,12 +107,10 @@ namespace types struct cstride_normalized_slice { long lower, upper; static constexpr long step = stride; - cstride_normalized_slice(); + cstride_normalized_slice() = default; cstride_normalized_slice(long lower, long upper, long = 0); normalized_slice operator*(normalized_slice const &other) const; - cstride_normalized_slice - operator*(contiguous_normalized_slice const &other) const; template typename std::conditional<(stride < 256 && other_stride < 256), cstride_normalized_slice, @@ -131,7 +123,6 @@ namespace types cstride_normalized_slice, normalized_slice>::type operator*(cstride_slice const &other) const; - cstride_normalized_slice operator*(contiguous_slice const &other) const; cstride_normalized_slice operator*(fast_contiguous_slice const &other) const; @@ -159,8 +150,6 @@ namespace types cstride_slice, slice>::type operator*(cstride_slice const &other) const; - cstride_slice operator*(contiguous_slice const &other) const; - cstride_slice operator*(fast_contiguous_slice const &other) const; /* @@ -182,58 +171,11 @@ namespace types template constexpr long cstride_slice::step; - struct contiguous_normalized_slice { - long lower, upper; - static constexpr long step = 1; - contiguous_normalized_slice(); - contiguous_normalized_slice(long lower, long upper); - - contiguous_normalized_slice - operator*(contiguous_normalized_slice const &other) const; - template - cstride_normalized_slice - operator*(cstride_normalized_slice const &other) const; - contiguous_normalized_slice operator*(contiguous_slice const &other) const; - contiguous_normalized_slice - operator*(fast_contiguous_slice const &other) const; - normalized_slice operator*(normalized_slice const &other) const; - normalized_slice operator*(slice const &other) const; - template - cstride_normalized_slice - operator*(cstride_slice const &other) const; - - long size() const; - - inline long get(long i) const; - }; - - struct contiguous_slice { - using normalized_type = contiguous_normalized_slice; - long lower; - bound upper; - static constexpr long step = 1; - contiguous_slice(none lower, none upper); - contiguous_slice() = default; - - contiguous_slice operator*(contiguous_slice const &other) const; - contiguous_slice operator*(fast_contiguous_slice const &other) const; - - slice operator*(slice const &other) const; - - /* - Normalize change a[:-1] to a[:len(a)-1] to have positif index. - It also check for value bigger than len(a) to fit the size of the - container - */ - contiguous_normalized_slice normalize(long max_size) const; - - long size() const; - - inline long get(long i) const; - }; + // Kept for compatibility with former pythran version -cython use it. + using contiguous_slice = cstride_slice<1>; struct fast_contiguous_slice { - using normalized_type = contiguous_normalized_slice; + using normalized_type = cstride_normalized_slice<1>; long lower; bound upper; static constexpr long step = 1; @@ -241,10 +183,11 @@ namespace types fast_contiguous_slice() = default; fast_contiguous_slice operator*(fast_contiguous_slice const &other) const; - contiguous_slice operator*(contiguous_slice const &other) const; + template + cstride_slice operator*(cstride_slice const &other) const; slice operator*(slice const &other) const; - contiguous_normalized_slice normalize(long max_size) const; + cstride_normalized_slice<1> normalize(long max_size) const; long size() const; }; @@ -263,23 +206,15 @@ namespace types using type = cstride_normalized_slice; }; - template <> - struct normalized { - using type = contiguous_normalized_slice; - }; - template <> struct normalized { - using type = contiguous_normalized_slice; + using type = cstride_normalized_slice<1>; }; template struct is_slice : std::false_type { }; template <> - struct is_slice : std::true_type { - }; - template <> struct is_slice : std::true_type { }; template <> @@ -293,9 +228,6 @@ namespace types struct is_normalized_slice : std::false_type { }; template <> - struct is_normalized_slice : std::true_type { - }; - template <> struct is_normalized_slice : std::true_type { }; template @@ -346,7 +278,7 @@ namespace types return s; } template - contiguous_slice adapt_slice(S const &s, I0 const &index0, I1 const &index1) + cstride_slice<1> adapt_slice(S const &s, I0 const &index0, I1 const &index1) { if ((long)index0 != (long)index1) return {0, 1}; @@ -398,16 +330,6 @@ struct to_python> { static PyObject *convert(types::bound const &n); }; -template <> -struct to_python { - static PyObject *convert(types::contiguous_slice const &n); -}; - -template <> -struct to_python { - static PyObject *convert(types::contiguous_normalized_slice const &n); -}; - template struct to_python> { static PyObject *convert(types::cstride_slice const &n); diff --git a/pythran/pythonic/include/types/tuple.hpp b/pythran/pythonic/include/types/tuple.hpp index 66557c0f4..ce7aa8972 100644 --- a/pythran/pythonic/include/types/tuple.hpp +++ b/pythran/pythonic/include/types/tuple.hpp @@ -87,7 +87,6 @@ namespace types class str; struct slice; - struct contiguous_slice; template struct cstride_slice; @@ -282,10 +281,6 @@ namespace types dynamic_tuple operator()(array const &b, cstride_slice const &s); - template - dynamic_tuple operator()(array const &b, - contiguous_slice const &s); - template dynamic_tuple operator()(array const &b, fast_contiguous_slice const &s); diff --git a/pythran/pythonic/numpy/correlate.hpp b/pythran/pythonic/numpy/correlate.hpp index 2cc511ea4..f87d8bf25 100644 --- a/pythran/pythonic/numpy/correlate.hpp +++ b/pythran/pythonic/numpy/correlate.hpp @@ -2,9 +2,9 @@ #define PYTHONIC_NUMPY_CORRELATE_HPP #include "pythonic/include/numpy/correlate.hpp" -#include "pythonic/numpy/dot.hpp" -#include "pythonic/numpy/conjugate.hpp" #include "pythonic/numpy/asarray.hpp" +#include "pythonic/numpy/conjugate.hpp" +#include "pythonic/numpy/dot.hpp" #include "pythonic/types/ndarray.hpp" PYTHONIC_NS_BEGIN @@ -59,37 +59,37 @@ namespace numpy if (out_inc == 1) { // Incomplete overlap left for (int i = iLeft; i < 0; i++, out_ptr++) { - *out_ptr = numpy::dot(inA_(types::contiguous_slice(0, NB + i)), - inB_(types::contiguous_slice(-i, NB))); + *out_ptr = numpy::dot(inA_(types::fast_contiguous_slice(0, NB + i)), + inB_(types::fast_contiguous_slice(-i, NB))); } // Complete overlap middle for (int i = 0; i <= NA - NB; i++, out_ptr++) { - *out_ptr = numpy::dot(inA_(types::contiguous_slice(i, i + NB)), - inB_(types::contiguous_slice(0, NB))); + *out_ptr = numpy::dot(inA_(types::fast_contiguous_slice(i, i + NB)), + inB_(types::fast_contiguous_slice(0, NB))); } // Incomplete overlap right. for (int i = NA - NB + 1; i < iRight; i++, out_ptr++) { - *out_ptr = numpy::dot(inA_(types::contiguous_slice(i, NA)), - inB_(types::contiguous_slice(0, NA - i))); + *out_ptr = numpy::dot(inA_(types::fast_contiguous_slice(i, NA)), + inB_(types::fast_contiguous_slice(0, NA - i))); } } else { // Incomplete overlap left for (int i = iLeft; i < 0; i++, out_ptr += out_inc) { *out_ptr = wrapper::conjugate( - numpy::dot(inA_(types::contiguous_slice(0, NB + i)), - inB_(types::contiguous_slice(-i, NB)))); + numpy::dot(inA_(types::fast_contiguous_slice(0, NB + i)), + inB_(types::fast_contiguous_slice(-i, NB)))); } // Complete overlap middle for (int i = 0; i <= NA - NB; i++, out_ptr += out_inc) { *out_ptr = wrapper::conjugate( - numpy::dot(inA_(types::contiguous_slice(i, i + NB)), - inB_(types::contiguous_slice(0, NB)))); + numpy::dot(inA_(types::fast_contiguous_slice(i, i + NB)), + inB_(types::fast_contiguous_slice(0, NB)))); } // Incomplete overlap right. for (int i = NA - NB + 1; i < iRight; i++, out_ptr += out_inc) { *out_ptr = wrapper::conjugate( - numpy::dot(inA_(types::contiguous_slice(i, NA)), - inB_(types::contiguous_slice(0, NA - i)))); + numpy::dot(inA_(types::fast_contiguous_slice(i, NA)), + inB_(types::fast_contiguous_slice(0, NA - i)))); } } @@ -114,7 +114,7 @@ namespace numpy } NUMPY_EXPR_TO_NDARRAY0_IMPL(correlate) -} +} // namespace numpy PYTHONIC_NS_END #endif diff --git a/pythran/pythonic/numpy/fliplr.hpp b/pythran/pythonic/numpy/fliplr.hpp index 2903f965e..e7354ff21 100644 --- a/pythran/pythonic/numpy/fliplr.hpp +++ b/pythran/pythonic/numpy/fliplr.hpp @@ -3,8 +3,8 @@ #include "pythonic/include/numpy/fliplr.hpp" -#include "pythonic/utils/functor.hpp" #include "pythonic/types/ndarray.hpp" +#include "pythonic/utils/functor.hpp" PYTHONIC_NS_BEGIN @@ -12,14 +12,14 @@ namespace numpy { template auto fliplr(E &&expr) -> decltype(std::forward(expr)( - types::contiguous_slice{builtins::None, builtins::None}, + types::cstride_slice<1>{builtins::None, builtins::None}, types::slice{builtins::None, builtins::None, -1})) { return std::forward(expr)( - types::contiguous_slice{builtins::None, builtins::None}, + types::cstride_slice<1>{builtins::None, builtins::None}, types::slice{builtins::None, builtins::None, -1}); } -} +} // namespace numpy PYTHONIC_NS_END #endif diff --git a/pythran/pythonic/numpy/trim_zeros.hpp b/pythran/pythonic/numpy/trim_zeros.hpp index 783f5feda..89b8be558 100644 --- a/pythran/pythonic/numpy/trim_zeros.hpp +++ b/pythran/pythonic/numpy/trim_zeros.hpp @@ -3,15 +3,15 @@ #include "pythonic/include/numpy/trim_zeros.hpp" -#include "pythonic/utils/functor.hpp" #include "pythonic/types/numpy_gexpr.hpp" +#include "pythonic/utils/functor.hpp" PYTHONIC_NS_BEGIN namespace numpy { template - types::numpy_gexpr + types::numpy_gexpr> trim_zeros(T const &expr, types::str const &trim) { static_assert(T::value == 1, @@ -20,15 +20,15 @@ namespace numpy long begin = 0; long end = expr.flat_size(); if (trim.find("f") != -1) - begin = std::find_if(expr.begin(), expr.end(), [](typename T::dtype i) { - return i != 0; - }) - expr.begin(); + begin = std::find_if(expr.begin(), expr.end(), + [](typename T::dtype i) { return i != 0; }) - + expr.begin(); if (trim.find("b") != -1) while (*(expr.begin() + --end) != 0) ; - return make_gexpr(expr, types::contiguous_slice(begin, end)); + return make_gexpr(expr, types::fast_contiguous_slice(begin, end)); } -} +} // namespace numpy PYTHONIC_NS_END #endif diff --git a/pythran/pythonic/types/ndarray.hpp b/pythran/pythonic/types/ndarray.hpp index fb661da72..1f4c0657c 100644 --- a/pythran/pythonic/types/ndarray.hpp +++ b/pythran/pythonic/types/ndarray.hpp @@ -1085,10 +1085,10 @@ namespace builtins template template auto _build_gexpr::operator()(E const &a, S const &...slices) - -> decltype(_build_gexpr{}(a, types::contiguous_slice(), + -> decltype(_build_gexpr{}(a, types::cstride_slice<1>(), slices...)) { - return _build_gexpr{}(a, types::contiguous_slice(0, a.size()), + return _build_gexpr{}(a, types::cstride_slice<1>(0, a.size()), slices...); } @@ -1526,7 +1526,8 @@ namespace impl { } - inline void set_slice(types::contiguous_normalized_slice &cs, long lower, + template + inline void set_slice(types::cstride_normalized_slice &cs, long lower, long upper, long step) { cs.lower = lower; diff --git a/pythran/pythonic/types/numpy_gexpr.hpp b/pythran/pythonic/types/numpy_gexpr.hpp index fb2fc57c0..095305427 100644 --- a/pythran/pythonic/types/numpy_gexpr.hpp +++ b/pythran/pythonic/types/numpy_gexpr.hpp @@ -125,7 +125,7 @@ namespace types return value; } - inline contiguous_normalized_slice + inline cstride_normalized_slice<1> to_normalized_slice::operator()(none_type) { return {0, 1}; diff --git a/pythran/pythonic/types/numpy_texpr.hpp b/pythran/pythonic/types/numpy_texpr.hpp index 9ae0f4bd1..a037a0103 100644 --- a/pythran/pythonic/types/numpy_texpr.hpp +++ b/pythran/pythonic/types/numpy_texpr.hpp @@ -3,17 +3,17 @@ #include "pythonic/include/types/numpy_texpr.hpp" -#include "pythonic/types/ndarray.hpp" #include "pythonic/numpy/array.hpp" #include "pythonic/numpy/transpose.hpp" +#include "pythonic/types/ndarray.hpp" #include "pythonic/operator_/iadd.hpp" #include "pythonic/operator_/iand.hpp" #include "pythonic/operator_/idiv.hpp" #include "pythonic/operator_/imul.hpp" #include "pythonic/operator_/ior.hpp" -#include "pythonic/operator_/ixor.hpp" #include "pythonic/operator_/isub.hpp" +#include "pythonic/operator_/ixor.hpp" PYTHONIC_NS_BEGIN @@ -26,8 +26,7 @@ namespace types } template - numpy_texpr_2::numpy_texpr_2(Arg const &arg) - : arg(arg) + numpy_texpr_2::numpy_texpr_2(Arg const &arg) : arg(arg) { } @@ -62,7 +61,7 @@ namespace types i)) { return arg( - contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), + cstride_slice<1>(pythonic::builtins::None, pythonic::builtins::None), i); } @@ -73,7 +72,7 @@ namespace types i)) { return arg( - contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), + cstride_slice<1>(pythonic::builtins::None, pythonic::builtins::None), i); } @@ -81,7 +80,7 @@ namespace types template template typename numpy_texpr_2::simd_iterator - numpy_texpr_2::vbegin(vectorizer) const + numpy_texpr_2::vbegin(vectorizer) const { return {*this}; } @@ -89,7 +88,7 @@ namespace types template template typename numpy_texpr_2::simd_iterator - numpy_texpr_2::vend(vectorizer) const + numpy_texpr_2::vend(vectorizer) const { return {*this}; // not vectorizable anyway } @@ -113,10 +112,10 @@ namespace types template template - auto numpy_texpr_2:: - operator[](S const &s0) const -> numpy_texprarg( - fast_contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), - (s0.step, s0)))> + auto numpy_texpr_2::operator[](S const &s0) const -> numpy_texpr< + decltype(this->arg(fast_contiguous_slice(pythonic::builtins::None, + pythonic::builtins::None), + (s0.step, s0)))> { return {arg(fast_contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), @@ -125,8 +124,8 @@ namespace types template template - auto numpy_texpr_2:: - operator[](S const &s0) -> numpy_texprarg( + auto + numpy_texpr_2::operator[](S const &s0) -> numpy_texprarg( fast_contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), (s0.step, s0)))> { @@ -176,8 +175,7 @@ namespace types std::is_same::value && F::value == 1 && !is_pod_array::value, numpy_vexpr, ndarray>>>::type - numpy_texpr_2:: - operator[](F const &filter) const + numpy_texpr_2::operator[](F const &filter) const { return fast(filter); } @@ -189,8 +187,8 @@ namespace types std::is_same::value && F::value != 1 && !is_pod_array::value, numpy_vexpr::dtype, pshape>, - ndarray>>>::type numpy_texpr_2:: - operator[](F const &filter) const + ndarray>>>::type + numpy_texpr_2::operator[](F const &filter) const { return fast(filter); } @@ -202,8 +200,7 @@ namespace types !std::is_same::value && !is_pod_array::value, numpy_vexpr, ndarray>>>::type - numpy_texpr_2:: - operator[](F const &filter) const + numpy_texpr_2::operator[](F const &filter) const { static_assert(F::value == 1, "advanced indexing only supporint with 1D index"); @@ -227,7 +224,7 @@ namespace types template template - auto numpy_texpr_2::operator()(S0 const &s0, S const &... s) const -> + auto numpy_texpr_2::operator()(S0 const &s0, S const &...s) const -> typename std::enable_if< !is_numexpr_arg::value, decltype(this->_reverse_index( @@ -240,7 +237,7 @@ namespace types } template template - auto numpy_texpr_2::operator()(S0 const &s0, S const &... s) const -> + auto numpy_texpr_2::operator()(S0 const &s0, S const &...s) const -> typename std::enable_if::value, decltype(this->copy()(s0, s...))>::type { @@ -277,8 +274,8 @@ namespace types } template template - numpy_texpr_2 &numpy_texpr_2:: - operator=(numpy_texpr const &expr) + numpy_texpr_2 & + numpy_texpr_2::operator=(numpy_texpr const &expr) { arg = expr.arg; return *this; @@ -374,7 +371,7 @@ namespace types : numpy_texpr_2>{arg} { } -} +} // namespace types PYTHONIC_NS_END #endif diff --git a/pythran/pythonic/types/slice.hpp b/pythran/pythonic/types/slice.hpp index 05276f41a..5d053247e 100644 --- a/pythran/pythonic/types/slice.hpp +++ b/pythran/pythonic/types/slice.hpp @@ -16,8 +16,6 @@ PYTHONIC_NS_BEGIN namespace types { - struct contiguous_slice; - namespace details { @@ -41,12 +39,7 @@ namespace types return {lower + step * other.lower, lower + step * other.upper, step * other.step}; } - inline normalized_slice - normalized_slice::operator*(contiguous_normalized_slice const &other) const - { - return {lower + step * other.lower, lower + step * other.upper, - step * other.step}; - } + template inline normalized_slice normalized_slice::operator*( cstride_normalized_slice const &other) const @@ -58,11 +51,7 @@ namespace types { return (*this) * other.normalize(size()); } - inline normalized_slice - normalized_slice::operator*(contiguous_slice const &other) const - { - return (*this) * other.normalize(size()); - } + template inline normalized_slice normalized_slice::operator*(cstride_slice const &other) const @@ -257,16 +246,16 @@ namespace types } template - inline cstride_normalized_slice - cstride_normalized_slice::operator*( - contiguous_normalized_slice const &other) const + inline normalized_slice + cstride_normalized_slice::operator*(slice const &other) const { - return {lower + step * other.lower, lower + step * other.upper}; + return (*this) * other.normalize(size()); } template - inline normalized_slice - cstride_normalized_slice::operator*(slice const &other) const + inline cstride_normalized_slice + cstride_normalized_slice::operator*( + fast_contiguous_slice const &other) const { return (*this) * other.normalize(size()); } @@ -283,14 +272,6 @@ namespace types return (*this) * other.normalize(size()); } - template - inline cstride_normalized_slice - cstride_normalized_slice::operator*( - contiguous_slice const &other) const - { - return (*this) * other.normalize(size()); - } - template inline long cstride_normalized_slice::size() const { @@ -456,113 +437,13 @@ namespace types return (long)lower + i * step; } - // - inline contiguous_normalized_slice::contiguous_normalized_slice() - { - } - - inline contiguous_normalized_slice::contiguous_normalized_slice(long lower, - long upper) - : lower(lower), upper(upper) - { - } - - inline contiguous_normalized_slice contiguous_normalized_slice::operator*( - contiguous_normalized_slice const &other) const - { - return contiguous_normalized_slice(lower + other.lower, - lower + other.upper); - } - inline contiguous_normalized_slice - contiguous_normalized_slice::operator*(contiguous_slice const &other) const - { - return (*this) * other.normalize(size()); - } - - inline contiguous_normalized_slice contiguous_normalized_slice::operator*( - fast_contiguous_slice const &other) const - { - return (*this) * other.normalize(size()); - } - template - inline cstride_normalized_slice - contiguous_normalized_slice::operator*( - cstride_normalized_slice const &other) const - { - return {lower + step * other.lower, lower + step * other.upper}; - } - - inline normalized_slice - contiguous_normalized_slice::operator*(normalized_slice const &other) const - { - return normalized_slice(lower + step * other.lower, - lower + step * other.upper, step * other.step); - } - - template - inline cstride_normalized_slice - contiguous_normalized_slice::operator*( - cstride_slice const &other) const - { - return (*this) * other.normalize(size()); - } - - inline normalized_slice - contiguous_normalized_slice::operator*(slice const &other) const - { - return (*this) * other.normalize(size()); - } - - inline long contiguous_normalized_slice::size() const - { - return std::max(0L, upper - lower); - } - - inline long contiguous_normalized_slice::get(long i) const - { - return lower + i; - } - - inline contiguous_slice::contiguous_slice(none lower, none upper) - : lower(lower.is_none ? 0 : (long)lower), upper(upper) - { - } - - inline contiguous_slice - contiguous_slice::operator*(contiguous_slice const &other) const - { - long new_lower; - if (other.lower < 0) - new_lower = upper + other.lower * step; - else - new_lower = lower + other.lower * step; - - bound new_upper; - if (other.upper.is_none()) - new_upper = upper; - else if ((long)other.upper < 0) { - if (upper.is_none()) - new_upper = (long)other.upper * step; - else - new_upper = upper + (long)other.upper * step; - } else - new_upper = lower + (long)other.upper * step; - - return {new_lower, new_upper}; - } - - inline slice contiguous_slice::operator*(slice const &other) const + inline cstride_slice + fast_contiguous_slice::operator*(cstride_slice const &other) const { none new_lower; if (other.lower.is_none() || (long)other.lower == 0) { - if (other.step > 0) - new_lower = lower; - else if (upper.is_none() || (long)upper == 0) - // 0 means the first value && ! the last value - new_lower = none_type{}; - else - new_lower = (long)upper - 1; + new_lower = lower; } else { if ((long)other.lower > 0) new_lower = lower + (long)other.lower * step; @@ -572,16 +453,9 @@ namespace types new_lower = (long)upper + (long)other.lower * step; } - long new_step = other.step; - bound new_upper; if (other.upper.is_none()) { - if (other.step > 0) - new_upper = upper; - else if ((long)lower == 0) - new_upper = none_type{}; - else - new_upper = (long)lower - 1; + new_upper = upper; } else { if ((long)other.upper > 0) new_upper = lower + (long)other.upper * step; @@ -590,52 +464,7 @@ namespace types else new_upper = (long)upper + (long)other.upper * step; } - return {new_lower, new_upper, new_step}; - } - - /* - Normalize change a[:-1] to a[:len(a)-1] to have positif index. - It also check for value bigger than len(a) to fit the size of the - container - */ - inline contiguous_normalized_slice - contiguous_slice::normalize(long max_size) const - { - long normalized_upper; - if (upper.is_none()) - normalized_upper = max_size; - else if (upper < 0L) - normalized_upper = std::max(-1L, max_size + upper); - else if (upper > max_size) - normalized_upper = max_size; - else - normalized_upper = (long)upper; - - long normalized_lower; - if (lower < 0L) - normalized_lower = std::max(0L, max_size + lower); - else if (lower > max_size) - normalized_lower = max_size; - else - normalized_lower = (long)lower; - - return contiguous_normalized_slice(normalized_lower, normalized_upper); - } - - inline long contiguous_slice::size() const - { - long len; - if (upper.is_none()) { - assert(lower < 0); - len = -lower; - } else - len = upper - lower; - return std::max(0L, len); - } - - inline long contiguous_slice::get(long i) const - { - return int(lower) + i; + return {new_lower, new_upper}; } inline fast_contiguous_slice::fast_contiguous_slice(none lower, @@ -657,28 +486,6 @@ namespace types return {new_lower, new_upper}; } - inline contiguous_slice - fast_contiguous_slice::operator*(contiguous_slice const &other) const - { - long new_lower; - if (other.lower < 0) - new_lower = upper + other.lower * step; - else - new_lower = lower + other.lower * step; - - bound new_upper; - if (other.upper.is_none()) - new_upper = upper; - else if ((long)other.upper < 0) { - if (upper.is_none()) - new_upper = (long)other.upper * step; - else - new_upper = upper + (long)other.upper * step; - } else - new_upper = lower + (long)other.upper * step; - - return {new_lower, new_upper}; - } inline slice fast_contiguous_slice::operator*(slice const &other) const { @@ -726,7 +533,7 @@ namespace types It also check for value bigger than len(a) to fit the size of the container */ - inline contiguous_normalized_slice + inline cstride_normalized_slice<1> fast_contiguous_slice::normalize(long max_size) const { long normalized_upper; @@ -752,47 +559,6 @@ namespace types return std::max(0L, upper - lower); } - inline slice slice::operator*(contiguous_slice const &other) const - { - // We do ! implement these because it requires to know the "end" - // value of the slice which is ! possible if it is ! "step == 1" slice - // TODO: We can skip these constraints if we know begin, end && step. - assert(!((static_cast(other.upper) < 0 || - static_cast(other.lower) < 0) && - step != 1 && step != -1) && - "not implemented"); - - bound new_lower; - if (other.lower == 0) - new_lower = lower; - else { - bound ref = ((long)other.lower > 0) ? lower : upper; - if (ref.is_none()) { - if (step > 0) - new_lower = (long)other.lower * step; - else - new_lower = (long)other.lower * step - 1; - } else - new_lower = (long)ref + (long)other.lower * step; - } - - long new_step = step; - - bound new_upper; - if (other.upper.is_none()) - new_upper = upper; - else { - bound ref = ((long)other.upper > 0) ? lower : upper; - if (ref.is_none()) { - if (step > 0) - new_upper = (long)other.upper * step; - else - new_upper = (long)other.upper * step - 1; - } else - new_upper = (long)ref + (long)other.upper * step; - } - return {new_lower, new_upper, new_step}; - } template std::ostream &operator<<(std::ostream &os, bound const &b) { @@ -820,20 +586,6 @@ PyObject *to_python>::convert(types::bound const &b) return ::to_python((T)b); } -inline PyObject *to_python::convert( - types::contiguous_normalized_slice const &v) -{ - return PySlice_New(::to_python(v.lower), ::to_python(v.upper), - ::to_python(types::none_type{})); -} - -inline PyObject * -to_python::convert(types::contiguous_slice const &v) -{ - return PySlice_New(::to_python(v.lower), ::to_python(v.upper), - ::to_python(types::none_type{})); -} - template inline PyObject *to_python>::convert( types::cstride_normalized_slice const &v) diff --git a/pythran/pythonic/types/tuple.hpp b/pythran/pythonic/types/tuple.hpp index d96822224..0316b52c8 100644 --- a/pythran/pythonic/types/tuple.hpp +++ b/pythran/pythonic/types/tuple.hpp @@ -417,25 +417,22 @@ namespace types dynamic_tuple array_base_slicer::operator()(array const &b, cstride_slice const &s) { - cstride_normalized_slice ns = s.normalize(b.size()); - array tmp; - for (long j = 0; j < ns.size(); ++j) - tmp[j] = b[ns.lower + j * ns.step]; - return {&tmp[0], &tmp[ns.size()]}; + auto ns = s.normalize(b.size()); + if (stride == 1) { + return {&b[ns.lower], &b[ns.upper]}; + } else { + array tmp; + for (long j = 0; j < ns.size(); ++j) + tmp[j] = b[ns.lower + j * ns.step]; + return {&tmp[0], &tmp[ns.size()]}; + } } - template - dynamic_tuple array_base_slicer::operator()(array const &b, - contiguous_slice const &s) - { - contiguous_normalized_slice cns = s.normalize(b.size()); - return {&b[cns.lower], &b[cns.upper]}; - } template dynamic_tuple array_base_slicer::operator()(array const &b, fast_contiguous_slice const &s) { - contiguous_normalized_slice cns = s.normalize(b.size()); + auto cns = s.normalize(b.size()); return {&b[cns.lower], &b[cns.upper]}; } } // namespace types diff --git a/pythran/tests/test_advanced.py b/pythran/tests/test_advanced.py index 6b35d93d5..9a637bd11 100644 --- a/pythran/tests/test_advanced.py +++ b/pythran/tests/test_advanced.py @@ -365,7 +365,7 @@ def static_list1(n): def test_static_list2(self): code = ''' def static_list2(t0, t1): - s = [slice(x, y) for x,y in zip(t0, t1)] + s = [slice(x, y, 1) for x,y in zip(t0, t1)] return tuple(s)''' self.run_test(code, (2, 2), (3,3), static_list2=[Tuple[int, int], Tuple[int, int]]) diff --git a/pythran/tests/test_ndarray.py b/pythran/tests/test_ndarray.py index d43580291..9cce9590f 100644 --- a/pythran/tests/test_ndarray.py +++ b/pythran/tests/test_ndarray.py @@ -711,6 +711,11 @@ def test_gexpr_composition21(self): numpy.arange(24), gexpr_composition21=[NDArray[int, :]]) + def test_gexpr_composition22(self): + self.run_test("def gexpr_composition22(n): import numpy as np; U = np.ones((n+2,n+2), dtype=np.float32); u = U[1:-1,1:-1]; u[:] = 2.0; return u", + 30, + gexpr_composition22=[int]) + def test_gexpr_copy0(self): self.run_test("def gexpr_copy0(a,b): a[:,0] = b[:,0]; return a",