Skip to content

Commit

Permalink
Make contiguous_slice a special instance of cstride_slice
Browse files Browse the repository at this point in the history
This makes the code much simpler to reason about and removes a lot of
redundancy between contiguous_slice and cstride_slice.
  • Loading branch information
serge-sans-paille committed Apr 23, 2023
1 parent c991b29 commit 7158247
Show file tree
Hide file tree
Showing 21 changed files with 168 additions and 486 deletions.
4 changes: 2 additions & 2 deletions pythran/pythonic/builtins/slice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ namespace builtins

namespace anonymous
{
inline types::contiguous_slice slice(types::none<long> stop)
inline types::cstride_slice<1> slice(types::none<long> stop)
{
return {types::none<long>(), stop};
}
inline types::contiguous_slice slice(types::none<long> start,
inline types::cstride_slice<1> slice(types::none<long> start,
types::none<long> stop)
{
return {start, stop};
Expand Down
8 changes: 4 additions & 4 deletions pythran/pythonic/include/builtins/slice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ namespace builtins

namespace anonymous
{
types::contiguous_slice slice(types::none<long> stop);
types::contiguous_slice slice(types::none<long> start,
types::cstride_slice<1> slice(types::none<long> stop);
types::cstride_slice<1> slice(types::none<long> start,
types::none<long> stop);
types::slice slice(types::none<long> start, types::none<long> stop,
types::none<long> step);
}
} // namespace anonymous

DEFINE_FUNCTOR(pythonic::builtins::anonymous, slice);
}
} // namespace builtins
PYTHONIC_NS_END

#endif
21 changes: 14 additions & 7 deletions pythran/pythonic/include/numpy/arange.hpp
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -128,20 +128,27 @@ namespace numpy
{
return operator[](s);
}
types::ndarray<dtype, shape_t> operator[](types::contiguous_slice s) const

template <long stride>
types::ndarray<dtype, shape_t>
operator[](types::cstride_slice<stride> 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<pythonic::operator_::functor::pos, arange_index>{
r}};
}
types::ndarray<dtype, shape_t> operator()(types::contiguous_slice s) const

template <long stride>
types::ndarray<dtype, shape_t>
operator()(types::cstride_slice<stride> s) const
{
return operator[](s);
}

template <class... S>
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<types::ndarray<dtype, shape_t>>()(s...))>::type
{
Expand All @@ -167,7 +174,7 @@ namespace numpy
return {*this, size};
}
};
}
} // namespace details

template <class T, class U, class S = long,
class dtype = types::dtype_t<typename __combined<T, U, S>::type>>
Expand All @@ -181,7 +188,7 @@ namespace numpy
arange(T end);

DEFINE_FUNCTOR(pythonic::numpy, arange);
}
} // namespace numpy
PYTHONIC_NS_END

#endif
6 changes: 3 additions & 3 deletions pythran/pythonic/include/numpy/fliplr.hpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
#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

namespace numpy
{
template <class E>
auto fliplr(E &&expr) -> decltype(std::forward<E>(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
6 changes: 3 additions & 3 deletions pythran/pythonic/include/numpy/trim_zeros.hpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
#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

namespace numpy
{
template <class T>

types::numpy_gexpr<T, types::contiguous_normalized_slice>
types::numpy_gexpr<T, types::cstride_normalized_slice<1>>
trim_zeros(T const &expr, types::str const &trim = "fb");

DEFINE_FUNCTOR(pythonic::numpy, trim_zeros)
}
} // namespace numpy
PYTHONIC_NS_END

#endif
30 changes: 20 additions & 10 deletions pythran/pythonic/include/types/dynamic_tuple.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <vector>

Expand Down Expand Up @@ -58,8 +58,7 @@ namespace types
dynamic_tuple &operator=(dynamic_tuple const &other) = default;

template <class Iter>
dynamic_tuple(Iter start, Iter end)
: data(start, end)
dynamic_tuple(Iter start, Iter end) : data(start, end)
{
}

Expand Down Expand Up @@ -148,10 +147,21 @@ namespace types
return res;
}

dynamic_tuple operator[](contiguous_slice const &s) const
template <long stride>
dynamic_tuple operator[](cstride_slice<stride> 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
Expand Down Expand Up @@ -191,7 +201,7 @@ namespace types
}
return os << ')';
}
}
} // namespace types

PYTHONIC_NS_END

Expand Down Expand Up @@ -223,7 +233,7 @@ namespace std
struct tuple_element<I, pythonic::types::dynamic_tuple<T>> {
using type = typename pythonic::types::dynamic_tuple<T>::value_type;
};
}
} // namespace std

