13namespace uni20::detail::native_math::airy_detail
15template <
int Capacity>
struct UInt
18 std::array<std::uint32_t, Capacity> w{};
22 while (size && !w[size - 1])
25 int bits()
const {
return size ? 32 * (
size - 1) + 32 - std::countl_zero(w[size - 1]) : 0; }
26 bool bit(
int k)
const {
return k >= 0 && k / 32 <
size && ((w[k / 32] >> (k % 32)) & 1); }
30 for (
int i = 0; i <
size; ++i)
32 auto t = (std::uint64_t(w[i]) << n) |
c;
33 w[i] = std::uint32_t(t);
38 assert(size < Capacity);
45 for (
int i = 0; i <
size; ++i)
47 auto t = std::uint64_t(w[i]) +
c;
48 w[i] = std::uint32_t(t);
54 assert(size < Capacity);
58 std::uint32_t trial_word(
int i)
const
60 return (i < size ? w[i] << 2 : 0u) | (i > 0 && i - 1 <
size ? w[i - 1] >> 30 : 0u) | (i == 0 ? 1u : 0u);
62 bool subtract_trial(UInt
const& root)
64 int n = root.size + (root.size && root.w[root.size - 1] >> 30 ? 1 : 0);
69 for (
int i = size - 1; i >= 0; --i)
71 auto b = root.trial_word(i);
79 if (!ge)
return false;
80 std::uint64_t borrow = 0;
81 for (
int i = 0; i <
size; ++i)
83 std::uint64_t b = std::uint64_t(root.trial_word(i)) + borrow;
84 auto a = std::uint64_t(w[i]);
85 w[i] = std::uint32_t(a - b);
92 static UInt mul(UInt
const& a, UInt
const& b)
95 r.size = a.size + b.size;
96 assert(r.size <= Capacity);
97 for (
int i = 0; i < a.size; ++i)
100 for (
int j = 0; j < b.size; ++j)
102 auto t = std::uint64_t(a.w[i]) * b.w[j] + r.w[i + j] +
c;
103 r.w[i + j] = std::uint32_t(t);
114template <
int Capacity> UInt<Capacity> root_scaled(UInt<Capacity>
const& n,
int shift)
116 UInt<Capacity> root, rem;
117 int pairs = (n.bits() + 2 * shift + 1) / 2;
118 for (
int i = pairs - 1; i >= 0; --i)
121 rem.add(
unsigned(n.bit(2 * i + 1 - 2 * shift)) * 2 + unsigned(n.bit(2 * i - 2 * shift)));
122 bool up = rem.subtract_trial(root);
131template <NativeReal R,
int Capacity> std::pair<R, R> phase_impl(R x)
133 using Integer = UInt<Capacity>;
136 R f = std::frexp(x, &exponent);
138 for (
int k = 0; k < L::digits(); ++k)
148 Integer n = Integer::mul(Integer::mul(m, m), m);
149 int e = 3 * (exponent - L::digits());
156 constexpr int guard = L::digits() + 32;
157 int shift = std::max(0, e + guard);
158 Integer root = root_scaled(n, shift);
159 int constant_bits = ((3 * exponent / 2 + guard + 16 + 31) / 32) * 32;
160 assert(constant_bits > 0 && constant_bits <= phase_constant_bits);
162 c.size = constant_bits / 32;
163 for (
int i = 0; i < constant_bits / 32; ++i)
164 c.w[i] = phase_constant[constant_bits / 32 - 1 - i];
165 Integer prod = Integer::mul(root,
c);
166 int binary_point = shift - e + constant_bits;
167 int q = (unsigned(prod.bit(binary_point)) + 2 * unsigned(prod.bit(binary_point + 1)) + 1) % 4;
169 for (
int k = L::digits() + 16; k >= 1; --k)
170 frac = (frac + R(prod.bit(binary_point - k))) / 2;
171 R angle = (frac - R(.5)) * (uni20::pi<R> / 2);
172 R s = std::sin(angle), co = std::cos(angle);
188template <NativeReal R> std::pair<R, R> phase(R x)
192 assert(x >= 4 && std::isfinite(x));
195 if (e <= 128)
return phase_impl<R, 32>(x);
197 return phase_impl<R, 2 * ((max_bits + 31) / 32) + 8>(x);
std::string trim(const std::string &s)
Definition terminal.cpp:162
std::pair< int, int > size(std::FILE *stream)
Return the terminal size associated with a C stream.
Definition terminal.cpp:504
int add(int a, int b)
Definition dummy.cpp:6
Project-level numeric limits customization point.
Definition numeric_limits.hpp:16