types::ndarray<T,N - 1> prod(types::ndarray<T,N> const& array, long axis) { if(axis<0 || axis >=long(N)) throw types::ValueError("axis out of bounds"); auto shape = array.shape; if(axis==0) { types::array<long, N> shp; shp[0] = 1; std::copy(shape.begin() + 1, shape.end(), shp.begin() + 1); types::ndarray<T,N> out(shp, 1); return std::accumulate(array.begin(), array.end(), *out.begin(), proxy::multiply()); } else { types::array<long, N-1> shp; std::copy(shape.begin(), shape.end() - 1, shp.begin()); types::ndarray<T,N-1> prody(shp, __builtin__::None); std::transform(array.begin(), array.end(), prody.begin(), [=](types::ndarray<T,N-1> const& other) {return prod(other, axis-1);}); return prody; } }
types::ndarray<T,N - 1 > max(types::ndarray<T,N> const& array, long axis) { if(axis<0 || axis >=long(N)) throw types::ValueError("axis out of bounds"); auto shape = array.shape; if(axis==0) { types::array<long, N> shp; shp[0] = 1; std::copy(shape.begin() + 1, shape.end(), shp.begin() + 1); types::ndarray<T,N> out(shp, std::numeric_limits<T>::lowest()); return std::accumulate(array.begin(), array.end(), *out.begin(), numpy::proxy::maximum()); } else { types::array<long, N-1> shp; std::copy(shape.begin(), shape.end() - 1, shp.begin()); types::ndarray<T,N-1> maxy(shp, __builtin__::None); std::transform(array.begin(), array.end(), maxy.begin(), [=](types::ndarray<T,N-1> const& other) {return max(other, axis-1);}); return maxy; } }
typename std::enable_if<types::is_iterable<I>::value, types::list<types::ndarray<T, N>>>::type array_split(types::ndarray<T, N> const &a, I const &split_mask) { long sz = std::distance(a.begin(), a.end()); types::list<types::ndarray<T, N>> out(1 + split_mask.flat_size()); long index = 0; auto inserter = out.begin(); for (auto next_index : split_mask) { *inserter++ = a[types::contiguous_slice(index, next_index)]; index = next_index; } *inserter = a[types::contiguous_slice(index, sz)]; return out; }
types::ndarray<typename types::numpy_type<dtype>::type,N> cumprod(types::ndarray<T,N> const& expr, long axis, dtype d = dtype()) { if(axis<0 || axis >=long(N)) throw types::ValueError("axis out of bounds"); auto shape = expr.shape; types::ndarray<typename types::numpy_type<dtype>::type,N> cumprody(shape, __builtin__::None); if(axis==0) { std::copy(expr.buffer, expr.buffer + shape[N-1], cumprody.buffer); std::transform(cumprody.begin(), cumprody.end()-1, expr.begin() + 1, cumprody.begin() + 1, std::multiplies<types::ndarray<T,N-1>>()); } else { std::transform(expr.begin(), expr.end(), cumprody.begin(), [=](types::ndarray<T,N-1> const& e) { return cumprod(e, axis-1, d); }); } return cumprody; }
types::list<types::ndarray<T, N>> array_split(types::ndarray<T, N> const &a, long nb_split) { long sz = std::distance(a.begin(), a.end()); long n = (sz + nb_split - 1) / nb_split; long end = n * nb_split; long nb_full_split = nb_split; if (end != sz) nb_full_split -= (end - sz); types::list<types::ndarray<T, N>> out(nb_split); long index = 0; for (long i = 0; i < nb_full_split; ++i, index += n) out[i] = a[types::contiguous_slice(index, index + n)]; for (long i = nb_full_split; i < nb_split; ++i, index += (n - 1)) out[i] = a[types::contiguous_slice(index, index + n - 1)]; return out; }