14#ifndef XTENSOR_MATH_HPP
15#define XTENSOR_MATH_HPP
23#include <xtl/xcomplex.hpp>
24#include <xtl/xsequence.hpp>
25#include <xtl/xtype_traits.hpp>
27#include "xaccumulator.hpp"
29#include "xmanipulation.hpp"
30#include "xoperation.hpp"
31#include "xreducer.hpp"
33#include "xstrided_view.hpp"
34#include "xtensor_config.hpp"
38 template <
class T =
double>
41 static constexpr T PI = 3.141592653589793238463;
42 static constexpr T PI_2 = 1.57079632679489661923;
43 static constexpr T PI_4 = 0.785398163397448309616;
44 static constexpr T D_1_PI = 0.318309886183790671538;
45 static constexpr T D_2_PI = 0.636619772367581343076;
46 static constexpr T D_2_SQRTPI = 1.12837916709551257390;
47 static constexpr T SQRT2 = 1.41421356237309504880;
48 static constexpr T SQRT1_2 = 0.707106781186547524401;
49 static constexpr T E = 2.71828182845904523536;
50 static constexpr T LOG2E = 1.44269504088896340736;
51 static constexpr T LOG10E = 0.434294481903251827651;
52 static constexpr T LN2 = 0.693147180559945309417;
59#define XTENSOR_UNSIGNED_ABS_FUNC(T) \
60 constexpr inline T abs(const T& x) \
65#define XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, T) \
66 constexpr inline bool FUNC_NAME(const T& ) noexcept \
71#define XTENSOR_INT_SPECIALIZATION(FUNC_NAME, RETURN_VAL) \
72 XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, char); \
73 XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, short); \
74 XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, int); \
75 XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, long); \
76 XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, long long); \
77 XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, unsigned char); \
78 XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, unsigned short); \
79 XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, unsigned int); \
80 XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, unsigned long); \
81 XTENSOR_INT_SPECIALIZATION_IMPL(FUNC_NAME, RETURN_VAL, unsigned long long);
84#define XTENSOR_UNARY_MATH_FUNCTOR(NAME) \
88 constexpr auto operator()(const T& arg) const \
94 constexpr auto simd_apply(const B& arg) const \
101#define XTENSOR_UNARY_MATH_FUNCTOR_COMPLEX_REDUCING(NAME) \
105 constexpr auto operator()(const T& arg) const \
111 constexpr auto simd_apply(const B& arg) const \
118#define XTENSOR_BINARY_MATH_FUNCTOR(NAME) \
121 template <class T1, class T2> \
122 constexpr auto operator()(const T1& arg1, const T2& arg2) const \
125 return NAME(arg1, arg2); \
128 constexpr auto simd_apply(const B& arg1, const B& arg2) const \
131 return NAME(arg1, arg2); \
135#define XTENSOR_TERNARY_MATH_FUNCTOR(NAME) \
138 template <class T1, class T2, class T3> \
139 constexpr auto operator()(const T1& arg1, const T2& arg2, const T3& arg3) const \
142 return NAME(arg1, arg2, arg3); \
145 auto simd_apply(const B& arg1, const B& arg2, const B& arg3) const \
148 return NAME(arg1, arg2, arg3); \
188 using std::nearbyint;
189 using std::remainder;
207#if !defined(_MSC_VER)
218 using std::fpclassify;
224 inline std::enable_if_t<xtl::is_arithmetic<T>::value,
bool> isinf(
const T&
t)
226 return bool(std::isinf(
t));
230 inline std::enable_if_t<xtl::is_arithmetic<T>::value,
bool> isnan(
const T& t)
232 return bool(std::isnan(t));
236 inline std::enable_if_t<xtl::is_arithmetic<T>::value,
bool> isfinite(
const T& t)
238 return bool(std::isfinite(t));
244 inline bool isinf(
const std::complex<T>& c)
246 return std::isinf(std::real(c)) || std::isinf(std::imag(c));
250 inline bool isnan(
const std::complex<T>& c)
252 return std::isnan(std::real(c)) || std::isnan(std::imag(c));
256 inline bool isfinite(
const std::complex<T>& c)
258 return !isinf(c) && !isnan(c);
263#if defined(_WIN32) && defined(XTENSOR_USE_XSIMD)
283 XTENSOR_UNSIGNED_ABS_FUNC(
unsigned char)
284 XTENSOR_UNSIGNED_ABS_FUNC(
unsigned short)
285 XTENSOR_UNSIGNED_ABS_FUNC(
unsigned int)
286 XTENSOR_UNSIGNED_ABS_FUNC(
unsigned long)
287 XTENSOR_UNSIGNED_ABS_FUNC(
unsigned long long)
290 XTENSOR_INT_SPECIALIZATION(isinf,
false);
291 XTENSOR_INT_SPECIALIZATION(isnan,
false);
292 XTENSOR_INT_SPECIALIZATION(isfinite,
true);
295 XTENSOR_UNARY_MATH_FUNCTOR_COMPLEX_REDUCING(abs);
297 XTENSOR_UNARY_MATH_FUNCTOR(fabs);
298 XTENSOR_BINARY_MATH_FUNCTOR(fmod);
299 XTENSOR_BINARY_MATH_FUNCTOR(remainder);
300 XTENSOR_TERNARY_MATH_FUNCTOR(fma);
301 XTENSOR_BINARY_MATH_FUNCTOR(fmax);
302 XTENSOR_BINARY_MATH_FUNCTOR(fmin);
303 XTENSOR_BINARY_MATH_FUNCTOR(fdim);
304 XTENSOR_UNARY_MATH_FUNCTOR(exp);
305 XTENSOR_UNARY_MATH_FUNCTOR(exp2);
306 XTENSOR_UNARY_MATH_FUNCTOR(expm1);
307 XTENSOR_UNARY_MATH_FUNCTOR(log);
308 XTENSOR_UNARY_MATH_FUNCTOR(log10);
309 XTENSOR_UNARY_MATH_FUNCTOR(log2);
310 XTENSOR_UNARY_MATH_FUNCTOR(log1p);
311 XTENSOR_BINARY_MATH_FUNCTOR(pow);
312 XTENSOR_UNARY_MATH_FUNCTOR(sqrt);
313 XTENSOR_UNARY_MATH_FUNCTOR(cbrt);
314 XTENSOR_BINARY_MATH_FUNCTOR(hypot);
315 XTENSOR_UNARY_MATH_FUNCTOR(sin);
316 XTENSOR_UNARY_MATH_FUNCTOR(cos);
317 XTENSOR_UNARY_MATH_FUNCTOR(tan);
318 XTENSOR_UNARY_MATH_FUNCTOR(asin);
319 XTENSOR_UNARY_MATH_FUNCTOR(acos);
320 XTENSOR_UNARY_MATH_FUNCTOR(atan);
321 XTENSOR_BINARY_MATH_FUNCTOR(atan2);
322 XTENSOR_UNARY_MATH_FUNCTOR(sinh);
323 XTENSOR_UNARY_MATH_FUNCTOR(cosh);
324 XTENSOR_UNARY_MATH_FUNCTOR(tanh);
325 XTENSOR_UNARY_MATH_FUNCTOR(asinh);
326 XTENSOR_UNARY_MATH_FUNCTOR(acosh);
327 XTENSOR_UNARY_MATH_FUNCTOR(atanh);
328 XTENSOR_UNARY_MATH_FUNCTOR(erf);
329 XTENSOR_UNARY_MATH_FUNCTOR(erfc);
330 XTENSOR_UNARY_MATH_FUNCTOR(tgamma);
331 XTENSOR_UNARY_MATH_FUNCTOR(lgamma);
332 XTENSOR_UNARY_MATH_FUNCTOR(ceil);
333 XTENSOR_UNARY_MATH_FUNCTOR(floor);
334 XTENSOR_UNARY_MATH_FUNCTOR(trunc);
335 XTENSOR_UNARY_MATH_FUNCTOR(round);
336 XTENSOR_UNARY_MATH_FUNCTOR(nearbyint);
337 XTENSOR_UNARY_MATH_FUNCTOR(rint);
338 XTENSOR_UNARY_MATH_FUNCTOR(isfinite);
339 XTENSOR_UNARY_MATH_FUNCTOR(isinf);
340 XTENSOR_UNARY_MATH_FUNCTOR(isnan);
341 XTENSOR_UNARY_MATH_FUNCTOR(conj);
344#undef XTENSOR_UNARY_MATH_FUNCTOR
345#undef XTENSOR_BINARY_MATH_FUNCTOR
346#undef XTENSOR_TERNARY_MATH_FUNCTOR
347#undef XTENSOR_UNARY_MATH_FUNCTOR_COMPLEX_REDUCING
348#undef XTENSOR_UNSIGNED_ABS_FUNC
352 template <
class R,
class T>
353 std::enable_if_t<!has_iterator_interface<R>::value,
R> fill_init(T init)
358 template <
class R,
class T>
359 std::enable_if_t<has_iterator_interface<R>::value,
R> fill_init(T init)
362 std::fill(std::begin(result), std::end(result), init);
367#define XTENSOR_REDUCER_FUNCTION(NAME, FUNCTOR, INIT_VALUE_TYPE, INIT) \
372 class EVS = DEFAULT_STRATEGY_REDUCERS, \
373 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::negation<xtl::is_integral<std::decay_t<X>>>)> \
374 inline auto NAME(E&& e, X&& axes, EVS es = EVS()) \
376 using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
377 using functor_type = FUNCTOR; \
378 using init_value_fct = xt::const_value<init_value_type>; \
380 make_xreducer_functor(functor_type(), init_value_fct(detail::fill_init<init_value_type>(INIT))), \
381 std::forward<E>(e), \
382 std::forward<X>(axes), \
391 class EVS = DEFAULT_STRATEGY_REDUCERS, \
392 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::is_integral<std::decay_t<X>>)> \
393 inline auto NAME(E&& e, X axis, EVS es = EVS()) \
395 return NAME(std::forward<E>(e), {axis}, es); \
398 template <class T = void, class E, class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)> \
399 inline auto NAME(E&& e, EVS es = EVS()) \
401 using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
402 using functor_type = FUNCTOR; \
403 using init_value_fct = xt::const_value<init_value_type>; \
405 make_xreducer_functor(functor_type(), init_value_fct(detail::fill_init<init_value_type>(INIT))), \
406 std::forward<E>(e), \
411 template <class T = void, class E, class I, std::size_t N, class EVS = DEFAULT_STRATEGY_REDUCERS> \
412 inline auto NAME(E&& e, const I(&axes)[N], EVS es = EVS()) \
414 using init_value_type = std::conditional_t<std::is_same<T, void>::value, INIT_VALUE_TYPE, T>; \
415 using functor_type = FUNCTOR; \
416 using init_value_fct = xt::const_value<init_value_type>; \
418 make_xreducer_functor(functor_type(), init_value_fct(detail::fill_init<init_value_type>(INIT))), \
419 std::forward<E>(e), \
443 inline auto abs(E&&
e)
noexcept -> detail::xfunction_type_t<math::abs_fun, E>
445 return detail::make_xfunction<math::abs_fun>(std::forward<E>(
e));
458 inline auto fabs(E&&
e)
noexcept -> detail::xfunction_type_t<math::fabs_fun, E>
460 return detail::make_xfunction<math::fabs_fun>(std::forward<E>(
e));
474 template <
class E1,
class E2>
475 inline auto fmod(
E1&&
e1,
E2&&
e2)
noexcept -> detail::xfunction_type_t<math::fmod_fun, E1, E2>
477 return detail::make_xfunction<math::fmod_fun>(std::forward<E1>(
e1), std::forward<E2>(
e2));
491 template <
class E1,
class E2>
492 inline auto remainder(
E1&&
e1,
E2&&
e2)
noexcept -> detail::xfunction_type_t<math::remainder_fun, E1, E2>
494 return detail::make_xfunction<math::remainder_fun>(std::forward<E1>(
e1), std::forward<E2>(
e2));
509 template <
class E1,
class E2,
class E3>
510 inline auto fma(
E1&&
e1,
E2&&
e2,
E3&&
e3)
noexcept -> detail::xfunction_type_t<math::fma_fun, E1, E2, E3>
512 return detail::make_xfunction<math::fma_fun>(
513 std::forward<E1>(
e1),
514 std::forward<E2>(
e2),
530 template <
class E1,
class E2>
531 inline auto fmax(
E1&&
e1,
E2&&
e2)
noexcept -> detail::xfunction_type_t<math::fmax_fun, E1, E2>
533 return detail::make_xfunction<math::fmax_fun>(std::forward<E1>(
e1), std::forward<E2>(
e2));
547 template <
class E1,
class E2>
548 inline auto fmin(
E1&&
e1,
E2&&
e2)
noexcept -> detail::xfunction_type_t<math::fmin_fun, E1, E2>
550 return detail::make_xfunction<math::fmin_fun>(std::forward<E1>(
e1), std::forward<E2>(
e2));
564 template <
class E1,
class E2>
565 inline auto fdim(
E1&&
e1,
E2&&
e2)
noexcept -> detail::xfunction_type_t<math::fdim_fun, E1, E2>
567 return detail::make_xfunction<math::fdim_fun>(std::forward<E1>(
e1), std::forward<E2>(
e2));
572 template <
class T =
void>
575 template <
class A1,
class A2>
576 constexpr auto operator()(
const A1&
t1,
const A2&
t2)
const noexcept
578 return xtl::select(
t1 <
t2,
t1,
t2);
581 template <
class A1,
class A2>
582 constexpr auto simd_apply(
const A1&
t1,
const A2&
t2)
const noexcept
584 return xt_simd::select(
t1 <
t2,
t1,
t2);
588 template <
class T =
void>
591 template <
class A1,
class A2>
592 constexpr auto operator()(
const A1&
t1,
const A2&
t2)
const noexcept
594 return xtl::select(
t1 >
t2,
t1,
t2);
597 template <
class A1,
class A2>
598 constexpr auto simd_apply(
const A1&
t1,
const A2&
t2)
const noexcept
600 return xt_simd::select(
t1 >
t2,
t1,
t2);
606 template <
class A1,
class A2,
class A3>
607 constexpr auto operator()(
const A1&
v,
const A2&
lo,
const A3&
hi)
const
609 return xtl::select(
v <
lo,
lo, xtl::select(
hi <
v,
hi,
v));
612 template <
class A1,
class A2,
class A3>
613 constexpr auto simd_apply(
const A1&
v,
const A2&
lo,
const A3&
hi)
const
615 return xt_simd::select(
v <
lo,
lo, xt_simd::select(
hi <
v,
hi,
v));
622 constexpr double operator()(
const A&
a)
const noexcept
628 constexpr auto operator()(
const A&
a)
const noexcept
634 constexpr double simd_apply(
const A&
a)
const noexcept
640 constexpr auto simd_apply(
const A&
a)
const noexcept
649 constexpr double operator()(
const A&
a)
const noexcept
655 constexpr auto operator()(
const A&
a)
const noexcept
661 constexpr double simd_apply(
const A&
a)
const noexcept
667 constexpr auto simd_apply(
const A&
a)
const noexcept
684 inline auto deg2rad(E&&
e)
noexcept -> detail::xfunction_type_t<math::deg2rad, E>
686 return detail::make_xfunction<math::deg2rad>(std::forward<E>(
e));
699 inline auto radians(E&&
e)
noexcept -> detail::xfunction_type_t<math::deg2rad, E>
701 return detail::make_xfunction<math::deg2rad>(std::forward<E>(
e));
714 inline auto rad2deg(E&&
e)
noexcept -> detail::xfunction_type_t<math::rad2deg, E>
716 return detail::make_xfunction<math::rad2deg>(std::forward<E>(
e));
729 inline auto degrees(E&&
e)
noexcept -> detail::xfunction_type_t<math::rad2deg, E>
731 return detail::make_xfunction<math::rad2deg>(std::forward<E>(
e));
744 template <
class E1,
class E2>
747 return detail::make_xfunction<math::maximum<void>>(std::forward<E1>(
e1), std::forward<E2>(
e2));
760 template <
class E1,
class E2>
763 return detail::make_xfunction<math::minimum<void>>(std::forward<E1>(
e1), std::forward<E2>(
e2));
777 XTENSOR_REDUCER_FUNCTION(
780 typename std::decay_t<E>::value_type,
781 std::numeric_limits<xvalue_type_t<std::decay_t<E>>>::lowest()
795 XTENSOR_REDUCER_FUNCTION(
816 -> detail::xfunction_type_t<math::clamp_fun,
E1,
E2,
E3>
818 return detail::make_xfunction<math::clamp_fun>(
819 std::forward<E1>(
e1),
820 std::forward<E2>(
lo),
830 template <
class XT = T>
831 static constexpr std::enable_if_t<xtl::is_signed<XT>::value, T> run(T
x)
833 return std::isnan(
x) ? std::numeric_limits<T>::quiet_NaN()
834 :
x == 0 ? T(copysign(T(0),
x))
835 : T(copysign(T(1),
x));
838 template <
class XT = T>
839 static constexpr std::enable_if_t<xtl::is_complex<XT>::value, T> run(T
x)
843 (
x.real() !=
typename T::value_type(0)) ?
x.real() :
x.imag()
849 template <
class XT = T>
850 static constexpr std::enable_if_t<std::is_unsigned<XT>::value, T> run(T
x)
859 constexpr auto operator()(
const T&
x)
const
877 inline auto sign(E&&
e)
noexcept -> detail::xfunction_type_t<math::sign_fun, E>
879 return detail::make_xfunction<math::sign_fun>(std::forward<E>(
e));
900 inline auto exp(E&&
e)
noexcept -> detail::xfunction_type_t<math::exp_fun, E>
902 return detail::make_xfunction<math::exp_fun>(std::forward<E>(
e));
915 inline auto exp2(E&&
e)
noexcept -> detail::xfunction_type_t<math::exp2_fun, E>
917 return detail::make_xfunction<math::exp2_fun>(std::forward<E>(
e));
930 inline auto expm1(E&&
e)
noexcept -> detail::xfunction_type_t<math::expm1_fun, E>
932 return detail::make_xfunction<math::expm1_fun>(std::forward<E>(
e));
945 inline auto log(E&&
e)
noexcept -> detail::xfunction_type_t<math::log_fun, E>
947 return detail::make_xfunction<math::log_fun>(std::forward<E>(
e));
960 inline auto log10(E&&
e)
noexcept -> detail::xfunction_type_t<math::log10_fun, E>
962 return detail::make_xfunction<math::log10_fun>(std::forward<E>(
e));
975 inline auto log2(E&&
e)
noexcept -> detail::xfunction_type_t<math::log2_fun, E>
977 return detail::make_xfunction<math::log2_fun>(std::forward<E>(
e));
990 inline auto log1p(E&&
e)
noexcept -> detail::xfunction_type_t<math::log1p_fun, E>
992 return detail::make_xfunction<math::log1p_fun>(std::forward<E>(
e));
1014 template <
class E1,
class E2>
1015 inline auto pow(
E1&&
e1,
E2&&
e2)
noexcept -> detail::xfunction_type_t<math::pow_fun, E1, E2>
1017 return detail::make_xfunction<math::pow_fun>(std::forward<E1>(
e1), std::forward<E2>(
e2));
1022 template <
class F,
class... T,
typename =
decltype(std::declval<F>()(std::declval<T>()...))>
1023 std::true_type supports_test(
const F&,
const T&...);
1024 std::false_type supports_test(...);
1026 template <
class... T>
1029 template <
class F,
class... T>
1030 struct supports<F(T...)> : decltype(supports_test(std::declval<F>(), std::declval<T>()...))
1037 explicit lambda_adapt(F&& lmbd)
1038 : m_lambda(std::move(lmbd))
1042 template <
class... T>
1043 auto operator()(T... args)
const
1045 return m_lambda(args...);
1048 template <
class... T, XTL_REQUIRES(detail::supports<F(T...)>)>
1049 auto simd_apply(T... args)
const
1051 return m_lambda(args...);
1084 template <
class F,
class... E>
1087 using xfunction_type =
typename detail::xfunction_type<detail::lambda_adapt<F>, E...>::type;
1088 return xfunction_type(detail::lambda_adapt<F>(std::forward<F>(
lambda)), std::forward<E>(
args)...);
1091#define XTENSOR_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
1094#if (defined(_MSC_VER) && _MSC_VER < 1910) || (defined(__GNUC__) && GCC_VERSION < 49999)
1095#define XTENSOR_DISABLE_LAMBDA_FCT
1098#ifdef XTENSOR_DISABLE_LAMBDA_FCT
1102 auto operator()(T x)
const ->
decltype(x * x)
1111 auto operator()(T x)
const ->
decltype(x * x * x)
1130#ifdef XTENSOR_DISABLE_LAMBDA_FCT
1133 auto fnct = [](
auto x) ->
decltype(
x *
x)
1153#ifdef XTENSOR_DISABLE_LAMBDA_FCT
1156 auto fnct = [](
auto x) ->
decltype(
x *
x *
x)
1164#undef XTENSOR_GCC_VERSION
1165#undef XTENSOR_DISABLE_LAMBDA_FCT
1170 template <std::
size_t N>
1173 template <std::
size_t N>
1177 auto operator()(T v)
const ->
decltype(v * v)
1179 T temp = pow_impl<N / 2>{}(v);
1180 return temp * temp * pow_impl<N & 1>{}(v);
1188 auto operator()(T v)
const -> T
1198 auto operator()(T )
const -> T
1222 template <std::
size_t N,
class E>
1225 static_assert(N > 0,
"integer power cannot be negative");
1239 inline auto sqrt(E&&
e)
noexcept -> detail::xfunction_type_t<math::sqrt_fun, E>
1241 return detail::make_xfunction<math::sqrt_fun>(std::forward<E>(
e));
1254 inline auto cbrt(E&&
e)
noexcept -> detail::xfunction_type_t<math::cbrt_fun, E>
1256 return detail::make_xfunction<math::cbrt_fun>(std::forward<E>(
e));
1271 template <
class E1,
class E2>
1272 inline auto hypot(
E1&&
e1,
E2&&
e2)
noexcept -> detail::xfunction_type_t<math::hypot_fun, E1, E2>
1274 return detail::make_xfunction<math::hypot_fun>(std::forward<E1>(
e1), std::forward<E2>(
e2));
1295 inline auto sin(E&&
e)
noexcept -> detail::xfunction_type_t<math::sin_fun, E>
1297 return detail::make_xfunction<math::sin_fun>(std::forward<E>(
e));
1310 inline auto cos(E&&
e)
noexcept -> detail::xfunction_type_t<math::cos_fun, E>
1312 return detail::make_xfunction<math::cos_fun>(std::forward<E>(
e));
1325 inline auto tan(E&&
e)
noexcept -> detail::xfunction_type_t<math::tan_fun, E>
1327 return detail::make_xfunction<math::tan_fun>(std::forward<E>(
e));
1340 inline auto asin(E&&
e)
noexcept -> detail::xfunction_type_t<math::asin_fun, E>
1342 return detail::make_xfunction<math::asin_fun>(std::forward<E>(
e));
1355 inline auto acos(E&&
e)
noexcept -> detail::xfunction_type_t<math::acos_fun, E>
1357 return detail::make_xfunction<math::acos_fun>(std::forward<E>(
e));
1370 inline auto atan(E&&
e)
noexcept -> detail::xfunction_type_t<math::atan_fun, E>
1372 return detail::make_xfunction<math::atan_fun>(std::forward<E>(
e));
1387 template <
class E1,
class E2>
1388 inline auto atan2(
E1&&
e1,
E2&&
e2)
noexcept -> detail::xfunction_type_t<math::atan2_fun, E1, E2>
1390 return detail::make_xfunction<math::atan2_fun>(std::forward<E1>(
e1), std::forward<E2>(
e2));
1411 inline auto sinh(E&&
e)
noexcept -> detail::xfunction_type_t<math::sinh_fun, E>
1413 return detail::make_xfunction<math::sinh_fun>(std::forward<E>(
e));
1426 inline auto cosh(E&&
e)
noexcept -> detail::xfunction_type_t<math::cosh_fun, E>
1428 return detail::make_xfunction<math::cosh_fun>(std::forward<E>(
e));
1441 inline auto tanh(E&&
e)
noexcept -> detail::xfunction_type_t<math::tanh_fun, E>
1443 return detail::make_xfunction<math::tanh_fun>(std::forward<E>(
e));
1456 inline auto asinh(E&&
e)
noexcept -> detail::xfunction_type_t<math::asinh_fun, E>
1458 return detail::make_xfunction<math::asinh_fun>(std::forward<E>(
e));
1471 inline auto acosh(E&&
e)
noexcept -> detail::xfunction_type_t<math::acosh_fun, E>
1473 return detail::make_xfunction<math::acosh_fun>(std::forward<E>(
e));
1486 inline auto atanh(E&&
e)
noexcept -> detail::xfunction_type_t<math::atanh_fun, E>
1488 return detail::make_xfunction<math::atanh_fun>(std::forward<E>(
e));
1509 inline auto erf(E&&
e)
noexcept -> detail::xfunction_type_t<math::erf_fun, E>
1511 return detail::make_xfunction<math::erf_fun>(std::forward<E>(
e));
1524 inline auto erfc(E&&
e)
noexcept -> detail::xfunction_type_t<math::erfc_fun, E>
1526 return detail::make_xfunction<math::erfc_fun>(std::forward<E>(
e));
1539 inline auto tgamma(E&&
e)
noexcept -> detail::xfunction_type_t<math::tgamma_fun, E>
1541 return detail::make_xfunction<math::tgamma_fun>(std::forward<E>(
e));
1554 inline auto lgamma(E&&
e)
noexcept -> detail::xfunction_type_t<math::lgamma_fun, E>
1556 return detail::make_xfunction<math::lgamma_fun>(std::forward<E>(
e));
1577 inline auto ceil(E&&
e)
noexcept -> detail::xfunction_type_t<math::ceil_fun, E>
1579 return detail::make_xfunction<math::ceil_fun>(std::forward<E>(
e));
1592 inline auto floor(E&&
e)
noexcept -> detail::xfunction_type_t<math::floor_fun, E>
1594 return detail::make_xfunction<math::floor_fun>(std::forward<E>(
e));
1607 inline auto trunc(E&&
e)
noexcept -> detail::xfunction_type_t<math::trunc_fun, E>
1609 return detail::make_xfunction<math::trunc_fun>(std::forward<E>(
e));
1623 inline auto round(E&&
e)
noexcept -> detail::xfunction_type_t<math::round_fun, E>
1625 return detail::make_xfunction<math::round_fun>(std::forward<E>(
e));
1639 inline auto nearbyint(E&&
e)
noexcept -> detail::xfunction_type_t<math::nearbyint_fun, E>
1641 return detail::make_xfunction<math::nearbyint_fun>(std::forward<E>(
e));
1655 inline auto rint(E&&
e)
noexcept -> detail::xfunction_type_t<math::rint_fun, E>
1657 return detail::make_xfunction<math::rint_fun>(std::forward<E>(
e));
1678 inline auto isfinite(E&&
e)
noexcept -> detail::xfunction_type_t<math::isfinite_fun, E>
1680 return detail::make_xfunction<math::isfinite_fun>(std::forward<E>(
e));
1693 inline auto isinf(E&&
e)
noexcept -> detail::xfunction_type_t<math::isinf_fun, E>
1695 return detail::make_xfunction<math::isinf_fun>(std::forward<E>(
e));
1708 inline auto isnan(E&&
e)
noexcept -> detail::xfunction_type_t<math::isnan_fun, E>
1710 return detail::make_xfunction<math::isnan_fun>(std::forward<E>(
e));
1715 template <
class FUNCTOR,
class T, std::size_t... Is>
1716 inline auto get_functor(T&& args, std::index_sequence<Is...>)
1718 return FUNCTOR(std::get<Is>(args)...);
1721 template <
class F,
class... A,
class... E>
1722 inline auto make_xfunction(std::tuple<A...>&& f_args, E&&... e)
noexcept
1724 using functor_type = F;
1725 using expression_tag = xexpression_tag_t<E...>;
1726 using type = select_xfunction_expression_t<expression_tag, functor_type, const_xclosure_t<E>...>;
1727 auto functor = get_functor<functor_type>(
1728 std::forward<std::tuple<A...>>(f_args),
1729 std::make_index_sequence<
sizeof...(A)>{}
1731 return type(std::move(functor), std::forward<E>(e)...);
1736 using result_type = bool;
1738 isclose(
double rtol,
double atol,
bool equal_nan)
1741 , m_equal_nan(equal_nan)
1745 template <
class A1,
class A2>
1746 bool operator()(
const A1& a,
const A2& b)
const
1748 using internal_type = xtl::promote_type_t<A1, A2, double>;
1749 if (math::isnan(a) && math::isnan(b))
1753 if (math::isinf(a) && math::isinf(b))
1758 auto d = math::abs(internal_type(a) - internal_type(b));
1761 * double((std::max)(math::abs(internal_type(a)), math::abs(internal_type(b)))
1788 template <
class E1,
class E2>
1792 return detail::make_xfunction<detail::isclose>(
1794 std::forward<E1>(
e1),
1795 std::forward<E2>(
e2)
1812 template <
class E1,
class E2>
1841 XTENSOR_REDUCER_FUNCTION(
sum, detail::plus,
typename std::decay_t<E>::value_type, 0)
1865 template <
class T,
class S,
class ST>
1868 using value_type =
typename std::conditional_t<std::is_same<T, void>::value,
double, T>;
1870 value_type
div =
s.size() !=
ST(0) ?
static_cast<value_type
>(
e_size /
s.size()) : value_type(0);
1871 return std::move(
s) / std::move(
div);
1885 using size_type =
typename std::decay_t<E>::size_type;
1886 const size_type size =
e.size();
1887 XTENSOR_ASSERT(
static_cast<size_type
>(
ddof) <= size);
1888 auto s =
sum<T>(std::forward<E>(
e), std::forward<X>(axes),
es);
1892 template <
class T,
class E,
class I, std::
size_t N,
class D,
class EVS>
1895 using size_type =
typename std::decay_t<E>::size_type;
1896 const size_type size =
e.size();
1897 XTENSOR_ASSERT(
static_cast<size_type
>(
ddof) <= size);
1898 auto s =
sum<T>(std::forward<E>(
e), axes,
es);
1902 template <
class T,
class E,
class D,
class EVS, XTL_REQUIRES(is_reducer_options<EVS>, xtl::is_
integral<D>)>
1903 inline auto mean_noaxis(E&&
e,
const D&
ddof,
EVS es)
1905 using value_type =
typename std::conditional_t<std::is_same<T, void>::value,
double, T>;
1906 using size_type =
typename std::decay_t<E>::size_type;
1907 const size_type size =
e.size();
1908 XTENSOR_ASSERT(
static_cast<size_type
>(
ddof) <= size);
1910 return std::move(
s) /
static_cast<value_type
>((size -
static_cast<size_type
>(
ddof)));
1933 class EVS = DEFAULT_STRATEGY_REDUCERS,
1934 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>)>
1937 return detail::mean<T>(std::forward<E>(
e), std::forward<X>(axes), 0
u,
es);
1940 template <
class T =
void,
class E,
class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)>
1941 inline auto mean(E&& e, EVS es = EVS())
1943 return detail::mean_noaxis<T>(std::forward<E>(e), 0u, es);
1946 template <
class T =
void,
class E,
class I, std::
size_t N,
class EVS = DEFAULT_STRATEGY_REDUCERS>
1947 inline auto mean(E&& e,
const I (&axes)[N], EVS es = EVS())
1949 return detail::mean<T>(std::forward<E>(e), axes, 0u, es);
1974 class EVS = DEFAULT_STRATEGY_REDUCERS,
1975 XTL_REQUIRES(is_reducer_options<EVS>, xtl::negation<xtl::is_integral<X>>)>
1979 xt::resize_container(broadcast_shape,
e.dimension());
1980 auto ax = normalize_axis(
e, axes);
1985 XTENSOR_THROW(std::runtime_error,
"Weights need to have the same shape as expression at axes.");
1988 std::fill(broadcast_shape.begin(), broadcast_shape.end(), std::size_t(1));
1989 broadcast_shape[
ax[0]] =
weights.size();
1997 "Weights with dim > 1 need to have the same shape as expression."
2001 std::copy(
e.shape().begin(),
e.shape().end(), broadcast_shape.begin());
2004 constexpr layout_type L = default_assignable_layout(std::decay_t<W>::static_layout);
2015 class EVS = DEFAULT_STRATEGY_REDUCERS,
2016 XTL_REQUIRES(is_reducer_options<EVS>, xtl::is_integral<X>)>
2017 inline auto average(E&& e, W&& weights, X axis, EVS ev = EVS())
2019 return average(std::forward<E>(e), std::forward<W>(weights), {axis}, std::forward<EVS>(ev));
2022 template <
class T =
void,
class E,
class W,
class X, std::
size_t N,
class EVS = DEFAULT_STRATEGY_REDUCERS>
2023 inline auto average(E&& e, W&& weights,
const X (&axes)[N], EVS ev = EVS())
2026 using ax_t = std::array<std::size_t, N>;
2030 template <
class T =
void,
class E,
class W,
class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)>
2031 inline auto average(E&& e, W&& weights, EVS ev = EVS())
2033 if (weights.dimension() != e.dimension()
2034 || !std::equal(weights.shape().begin(), weights.shape().end(), e.shape().begin()))
2036 XTENSOR_THROW(std::runtime_error,
"Weights need to have the same shape as expression.");
2039 auto div = sum<T>(weights, evaluation_strategy::immediate)();
2040 auto s = sum<T>(std::forward<E>(e) * std::forward<W>(weights), ev) / std::move(div);
2044 template <
class T =
void,
class E,
class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)>
2045 inline auto average(E&& e, EVS ev = EVS())
2047 return mean<T>(e, ev);
2052 template <
typename E>
2053 std::enable_if_t<std::is_lvalue_reference<E>::value, E> shared_forward(E e)
noexcept
2058 template <
typename E>
2059 std::enable_if_t<!std::is_lvalue_reference<E>::value, xshared_expression<E>> shared_forward(E e)
noexcept
2069 class EVS = DEFAULT_STRATEGY_REDUCERS,
2070 XTL_REQUIRES(is_reducer_options<EVS>, xtl::is_integral<D>)>
2071 inline auto variance(E&& e,
const D& ddof, EVS es = EVS())
2073 auto cached_mean = mean<T>(e, es)();
2074 return detail::mean_noaxis<T>(
square(std::forward<E>(e) - std::move(cached_mean)), ddof, es);
2077 template <
class T =
void,
class E,
class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)>
2078 inline auto variance(E&& e, EVS es = EVS())
2080 return variance<T>(std::forward<E>(e), 0u, es);
2083 template <
class T =
void,
class E,
class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)>
2084 inline auto stddev(E&& e, EVS es = EVS())
2086 return sqrt(variance<T>(std::forward<E>(e), es));
2118 class EVS = DEFAULT_STRATEGY_REDUCERS,
2119 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::is_integral<D>)>
2122 decltype(
auto)
sc = detail::shared_forward<E>(
e);
2134 for (
const auto&
el : axes)
2140 return detail::mean<T>(
square(
sc - std::move(
mrv)), std::forward<X>(axes),
ddof,
es);
2147 class EVS = DEFAULT_STRATEGY_REDUCERS,
2148 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::negation<xtl::is_integral<std::decay_t<X>>>, is_reducer_options<EVS>)>
2149 inline auto variance(E&& e, X&& axes, EVS es = EVS())
2151 return variance<T>(std::forward<E>(e), std::forward<X>(axes), 0u, es);
2179 class EVS = DEFAULT_STRATEGY_REDUCERS,
2180 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>)>
2186 template <
class T =
void,
class E,
class A, std::
size_t N,
class EVS = DEFAULT_STRATEGY_REDUCERS>
2187 inline auto stddev(E&& e,
const A (&axes)[N], EVS es = EVS())
2191 xtl::forward_sequence<std::array<std::size_t, N>,
decltype(axes)>(axes),
2201 class EVS = DEFAULT_STRATEGY_REDUCERS,
2202 XTL_REQUIRES(is_reducer_options<EVS>)>
2203 inline auto variance(E&& e,
const A (&axes)[N], EVS es = EVS())
2207 xtl::forward_sequence<std::array<std::size_t, N>,
decltype(axes)>(axes),
2212 template <
class T =
void,
class E,
class A, std::
size_t N,
class D,
class EVS = DEFAULT_STRATEGY_REDUCERS>
2213 inline auto variance(E&& e,
const A (&axes)[N],
const D& ddof, EVS es = EVS())
2217 xtl::forward_sequence<std::array<std::size_t, N>,
decltype(axes)>(axes),
2233 template <
class E,
class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)>
2238 using value_type =
typename std::decay_t<E>::value_type;
2239 using result_type = std::array<value_type, 2>;
2250 result_type{std::numeric_limits<value_type>::max(), std::numeric_limits<value_type>::lowest()}
2255 r[0] = (
min) (
r[0],
s[0]);
2256 r[1] = (
max) (
r[1],
s[1]);
2285 template <
class T =
void,
class E>
2288 using init_value_type = std::conditional_t<std::is_same<T, void>::value,
typename std::decay_t<E>::value_type, T>;
2290 make_xaccumulator_functor(detail::plus(), detail::accumulator_identity<init_value_type>()),
2296 template <
class T =
void,
class E>
2297 inline auto cumsum(E&& e)
2299 using init_value_type = std::conditional_t<std::is_same<T, void>::value,
typename std::decay_t<E>::value_type, T>;
2301 make_xaccumulator_functor(detail::plus(), detail::accumulator_identity<init_value_type>()),
2320 template <
class T =
void,
class E>
2323 using init_value_type = std::conditional_t<std::is_same<T, void>::value,
typename std::decay_t<E>::value_type, T>;
2325 make_xaccumulator_functor(detail::multiplies(), detail::accumulator_identity<init_value_type>()),
2331 template <
class T =
void,
class E>
2334 using init_value_type = std::conditional_t<std::is_same<T, void>::value,
typename std::decay_t<E>::value_type, T>;
2336 make_xaccumulator_functor(detail::multiplies(), detail::accumulator_identity<init_value_type>()),
2347 struct nan_to_num_functor
2350 inline auto operator()(
const A& a)
const
2360 return std::numeric_limits<A>::lowest();
2364 return (std::numeric_limits<A>::max)();
2373 template <
class T,
class U>
2374 constexpr auto operator()(
const T lhs,
const U rhs)
const
2377 return math::isnan(lhs)
2379 : (math::isnan(rhs) ? lhs
2380 : std::common_type_t<T, U>(
2381 detail::make_xfunction<math::minimum<void>>(lhs, rhs)
2388 template <
class T,
class U>
2389 constexpr auto operator()(
const T lhs,
const U rhs)
const
2392 return math::isnan(lhs)
2394 : (math::isnan(rhs) ? lhs
2395 : std::common_type_t<T, U>(
2396 detail::make_xfunction<math::maximum<void>>(lhs, rhs)
2403 template <
class T,
class U>
2404 constexpr auto operator()(
const T lhs,
const U rhs)
const
2406 return !math::isnan(rhs) ? lhs + rhs : lhs;
2410 struct nan_multiplies
2412 template <
class T,
class U>
2413 constexpr auto operator()(
const T lhs,
const U rhs)
const
2415 return !math::isnan(rhs) ? lhs * rhs : lhs;
2419 template <
class T,
int V>
2422 using value_type = T;
2423 using result_type = T;
2425 constexpr result_type operator()(
const value_type lhs)
const
2427 return math::isnan(lhs) ? result_type(V) : lhs;
2449 return detail::make_xfunction<detail::nan_to_num_functor>(std::forward<E>(
e));
2465 XTENSOR_REDUCER_FUNCTION(
nanmin, detail::nan_min,
typename std::decay_t<E>::value_type, std::nan(
"0"))
2516#define COUNT_NON_ZEROS_CONTENT \
2517 using value_type = typename std::decay_t<E>::value_type; \
2518 using result_type = xt::detail::xreducer_size_type_t<value_type>; \
2519 using init_value_fct = xt::const_value<result_type>; \
2521 auto init_fct = init_value_fct(0); \
2523 auto reduce_fct = [](const auto& lhs, const auto& rhs) \
2525 using value_t = xt::detail::xreducer_temporary_type_t<std::decay_t<decltype(rhs)>>; \
2526 using result_t = std::decay_t<decltype(lhs)>; \
2528 return (rhs != value_t(0)) ? lhs + result_t(1) : lhs; \
2530 auto merge_func = detail::plus();
2532 template <
class E,
class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)>
2533 inline auto count_nonzero(E&&
e,
EVS es =
EVS())
2535 COUNT_NON_ZEROS_CONTENT;
2546 class EVS = DEFAULT_STRATEGY_REDUCERS,
2547 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::negation<xtl::is_integral<X>>)>
2548 inline auto count_nonzero(E&& e, X&& axes, EVS es = EVS())
2550 COUNT_NON_ZEROS_CONTENT;
2552 make_xreducer_functor(std::move(reduce_fct), std::move(init_fct), std::move(merge_func)),
2554 std::forward<X>(axes),
2562 class EVS = DEFAULT_STRATEGY_REDUCERS,
2563 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::is_integral<X>)>
2564 inline auto count_nonzero(E&& e, X axis, EVS es = EVS())
2566 return count_nonzero(std::forward<E>(e), {axis}, es);
2569 template <
class E,
class I, std::
size_t N,
class EVS = DEFAULT_STRATEGY_REDUCERS>
2570 inline auto count_nonzero(E&& e,
const I (&axes)[N], EVS es = EVS())
2572 COUNT_NON_ZEROS_CONTENT;
2574 make_xreducer_functor(std::move(reduce_fct), std::move(init_fct), std::move(merge_func)),
2581#undef COUNT_NON_ZEROS_CONTENT
2583 template <
class E,
class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)>
2584 inline auto count_nonnan(E&& e, EVS es = EVS())
2586 return xt::count_nonzero(!
xt::isnan(std::forward<E>(e)), es);
2592 class EVS = DEFAULT_STRATEGY_REDUCERS,
2593 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::negation<xtl::is_integral<X>>)>
2594 inline auto count_nonnan(E&& e, X&& axes, EVS es = EVS())
2596 return xt::count_nonzero(!
xt::isnan(std::forward<E>(e)), std::forward<X>(axes), es);
2602 class EVS = DEFAULT_STRATEGY_REDUCERS,
2603 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>, xtl::is_integral<X>)>
2604 inline auto count_nonnan(E&& e, X&& axes, EVS es = EVS())
2606 return xt::count_nonzero(!
xt::isnan(std::forward<E>(e)), {axes}, es);
2609 template <
class E,
class I, std::
size_t N,
class EVS = DEFAULT_STRATEGY_REDUCERS>
2610 inline auto count_nonnan(E&& e,
const I (&axes)[N], EVS es = EVS())
2612 return xt::count_nonzero(!
xt::isnan(std::forward<E>(e)), axes, es);
2629 template <
class T =
void,
class E>
2632 using init_value_type = std::conditional_t<std::is_same<T, void>::value,
typename std::decay_t<E>::value_type, T>;
2634 make_xaccumulator_functor(detail::nan_plus(), detail::nan_init<init_value_type, 0>()),
2640 template <
class T =
void,
class E>
2643 using init_value_type = std::conditional_t<std::is_same<T, void>::value,
typename std::decay_t<E>::value_type, T>;
2645 make_xaccumulator_functor(detail::nan_plus(), detail::nan_init<init_value_type, 0>()),
2664 template <
class T =
void,
class E>
2667 using init_value_type = std::conditional_t<std::is_same<T, void>::value,
typename std::decay_t<E>::value_type, T>;
2669 make_xaccumulator_functor(detail::nan_multiplies(), detail::nan_init<init_value_type, 1>()),
2675 template <
class T =
void,
class E>
2678 using init_value_type = std::conditional_t<std::is_same<T, void>::value,
typename std::decay_t<E>::value_type, T>;
2680 make_xaccumulator_functor(detail::nan_multiplies(), detail::nan_init<init_value_type, 1>()),
2690 template <
class Arg>
2691 inline void operator()(
2693 const std::size_t& n,
2699 for (std::size_t i = 0; i < n; ++i)
2701 slice2[saxis] =
range(xnone(), ad.shape()[saxis] - 1);
2708 struct diff_impl<bool>
2710 template <
class Arg>
2711 inline void operator()(
2713 const std::size_t& n,
2719 for (std::size_t i = 0; i < n; ++i)
2721 slice2[saxis] =
range(xnone(), ad.shape()[saxis] - 1);
2747 class EVS = DEFAULT_STRATEGY_REDUCERS,
2748 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>)>
2751 decltype(
auto)
sc = detail::shared_forward<E>(
e);
2754 using value_type =
typename std::conditional_t<std::is_same<T, void>::value,
double, T>;
2755 using sum_type =
typename std::conditional_t<
2756 std::is_same<T, void>::value,
2757 typename std::common_type_t<typename std::decay_t<E>::value_type, value_type>,
2765 template <
class T =
void,
class E,
class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)>
2766 inline auto nanmean(E&& e, EVS es = EVS())
2768 decltype(
auto) sc = detail::shared_forward<E>(e);
2769 using value_type =
typename std::conditional_t<std::is_same<T, void>::value, double, T>;
2770 using sum_type =
typename std::conditional_t<
2771 std::is_same<T, void>::value,
2772 typename std::common_type_t<typename std::decay_t<E>::value_type, value_type>,
2777 template <
class T =
void,
class E,
class I, std::
size_t N,
class EVS = DEFAULT_STRATEGY_REDUCERS>
2778 inline auto nanmean(E&& e,
const I (&axes)[N], EVS es = EVS())
2782 xtl::forward_sequence<std::array<std::size_t, N>,
decltype(axes)>(axes),
2787 template <
class T =
void,
class E,
class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)>
2788 inline auto nanvar(E&& e, EVS es = EVS())
2790 decltype(
auto) sc = detail::shared_forward<E>(e);
2791 return nanmean<T>(
square(sc - nanmean<T>(sc)), es);
2794 template <
class T =
void,
class E,
class EVS = DEFAULT_STRATEGY_REDUCERS, XTL_REQUIRES(is_reducer_options<EVS>)>
2795 inline auto nanstd(E&& e, EVS es = EVS())
2797 return sqrt(nanvar<T>(std::forward<E>(e), es));
2824 class EVS = DEFAULT_STRATEGY_REDUCERS,
2825 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>)>
2828 decltype(
auto)
sc = detail::shared_forward<E>(
e);
2831 using result_type =
typename std::conditional_t<std::is_same<T, void>::value,
double, T>;
2840 for (
const auto&
el : axes)
2872 class EVS = DEFAULT_STRATEGY_REDUCERS,
2873 XTL_REQUIRES(xtl::negation<is_reducer_options<X>>)>
2879 template <
class T =
void,
class E,
class A, std::
size_t N,
class EVS = DEFAULT_STRATEGY_REDUCERS>
2880 inline auto nanstd(E&& e,
const A (&axes)[N], EVS es = EVS())
2884 xtl::forward_sequence<std::array<std::size_t, N>,
decltype(axes)>(axes),
2889 template <
class T =
void,
class E,
class A, std::
size_t N,
class EVS = DEFAULT_STRATEGY_REDUCERS>
2890 inline auto nanvar(E&& e,
const A (&axes)[N], EVS es = EVS())
2894 xtl::forward_sequence<std::array<std::size_t, N>,
decltype(axes)>(axes),
2913 typename std::decay_t<T>::temporary_type
ad =
a.derived_cast();
2914 std::size_t
saxis = normalize_axis(
ad.dimension(), axis);
2917 if (
n != std::size_t(0))
2923 detail::diff_impl<typename T::value_type>
impl;
2929 auto shape =
ad.shape();
2930 shape[
saxis] = std::size_t(0);
2950 auto&
yd =
y.derived_cast();
2951 std::size_t
saxis = normalize_axis(
yd.dimension(), axis);
2974 template <
class T,
class E>
2977 auto&
yd =
y.derived_cast();
2978 auto&
xd =
x.derived_cast();
2981 std::size_t
saxis = normalize_axis(
yd.dimension(), axis);
2983 if (
xd.dimension() == 1)
2986 typename std::decay_t<
decltype(
yd)>::shape_type shape;
2987 resize_container(shape,
yd.dimension());
2988 std::fill(shape.begin(), shape.end(), 1);
3019 template <
class E1,
class E2,
class E3,
typename T>
3023 using value_type =
typename E3::value_type;
3026 XTENSOR_ASSERT(
xp.dimension() == 1);
3027 XTENSOR_ASSERT(std::is_sorted(
x.cbegin(),
x.cend()));
3028 XTENSOR_ASSERT(std::is_sorted(
xp.cbegin(),
xp.cend()));
3037 for (;
i <
x.size(); ++
i)
3043 f[
i] =
static_cast<value_type
>(
left);
3048 size_type imax =
x.size();
3051 for (; imax > 0; --imax)
3053 if (
x[imax - 1] <
xp[
xp.size() - 1])
3057 f[imax - 1] =
static_cast<value_type
>(
right);
3074 for (;
i <= imax; ++
i)
3082 double dfp =
static_cast<double>(
fp[
ip] -
fp[
ip - 1]);
3083 double dxp =
static_cast<double>(
xp[
ip] -
xp[
ip - 1]);
3084 double dx =
static_cast<double>(
x[
i] -
xp[
ip - 1]);
3094 template <
class E1,
class E2>
3095 auto calculate_discontinuity(E1&& discontinuity, E2&&)
3097 return discontinuity;
3103 return 0.5 * period;
3106 template <
class E1,
class E2>
3108 calculate_interval(E2&& period,
typename std::enable_if<std::is_integral<E1>::value, E1>::type* = 0)
3110 auto interval_high = 0.5 * period;
3111 uint64_t remainder =
static_cast<uint64_t
>(period) % 2;
3112 auto boundary_ambiguous = (remainder == 0);
3113 return std::make_tuple(interval_high, boundary_ambiguous);
3116 template <
class E1,
class E2>
3118 calculate_interval(E2&& period,
typename std::enable_if<std::is_floating_point<E1>::value, E1>::type* = 0)
3120 auto interval_high = 0.5 * period;
3121 auto boundary_ambiguous =
true;
3122 return std::make_tuple(interval_high, boundary_ambiguous);
3139 template <
class E1,
class E2 = xt::placeholders::xtuph,
class E3 =
double>
3143 std::ptrdiff_t axis = -1,
3148 using value_type =
typename std::decay_t<E1>::value_type;
3149 std::size_t
saxis = normalize_axis(
p.dimension(), axis);
3184 template <
class E1,
class E2,
class E3>
3199 using value_type =
typename E1::value_type;
3201 if (
y.dimension() == 0)
3204 using size_type = std::decay_t<
decltype(
s[0])>;
3205 if (
x.dimension() == 1)
3210 / value_type(
s[0] - 1);
3214 XTENSOR_ASSERT(
x.dimension() == 2);
3218 m.reshape({
m.shape()[0], 1});
3220 for (size_type
i = 0;
i <
s[0];
i++)
3223 for (size_type
j =
i;
j <
s[0];
j++)
3226 covar(
j,
i) = std::inner_product(
xi.begin(),
xi.end(),
xj.begin(), 0.0)
3227 / value_type(
s[1] - 1);
3243 namespace convolve_mode
3256 template <
class E1,
class E2>
3259 using value_type =
typename std::decay<E1>::type::value_type;
3261 const std::size_t
na =
e1.size();
3262 const std::size_t
nv =
e2.size();
3263 const std::size_t
n =
na -
nv + 1;
3265 for (std::size_t i = 0; i < n; i++)
3267 for (std::size_t j = 0; j < nv; j++)
3269 out(i) += e1(j) * e2(j + i);
3275 template <
class E1,
class E2>
3276 inline auto convolve_impl(E1&& e1, E2&& e2, convolve_mode::full)
3278 using value_type =
typename std::decay<E1>::type::value_type;
3280 const std::size_t na = e1.size();
3281 const std::size_t nv = e2.size();
3282 const std::size_t n = na + nv - 1;
3284 for (std::size_t i = 0; i < n; i++)
3286 const std::size_t jmn = (i >= nv - 1) ? i - (nv - 1) : 0;
3287 const std::size_t jmx = (i < na - 1) ? i : na - 1;
3288 for (std::size_t j = jmn; j <= jmx; ++j)
3290 out(i) += e1(j) * e2(i - j);
3307 template <
class E1,
class E2,
class E3>
3308 inline auto convolve(E1&& a, E2&& v, E3 mode)
3310 if (a.dimension() != 1 || v.dimension() != 1)
3312 XTENSOR_THROW(std::runtime_error,
"Invalid dimentions convolution arguments must be 1D expressions");
3315 XTENSOR_ASSERT(a.size() > 0 && v.size() > 0);
3318 if (a.size() < v.size())
3320 return detail::convolve_impl(std::forward<E2>(v), std::forward<E1>(a), mode);
3324 return detail::convolve_impl(std::forward<E1>(a), std::forward<E2>(v), mode);
auto cumprod(E &&e, std::ptrdiff_t axis)
Cumulative product.
auto cumsum(E &&e, std::ptrdiff_t axis)
Cumulative sum.
auto fma(E1 &&e1, E2 &&e2, E3 &&e3) noexcept -> detail::xfunction_type_t< math::fma_fun, E1, E2, E3 >
Fused multiply-add operation.
auto deg2rad(E &&e) noexcept -> detail::xfunction_type_t< math::deg2rad, E >
Convert angles from degrees to radians.
auto amax(E &&e, X &&axes, EVS es=EVS())
Maximum element along given axis.
auto remainder(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< math::remainder_fun, E1, E2 >
Signed remainder of the division operation.
auto degrees(E &&e) noexcept -> detail::xfunction_type_t< math::rad2deg, E >
Convert angles from radians to degrees.
auto interp(const E1 &x, const E2 &xp, const E3 &fp, T left, T right)
Returns the one-dimensional piecewise linear interpolant to a function with given discrete data point...
auto fmod(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< math::fmod_fun, E1, E2 >
Remainder of the floating point division operation.
auto abs(E &&e) noexcept -> detail::xfunction_type_t< math::abs_fun, E >
Absolute value function.
auto fabs(E &&e) noexcept -> detail::xfunction_type_t< math::fabs_fun, E >
Absolute value function.
auto minimum(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< math::minimum< void >, E1, E2 >
Elementwise minimum.
auto maximum(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< math::maximum< void >, E1, E2 >
Elementwise maximum.
auto fmax(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< math::fmax_fun, E1, E2 >
Maximum function.
auto clip(E1 &&e1, E2 &&lo, E3 &&hi) noexcept -> detail::xfunction_type_t< math::clamp_fun, E1, E2, E3 >
Clip values between hi and lo.
auto radians(E &&e) noexcept -> detail::xfunction_type_t< math::deg2rad, E >
Convert angles from degrees to radians.
auto fdim(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< math::fdim_fun, E1, E2 >
Positive difference function.
auto amin(E &&e, X &&axes, EVS es=EVS())
Minimum element along given axis.
auto rad2deg(E &&e) noexcept -> detail::xfunction_type_t< math::rad2deg, E >
Convert angles from radians to degrees.
auto fmin(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< math::fmin_fun, E1, E2 >
Minimum function.
auto sign(E &&e) noexcept -> detail::xfunction_type_t< math::sign_fun, E >
Returns an element-wise indication of the sign of a number.
auto unwrap(E1 &&p, E2 discontinuity=xnone(), std::ptrdiff_t axis=-1, E3 period=2.0 *xt::numeric_constants< double >::PI)
Unwrap by taking the complement of large deltas with respect to the period.
auto allclose(E1 &&e1, E2 &&e2, double rtol=1e-05, double atol=1e-08) noexcept
Check if all elements in e1 are close to the corresponding elements in e2.
auto isfinite(E &&e) noexcept -> detail::xfunction_type_t< math::isfinite_fun, E >
finite value check
auto isnan(E &&e) noexcept -> detail::xfunction_type_t< math::isnan_fun, E >
NaN check.
auto isclose(E1 &&e1, E2 &&e2, double rtol=1e-05, double atol=1e-08, bool equal_nan=false) noexcept
Element-wise closeness detection.
auto isinf(E &&e) noexcept -> detail::xfunction_type_t< math::isinf_fun, E >
infinity check
auto not_equal(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< detail::not_equal_to, E1, E2 >
Element-wise inequality.
auto equal(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< detail::equal_to, E1, E2 >
Element-wise equality.
auto greater(E1 &&e1, E2 &&e2) noexcept -> decltype(std::forward< E1 >(e1) > std::forward< E2 >(e2))
Greater than.
auto lgamma(E &&e) noexcept -> detail::xfunction_type_t< math::lgamma_fun, E >
Natural logarithm of the gamma function.
auto erfc(E &&e) noexcept -> detail::xfunction_type_t< math::erfc_fun, E >
Complementary error function.
auto erf(E &&e) noexcept -> detail::xfunction_type_t< math::erf_fun, E >
Error function.
auto tgamma(E &&e) noexcept -> detail::xfunction_type_t< math::tgamma_fun, E >
Gamma function.
auto log1p(E &&e) noexcept -> detail::xfunction_type_t< math::log1p_fun, E >
Natural logarithm of one plus function.
auto expm1(E &&e) noexcept -> detail::xfunction_type_t< math::expm1_fun, E >
Natural exponential minus one function.
auto exp2(E &&e) noexcept -> detail::xfunction_type_t< math::exp2_fun, E >
Base 2 exponential function.
auto log(E &&e) noexcept -> detail::xfunction_type_t< math::log_fun, E >
Natural logarithm function.
auto log2(E &&e) noexcept -> detail::xfunction_type_t< math::log2_fun, E >
Base 2 logarithm function.
auto exp(E &&e) noexcept -> detail::xfunction_type_t< math::exp_fun, E >
Natural exponential function.
auto log10(E &&e) noexcept -> detail::xfunction_type_t< math::log10_fun, E >
Base 10 logarithm function.
auto asinh(E &&e) noexcept -> detail::xfunction_type_t< math::asinh_fun, E >
Inverse hyperbolic sine function.
auto tanh(E &&e) noexcept -> detail::xfunction_type_t< math::tanh_fun, E >
Hyperbolic tangent function.
auto cosh(E &&e) noexcept -> detail::xfunction_type_t< math::cosh_fun, E >
Hyperbolic cosine function.
auto sinh(E &&e) noexcept -> detail::xfunction_type_t< math::sinh_fun, E >
Hyperbolic sine function.
auto acosh(E &&e) noexcept -> detail::xfunction_type_t< math::acosh_fun, E >
Inverse hyperbolic cosine function.
auto atanh(E &&e) noexcept -> detail::xfunction_type_t< math::atanh_fun, E >
Inverse hyperbolic tangent function.
auto where(E1 &&e1, E2 &&e2, E3 &&e3) noexcept -> detail::xfunction_type_t< detail::conditional_ternary, E1, E2, E3 >
Ternary selection.
auto nanmax(E &&e, X &&axes, EVS es=EVS())
Maximum element along given axes, ignoring NaNs.
auto nancumsum(E &&e, std::ptrdiff_t axis)
Cumulative sum, replacing nan with 0.
auto nancumprod(E &&e, std::ptrdiff_t axis)
Cumulative product, replacing nan with 1.
auto nanmean(E &&e, X &&axes, EVS es=EVS())
Mean of elements over given axes, excluding NaNs.
auto nanmin(E &&e, X &&axes, EVS es=EVS())
Minimum element over given axes, ignoring NaNs.
auto nanprod(E &&e, X &&axes, EVS es=EVS())
Product of elements over given axes, replacing NaN with 1.
auto nansum(E &&e, X &&axes, EVS es=EVS())
Sum of elements over given axes, replacing NaN with 0.
auto nan_to_num(E &&e)
Convert nan or +/- inf to numbers.
auto ceil(E &&e) noexcept -> detail::xfunction_type_t< math::ceil_fun, E >
ceil function.
auto trunc(E &&e) noexcept -> detail::xfunction_type_t< math::trunc_fun, E >
trunc function.
auto nearbyint(E &&e) noexcept -> detail::xfunction_type_t< math::nearbyint_fun, E >
nearbyint function.
auto floor(E &&e) noexcept -> detail::xfunction_type_t< math::floor_fun, E >
floor function.
auto round(E &&e) noexcept -> detail::xfunction_type_t< math::round_fun, E >
round function.
auto rint(E &&e) noexcept -> detail::xfunction_type_t< math::rint_fun, E >
rint function.
auto cube(E1 &&e1) noexcept
Cube power function, equivalent to e1 * e1 * e1.
auto sqrt(E &&e) noexcept -> detail::xfunction_type_t< math::sqrt_fun, E >
Square root function.
auto square(E1 &&e1) noexcept
Square power function, equivalent to e1 * e1.
auto pow(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< math::pow_fun, E1, E2 >
Power function.
auto hypot(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< math::hypot_fun, E1, E2 >
Hypotenuse function.
auto cbrt(E &&e) noexcept -> detail::xfunction_type_t< math::cbrt_fun, E >
Cubic root function.
auto sum(E &&e, X &&axes, EVS es=EVS())
Sum of elements over given axes.
auto prod(E &&e, X &&axes, EVS es=EVS())
Product of elements over given axes.
auto trapz(const xexpression< T > &y, double dx=1.0, std::ptrdiff_t axis=-1)
Integrate along the given axis using the composite trapezoidal rule.
auto diff(const xexpression< T > &a, std::size_t n=1, std::ptrdiff_t axis=-1)
Calculate the n-th discrete difference along the given axis.
auto minmax(E &&e, EVS es=EVS())
Minimum and maximum among the elements of an array or expression.
auto average(E &&e, W &&weights, X &&axes, EVS ev=EVS())
Average of elements over given axes using weights.
auto mean(E &&e, X &&axes, EVS es=EVS())
Mean of elements over given axes.
auto atan(E &&e) noexcept -> detail::xfunction_type_t< math::atan_fun, E >
Arctangent function.
auto atan2(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< math::atan2_fun, E1, E2 >
Artangent function, using signs to determine quadrants.
auto asin(E &&e) noexcept -> detail::xfunction_type_t< math::asin_fun, E >
Arcsine function.
auto cos(E &&e) noexcept -> detail::xfunction_type_t< math::cos_fun, E >
Cosine function.
auto sin(E &&e) noexcept -> detail::xfunction_type_t< math::sin_fun, E >
Sine function.
auto tan(E &&e) noexcept -> detail::xfunction_type_t< math::tan_fun, E >
Tangent function.
auto acos(E &&e) noexcept -> detail::xfunction_type_t< math::acos_fun, E >
Arccosine function.
auto eval(T &&t) -> std::enable_if_t< detail::is_container< std::decay_t< T > >::value, T && >
Force evaluation of xexpression.
auto transpose(E &&e) noexcept
Returns a transpose view by reversing the dimensions of xexpression e.
bool same_shape(const S1 &s1, const S2 &s2) noexcept
Check if two objects have the same shape.
standard mathematical functions for xexpressions
auto stack(std::tuple< CT... > &&t, std::size_t axis=0)
Stack xexpressions along axis.
auto range(A start_val, B stop_val)
Select a range from start_val to stop_val (excluded).
auto arange(T start, T stop, S step=1) noexcept
Generates numbers evenly spaced within given half-open interval [start, stop).
auto all() noexcept
Returns a slice representing a full dimension, to be used as an argument of view function.
auto make_lambda_xfunction(F &&lambda, E &&... args)
Create a xfunction from a lambda.
auto reduce(F &&f, E &&e, X &&axes, EVS &&options=EVS())
Returns an xexpression applying the specified reducing function to an expression over the given axes.
std::vector< xstrided_slice< std::ptrdiff_t > > xstrided_slice_vector
vector of slices used to build a xstrided_view
auto accumulate(F &&f, E &&e, EVS evaluation_strategy=EVS())
Accumulate and flatten array NOTE This function is not lazy!
auto diagonal(E &&arr, int offset=0, std::size_t axis_1=0, std::size_t axis_2=1)
Returns the elements on the diagonal of arr If arr has more than two dimensions, then the axes specif...
xshared_expression< E > make_xshared(xexpression< E > &&expr)
Helper function to create shared expression from any xexpression.
auto strided_view(E &&e, S &&shape, X &&stride, std::size_t offset=0, layout_type layout=L) noexcept
Construct a strided view from an xexpression, shape, strides and offset.
auto diag(E &&arr, int k=0)
xexpression with values of arr on the diagonal, zeroes otherwise
auto xtuple(Types &&... args)
Creates tuples from arguments for concatenate and stack.
auto cov(const E1 &x, const E1 &y=E1())
Returns the covariance matrix.