1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
//! The per-axis form of the error bound of the filter.
//!
//! A form is multihomogeneous when every sum and difference combines nodes
//! of the same degree in each axis (see [`DiffGraph::axis_degrees`]). For
//! such a form the bound keeps one size and one uncertainty per axis
//! instead of a single one. For a call, on each axis `k` (0, 1 and 2 for x,
//! y and z), let `delta_k` be the largest magnitude of the computed leaves of
//! that axis, `E_k` the sum of the two largest errors of the points on that
//! axis, and `D_k = delta_k + E_k`. A node has a degree vector
//! `g = (g_0, g_1, g_2)`; write `D^g = D_0^g_0 * D_1^g_1 * D_2^g_2` and `e_k`
//! for the unit vector of axis `k`. Every node gets exact coefficients `m`,
//! `c`, `alpha` and one `beta_k` per axis such that
//!
//! ```text
//! |true value| <= m * D^g
//! |computed value| <= c * D^g
//! |computed - true| <= alpha * D^g + sum over k of beta_k * E_k * D^(g - e_k)
//! ```
//!
//! with `beta_k = 0` whenever `g_k = 0`. The rules are those of the global
//! form ([`filter_bound`]) with `beta` split by axis:
//!
//! - a leaf of axis `k` has `g = e_k`, `m = 1 + u`, `c = 1`, `alpha = u`,
//! `beta_k = 1` and the other two `beta` zero: its computed value is at
//! most `delta_k <= D_k`, and it differs from the true one by the rounding
//! of the subtraction, at most `u delta_k`, plus the errors of its two
//! points on axis `k`, at most `E_k`;
//! - a negation is exact and keeps the coefficients of its operand;
//! - a sum or difference of `x` and `y`, of equal degree vectors, has the
//! `m`, `c` and `alpha` of the global form and `beta_k = beta_x,k +
//! beta_y,k`;
//! - a product of `x` and `y` adds the degree vectors, has the `m`, `c` and
//! `alpha` of the global form and `beta_k = c_x beta_y,k + m_y beta_x,k`,
//! from `x~ y~ - x y = x~ (y~ - y) + y (x~ - x)`: the factor
//! `D^(g_y - e_k)` of an error term of `y` times the `D^(g_x)` of `x~`
//! gives `D^(g - e_k)`.
//!
//! The root gives `epsilon = alpha` and `kappa_k = beta_k`. The rules for
//! `m`, `c` and `alpha` are those of the global form, and those for `beta`
//! are linear with the same coefficients, so `epsilon` is the `epsilon` of
//! the global form and the `kappa_k` add up to its `kappa`.
//!
//! # Range of validity
//!
//! The node rules assume that no value overflows and that every rounding
//! error is at most `u` times the computed magnitude. With `G` the degree
//! vector of the root and `K` its total degree (the degree of the global
//! form), let `d_min = 2^j_min` and `d_max = 2^j_max` be the powers of two
//! that [`FilterBound::constants`] gives for the same graph: `j_max` the
//! largest `j >= 1` with `c_x * 2^(j |g_x|) <= 2^1022` at every node `x`,
//! where `|g_x|` is the total degree of `x`, and `j_min` the smallest
//! `j <= -1` with, for `P = 2^j`,
//!
//! 1. `epsilon * P^K * 2^-32 >= N * K * c_max * 2^-1074`, with `N` the number
//! of products and `c_max` the largest `c`, and
//! 2. `epsilon * P^K >= 2^-1021`.
//!
//! **Claim.** Let the filter compute `d_k = delta_k + E_k` in `f64` on every
//! axis `k` with `G_k >= 1` and accept the bound only when
//! `d_min <= d_k <= d_max` on each of them, with `E_k` finite, nonnegative and
//! not below the true sum of the two largest errors. Let it evaluate the
//! bound in `f64` as a sum, in any order, of the terms
//! `EPSILON * D^G` and, for each axis with `G_k >= 1`,
//! `KAPPA_k * E_k * D^(G - e_k)`, each term a chain of products that starts
//! with its constant and multiplies the factors in any order, with the `d_k`
//! in place of the `D_k` and the emitted constants `EPSILON` and `KAPPA_k`,
//! at least `1 + 2^-30` times the exact ones. Then the computed bound is at
//! least the error of the computed value of the form. The axes with
//! `G_k = 0` take no part: no leaf and no factor uses them.
//!
//! **Proof.** Write `D_k = d_k / (1 - u)`. A sum of nonnegative values rounds
//! down by at most a factor `1 - u` (it is exact when the result is
//! subnormal), so `D_k >= delta_k + E_k`. The node bounds hold for any
//! `D_k >= delta_k + E_k`, since they only grow with `D_k`, so they hold with
//! these `D_k`, and `d_k >= d_min` gives `D_k >= d_min`. Let `B` be the exact
//! bound `epsilon * D^G + sum over k of kappa_k * E_k * D^(G - e_k)` with
//! these `D_k`.
//!
//! - Overflow. Every computed node is at most `c_x * (delta + E)^(g_x)`, and
//! on each axis `delta_k + E_k <= D_k <= d_max / (1 - u)`, so it is at most
//! `c_x * 2^(j_max |g_x|) * (1 - u)^-|g_x| <= 2^1022 * (1 - u)^-1022`, below
//! `2^1023`: no node overflows. An overflow in the evaluation of the bound
//! gives an infinite bound, or a NaN one when an infinite partial product
//! is then multiplied by an `E_k` of zero; either only makes the filter
//! abstain, since it decides on `|value| > bound`, false for both.
//! - Underflow of the form. A sum or difference whose result is subnormal is
//! exact; a product that underflows errs by at most `2^-1075` in absolute
//! terms; allow `2^-1074`. As in the global form, that error reaches the
//! root multiplied by at most `p'(c_x)` times the product of the bounds on
//! the other factors met on the way, where `p(t)` is `c_root` computed by
//! the rules with `c_x` replaced by `t`. Degree vectors add along products,
//! so the other factors on any path from `x` to the root have degree vector
//! `G - g_x` and their bounds multiply to `D^(G - g_x)`; and as in the
//! global form `p'(c_x) <= K * c_max`. So the total underflow error is at
//! most `U = sum over the products x of K * c_max * 2^-1074 * D^(G - g_x)`.
//! On every axis with `g_x,k >= 1` the root has `G_k >= 1`, so `D_k >= P`
//! with `P = d_min < 1`: the factors with `D_k >= 1` are at least 1 and the
//! others at least `P`, so `D^(g_x) >= P^|g_x| >= P^K`, and
//! `D^(G - g_x) <= D^G / P^K`. Condition 1 then gives
//! `U <= N * K * c_max * 2^-1074 * D^G / P^K <= 2^-32 * epsilon * D^G
//! <= 2^-32 * B`. Terms of second order in these errors are smaller by a
//! factor of about `2^-1000` and are absorbed by the same slack, as in the
//! global form. The computed value of the form errs by at most
//! `(1 + 2^-32) * B`.
//! - Rounding of the bound. Each term is a chain of `K` products of
//! nonnegative values, and its factors `d_k` are `(1 - u) D_k`, exactly.
//! While no partial product is subnormal, the computed term is at least the
//! exact term with the `D_k` times `(1 - u)^(2K)`: `K` roundings and at most
//! `K` uses of a `d_k`. The terms are summed with at most 3 more roundings,
//! so the computed bound is at least `(1 + 2^-30) (1 - u)^(2K + 3) B`,
//! which is at least `(1 + 2^-31) B` for `K <= 1022`, as in the global
//! form, less the losses to underflow.
//! - Underflow of the bound. A partial product of the term of `EPSILON` is
//! `EPSILON` times at most `K` of the `d_k`, each `d_k >= P` or above 1,
//! so before rounding it is at least `epsilon * P^K`, at least `2^-1021`
//! by condition 2, and after at most `K` roundings at least
//! `(1 - u)^K * 2^-1021 > 2^-1022`: those partial products are normal. A
//! partial product of the term of `KAPPA_k` may underflow, and loses at
//! most `2^-1075`, which the remaining factors then multiply. Those factors
//! are `d` values and perhaps `E_k <= D_k`, so the loss is at most
//! `2^-1075 * (1 + u)^K * D^G / Q`, where `Q` is the product of the `D_k`
//! of the factors already multiplied, counting `D_k` for `E_k`. As above,
//! `Q >= P^K`, and condition 2 gives `1 / P^K <= 2^1021 * epsilon`, so the
//! loss is at most `2^-54 * (1 + u)^K * epsilon * D^G <= 2^-53 * B`. At
//! most `3K` partial products can underflow, so the losses are at most
//! `3 * 1022 * 2^-53 * B < 2^-41 * B`.
//!
//! The computed bound is then at least `(1 + 2^-31 - 2^-41) * B`, more than
//! the error `(1 + 2^-32) * B`. The conditions on `P` are those of the global
//! form with `k = K`, so `d_min` and `d_max` are the same two powers of two.
//!
//! A condition on the product of the `D_k` alone is not enough: with
//! `D_y = D_z = 2^-520` and `D_x = 2^100` the product is far from the limits,
//! but a product of a leaf of y and a leaf of z is subnormal, and its
//! rounding error, multiplied by a leaf of x, exceeds the bound. The proof
//! above needs `D^(g_x) >= P^K` at every product, which bounding each `D_k`
//! separately gives.
//!
//! An axis with `D_k = 0` (every leaf of the axis is zero and `E_k = 0`) is
//! below the range; [`AxisBound::certain_zero`] says when the value of the
//! form is then exactly zero.
use ;
use crate;
use crateDyadic;
use crateError;
use crateNodeId;
use cratePosition;
/// The form of the error bound of the filter of a predicate.
/// Derives the error bound of the `f64` evaluation of `graph`: the per-axis
/// form when every term has the same degree in each axis, and the global
/// form of [`filter_bound`] otherwise.
///
/// The per-axis bound follows the rules of the global form with one `beta`
/// per axis; the documentation of [`AxisBound`] gives them, and its range of
/// validity.
///
/// # Errors
///
/// The errors of [`filter_bound`], with the same limits, for either form:
/// the per-axis form has the same degrees, the same `m`, `c` and `alpha`,
/// and the same range as the global one.
/// The bounds of one node of degree vector `degrees`, in terms of the `D_k`
/// and `E_k`: `|true value| <= m * D^g`, `|computed value| <= c * D^g` and
/// `|computed - true| <= alpha * D^g + sum of beta_k * E_k * D^(g - e_k)`.
pub
/// The exact per-axis error bound of the `f64` evaluation of a
/// multihomogeneous difference form.
///
/// For a call, with `D_k = delta_k + E_k` on each axis (see the
/// documentation of this module, in the source, for the definitions and the
/// proof), the `f64` value of the form differs from the exact value at the
/// exact points by at most
/// `epsilon * D^G + sum over k of kappa_k * E_k * D^(G - e_k)`, where `G` is
/// [`AxisBound::degrees`], while on every axis of positive degree the size
/// computed in `f64`, `d_k = delta_k + E_k`, is in the range of
/// [`AxisBound::constants`].
/// The constants of the per-axis filter of a predicate, as `f64`.
///
/// The filter decides when `d_min <= d_k <= d_max` on every axis `k` with
/// `degrees[k] >= 1`, where `d_k = delta_k + E_k` is computed in `f64`, and
/// `|value| > epsilon * d^G + sum over k of kappa[k] * E_k * d^(G - e_k)`,
/// evaluated as a sum of chains of products, each starting with its
/// constant.
/// Applies the per-axis rules to `graph`, whose nodes have the degree
/// vectors `degrees`.