Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
native_airy_expansion.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "native_math.hpp"
4#include <algorithm>
5#include <array>
6#include <cmath>
7
8namespace uni20::detail::native_math::airy_detail
9{
10// Four nonoverlapping native words protect central-series cancellation.
11// This private arithmetic has no independent scalar API or dynamic storage.
12template <NativeReal R> class Expansion {
13 static constexpr int words_ = 4;
14 std::array<R, 2 * words_ * words_ + 2> terms_{};
15 int size_ = 0;
16 void add(R v)
17 {
18 int n = 0;
19 for (int i = 0; i < size_; ++i)
20 {
21 R s = v + terms_[i], p = s - v, e = (v - (s - p)) + (terms_[i] - p);
22 if (e != 0) terms_[n++] = e;
23 v = s;
24 }
25 if (v != 0 || n == 0) terms_[n++] = v;
26 size_ = n;
27 }
28 void compress()
29 {
30 R carry = this->high();
31 int bottom = size_;
32 for (int i = size_ - 2; i >= 0; --i)
33 {
34 R s = carry + terms_[i], e = terms_[i] - (s - carry);
35 if (e != 0)
36 {
37 terms_[--bottom] = s;
38 carry = e;
39 }
40 else
41 carry = s;
42 }
43 int n = 0;
44 for (int i = bottom; i < size_; ++i)
45 {
46 R s = terms_[i] + carry, e = carry - (s - terms_[i]);
47 if (e != 0) terms_[n++] = e;
48 carry = s;
49 }
50 terms_[n++] = carry;
51 size_ = n;
52 if (size_ > words_)
53 {
54 std::copy(terms_.begin() + size_ - words_, terms_.begin() + size_, terms_.begin());
55 size_ = words_;
56 }
57 }
58
59 public:
60 Expansion(R x = 0) { this->add(x); }
61 R high() const { return terms_[size_ - 1]; }
62 Expansion scaled(int n) const
63 {
64 Expansion r = *this;
65 for (int k = 0; k < size_; ++k)
66 r.terms_[k] = std::ldexp(r.terms_[k], n);
67 return r;
68 }
69 R rounded() const
70 {
71 R r = 0;
72 for (int i = 0; i < size_; ++i)
73 r += terms_[i];
74 return r;
75 }
76 friend Expansion operator+(Expansion a, Expansion const& b)
77 {
78 for (int i = 0; i < b.size_; ++i)
79 a.add(b.terms_[i]);
80 a.compress();
81 return a;
82 }
83 friend Expansion operator-(Expansion a)
84 {
85 for (int i = 0; i < a.size_; ++i)
86 a.terms_[i] = -a.terms_[i];
87 return a;
88 }
89 friend Expansion operator-(Expansion a, Expansion const& b) { return a + -b; }
90 friend Expansion operator*(Expansion const& a, Expansion const& b)
91 {
92 Expansion r;
93 for (int i = 0; i < a.size_; ++i)
94 for (int j = 0; j < b.size_; ++j)
95 {
96 R p = a.terms_[i] * b.terms_[j];
97 r.add(std::fma(a.terms_[i], b.terms_[j], -p));
98 r.add(p);
99 }
100 r.compress();
101 return r;
102 }
103 friend Expansion operator/(Expansion a, Expansion const& b)
104 {
105 Expansion q;
106 for (int i = 0; i < words_; ++i)
107 {
108 R next = a.high() / b.high();
109 Expansion v(next);
110 q = q + v;
111 a = a - v * b;
112 }
113 return q;
114 }
115 friend Expansion operator/(Expansion a, R b)
116 {
117 Expansion q;
118 for (int i = 0; i < words_; ++i)
119 {
120 R next = a.high() / b;
121 Expansion v(next);
122 q = q + v;
123 a = a - v * Expansion(b);
124 }
125 return q;
126 }
127};
128} // namespace uni20::detail::native_math::airy_detail
auto operator-(Async< T > const &x)
Unary negation overload for Async values.
Definition async_ops.hpp:477
Var< T > operator*(T x, Var< T > y)
Computes x * y with reverse-mode gradient propagation.
Definition var_toys.hpp:176
Var< T > operator+(Var< T > x, T y)
Computes x + y with reverse-mode gradient propagation.
Definition var_toys.hpp:136
Definition data_table.cpp:8
int add(int a, int b)
Definition dummy.cpp:6
constexpr auto operator/(basic_half_int< T > lhs, U rhs) -> U
Divide a half-integer value by a floating-point scalar.
Definition half_int.hpp:422