| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- #ifndef XTENSOR_XBLOCKWISE_REDUCER_FUNCTORS_HPP
- #define XTENSOR_XBLOCKWISE_REDUCER_FUNCTORS_HPP
- #include <sstream>
- #include <string>
- #include <tuple>
- #include <typeinfo>
- #include "xarray.hpp"
- #include "xbuilder.hpp"
- #include "xchunked_array.hpp"
- #include "xchunked_assign.hpp"
- #include "xchunked_view.hpp"
- #include "xexpression.hpp"
- #include "xmath.hpp"
- #include "xnorm.hpp"
- #include "xreducer.hpp"
- #include "xtl/xclosure.hpp"
- #include "xtl/xsequence.hpp"
- #include "xutils.hpp"
- namespace xt
- {
- namespace detail
- {
- namespace blockwise
- {
- struct empty_reduction_variable
- {
- };
- struct simple_functor_base
- {
- template <class E>
- auto reduction_variable(const E&) const
- {
- return empty_reduction_variable();
- }
- template <class MR, class E, class R>
- void finalize(const MR&, E&, const R&) const
- {
- }
- };
- template <class T_E, class T_I = void>
- struct sum_functor : public simple_functor_base
- {
- using value_type = typename std::decay_t<decltype(xt::sum<T_I>(std::declval<xarray<T_E>>()))>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::sum<value_type>(input, axes, options);
- }
- template <class BR, class E, class MR>
- auto merge(const BR& block_result, bool first, E& result, MR&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) += block_result;
- }
- }
- };
- template <class T_E, class T_I = void>
- struct prod_functor : public simple_functor_base
- {
- using value_type = typename std::decay_t<decltype(xt::sum<T_I>(std::declval<xarray<T_E>>()))>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::prod<value_type>(input, axes, options);
- }
- template <class BR, class E, class MR>
- auto merge(const BR& block_result, bool first, E& result, MR&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) *= block_result;
- }
- }
- };
- template <class T_E, class T_I = void>
- struct amin_functor : public simple_functor_base
- {
- using value_type = typename std::decay_t<decltype(xt::amin<T_I>(std::declval<xarray<T_E>>()))>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::amin(input, axes, options);
- }
- template <class BR, class E, class MR>
- auto merge(const BR& block_result, bool first, E& result, MR&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) = xt::minimum(block_result, result);
- }
- }
- };
- template <class T_E, class T_I = void>
- struct amax_functor : public simple_functor_base
- {
- using value_type = typename std::decay_t<decltype(xt::amax<T_I>(std::declval<xarray<T_E>>()))>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::amax(input, axes, options);
- }
- template <class BR, class E, class MR>
- auto merge(const BR& block_result, bool first, E& result, MR&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) = xt::maximum(block_result, result);
- }
- }
- };
- template <class T_E, class T_I = void>
- struct mean_functor
- {
- using value_type = typename std::decay_t<decltype(xt::mean<T_I>(std::declval<xarray<T_E>>()))>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::sum<value_type>(input, axes, options);
- }
- template <class E>
- auto reduction_variable(const E&) const
- {
- return empty_reduction_variable();
- }
- template <class BR, class E>
- auto merge(const BR& block_result, bool first, E& result, empty_reduction_variable&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) += block_result;
- }
- }
- template <class E, class R>
- void finalize(const empty_reduction_variable&, E& results, const R& reducer) const
- {
- const auto& axes = reducer.axes();
- std::decay_t<decltype(reducer.input_shape()[0])> factor = 1;
- for (auto a : axes)
- {
- factor *= reducer.input_shape()[a];
- }
- xt::noalias(results) /= static_cast<typename E::value_type>(factor);
- }
- };
- template <class T_E, class T_I = void>
- struct variance_functor
- {
- using value_type = typename std::decay_t<decltype(xt::variance<T_I>(std::declval<xarray<T_E>>())
- )>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- double weight = 1.0;
- for (auto a : axes)
- {
- weight *= static_cast<double>(input.shape()[a]);
- }
- return std::make_tuple(
- xt::variance<value_type>(input, axes, options),
- xt::mean<value_type>(input, axes, options),
- weight
- );
- }
- template <class E>
- auto reduction_variable(const E&) const
- {
- return std::make_tuple(xarray<value_type>(), 0.0);
- }
- template <class BR, class E, class MR>
- auto merge(const BR& block_result, bool first, E& variance_a, MR& mr) const
- {
- auto& mean_a = std::get<0>(mr);
- auto& n_a = std::get<1>(mr);
- const auto& variance_b = std::get<0>(block_result);
- const auto& mean_b = std::get<1>(block_result);
- const auto& n_b = std::get<2>(block_result);
- if (first)
- {
- xt::noalias(variance_a) = variance_b;
- xt::noalias(mean_a) = mean_b;
- n_a += n_b;
- }
- else
- {
- auto new_mean = (n_a * mean_a + n_b * mean_b) / (n_a + n_b);
- auto new_variance = (n_a * variance_a + n_b * variance_b
- + n_a * xt::pow(mean_a - new_mean, 2)
- + n_b * xt::pow(mean_b - new_mean, 2))
- / (n_a + n_b);
- xt::noalias(variance_a) = new_variance;
- xt::noalias(mean_a) = new_mean;
- n_a += n_b;
- }
- }
- template <class MR, class E, class R>
- void finalize(const MR&, E&, const R&) const
- {
- }
- };
- template <class T_E, class T_I = void>
- struct stddev_functor : public variance_functor<T_E, T_I>
- {
- template <class MR, class E, class R>
- void finalize(const MR&, E& results, const R&) const
- {
- xt::noalias(results) = xt::sqrt(results);
- }
- };
- template <class T_E>
- struct norm_l0_functor : public simple_functor_base
- {
- using value_type = typename std::decay_t<decltype(xt::norm_l0(std::declval<xarray<T_E>>()))>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::sum<value_type>(xt::not_equal(input, xt::zeros<T_E>(input.shape())), axes, options);
- }
- template <class BR, class E, class MR>
- auto merge(const BR& block_result, bool first, E& result, MR&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) += block_result;
- }
- }
- };
- template <class T_E>
- struct norm_l1_functor : public simple_functor_base
- {
- using value_type = typename std::decay_t<decltype(xt::norm_l1(std::declval<xarray<T_E>>()))>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::sum<value_type>(xt::abs(input), axes, options);
- }
- template <class BR, class E, class MR>
- auto merge(const BR& block_result, bool first, E& result, MR&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) += block_result;
- }
- }
- };
- template <class T_E>
- struct norm_l2_functor
- {
- using value_type = typename std::decay_t<decltype(xt::norm_l2(std::declval<xarray<T_E>>()))>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::sum<value_type>(xt::square(input), axes, options);
- }
- template <class E>
- auto reduction_variable(const E&) const
- {
- return empty_reduction_variable();
- }
- template <class BR, class E>
- auto merge(const BR& block_result, bool first, E& result, empty_reduction_variable&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) += block_result;
- }
- }
- template <class E, class R>
- void finalize(const empty_reduction_variable&, E& results, const R&) const
- {
- xt::noalias(results) = xt::sqrt(results);
- }
- };
- template <class T_E>
- struct norm_sq_functor : public simple_functor_base
- {
- using value_type = typename std::decay_t<decltype(xt::norm_sq(std::declval<xarray<T_E>>()))>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::sum<value_type>(xt::square(input), axes, options);
- }
- template <class BR, class E, class MR>
- auto merge(const BR& block_result, bool first, E& result, MR&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) += block_result;
- }
- }
- };
- template <class T_E>
- struct norm_linf_functor : public simple_functor_base
- {
- using value_type = typename std::decay_t<decltype(xt::norm_linf(std::declval<xarray<T_E>>()))>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::amax<value_type>(xt::abs(input), axes, options);
- }
- template <class BR, class E, class MR>
- auto merge(const BR& block_result, bool first, E& result, MR&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) = xt::maximum(block_result, result);
- }
- }
- };
- template <class T_E>
- class norm_lp_to_p_functor
- {
- public:
- using value_type = typename std::decay_t<
- decltype(xt::norm_lp_to_p(std::declval<xarray<T_E>>(), 1.0))>::value_type;
- norm_lp_to_p_functor(double p)
- : m_p(p)
- {
- }
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::sum<value_type>(xt::pow(input, m_p), axes, options);
- }
- template <class E>
- auto reduction_variable(const E&) const
- {
- return empty_reduction_variable();
- }
- template <class BR, class E>
- auto merge(const BR& block_result, bool first, E& result, empty_reduction_variable&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) += block_result;
- }
- }
- template <class E, class R>
- void finalize(const empty_reduction_variable&, E&, const R&) const
- {
- }
- private:
- double m_p;
- };
- template <class T_E>
- class norm_lp_functor
- {
- public:
- norm_lp_functor(double p)
- : m_p(p)
- {
- }
- using value_type = typename std::decay_t<decltype(xt::norm_lp(std::declval<xarray<T_E>>(), 1.0)
- )>::value_type;
- template <class E, class A, class O>
- auto compute(const E& input, const A& axes, const O& options) const
- {
- return xt::sum<value_type>(xt::pow(input, m_p), axes, options);
- }
- template <class E>
- auto reduction_variable(const E&) const
- {
- return empty_reduction_variable();
- }
- template <class BR, class E>
- auto merge(const BR& block_result, bool first, E& result, empty_reduction_variable&) const
- {
- if (first)
- {
- xt::noalias(result) = block_result;
- }
- else
- {
- xt::noalias(result) += block_result;
- }
- }
- template <class E, class R>
- void finalize(const empty_reduction_variable&, E& results, const R&) const
- {
- results = xt::pow(results, 1.0 / m_p);
- }
- private:
- double m_p;
- };
- }
- }
- }
- #endif
|