| Server IP : 217.160.0.135 / Your IP : 216.73.217.117 Web Server : Apache System : Linux www 6.18.52-i1-ampere #1203 SMP Mon Sep 14 18:29:59 CEST 2026 aarch64 User : sws1074145052 ( 1074145052) PHP Version : 8.3.32 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /lib/python3/dist-packages/pythran/pythonic/include/types/ |
Upload File : |
#ifndef PYTHONIC_INCLUDE_TYPES_NUMPY_TEXPR_HPP
#define PYTHONIC_INCLUDE_TYPES_NUMPY_TEXPR_HPP
#include "pythonic/include/types/ndarray.hpp"
#include "pythonic/include/builtins/None.hpp"
#include "pythonic/include/numpy/transpose.hpp"
PYTHONIC_NS_BEGIN
namespace types
{
template <class Arg, class... S>
struct numpy_gexpr;
/* expression template for Transposed matrix */
template <class Arg>
struct numpy_texpr;
// wrapper around numpy expression for 2D transposed matrix using gexpr
// representation
// >>> b = a.transpose
// >>> b[i] == a[:,i]
// True
//
// for N = 2
template <class E>
struct numpy_texpr_2 {
static_assert(E::value == 2, "texpr only implemented for matrices");
static const bool is_vectorizable = false;
static const bool is_strided = true;
using Arg = E;
using iterator = nditerator<numpy_texpr_2<Arg>>;
using const_iterator = const_nditerator<numpy_texpr_2<Arg>>;
static constexpr size_t value = Arg::value;
using value_type = numpy_gexpr<Arg, contiguous_normalized_slice, long>;
using dtype = typename E::dtype;
Arg arg;
using shape_t = sutils::transpose_t<typename E::shape_t>;
template <size_t I>
auto shape() const -> decltype(arg.template shape < I == 0 ? 1 : 0 > ())
{
return arg.template shape < I == 0 ? 1 : 0 > ();
}
numpy_texpr_2();
numpy_texpr_2(numpy_texpr_2 const &) = default;
numpy_texpr_2(numpy_texpr_2 &&) = default;
numpy_texpr_2 &operator=(numpy_texpr_2 const &) = default;
numpy_texpr_2(Arg const &arg);
const_iterator begin() const;
const_iterator end() const;
iterator begin();
iterator end();
long size() const
{
return this->template shape<0>();
}
auto fast(long i) const
-> decltype(this->arg(fast_contiguous_slice(pythonic::builtins::None,
pythonic::builtins::None),
i));
auto fast(long i)
-> decltype(this->arg(fast_contiguous_slice(pythonic::builtins::None,
pythonic::builtins::None),
i));
auto fast(array<long, value> const &indices)
-> decltype(arg.fast(array<long, 2>{{indices[1], indices[0]}}))
{
return arg.fast(array<long, 2>{{indices[1], indices[0]}});
}
auto fast(array<long, value> const &indices) const
-> decltype(arg.fast(array<long, 2>{{indices[1], indices[0]}}))
{
return arg.fast(array<long, 2>{{indices[1], indices[0]}});
}
auto load(long i, long j) const -> decltype(arg.load(j, i))
{
return arg.load(j, i);
}
template <class Elt>
void store(Elt elt, long i, long j)
{
arg.store(elt, j, i);
}
template <class Op, class Elt>
void update(Elt elt, long i, long j) const
{
arg.template update<Op>(elt, j, i);
}
#ifdef USE_XSIMD
using simd_iterator = const_simd_nditerator<numpy_texpr_2>;
using simd_iterator_nobroadcast = simd_iterator;
template <class vectorizer>
simd_iterator vbegin(vectorizer) const;
template <class vectorizer>
simd_iterator vend(vectorizer) const;
#endif
/* element filtering */
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, ndarray<long, pshape<long>>>>::type
fast(F const &filter) const;
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<dtype, pshape<long>>,
ndarray<long, pshape<long>>>>::type
fast(F const &filter) const;
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, ndarray<long, pshape<long>>>>::type
fast(F const &filter) const;
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, ndarray<long, pshape<long>>>>::type
operator[](F const &filter) const;
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<dtype, pshape<long>>,
ndarray<long, pshape<long>>>>::type
operator[](F const &filter) const;
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, ndarray<long, pshape<long>>>>::type
operator[](F const &filter) const;
auto operator[](long i) const -> decltype(this->fast(i));
auto operator[](long i) -> decltype(this->fast(i));
template <class T>
auto operator[](array<T, value> const &indices)
-> decltype(arg[array<T, 2>{{indices[1], indices[0]}}])
{
return arg[array<T, 2>{{indices[1], indices[0]}}];
}
template <class T>
auto operator[](array<T, value> const &indices) const
-> decltype(arg[array<T, 2>{{indices[1], indices[0]}}])
{
return arg[array<T, 2>{{indices[1], indices[0]}}];
}
template <class T0, class T1>
auto operator[](std::tuple<T0, T1> const &indices) -> decltype(
arg[std::tuple<T1, T0>{std::get<1>(indices), std::get<0>(indices)}])
{
return arg[std::tuple<T1, T0>{std::get<1>(indices),
std::get<0>(indices)}];
}
template <class T0, class T1>
auto operator[](std::tuple<T0, T1> const &indices) const -> decltype(
arg[std::tuple<T1, T0>{std::get<1>(indices), std::get<0>(indices)}])
{
return arg[std::tuple<T1, T0>{std::get<1>(indices),
std::get<0>(indices)}];
}
template <class S>
auto operator[](S const &s0) const -> numpy_texpr<
decltype(this->arg(fast_contiguous_slice(pythonic::builtins::None,
pythonic::builtins::None),
(s0.step, s0)))>;
template <class S>
auto operator[](S const &s0) -> numpy_texpr<
decltype(this->arg(fast_contiguous_slice(pythonic::builtins::None,
pythonic::builtins::None),
(s0.step, s0)))>;
template <class S, size_t... I>
auto _reverse_index(S const &indices, utils::index_sequence<I...>) const
-> decltype(
numpy::functor::transpose{}(this->arg(std::get<I>(indices)...)))
{
return numpy::functor::transpose{}(arg(std::get<I>(indices)...));
}
ndarray<dtype, typename E::shape_t> copy() const
{
return *this;
}
template <class S0, class... S>
auto
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;
template <class S0, class... S>
auto operator()(S0 const &s0, S const &... s) const ->
typename std::enable_if<is_numexpr_arg<S0>::value,
decltype(this->copy()(s0, s...))>::type;
explicit operator bool() const;
long flat_size() const;
intptr_t id() const;
template <class Expr>
numpy_texpr_2 &operator=(Expr const &expr);
template <class Expr>
numpy_texpr_2 &operator=(numpy_texpr<Expr> const &expr);
template <class Op, class Expr>
numpy_texpr_2 &update_(Expr const &expr);
template <class Expr>
numpy_texpr_2 &operator+=(Expr const &expr);
template <class Expr>
numpy_texpr_2 &operator-=(Expr const &expr);
template <class Expr>
numpy_texpr_2 &operator*=(Expr const &expr);
template <class Expr>
numpy_texpr_2 &operator/=(Expr const &expr);
template <class Expr>
numpy_texpr_2 &operator&=(Expr const &expr);
template <class Expr>
numpy_texpr_2 &operator|=(Expr const &expr);
template <class Expr>
numpy_texpr_2 &operator^=(Expr const &expr);
template <class NewShape>
ndarray<dtype, NewShape> reshape(NewShape const &shape) const
{
return copy().reshape(shape);
}
};
// only implemented for N = 2
template <class T, class S0, class S1>
struct numpy_texpr<ndarray<T, pshape<S0, S1>>>
: numpy_texpr_2<ndarray<T, pshape<S0, S1>>> {
numpy_texpr() = default;
numpy_texpr(numpy_texpr const &) = default;
numpy_texpr(numpy_texpr &&) = default;
numpy_texpr(ndarray<T, pshape<S0, S1>> const &arg);
numpy_texpr &operator=(numpy_texpr const &) = default;
using numpy_texpr_2<ndarray<T, pshape<S0, S1>>>::operator=;
};
template <class T>
struct numpy_texpr<ndarray<T, array<long, 2>>>
: numpy_texpr_2<ndarray<T, array<long, 2>>> {
numpy_texpr() = default;
numpy_texpr(numpy_texpr const &) = default;
numpy_texpr(numpy_texpr &&) = default;
numpy_texpr(ndarray<T, array<long, 2>> const &arg);
numpy_texpr &operator=(numpy_texpr const &) = default;
using numpy_texpr_2<ndarray<T, array<long, 2>>>::operator=;
};
template <class E, class... S>
struct numpy_texpr<numpy_gexpr<E, S...>>
: numpy_texpr_2<numpy_gexpr<E, S...>> {
numpy_texpr() = default;
numpy_texpr(numpy_texpr const &) = default;
numpy_texpr(numpy_texpr &&) = default;
numpy_texpr(numpy_gexpr<E, S...> const &arg);
template <class F>
numpy_texpr(numpy_texpr<F> const &other)
: numpy_texpr(numpy_gexpr<E, S...>(other.arg))
{
}
numpy_texpr &operator=(numpy_texpr const &) = default;
using numpy_texpr_2<numpy_gexpr<E, S...>>::operator=;
};
template <class E>
struct numpy_texpr<broadcasted<E>> {
static constexpr auto value = broadcasted<E>::value;
using value_type = broadcast<typename E::dtype, typename E::dtype>;
using dtype = typename broadcasted<E>::dtype;
using shape_t = types::array<long, value>;
using iterator = nditerator<numpy_texpr<broadcasted<E>>>;
using const_iterator = const_nditerator<numpy_texpr<broadcasted<E>>>;
static constexpr bool is_vectorizable = false;
static constexpr bool is_strided = true;
broadcasted<E> arg;
numpy_texpr() = default;
numpy_texpr(numpy_texpr const &) = default;
numpy_texpr(numpy_texpr &&) = default;
numpy_texpr(broadcasted<E> const &arg) : arg(arg)
{
}
value_type fast(long i) const
{
return arg.ref.fast(i);
}
template <size_t I>
long shape() const
{
return arg.template shape < I == 0 ? 1 : 0 > ();
}
auto load(long i, long j) const -> decltype(arg.ref.load(i))
{
return arg.ref.load(i);
}
template <class Elt>
void store(Elt elt, long i, long j)
{
arg.ref.store(elt, i);
}
const_iterator begin() const
{
return {*this, 0};
}
const_iterator end() const
{
return {*this, shape<0>()};
}
iterator begin()
{
return {*this, 0};
}
iterator end()
{
return {*this, shape<0>()};
}
};
}
template <class Arg>
struct assignable_noescape<types::numpy_texpr<Arg>> {
using type = types::numpy_texpr<Arg>;
};
template <class Arg>
struct assignable<types::numpy_texpr<Arg>> {
using type = types::numpy_texpr<typename assignable<Arg>::type>;
};
template <class Arg>
struct returnable<types::numpy_texpr<Arg>> {
using type = types::numpy_texpr<typename returnable<Arg>::type>;
};
template <class Arg>
struct lazy<types::numpy_texpr<Arg>> {
using type = types::numpy_texpr<typename lazy<Arg>::type>;
};
PYTHONIC_NS_END
/* type inference stuff {*/
#include "pythonic/include/types/combined.hpp"
template <class E>
struct __combined<pythonic::types::numpy_texpr<E>,
pythonic::types::numpy_texpr<E>> {
using type = pythonic::types::numpy_texpr<E>;
};
template <class E0, class E1>
struct __combined<pythonic::types::numpy_texpr<E0>,
pythonic::types::numpy_texpr<E1>> {
using type = pythonic::types::numpy_texpr<typename __combined<E0, E1>::type>;
};
template <class E, class K>
struct __combined<pythonic::types::numpy_texpr<E>, K> {
using type = pythonic::types::numpy_texpr<E>;
};
template <class E0, class E1, class... S>
struct __combined<pythonic::types::numpy_texpr<E0>,
pythonic::types::numpy_gexpr<E1, S...>> {
using type = pythonic::types::numpy_texpr<E0>;
};
template <class E, class O>
struct __combined<pythonic::types::numpy_texpr<E>, pythonic::types::none<O>> {
using type = pythonic::types::none<
typename __combined<pythonic::types::numpy_texpr<E>, O>::type>;
};
template <class E, class O>
struct __combined<pythonic::types::none<O>, pythonic::types::numpy_texpr<E>> {
using type = pythonic::types::none<
typename __combined<O, pythonic::types::numpy_texpr<E>>::type>;
};
template <class E>
struct __combined<pythonic::types::numpy_texpr<E>, pythonic::types::none_type> {
using type = pythonic::types::none<pythonic::types::numpy_texpr<E>>;
};
template <class E>
struct __combined<pythonic::types::none_type, pythonic::types::numpy_texpr<E>> {
using type = pythonic::types::none<pythonic::types::numpy_texpr<E>>;
};
/*}*/
#endif