/* specialize std::hash */
namespace std
Expand All @@ -232,12 +242,12 @@ namespace std
struct hash<pythonic::types::dynamic_tuple<T>> {
size_t operator()(pythonic::types::dynamic_tuple<T> 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
Expand Down
14 changes: 10 additions & 4 deletions pythran/pythonic/include/types/ndarray.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ namespace types
const & -> decltype((*this)(std::get<Is>(indices)...))
{
return (*this)((indices.size() > Is ? std::get<Is>(indices)
: contiguous_slice())...);
: cstride_slice<1>())...);
}

template <class Ty0, class Ty1, class... Tys,
Expand Down Expand Up @@ -647,8 +647,14 @@ namespace types
flat_iterator fend();

/* member functions */
T* data() { return buffer;}
T const* data() const { return buffer;}
T *data()
{
return buffer;
}
T const *data() const
{
return buffer;
}
long flat_size() const;
bool may_overlap(ndarray const &) const;

Expand Down Expand Up @@ -793,7 +799,7 @@ namespace builtins
struct _build_gexpr {
template <class E, class... S>
auto operator()(E const &a, S const &...slices)
-> decltype(_build_gexpr<N - 1>{}(a, types::contiguous_slice(),
-> decltype(_build_gexpr<N - 1>{}(a, types::cstride_slice<1>(),
slices...));
};

Expand Down
30 changes: 9 additions & 21 deletions pythran/pythonic/include/types/numpy_gexpr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ namespace types

template <>
struct to_normalized_slice<none_type> {
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
Expand Down Expand Up @@ -131,7 +131,7 @@ namespace types
!is_slice<F>::value,
numpy_gexpr<ndarray<typename std::decay<E>::type::dtype,
array<long, std::decay<E>::type::value>>,
contiguous_normalized_slice, normalize_t<S>...>>::type
cstride_normalized_slice<1>, normalize_t<S>...>>::type
operator()(E &&expr, F const &s0, S const &...s)
{
return numpy_vexpr<ndarray<typename std::decay<E>::type::dtype,
Expand All @@ -156,11 +156,6 @@ namespace types
static constexpr size_t value = 0;
};

template <>
struct count_long<contiguous_normalized_slice> {
static constexpr size_t value = 0;
};

template <long stride>
struct count_long<cstride_normalized_slice<stride>> {
static constexpr size_t value = 0;
Expand Down Expand Up @@ -198,7 +193,7 @@ namespace types
};

template <class... S>
struct is_contiguous<contiguous_normalized_slice, S...> {
struct is_contiguous<cstride_normalized_slice<1>, S...> {
static const bool value = true;
};

Expand Down Expand Up @@ -509,13 +504,6 @@ namespace types
: gexpr_shape<pshape<Tys..., long>, array<long, N - 1>> {
};

template <class... Tys, class... oTys, class... S>
struct gexpr_shape<pshape<Tys...>,
pshape<std::integral_constant<long, 1>, oTys...>,
contiguous_normalized_slice, S...>
: gexpr_shape<pshape<Tys..., std::integral_constant<long, 1>>,
pshape<oTys...>, S...> {
};
template <class... Tys, class... oTys, class... S, long stride>
struct gexpr_shape<pshape<Tys...>,
pshape<std::integral_constant<long, 1>, oTys...>,
Expand Down Expand Up @@ -595,15 +583,15 @@ namespace types
static const bool is_vectorizable =
std::remove_reference<Arg>::type::is_vectorizable &&
(sizeof...(S) < std::remove_reference<Arg>::type::value ||
std::is_same<contiguous_normalized_slice, last_slice_t>::value);
std::is_same<cstride_normalized_slice<1>, last_slice_t>::value);
static const bool is_flat =
std::remove_reference<Arg>::type::is_flat && value == 1 &&
utils::all_of<
std::is_same<contiguous_normalized_slice, S>::value...>::value;
std::is_same<cstride_normalized_slice<1>, S>::value...>::value;
static const bool is_strided =
std::remove_reference<Arg>::type::is_strided ||
(((sizeof...(S) - count_long<S...>::value) == value) &&
!std::is_same<contiguous_normalized_slice, last_slice_t>::value);
!std::is_same<cstride_normalized_slice<1>, last_slice_t>::value);

using value_type =
typename std::decay<decltype(numpy_iexpr_helper<value>::get(
Expand All @@ -627,11 +615,11 @@ namespace types
shape_t _shape;
dtype *buffer;

static constexpr types::pshape<std::integral_constant<long, 1>>
last_stride(cstride_normalized_slice<1>);
template <long stride>
static constexpr types::pshape<std::integral_constant<long, stride>>
last_stride(cstride_normalized_slice<stride>);
static constexpr types::pshape<std::integral_constant<long, 1>>
last_stride(contiguous_normalized_slice);
static constexpr types::array<long, 1> last_stride(...);

sutils::concat_t<types::array<long, value - 1>,
Expand Down
Loading

0 comments on commit 7158247

Please sign in to comment.