6namespace uni20::detail::native_math
8template <NativeReal R> R
agm(R a, R b)
10 using L = numeric_limits<R>;
11 if (std::isnan(a) || std::isnan(b))
return L::quiet_NaN();
12 if (a == 0 || b == 0)
return std::isfinite(a) && std::isfinite(b) ? R(0) : L::quiet_NaN();
13 if (a < 0 || b < 0)
return L::quiet_NaN();
15 if (std::isinf(a) || std::isinf(b))
return L::infinity();
16 if (a < b) std::swap(a, b);
19 a = std::frexp(a, &ae);
20 b = std::frexp(b, &be);
21 while (ae - be > L::digits() + 2)
27 int odd = (
sum % 2 + 2) % 2;
28 int exponent = (
sum - odd) / 2;
29 R geometric = std::sqrt(a * b * R(odd ? 2 : 1));
31 b = std::frexp(geometric, &shift);
32 be = exponent + shift;
38 b = std::ldexp(b, be - ae);
39 constexpr int limit = 2 * std::bit_width(
static_cast<unsigned>(L::digits())) + 8;
40 for (
int iteration = 0; iteration < limit; ++iteration)
42 R arithmetic = (a + b) / 2;
43 if (std::abs(a - b) <= std::ldexp(a, 1 - L::digits()))
return std::ldexp(arithmetic, ae);
49 return L::quiet_NaN();
constexpr detail::scalar_math::agm_fn agm
Nonnegative arithmetic-geometric mean.
Definition math.hpp:625
void sum(BackendSelector selector, async::Async< OutputTensor > &output, async::Async< InputTensor > const &input)
Schedule a full sum into an explicit async scalar tensor.
Definition linalg/async/reductions.hpp:309