xtensor-stack / xtensor

C++ tensors with broadcasting and lazy computing
BSD 3-Clause "New" or "Revised" License
3.34k stars 399 forks source link

`any()` and `all()` should support `axis` and `keep_dims` #1555

Open DavisVaughan opened 5 years ago

DavisVaughan commented 5 years ago

To match numpy, xt::any() and xt::all() should have an axis argument allowing for multiple axes (it should probably be called axes). Maybe it can be implemented with the reduction framework that already exists?

https://docs.scipy.org/doc/numpy/reference/generated/numpy.any.html https://docs.scipy.org/doc/numpy/reference/generated/numpy.all.html

The only trouble is making sure you can early exit with things like xt::any(). If you see any true values along the way, exit immediately for performance.

It actually doesn't look like numpy has optimized for the case I mention above, unless _wrapreduction() does something clever that I'm not aware of https://github.com/numpy/numpy/blob/v1.16.1/numpy/core/fromnumeric.py#L2164

wolfv commented 5 years ago

we should move any and all to the reducer framework.

DavisVaughan commented 5 years ago

i agree!

wolfv commented 5 years ago

It's actually a "simple" fix - just need to pass a correct reducing lambda or struct to the make reducer macro.

btw. where was your issue with the cum* functions? I was looking for that :)

wolfv commented 5 years ago

ah yeah, except for the fast exit ...

DavisVaughan commented 5 years ago

i believe its this one https://github.com/QuantStack/xtensor/issues/1334

linked them all from https://github.com/DavisVaughan/rray/issues/30

Ivorforce commented 1 month ago

I was able to get axis support for any / all pretty easily using the reduction macros:

using namespace xt;
XTENSOR_REDUCER_FUNCTION(va_any, xt::detail::logical_or, bool, true)
XTENSOR_REDUCER_FUNCTION(va_all, xt::detail::logical_and, bool, false)

To make use of the optimized implementation with no axes provided, I currently use:

#define ReducerAnyAll(Name, fun_name_axes, fun_name_no_axes)\
    template <typename GivenAxes, typename A>\
    auto operator()(GivenAxes&& axes, A&& a) const {\
        return fun_name_axes(std::forward<A>(a), std::forward<GivenAxes>(axes), std::tuple<xt::evaluation_strategy::lazy_type>());\
    }\
\
    template <typename A>\
    auto operator()(A&& a) const {\
        return xt::xtensor_fixed<bool, xshape<>>(fun_name_no_axes(std::forward<A>(a)));\
    }

struct All { ReducerAnyAll(All, va_all, xt::all) };
struct Any { ReducerAnyAll(Any, va_any, xt::any) };

It would be nice if the implementations were unified so this workaround can be dropped.