types::ndarray<T, M> reshape(types::ndarray<T, N> const &expr, types::array<long, M> const &new_shape) { auto where = std::find(new_shape.begin(), new_shape.end(), -1); if (where != new_shape.end()) { auto auto_shape = new_shape; auto_shape[where - new_shape.begin()] = expr.flat_size() / std::accumulate(new_shape.begin(), new_shape.end(), -1L, std::multiplies<long>()); return expr.reshape(auto_shape); } else return expr.reshape(new_shape); }
types::ndarray<typename types::numpy_type<dtype>::type, N> zeros(types::array<long, N> const &shape, dtype d) { using T = typename types::numpy_type<dtype>::type; // use calloc even if we have a non integer type. This looks ok on modern // architecture, although not really standard T *buffer = (T *)calloc(std::accumulate(shape.begin(), shape.end(), 1L, std::multiplies<long>()), sizeof(T)); return types::ndarray<T, N>{buffer, shape.data()}; }
types::ndarray<T,M> resize(types::ndarray<T,N> const& expr, types::array<long, M> const& new_shape) { auto where = std::find(new_shape.begin(), new_shape.end(), -1); if(where != new_shape.end()) { types::array<long, M> auto_shape(new_shape); auto_shape[where - new_shape.begin()] = expr.size() / std::accumulate(new_shape.begin(), new_shape.end(), -1L, std::multiplies<long>()); return resize(expr, auto_shape); } types::ndarray<T,M> out(new_shape, __builtin__::None); auto nshape = out.size(); auto n = expr.size(); if(n < nshape) { auto iter = std::copy(expr.fbegin(), expr.fend(), out.fbegin()); for(size_t i = 1; i < nshape / n; ++i) { iter = std::copy(out.fbegin(), out.fbegin() + n, iter); } std::copy(out.fbegin(), out.fbegin() + nshape % n, iter); } else std::copy(expr.fbegin(), expr.fbegin() + nshape, out.fbegin()); return out; }
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<dtype, N+1> indices(types::array<long, N> const& shape, dtype d = dtype()) { types::array<long, N+1> oshape; oshape[0] = N ; std::copy(shape.begin(), shape.end(), oshape.begin() + 1); types::ndarray<dtype, N+1> out(oshape, __builtin__::None); dtype* iters[N]; for(size_t n=0; n<N; ++n) iters[n]=out[n].buffer; size_t lens[N]; lens[0] = out.size() / shape[0]; for(size_t n=1; n<N; ++n) lens[n] = lens[n-1] / shape[n]; for(long i=0, n=out.size()/N; i<n; ++i) { long mult = 1; for(long n=N-1; n>0; n--) { *(iters[n]++) = (i/mult)%shape[n]; mult *= shape[n]; } *(iters[0]++) = i/mult; } return out; }
_ndindex<N>::_ndindex(types::array<long, N> const &shape) : ndindex_iterator<N>(shape, 0), shape(shape), end_iter(shape, std::accumulate(shape.begin(), shape.end(), 1L, std::multiplies<long>())) { }