types::ndarray< typename __combined<typename types::numpy_expr_to_ndarray<E>::T, typename types::numpy_expr_to_ndarray<F>::T>::type, 1> intersect1d(E const &e, F const &f) { using T = typename __combined< typename types::numpy_expr_to_ndarray<E>::T, typename types::numpy_expr_to_ndarray<F>::T>::type; auto ae = asarray(e); auto af = asarray(f); std::set<T> sae(ae.fbegin(), ae.fend()); std::set<T> found; types::list<T> lout(0); lout.reserve(sae.size()); for (auto iter = af.fbegin(), end = af.fend(); iter != end; ++iter) { auto curr = *iter; if (sae.find(curr) != sae.end() and found.find(curr) == found.end()) { found.insert(curr); lout.push_back(curr); } } std::sort(lout.begin(), lout.end()); return types::ndarray<T, 1>(lout); }
typename std::enable_if< (std::is_scalar<E>::value or types::is_complex<E>::value) and (std::is_scalar<F>::value or types::is_complex<F>::value), decltype(std::declval<E>()*std::declval<F>()) >::type dot(types::list<E> const& e, types::list<F> const& f) { return dot(asarray(e), asarray(f)); }
template<class In> static void nasty_predicate(RawArray<mp_limb_t> result, RawArray<const Vector<In,3>> X) { typename remove_const_reference<decltype(X[0])>::type p1,p2; for (int i=0;i<3;i++) { mpz_set(asarray(p1[i].n),Exact<1>(perturbation<3>(1,nasty_index)[i])); mpz_set(asarray(p2[i].n),Exact<1>(perturbation<3>(2,nasty_index)[i])); } nasty_pow(result,edet(X[0],p1,p2)); }
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; }
static void perturbed_ratio_test() { typedef Vector<Quantized,2> EV; for (const int power : vec(1,2)) for (const int index : range(20)) { nasty_power = power; nasty_index = index; Vector<const exact::Perturbed2,2> X(exact::Perturbed2(index,EV()),exact::Perturbed2(index+1,EV(perturbation<2>(7,index+1)))); Vector<Quantized,1> result; const bool s = perturbed_ratio(asarray(result),nasty_ratio,2+power,asarray(X),power==2); GEODE_ASSERT(result.x==(power==1?X.y.value().x:abs(X.y.value().x))); GEODE_ASSERT(s==perturbed_sign(nasty_denominator,1+power,asarray(X))); } }
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; }
long argmax(E&& expr) { auto arr = asarray(expr); long sz = arr.size(); if(not sz) throw types::ValueError("empty sequence"); return std::max_element(arr.fbegin(), arr.fend()) - arr.fbegin(); }
template<int axis,int d> bool axis_less_degenerate(const Tuple<int,Vector<Quantized,d>> a, const Tuple<int,Vector<Quantized,d>> b) { struct F { static void eval(RawArray<mp_limb_t> result, RawArray<const Vector<Exact<1>,d>> X) { mpz_set(result,X[1][axis]-X[0][axis]); }}; const typename Point<d>::type X[2] = {a,b}; return perturbed_sign(F::eval,1,asarray(X)); }
namespace numpy { template <class T> typename std::enable_if< types::is_dtype<T>::value, types::ndarray<T, types::pshape<std::integral_constant<long, 1>, std::integral_constant<long, 1>, std::integral_constant<long, 1>>>>::type atleast_3d(T t); template <class T> auto atleast_3d(T const &t) -> typename std::enable_if< (!types::is_dtype<T>::value) && (T::value == 1), types::ndarray<typename T::dtype, types::pshape<std::integral_constant<long, 1>, typename std::tuple_element< 0, typename T::shape_t>::type, std::integral_constant<long, 1>>>>::type; template <class T> auto atleast_3d(T const &t) -> typename std::enable_if< (!types::is_dtype<T>::value) && (T::value == 2), types::ndarray< typename T::dtype, types::pshape< typename std::tuple_element<0, typename T::shape_t>::type, typename std::tuple_element<1, typename T::shape_t>::type, std::integral_constant<long, 1>>>>::type; template <class T> auto atleast_3d(T const &t) -> typename std::enable_if<(!types::is_dtype<T>::value) && T::value >= 3, decltype(asarray(t))>::type; DEFINE_FUNCTOR(pythonic::numpy, atleast_3d); }
typename std::enable_if < U::value<V::value, bool>::type array_equiv(U const &u, V const &v) { if (v.flat_size() % u.flat_size() == 0) // requires allocation for u' as it is used multiple times. return _array_equiv(v.begin(), v.end(), asarray(u)); return false; }
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; }
static void nasty_denominator(RawArray<mp_limb_t> result, RawArray<const Vector<Exact<1>,2>> X) { assert(X.size()==2); typename remove_const_reference<decltype(X[0])>::type p1; for (int i=0;i<2;i++) mpz_set(asarray(p1[i].n),Exact<1>(perturbation<2>(1,nasty_index)[i])); const auto d = edet(X[0],p1); mpz_set(result,d); }
namespace ndarray { template <class E, class dtype> auto astype(E &&e, dtype d) -> decltype(asarray(std::forward<E>(e), d)); DECLARE_FUNCTOR(pythonic::numpy::ndarray, astype); }
namespace numpy { template <class E> auto average(E const &expr, types::none_type const &axis = __builtin__::None) -> decltype(sum(expr, axis) / 1.); template <class E> auto average(E const &expr, long axis) -> decltype(sum(expr, axis) / 1.); template <class E, class W> auto average(E const &expr, types::none_type const &axis, W const &weights) -> decltype(average(expr *asarray(weights) / average(asarray(weights)))); PROXY_DECL(pythonic::numpy, average); }
typename std::enable_if< (std::is_scalar<E>::value or types::is_complex<E>::value) and types::is_numexpr_arg<F>::value and types::numpy_expr_to_ndarray<F>::N ==1, decltype(std::declval<E>()*std::declval<typename types::numpy_expr_to_ndarray<F>::T>()) >::type dot(types::list<E> const& e, F const& f) { return dot(asarray(e), f); }
template<int m> static void perturbed_sign_test() { for (const int power : vec(1,2,3)) for (const int index : range(20)) { if (verbose) cout << endl; // Evaluate perturbed sign using our fancy routine nasty_power = power; nasty_index = index; Array<exact::Perturbed<m>> fX(1); fX[0].seed_ = index; const bool fast = perturbed_sign<exact::Perturbed<m>>(nasty_predicate,m*power,fX); GEODE_ASSERT((power&1) || fast); // Evaluate the series out to several terms using brute force Array<int> powers(m+1); // Choose powers of 2 to approximate nested infinitesimals for (int i=0;i<m;i++) powers[i+1] = (power+1)*powers[i]+128; mpz_t yp; mpz_init(yp); const int enough = 5120/(8*sizeof(ExactInt)); Vector<Exact<enough>,m> sX[1]; for (int i=0;i<=m+1;i++) { if (i) { const Vector<Exact<1>,m> y(perturbation<m>(i,index)); for (int j=0;j<m;j++) { auto& x = sX[0][j]; Exact<enough> yp; const int skip = (powers.back()-powers[i-1])/(8*sizeof(mp_limb_t)); mpz_set(asarray(yp.n).slice(skip,yp.limbs),y[j]); // yp = y[j]<<(powers[-1]-powers[i-1]) x += yp; } } // We should be initially zero, and then match the correct sign once nonzero Array<mp_limb_t> result(enough*m*power,uninit); nasty_predicate(result,asconstarray(sX)); const int slow = mpz_sign(result); if (0) { cout << "m "<<m<<", power "<<power<<", index "<<index<<", i "<<i<<", fast "<<2*fast-1<<", slow "<<slow<<endl; cout << " fX = "<<fX[0]<<", sX = "<<sX[0]<<" (x = "<<mpz_str(asarray(sX[0].x.n),true)<<')'<<endl; cout << " sX result = "<<mpz_str(result,true)<<endl; } GEODE_ASSERT(slow==(i<m?0:2*fast-1)); } mpz_clear(yp); } }
typename std::enable_if<types::has_shape<U>::value and types::has_shape<V>::value,bool>::type array_equiv(U const& u, V const&v) { if(u.shape == v.shape) { return array_equal(u,v); } else if(u.size() > v.size()) { return array_equiv(v,u); } else if(v.size()%u.size() ==0) { auto uu = asarray(u); auto vv = asarray(v); for(auto vi = vv.fbegin(), ve = vv.fend(); vi != ve;) for(auto ui = uu.fbegin(), ue = uu.fend(); ui != ue; ++ui, ++vi) if(*ui != *vi) return false; return true; } return false; }
namespace numpy { template <class T0, size_t N0, class T1, size_t N1> types::ndarray<decltype(std::declval<T0>() + std::declval<T1>()), 2> outer(types::ndarray<T0, N0> const &a, types::ndarray<T1, N1> const &b); template <class T0, size_t N0, class E1> auto outer(types::ndarray<T0, N0> const &a, E1 const &b) -> decltype(outer(a, asarray(b))); template <class E0, class T1, size_t N1> auto outer(E0 const &a, types::ndarray<T1, N1> const &b) -> decltype(outer(asarray(a), b)); template <class E0, class E1> auto outer(E0 const &a, E1 const &b) -> decltype(outer(asarray(a), asarray(b))); PROXY_DECL(pythonic::numpy, outer); }
static void nasty_ratio(RawArray<mp_limb_t,2> result, RawArray<const Vector<Exact<1>,2>> X) { assert(result.m==2 && X.size()==2); typename remove_const_reference<decltype(X[0])>::type p1; for (int i=0;i<2;i++) mpz_set(asarray(p1[i].n),Exact<1>(perturbation<2>(1,nasty_index)[i])); const auto d = edet(X[0],p1); if (nasty_power==1) mpz_set(result[0],d*X[1].x); else mpz_set(result[0],d*sqr(X[1].x)); mpz_set(result[1],d); }
types::ndarray<typename types::numpy_expr_to_ndarray<E>::T, 1> ediff1d(E const& expr) { auto arr = asarray(expr); long n = arr.size() -1 ; types::ndarray<typename types::numpy_expr_to_ndarray<E>::T, 1> out(types::make_tuple(n), __builtin__::None); // Compute adjacent difference except for the first element std::adjacent_difference (arr.fbegin() + 1, arr.fend(), out.fbegin()); // First element can be done now (*out.fbegin()) = *(arr.fbegin()+1) - *(arr.fbegin()); return out; }
/* Duplicate a value_t. On duplication we do verification of the value_ts involved. this is to make it possible to pass array to subfunctions and to override specific value_ts that also have arrays attached to them. */ void sial_dupval(value_t *v, value_t *vs) { int isvoid=(v->type.typattr & B_VOID); /* if both have an attached array ... fail */ if(asarray(v) && asarray(vs)) { sial_error("Can't override array"); } /* when we are attaching a new array to the destination value_t we need to add the destination reference count to the source */ if(asarray(v)) { array_t*a=v->arr; /* preserve the array accross the freedata and memmove */ v->arr=0; sial_freedata(v); /* copy the new value_t over it */ memmove(v, vs, sizeof(value_t)); /* and restore the array_t*/ v->arr=a; } else { sial_refarray(vs, 1); sial_freedata(v); memmove(v, vs, sizeof(value_t)); } sial_duptype(&v->type, &vs->type); sial_dupdata(v, vs); /* conserve the void atribute across asignements */ v->type.typattr |= isvoid; }
types::ndarray< long, 1 > digitize(E const& expr, F const& b) { auto bins = asarray(b); bool is_increasing = bins.size() > 1 and *bins.fbegin() < *(bins.fbegin() +1); types::ndarray<long, 1> out(types::make_tuple(long(expr.size())), __builtin__::None); auto out_iter = out.fbegin(); if(is_increasing) { _digitize(expr.begin(), expr.end(), out_iter, bins, operator_::proxy::lt(), utils::int_<types::numpy_expr_to_ndarray<E>::N>()); } else { _digitize(expr.begin(), expr.end(), out_iter, bins, operator_::proxy::gt(), utils::int_<types::numpy_expr_to_ndarray<E>::N>()); } return out; }
namespace numpy { template <class T> types::ndarray<T, 1> diag(types::ndarray<T, 2> const &a, long k = 0); template <class T> types::ndarray<T, 2> diag(types::ndarray<T, 1> const &a, long k = 0); template <class T> auto diag(types::list<T> const &a, long k = 0) -> decltype(diag(asarray(a), k)); NUMPY_EXPR_TO_NDARRAY0_DECL(diag); DECLARE_FUNCTOR(pythonic::numpy, diag); }
namespace numpy { template <class T> typename std::enable_if<types::is_dtype<T>::value, types::ndarray<T, 3>>::type atleast_3d(T t); template <class T> auto atleast_3d(T const &t) -> typename std::enable_if<(not types::is_dtype<T>::value) and (T::value < 3), types::ndarray<typename T::dtype, 3>>::type; template <class T> auto atleast_3d(T const &t) -> typename std::enable_if<(not types::is_dtype<T>::value) and T::value >= 3, decltype(asarray(t))>::type; PROXY_DECL(pythonic::numpy, atleast_3d); }
types::ndarray<typename E::dtype, E::value> diff(E const &expr, long n) { auto arr = asarray(expr); auto shape = expr.shape(); --shape[E::value - 1]; types::ndarray<typename E::dtype, E::value> out(shape, __builtin__::None); auto slice = expr.shape()[E::value - 1]; auto iter = arr.fbegin(); auto out_iter = out.fbegin(); for (long i = 0, sz = expr.flat_size(); i < sz; i += slice) { auto prev = *(iter + i); for (long k = 1; k < slice; ++k, ++out_iter) { auto nprev = *(iter + i + k); *(out_iter) = nprev - prev; prev = nprev; } } if (n == 1) return out; else return diff( out, n - 1); // TODO: inplace modification to avoid n-1 allocations }
typename std::decay<E>::type::dtype item(E &&expr, long i) { if (i < 0) i += expr.flat_size(); return asarray(std::forward<E>(expr)).flat()[i]; }
types::none_type place(types::ndarray<T, N> &expr, M const &mask, F const &values) { return place(expr, asarray(mask), values); }