← Back
Editing: numpy_texpr.hpp
#ifndef PYTHONIC_TYPES_NUMPY_TEXPR_HPP #define PYTHONIC_TYPES_NUMPY_TEXPR_HPP #include "pythonic/include/types/numpy_texpr.hpp" #include "pythonic/types/ndarray.hpp" #include "pythonic/numpy/array.hpp" #include "pythonic/numpy/transpose.hpp" #include "pythonic/operator_/iadd.hpp" #include "pythonic/operator_/iand.hpp" #include "pythonic/operator_/idiv.hpp" #include "pythonic/operator_/imul.hpp" #include "pythonic/operator_/ior.hpp" #include "pythonic/operator_/ixor.hpp" #include "pythonic/operator_/isub.hpp" PYTHONIC_NS_BEGIN namespace types { template <class E> numpy_texpr_2<E>::numpy_texpr_2() { } template <class E> numpy_texpr_2<E>::numpy_texpr_2(Arg const &arg) : arg(arg) { } template <class E> typename numpy_texpr_2<E>::const_iterator numpy_texpr_2<E>::begin() const { return {*this, 0}; } template <class E> typename numpy_texpr_2<E>::const_iterator numpy_texpr_2<E>::end() const { return {*this, size()}; } template <class E> typename numpy_texpr_2<E>::iterator numpy_texpr_2<E>::begin() { return {*this, 0}; } template <class E> typename numpy_texpr_2<E>::iterator numpy_texpr_2<E>::end() { return {*this, size()}; } template <class E> auto numpy_texpr_2<E>::fast(long i) const -> decltype(this->arg(fast_contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), i)) { return arg( contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), i); } template <class E> auto numpy_texpr_2<E>::fast(long i) -> decltype(this->arg(fast_contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), i)) { return arg( contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), i); } #ifdef USE_XSIMD template <class E> template <class vectorizer> typename numpy_texpr_2<E>::simd_iterator numpy_texpr_2<E>::vbegin(vectorizer) const { return {*this}; } template <class E> template <class vectorizer> typename numpy_texpr_2<E>::simd_iterator numpy_texpr_2<E>::vend(vectorizer) const { return {*this}; // ! vectorizable anyway } #endif template <class E> auto numpy_texpr_2<E>::operator[](long i) const -> decltype(this->fast(i)) { if (i < 0) i += size(); return fast(i); } template <class E> auto numpy_texpr_2<E>::operator[](long i) -> decltype(this->fast(i)) { if (i < 0) i += size(); return fast(i); } template <class E> template <class S> auto numpy_texpr_2<E>:: operator[](S const &s0) const -> numpy_texpr<decltype(this->arg( fast_contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), (s0.step, s0)))> { return {arg(fast_contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), s0)}; } template <class E> template <class S> auto numpy_texpr_2<E>:: operator[](S const &s0) -> numpy_texpr<decltype(this->arg( fast_contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), (s0.step, s0)))> { return {arg(fast_contiguous_slice(pythonic::builtins::None, pythonic::builtins::None), s0)}; } /* element filtering */ template <class E> template <class F> // indexing through an array of boolean -- a mask typename std::enable_if< is_numexpr_arg<F>::value && std::is_same<bool, typename F::dtype>::value && F::value == 1 && !is_pod_array<F>::value, numpy_vexpr<numpy_texpr_2<E>, ndarray<long, pshape<long>>>>::type numpy_texpr_2<E>::fast(F const &filter) const { long sz = filter.template shape<0>(); long *raw = (long *)malloc(sz * sizeof(long)); long n = 0; for (long i = 0; i < sz; ++i) if (filter.fast(i)) raw[n++] = i; // realloc(raw, n * sizeof(long)); return this->fast(ndarray<long, pshape<long>>(raw, pshape<long>(n), types::ownership::owned)); } template <class E> template <class F> // indexing through an array of boolean -- a mask typename std::enable_if< is_numexpr_arg<F>::value && std::is_same<bool, typename F::dtype>::value && F::value != 1 && !is_pod_array<F>::value, numpy_vexpr<ndarray<typename numpy_texpr_2<E>::dtype, pshape<long>>, ndarray<long, pshape<long>>>>::type numpy_texpr_2<E>::fast(F const &filter) const { return numpy::functor::array{}(*this) .flat()[ndarray<typename F::dtype, typename F::shape_t>(filter).flat()]; } template <class E> template <class F> // indexing through an array of boolean -- a mask typename std::enable_if< is_numexpr_arg<F>::value && std::is_same<bool, typename F::dtype>::value && F::value == 1 && !is_pod_array<F>::value, numpy_vexpr<numpy_texpr_2<E>, ndarray<long, pshape<long>>>>::type numpy_texpr_2<E>:: operator[](F const &filter) const { return fast(filter); } template <class E> template <class F> // indexing through an array of boolean -- a mask typename std::enable_if< is_numexpr_arg<F>::value && std::is_same<bool, typename F::dtype>::value && F::value != 1 && !is_pod_array<F>::value, numpy_vexpr<ndarray<typename numpy_texpr_2<E>::dtype, pshape<long>>, ndarray<long, pshape<long>>>>::type numpy_texpr_2<E>:: operator[](F const &filter) const { return fast(filter); } template <class E> template <class F> // indexing through an array of indices -- a view typename std::enable_if< is_numexpr_arg<F>::value && !std::is_same<bool, typename F::dtype>::value && !is_pod_array<F>::value, numpy_vexpr<numpy_texpr_2<E>, ndarray<long, pshape<long>>>>::type numpy_texpr_2<E>:: operator[](F const &filter) const { static_assert(F::value == 1, "advanced indexing only supporint with 1D index"); return {*this, filter}; } template <class E> template <class F> // indexing through an array of indices -- a view typename std::enable_if< is_numexpr_arg<F>::value && !std::is_same<bool, typename F::dtype>::value && !is_pod_array<F>::value, numpy_vexpr<numpy_texpr_2<E>, ndarray<long, pshape<long>>>>::type numpy_texpr_2<E>::fast(F const &filter) const { static_assert(F::value == 1, "advanced indexing only supported with 1D index"); return {*this, filter}; } template <class E> template <class S0, class... S> auto numpy_texpr_2<E>::operator()(S0 const &s0, S const &... s) const -> typename std::enable_if< !is_numexpr_arg<S0>::value, decltype(this->_reverse_index( std::tuple<S0 const &, S const &...>{s0, s...}, utils::make_reversed_index_sequence<1 + sizeof...(S)>()))>::type { return _reverse_index( std::tuple<S0 const &, S const &...>{s0, s...}, utils::make_reversed_index_sequence<1 + sizeof...(S)>()); } template <class E> template <class S0, class... S> auto numpy_texpr_2<E>::operator()(S0 const &s0, S const &... s) const -> typename std::enable_if<is_numexpr_arg<S0>::value, decltype(this->copy()(s0, s...))>::type { return copy()(s0, s...); } template <class E> numpy_texpr_2<E>::operator bool() const { return (bool)arg; } template <class E> long numpy_texpr_2<E>::flat_size() const { return arg.flat_size(); } template <class E> intptr_t numpy_texpr_2<E>::id() const { return arg.id(); } template <class Arg> template <class Expr> numpy_texpr_2<Arg> &numpy_texpr_2<Arg>::operator=(Expr const &expr) { return utils::broadcast_copy < numpy_texpr_2 &, Expr, value, value - utils::dim_of<Expr>::value, is_vectorizable && std::is_same<dtype, typename dtype_of<Expr>::type>::value && types::is_vectorizable<Expr>::value > (*this, expr); } template <class Arg> template <class Expr> numpy_texpr_2<Arg> &numpy_texpr_2<Arg>:: operator=(numpy_texpr<Expr> const &expr) { arg = expr.arg; return *this; } template <class Arg> template <class Op, class Expr> numpy_texpr_2<Arg> &numpy_texpr_2<Arg>::update_(Expr const &expr) { using BExpr = typename std::conditional<std::is_scalar<Expr>::value, broadcast<Expr, dtype>, Expr const &>::type; BExpr bexpr = expr; utils::broadcast_update< Op, numpy_texpr_2 &, BExpr, value, value - (std::is_scalar<Expr>::value + utils::dim_of<Expr>::value), is_vectorizable && types::is_vectorizable<typename std::remove_cv< typename std::remove_reference<BExpr>::type>::type>::value && std::is_same<dtype, typename dtype_of<typename std::decay< BExpr>::type>::type>::value>(*this, bexpr); return *this; } template <class Arg> template <class Expr> numpy_texpr_2<Arg> &numpy_texpr_2<Arg>::operator+=(Expr const &expr) { return update_<pythonic::operator_::functor::iadd>(expr); } template <class Arg> template <class E> numpy_texpr_2<Arg> &numpy_texpr_2<Arg>::operator-=(E const &expr) { return update_<pythonic::operator_::functor::isub>(expr); } template <class Arg> template <class E> numpy_texpr_2<Arg> &numpy_texpr_2<Arg>::operator*=(E const &expr) { return update_<pythonic::operator_::functor::imul>(expr); } template <class Arg> template <class E> numpy_texpr_2<Arg> &numpy_texpr_2<Arg>::operator/=(E const &expr) { return update_<pythonic::operator_::functor::idiv>(expr); } template <class Arg> template <class E> numpy_texpr_2<Arg> &numpy_texpr_2<Arg>::operator&=(E const &expr) { return update_<pythonic::operator_::functor::iand>(expr); } template <class Arg> template <class E> numpy_texpr_2<Arg> &numpy_texpr_2<Arg>::operator|=(E const &expr) { return update_<pythonic::operator_::functor::ior>(expr); } template <class Arg> template <class E> numpy_texpr_2<Arg> &numpy_texpr_2<Arg>::operator^=(E const &expr) { return update_<pythonic::operator_::functor::ixor>(expr); } // only implemented for N = 2 template <class T, class S0, class S1> numpy_texpr<ndarray<T, pshape<S0, S1>>>::numpy_texpr( ndarray<T, pshape<S0, S1>> const &arg) : numpy_texpr_2<ndarray<T, pshape<S0, S1>>>{arg} { } template <class T> numpy_texpr<ndarray<T, array<long, 2>>>::numpy_texpr( ndarray<T, array<long, 2>> const &arg) : numpy_texpr_2<ndarray<T, array<long, 2>>>{arg} { } template <class E, class... S> numpy_texpr<numpy_gexpr<E, S...>>::numpy_texpr( numpy_gexpr<E, S...> const &arg) : numpy_texpr_2<numpy_gexpr<E, S...>>{arg} { } } PYTHONIC_NS_END #endif
Save File
Cancel