To _roll(To to, From from, long shift, long axis, types::array<long, N> const &shape, utils::int_<M>) { long n = shape[N - M]; long offset = std::accumulate(shape.begin() + N - M + 1, shape.end(), 1L, std::multiplies<long>()); if (axis == N - M) { for (long i = 0; i < shift; ++i) to = _roll(to, from + (n - shift + i) * offset, shift, axis, shape, utils::int_<M - 1>()); for (long i = shift; i < n; ++i) to = _roll(to, from + (i - shift) * offset, shift, axis, shape, utils::int_<M - 1>()); } else for (From end = from + n * offset; from != end; from += offset) to = _roll(to, from, shift, axis, shape, utils::int_<M - 1>()); return to; }
types::ndarray<T,N> roll(types::ndarray<T,N> const& expr, long shift, long axis) { auto&& expr_shape = expr.shape(); while(shift<0) shift+=expr_shape[axis]; types::ndarray<T,N> out(expr_shape, __builtin__::None); _roll(out.fbegin(), expr.fbegin(), shift, axis, expr_shape, utils::int_<N>()); return out; }