6namespace uni20::detail::native_math
12template <NativeReal R>
class compound_expansion {
17 for (
int i = 0; i < size_; ++i)
29 static compound_expansion
multiply(compound_expansion
const& a, compound_expansion
const& b)
31 compound_expansion result;
32 for (
int i = 0; i < a.size_; ++i)
33 for (
int j = 0; j < b.size_; ++j)
35 R
product = a.terms_[i] * b.terms_[j];
36 result.add(std::fma(a.terms_[i], b.terms_[j], -
product));
48 std::frexp(this->high(), &exponent);
49 for (
int i = 0; i < size_; ++i)
50 terms_[i] = std::ldexp(terms_[i], -exponent);
54 R rounded(
bool reciprocal)
const
59 for (
int i = 0; i < size_; ++i)
65 R quotient = R(1) / this->high();
66 R residual = std::fma(-quotient, this->high(), R(1));
67 for (
int i = size_ - 2; i >= 0; --i)
68 residual = std::fma(-quotient, terms_[i], residual);
69 return quotient + residual / this->high();
73 static constexpr int digits_ = numeric_limits<R>::digits();
74 static constexpr int words_ = (digits_ + 72 + digits_ - 1) / digits_;
76 std::array<R, 2 * words_ * words_ + 2> terms_{};
79 R high()
const {
return terms_[size_ - 1]; }
86 R carry = this->high();
88 for (
int i = size_ - 2; i >= 0; --i)
90 R
sum = carry + terms_[i];
94 terms_[--bottom] =
sum;
101 for (
int i = bottom; i < size_; ++i)
103 R
sum = terms_[i] + carry;
104 R
error = carry - (
sum - terms_[i]);
108 terms_[
size++] = carry;
112 std::copy(terms_.begin() + size_ - words_, terms_.begin() + size_, terms_.begin());
118template <NativeReal R> R portable_compound(R x, std::int64_t exponent)
120 using L = numeric_limits<R>;
121 if (x < R(-1))
return L::quiet_NaN();
122 if (exponent == 0 || x == 0)
return R(1);
123 if (std::isnan(x))
return x;
124 if (x == R(-1))
return exponent < 0 ? L::infinity() : R(0);
125 if (std::isinf(x))
return exponent > 0 ? L::infinity() : R(0);
126 if (exponent == 1)
return R(1) + x;
128 compound_expansion<R> base;
131 int base_exponent = base.normalize();
132 compound_expansion<R> result;
134 int result_exponent = 1;
136 auto remaining = exponent < 0 ? std::uint64_t(0) - std::uint64_t(exponent) :
std::uint64_t(exponent);
137 constexpr int limit = 2 * (L::max_exponent - L::min_exponent + L::digits());
142 result = compound_expansion<R>::multiply(result, base);
143 result_exponent += base_exponent + result.normalize();
149 if (result_exponent > limit || base_exponent > limit)
return exponent > 0 ? L::infinity() : R(0);
150 if (result_exponent < -limit || base_exponent < -limit)
return exponent > 0 ? R(0) : L::infinity();
154 base = compound_expansion<R>::multiply(base, base);
155 base_exponent = 2 * base_exponent + base.normalize();
158 return std::ldexp(result.rounded(exponent < 0), exponent < 0 ? -result_exponent : result_exponent);
161template <NativeReal R>
struct compound_math_provider
163 static R evaluate(R x, std::int64_t exponent) {
return portable_compound(x, exponent); }
165#if UNI20_HAS_COMPOUNDN_FLOAT
166template <>
struct compound_math_provider<float>
168 static float evaluate(
float x, std::int64_t exponent) { return ::compoundnf(x, exponent); }
171#if UNI20_HAS_COMPOUNDN_DOUBLE
172template <>
struct compound_math_provider<double>
174 static double evaluate(
double x, std::int64_t exponent) { return ::compoundn(x, exponent); }
177#if UNI20_HAS_COMPOUNDN_LONG_DOUBLE
178template <>
struct compound_math_provider<long double>
180 static long double evaluate(
long double x, std::int64_t exponent) { return ::compoundnl(x, exponent); }
183#if UNI20_HAS_FLOAT128 && UNI20_HAS_COMPOUNDN_FLOAT128
184template <>
struct compound_math_provider<float128>
186 static float128 evaluate(float128 x, std::int64_t exponent) { return ::compoundnf128(x, exponent); }
190template <NativeReal R, MathInteger I> R
compound(R x, I exponent)
192 return compound_math_provider<R>::evaluate(x, math_integer(exponent));
locale_t value
Definition data_table.cpp:49
T product(std::vector< T > const &values)
Definition mpreal_exact_example.cpp:13
std::pair< int, int > size(std::FILE *stream)
Return the terminal size associated with a C stream.
Definition terminal.cpp:504
void normalize(Ops &ops, V &v, make_real_t< S > const &length, Precision p)
Definition gmres.hpp:139
constexpr detail::scalar_math::compound_fn compound
Integer power of one plus x, retaining the original increment.
Definition math.hpp:668
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
int add(int a, int b)
Definition dummy.cpp:6
double multiply(double a, double b)
Definition dummy.cpp:8