types::ndarray< typename std::remove_cv< typename std::remove_reference< decltype( std::declval<T>() + std::declval<typename utils::nested_container_value_type<F>::type>()) >::type >::type, 1> append(types::ndarray<T,N> const& nto, F const& data) { typename types::numpy_expr_to_ndarray<F>::type ndata(data); long nsize = nto.size() + ndata.size(); types::ndarray< typename std::remove_cv< typename std::remove_reference< decltype( std::declval<T>() + std::declval<typename utils::nested_container_value_type<F>::type>()) >::type >::type, 1> out(types::make_tuple(nsize), __builtin__::None); size_t i=0; auto out_back = std::copy(nto.fbegin(), nto.fend(), out.fbegin()); std::copy(ndata.fbegin(), ndata.fend(), out_back); return out; }
types::ndarray<T, N> _transpose(types::ndarray<T, N> const &a, long const l[N]) { auto shape = a.shape(); types::array<long, N> shp; for (unsigned long i = 0; i < N; ++i) shp[i] = shape[l[i]]; types::ndarray<T, N> new_array(shp, __builtin__::None); types::array<long, N> new_strides; new_strides[N - 1] = 1; std::transform(new_strides.rbegin(), new_strides.rend() - 1, shp.rbegin(), new_strides.rbegin() + 1, std::multiplies<long>()); types::array<long, N> old_strides; old_strides[N - 1] = 1; std::transform(old_strides.rbegin(), old_strides.rend() - 1, shape.rbegin(), old_strides.rbegin() + 1, std::multiplies<long>()); auto iter = a.buffer, iter_end = a.buffer + a.flat_size(); for (long i = 0; iter != iter_end; ++iter, ++i) { long offset = 0; for (unsigned long s = 0; s < N; s++) offset += ((i / old_strides[l[s]]) % shape[l[s]]) * new_strides[s]; new_array.buffer[offset] = *iter; } return new_array; }
types::none_type put(types::ndarray<T, N> &expr, long int ind, T const &v) { if (ind >= expr.flat_size() || ind < 0) throw types::ValueError("indice out of bound"); *(expr.fbegin() + ind) = v; return __builtin__::None; }
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; }
types::ndarray<T, 1> repeat(types::ndarray<T, N> const &expr, int repeats) { types::ndarray<T, 1> out( types::array<long, 1>{{expr.flat_size() * repeats}}, __builtin__::None); auto out_iter = out.fbegin(); for (auto iter = expr.fbegin(), end = expr.fend(); iter != end; ++iter) for (int i = 0; i < repeats; ++i) *out_iter++ = *iter; return out; }
types::ndarray<decltype(std::declval<T0>() + std::declval<T1>()), 2> outer(types::ndarray<T0, N0> const& a, types::ndarray<T1, N1> const& b) { types::ndarray<decltype(std::declval<T0>() + std::declval<T1>()), 2> out(types::array<long, 2>{{a.flat_size(), b.flat_size()}}, __builtin__::None); auto iter = out.fbegin(); for(auto iter_a = a.fbegin(), end_a = a.fend(); iter_a != end_a; ++iter_a) { auto val_a = *iter_a; iter = std::transform(b.fbegin(), b.fend(), iter, [=](T1 val) { return val_a * val; }); } return out; }
types::none_type putmask(types::ndarray<T, pS> &expr, E const &mask, F const &values) { auto amask = asarray(mask); auto avalues = asarray(values); auto iexpr = expr.fbegin(); auto n = avalues.flat_size(); for (long i = 0; i < expr.flat_size(); ++i) if (*(amask.fbegin() + i)) *(iexpr + i) = *(avalues.fbegin() + i % n); return __builtin__::None; }
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); }
typename std::enable_if<types::is_numexpr_arg<F>::value, types::none_type>::type put(types::ndarray<T, N> &expr, F const &ind, E const &v) { auto vind = asarray(ind); auto vv = asarray(v); for (long i = 0; i < ind.flat_size(); ++i) { auto val = *(vind.fbegin() + i); if (val >= expr.flat_size() || val < 0) throw types::ValueError("indice out of bound"); *(expr.fbegin() + val) = *(vv.fbegin() + i % vv.flat_size()); } return __builtin__::None; }
types::ndarray<T,1> resize(types::ndarray<T,N> const& expr, int new_shape) { types::ndarray<T,1> out(types::array<long, N> {{new_shape}}, __builtin__::None); auto n = expr.size(); if(n < new_shape) { auto iter = std::copy(expr.fbegin(), expr.fend(), out.fbegin()); for(size_t i = 1; i < new_shape / n; ++i) iter = std::copy(out.fbegin(), out.fbegin() + n, iter); std::copy(out.fbegin(), out.fbegin() + new_shape % n, iter); } else std::copy(expr.fbegin(), expr.fbegin() + new_shape, out.fbegin()); return out; }
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::ndarray<T, types::array<long, std::tuple_size<pS>::value>> rot90(types::ndarray<T, pS> const &expr, int k) { auto constexpr N = std::tuple_size<pS>::value; if (k % 4 == 0) return copy(expr); types::array<long, N> shape = sutils::array(expr.shape()); if (k % 4 != 2) std::swap(shape[0], shape[1]); types::ndarray<T, types::array<long, N>> out(shape, __builtin__::None); if (k % 4 == 1) { for (int i = 0; i < shape[1]; ++i) for (int j = 0; j < shape[0]; ++j) out[shape[0] - 1 - j][i] = expr[i][j]; } else if (k % 4 == 2) { for (int i = 0; i < shape[1]; ++i) for (int j = 0; j < shape[0]; ++j) out[shape[0] - 1 - j][shape[1] - 1 - i] = expr[j][i]; } else { for (int i = 0; i < shape[1]; ++i) for (int j = 0; j < shape[0]; ++j) out[j][shape[1] - 1 - i] = expr[i][j]; } return out; }
types::ndarray<long, N> argsort(types::ndarray<T,N> const& a) { size_t last_axis = a.shape[N-1]; size_t n = a.flat_size(); types::ndarray<long, N> indices(a.shape, __builtin__::None); for(long j=0, * iter_indices = indices.buffer, *end_indices = indices.buffer + n; iter_indices != end_indices; iter_indices += last_axis, j+=last_axis) { // fill with the original indices std::iota(iter_indices, iter_indices + last_axis, 0L); // sort the index using the value from a std::sort(iter_indices, iter_indices + last_axis, [&a,j](long i1, long i2) {return *(a.fbegin() + j + i1) < *(a.fbegin() + j + i2);}); } return indices; }
types::ndarray<T, 1> flatten(types::ndarray<T,N> const& a) { long n = a.size(); T *buffer = new T[n]; std::copy(a.buffer, a.buffer + n, buffer); long shape[1] = {n}; return types::ndarray<T, 1>(buffer, shape); }
typename types::numpy_expr_to_ndarray<F>::type take(types::ndarray<T,N> const & expr, F const& indices) { typename types::numpy_expr_to_ndarray<F>::type out = asarray(indices); auto expr_iter = expr.fbegin(); for(auto out_iter = out.fbegin(), out_end = out.fend(); out_iter != out_end; ++out_iter) *out_iter = *(expr_iter + *out_iter); return out; }
types::list<types::ndarray<T, N>> split(types::ndarray<T, N> const &a, long nb_split) { if (a.flat_size() % nb_split != 0) throw types::ValueError( "array split does not result in an equal division"); return array_split(a, nb_split); }
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; }
decltype(std::declval<T>() + 1.) median(types::ndarray<T, N> const &arr) { size_t n = arr.flat_size(); T *tmp = new T[n]; std::copy(arr.buffer, arr.buffer + n, tmp); std::sort(tmp, tmp + n); auto out = (tmp[n / 2] + tmp[(n - 1) / 2]) / double(2); delete[] tmp; return out; }
types::none_type place(types::ndarray<T, N> &expr, types::ndarray<Tp, Np> const &mask, F const &values) { auto first = expr.fend(); auto viter = values.begin(), vend = values.end(); auto miter = mask.fbegin(); for (auto iter = expr.fbegin(), end = expr.fend(); iter != end; ++iter, ++miter) { if (*miter) { if (first == expr.fend()) first = iter; if (viter != vend) { *iter = *viter; ++viter; } else *iter = *first; } } return __builtin__::None; }
types::ndarray<T,2> diag(types::ndarray<T,1> const &a, long k=0) { long n = a.size() + std::abs(k); types::ndarray<T,2> out(types::make_tuple(n,n), 0); if(k>=0) for(long i=0,j =k ; i< n and j<n ;++i,++j) out[i][j] = a[i]; else for(long i=-k,j =0 ; i< n and j<n ;++i,++j) out[i][j] = a[j]; return out; }
types::ndarray<T, N> roll(types::ndarray<T, N> const &expr, long shift) { while (shift < 0) shift += expr.flat_size(); shift %= expr.flat_size(); types::ndarray<T, N> out(expr.shape(), __builtin__::None); std::copy(expr.fbegin(), expr.fend() - shift, std::copy(expr.fend() - shift, expr.fend(), out.fbegin())); return out; }
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; } }
types::ndarray<T,2> tril(types::ndarray<T,2> const& expr, int k = 0) { auto&& expr_shape = expr.shape(); types::ndarray<T,2> out(expr_shape, __builtin__::None); for(int i=0; i<expr_shape[0]; ++i) { auto out_i = out[i]; auto expr_i = expr[i]; for(long j=0 ; j<expr_shape[1]; ++j) if( j - i <= k) out_i[j] = expr_i[j]; else out_i[j] = 0; } return out; }
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; }
T item(types::ndarray<T, N> const& expr, long i) { if(i<0) i += expr.size(); return *(expr.fbegin() + i); }
types::ndarray<T, 1> flatten(types::ndarray<T, N> const &a) { return {a.mem, types::array<long, 1>{{a.flat_size()}}}; }
types::str tostring(types::ndarray<T, N> const &expr) { return types::str(reinterpret_cast<const char *>(expr.buffer), expr.flat_size() * sizeof(T)); }
types::none_type fill(types::ndarray<T, N> &e, F f) { std::fill(e.fbegin(), e.fend(), f); return __builtin__::None; }