Coverage Report

Created: 2026-11-03 08:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/robust-1.2.0/src/lib.rs
Line
Count
Source
1
#![cfg_attr(feature = "no_std", no_std)]
2
#![doc(html_logo_url = "https://raw.githubusercontent.com/georust/meta/master/logo/logo.png")]
3
// Copyright 2017 The Spade Developers.
4
// Copyright 2020 The GeoRust Project Developers.
5
//
6
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
7
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
9
// option. This file may not be copied, modified, or distributed
10
// except according to those terms.
11
#![allow(non_snake_case)]
12
13
//! # Adaptive Precision Floating-Point Arithmetic and Fast Robust Predicates for Computational Geometry
14
//! This is a direct transcript of the source code and algorithms provided by
15
//! Jonathan Richard Shewchuk ([https://www.cs.cmu.edu/~quake/robust.html](https://www.cs.cmu.edu/~quake/robust.html))
16
//! See the paper and the source code for more information.
17
//!
18
//! The module offers adaptive and precise calculations for orientation queries
19
//! – "on which side of a line (2d) or plane (3d) does a point lie?" – and in-circle / in-sphere queries
20
//! – "is a given point contained in the circumference of a triangle?".  
21
//! The "adaptive" nature will increase performance only if a simpler calculation
22
//! cannot be guaranteed to be accurate enough, yielding higher performance on
23
//! average.
24
//!
25
//! The public API will accept both `f32` and `f64` input points for predicate checking, with input being converted to
26
//! `f64` values for internal use.
27
//! This has no effect on precision, as the [IEEE-754 standard](https://drive.google.com/file/d/0B3O3Ys97VjtxYXBCY08wanNoZ1U/view) (section 5.3)
28
//! guarantees that conversion from `f32` to `f64` must be exact.
29
//!
30
//! # Features
31
//! - `no_std`: Build without the Rust standard library
32
33
#[cfg(test)]
34
mod tests;
35
36
/// A two dimensional coordinate.
37
#[derive(Copy, Clone, Debug, PartialEq)]
38
pub struct Coord<T: Into<f64>> {
39
    pub x: T,
40
    pub y: T,
41
}
42
43
/// A three dimensional coordinate.
44
#[derive(Copy, Clone, Debug, PartialEq)]
45
pub struct Coord3D<T: Into<f64>> {
46
    pub x: T,
47
    pub y: T,
48
    pub z: T,
49
}
50
51
// These values are precomputed from the "exactinit" method of the c-source code. They should? be
52
// the same in all IEEE-754 environments, including rust f64
53
const SPLITTER: f64 = 134_217_729f64;
54
const EPSILON: f64 = 0.000_000_000_000_000_111_022_302_462_515_65;
55
const RESULTERRBOUND: f64 = (3.0 + 8.0 * EPSILON) * EPSILON;
56
const CCWERRBOUND_B: f64 = (2.0 + 12.0 * EPSILON) * EPSILON;
57
const CCWERRBOUND_C: f64 = (9.0 + 64.0 * EPSILON) * EPSILON * EPSILON;
58
const O3DERRBOUND_A: f64 = (7.0 + 56.0 * EPSILON) * EPSILON;
59
const O3DERRBOUND_B: f64 = (3.0 + 28.0 * EPSILON) * EPSILON;
60
const O3DERRBOUND_C: f64 = (26.0 + 288.0 * EPSILON) * EPSILON * EPSILON;
61
const ICCERRBOUND_A: f64 = (10.0 + 96.0 * EPSILON) * EPSILON;
62
const ICCERRBOUND_B: f64 = (4.0 + 48.0 * EPSILON) * EPSILON;
63
const ICCERRBOUND_C: f64 = (44.0 + 576.0 * EPSILON) * EPSILON * EPSILON;
64
const ISPERRBOUND_A: f64 = (16.0 + 224.0 * EPSILON) * EPSILON;
65
const ISPERRBOUND_B: f64 = (5.0 + 72.0 * EPSILON) * EPSILON;
66
const ISPERRBOUND_C: f64 = (71.0 + 1408.0 * EPSILON) * EPSILON * EPSILON;
67
68
#[inline(always)]
69
0
fn abs(x: f64) -> f64 {
70
0
    x.abs()
71
0
}
72
73
/// Returns a positive value if the coordinates `pa`, `pb`, and `pc` occur in counterclockwise order
74
/// (`pc` lies to the **left** of the directed line defined by coordinates `pa` and `pb`).  
75
/// Returns a negative value if they occur in clockwise order (`pc` lies to the **right** of the directed line `pa, pb`).  
76
/// Returns `0` if they are **collinear**.  
77
0
pub fn orient2d<T: Into<f64>>(pa: Coord<T>, pb: Coord<T>, pc: Coord<T>) -> f64 {
78
0
    let pa = Coord {
79
0
        x: pa.x.into(),
80
0
        y: pa.y.into(),
81
0
    };
82
0
    let pb = Coord {
83
0
        x: pb.x.into(),
84
0
        y: pb.y.into(),
85
0
    };
86
0
    let pc = Coord {
87
0
        x: pc.x.into(),
88
0
        y: pc.y.into(),
89
0
    };
90
91
0
    let detleft = (pa.x - pc.x) * (pb.y - pc.y);
92
0
    let detright = (pa.y - pc.y) * (pb.x - pc.x);
93
0
    let det = detleft - detright;
94
95
    // The errbound calculation was changed to require only one branch on the likely execution path.
96
    // This improves performance on modern processors as discussed by Ozaki et al in
97
    // https://doi.org/10.1007/s10543-015-0574-9
98
    // The underflow guard "+ u_N" was omitted because orient2dadapt(...) would not guarantee
99
    // correct results in cases of underflow, the derivation of THETA is given in the reference.
100
0
    let detsum = abs(detleft + detright);
101
    const THETA: f64 = 3.3306690621773722e-16;
102
0
    let errbound = THETA * detsum;
103
0
    if det >= errbound || -det >= errbound {
104
0
        det
105
    } else {
106
0
        orient2dadapt(pa, pb, pc, detsum)
107
    }
108
0
}
Unexecuted instantiation: robust::orient2d::<f64>
Unexecuted instantiation: robust::orient2d::<_>
109
110
0
fn orient2dadapt(pa: Coord<f64>, pb: Coord<f64>, pc: Coord<f64>, detsum: f64) -> f64 {
111
0
    let acx = pa.x - pc.x;
112
0
    let bcx = pb.x - pc.x;
113
0
    let acy = pa.y - pc.y;
114
0
    let bcy = pb.y - pc.y;
115
116
0
    let (detleft, detlefttail) = two_product(acx, bcy);
117
0
    let (detright, detrighttail) = two_product(acy, bcx);
118
119
0
    let (B3, B2, B1, B0) = two_two_diff(detleft, detlefttail, detright, detrighttail);
120
0
    let B = [B0, B1, B2, B3];
121
122
0
    let mut det = estimate(&B);
123
0
    let errbound = CCWERRBOUND_B * detsum;
124
0
    if det >= errbound || (-det >= errbound) {
125
0
        return det;
126
0
    }
127
128
0
    let acxtail = two_diff_tail(pa.x, pc.x, acx);
129
0
    let bcxtail = two_diff_tail(pb.x, pc.x, bcx);
130
0
    let acytail = two_diff_tail(pa.y, pc.y, acy);
131
0
    let bcytail = two_diff_tail(pb.y, pc.y, bcy);
132
133
0
    if acxtail == 0.0 && acytail == 0.0 && bcxtail == 0.0 && bcytail == 0.0 {
134
0
        return det;
135
0
    }
136
137
0
    let errbound = CCWERRBOUND_C * detsum + RESULTERRBOUND * abs(det);
138
0
    det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);
139
140
0
    if det >= errbound || -det >= errbound {
141
0
        return det;
142
0
    }
143
144
0
    let (s1, s0) = two_product(acxtail, bcy);
145
0
    let (t1, t0) = two_product(acytail, bcx);
146
0
    let (u3, u2, u1, u0) = two_two_diff(s1, s0, t1, t0);
147
0
    let U = [u0, u1, u2, u3];
148
149
0
    let mut C1 = [0.0f64; 8];
150
0
    let c1length = fast_expansion_sum_zeroelim(&B, &U, &mut C1);
151
152
0
    let (s1, s0) = two_product(acx, bcytail);
153
0
    let (t1, t0) = two_product(acy, bcxtail);
154
0
    let (u3, u2, u1, u0) = two_two_diff(s1, s0, t1, t0);
155
0
    let U = [u0, u1, u2, u3];
156
157
0
    let mut C2 = [0.0f64; 12];
158
0
    let c2length = fast_expansion_sum_zeroelim(&C1[..c1length], &U, &mut C2);
159
160
0
    let (s1, s0) = two_product(acxtail, bcytail);
161
0
    let (t1, t0) = two_product(acytail, bcxtail);
162
0
    let (u3, u2, u1, u0) = two_two_diff(s1, s0, t1, t0);
163
0
    let U = [u0, u1, u2, u3];
164
0
    let mut D = [0.0f64; 16];
165
0
    let dlength = fast_expansion_sum_zeroelim(&C2[..c2length], &U, &mut D);
166
0
    D[dlength - 1]
167
0
}
168
169
/// Returns a positive value if the point `pd` lies below the plane passing through `pa`, `pb`, and `pc`
170
/// ("below" is defined so that `pa`, `pb`, and `pc` appear in counterclockwise order when viewed from above the plane).  
171
/// Returns a negative value if `pd` lies above the plane.  
172
/// Returns `0` if they are **coplanar**.  
173
0
pub fn orient3d<T: Into<f64>>(
174
0
    pa: Coord3D<T>,
175
0
    pb: Coord3D<T>,
176
0
    pc: Coord3D<T>,
177
0
    pd: Coord3D<T>,
178
0
) -> f64 {
179
0
    let pa = Coord3D {
180
0
        x: pa.x.into(),
181
0
        y: pa.y.into(),
182
0
        z: pa.z.into(),
183
0
    };
184
0
    let pb = Coord3D {
185
0
        x: pb.x.into(),
186
0
        y: pb.y.into(),
187
0
        z: pb.z.into(),
188
0
    };
189
0
    let pc = Coord3D {
190
0
        x: pc.x.into(),
191
0
        y: pc.y.into(),
192
0
        z: pc.z.into(),
193
0
    };
194
0
    let pd = Coord3D {
195
0
        x: pd.x.into(),
196
0
        y: pd.y.into(),
197
0
        z: pd.z.into(),
198
0
    };
199
200
0
    let adx = pa.x - pd.x;
201
0
    let bdx = pb.x - pd.x;
202
0
    let cdx = pc.x - pd.x;
203
0
    let ady = pa.y - pd.y;
204
0
    let bdy = pb.y - pd.y;
205
0
    let cdy = pc.y - pd.y;
206
0
    let adz = pa.z - pd.z;
207
0
    let bdz = pb.z - pd.z;
208
0
    let cdz = pc.z - pd.z;
209
210
0
    let bdxcdy = bdx * cdy;
211
0
    let cdxbdy = cdx * bdy;
212
213
0
    let cdxady = cdx * ady;
214
0
    let adxcdy = adx * cdy;
215
216
0
    let adxbdy = adx * bdy;
217
0
    let bdxady = bdx * ady;
218
219
0
    let det = adz * (bdxcdy - cdxbdy) + bdz * (cdxady - adxcdy) + cdz * (adxbdy - bdxady);
220
221
0
    let permanent = (abs(bdxcdy) + abs(cdxbdy)) * abs(adz)
222
0
        + (abs(cdxady) + abs(adxcdy)) * abs(bdz)
223
0
        + (abs(adxbdy) + abs(bdxady)) * abs(cdz);
224
225
0
    let errbound = O3DERRBOUND_A * permanent;
226
0
    if det > errbound || -det > errbound {
227
0
        return det;
228
0
    }
229
230
0
    orient3dadapt(pa, pb, pc, pd, permanent)
231
0
}
232
233
0
fn orient3dadapt(
234
0
    pa: Coord3D<f64>,
235
0
    pb: Coord3D<f64>,
236
0
    pc: Coord3D<f64>,
237
0
    pd: Coord3D<f64>,
238
0
    permanent: f64,
239
0
) -> f64 {
240
0
    let adx = pa.x - pd.x;
241
0
    let bdx = pb.x - pd.x;
242
0
    let cdx = pc.x - pd.x;
243
0
    let ady = pa.y - pd.y;
244
0
    let bdy = pb.y - pd.y;
245
0
    let cdy = pc.y - pd.y;
246
0
    let adz = pa.z - pd.z;
247
0
    let bdz = pb.z - pd.z;
248
0
    let cdz = pc.z - pd.z;
249
250
0
    let (bdxcdy1, bdxcdy0) = two_product(bdx, cdy);
251
0
    let (cdxbdy1, cdxbdy0) = two_product(cdx, bdy);
252
0
    let (bc3, bc2, bc1, bc0) = two_two_diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0);
253
0
    let bc = [bc0, bc1, bc2, bc3];
254
0
    let mut adet = [0f64; 8];
255
0
    let alen = scale_expansion_zeroelim(&bc[..4], adz, &mut adet);
256
257
0
    let (cdxady1, cdxady0) = two_product(cdx, ady);
258
0
    let (adxcdy1, adxcdy0) = two_product(adx, cdy);
259
0
    let (ca3, ca2, ca1, ca0) = two_two_diff(cdxady1, cdxady0, adxcdy1, adxcdy0);
260
0
    let ca = [ca0, ca1, ca2, ca3];
261
0
    let mut bdet = [0f64; 8];
262
0
    let blen = scale_expansion_zeroelim(&ca[..4], bdz, &mut bdet);
263
264
0
    let (adxbdy1, adxbdy0) = two_product(adx, bdy);
265
0
    let (bdxady1, bdxady0) = two_product(bdx, ady);
266
0
    let (ab3, ab2, ab1, ab0) = two_two_diff(adxbdy1, adxbdy0, bdxady1, bdxady0);
267
0
    let ab = [ab0, ab1, ab2, ab3];
268
0
    let mut cdet = [0f64; 8];
269
0
    let clen = scale_expansion_zeroelim(&ab[..4], cdz, &mut cdet);
270
271
0
    let mut abdet = [0f64; 16];
272
0
    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
273
0
    let mut fin1 = [0f64; 192];
274
0
    let finlength = fast_expansion_sum_zeroelim(&abdet[..ablen], &cdet[..clen], &mut fin1);
275
276
0
    let mut det = estimate(&fin1[..finlength]);
277
0
    let mut errbound = O3DERRBOUND_B * permanent;
278
0
    if det >= errbound || -det >= errbound {
279
0
        return det;
280
0
    }
281
282
0
    let adxtail = two_diff_tail(pa.x, pd.x, adx);
283
0
    let bdxtail = two_diff_tail(pb.x, pd.x, bdx);
284
0
    let cdxtail = two_diff_tail(pc.x, pd.x, cdx);
285
0
    let adytail = two_diff_tail(pa.y, pd.y, ady);
286
0
    let bdytail = two_diff_tail(pb.y, pd.y, bdy);
287
0
    let cdytail = two_diff_tail(pc.y, pd.y, cdy);
288
0
    let adztail = two_diff_tail(pa.z, pd.z, adz);
289
0
    let bdztail = two_diff_tail(pb.z, pd.z, bdz);
290
0
    let cdztail = two_diff_tail(pc.z, pd.z, cdz);
291
292
0
    if (adxtail == 0.0)
293
0
        && (bdxtail == 0.0)
294
0
        && (cdxtail == 0.0)
295
0
        && (adytail == 0.0)
296
0
        && (bdytail == 0.0)
297
0
        && (cdytail == 0.0)
298
0
        && (adztail == 0.0)
299
0
        && (bdztail == 0.0)
300
0
        && (cdztail == 0.0)
301
    {
302
0
        return det;
303
0
    }
304
305
0
    errbound = O3DERRBOUND_C * permanent + RESULTERRBOUND * abs(det);
306
0
    det += (adz * ((bdx * cdytail + cdy * bdxtail) - (bdy * cdxtail + cdx * bdytail))
307
0
        + adztail * (bdx * cdy - bdy * cdx))
308
0
        + (bdz * ((cdx * adytail + ady * cdxtail) - (cdy * adxtail + adx * cdytail))
309
0
            + bdztail * (cdx * ady - cdy * adx))
310
0
        + (cdz * ((adx * bdytail + bdy * adxtail) - (ady * bdxtail + bdx * adytail))
311
0
            + cdztail * (adx * bdy - ady * bdx));
312
0
    if det >= errbound || -det >= errbound {
313
0
        return det;
314
0
    }
315
316
0
    let mut finnow = fin1;
317
0
    let mut finother = [0f64; 192];
318
319
0
    let mut at_b = [0f64; 4];
320
0
    let mut at_c = [0f64; 4];
321
0
    let mut bt_c = [0f64; 4];
322
0
    let mut bt_a = [0f64; 4];
323
0
    let mut ct_a = [0f64; 4];
324
0
    let mut ct_b = [0f64; 4];
325
    let at_blen: usize;
326
    let at_clen: usize;
327
    let bt_clen: usize;
328
    let bt_alen: usize;
329
    let ct_alen: usize;
330
    let ct_blen: usize;
331
0
    if adxtail == 0.0 {
332
0
        if adytail == 0.0 {
333
0
            at_b[0] = 0.0;
334
0
            at_blen = 1;
335
0
            at_c[0] = 0.0;
336
0
            at_clen = 1;
337
0
        } else {
338
0
            let negate = -adytail;
339
0
            (at_b[1], at_b[0]) = two_product(negate, bdx);
340
0
            at_blen = 2;
341
0
            (at_c[1], at_c[0]) = two_product(adytail, cdx);
342
0
            at_clen = 2;
343
0
        }
344
0
    } else if adytail == 0.0 {
345
0
        (at_b[1], at_b[0]) = two_product(adxtail, bdy);
346
0
        at_blen = 2;
347
0
        let negate = -adxtail;
348
0
        (at_c[1], at_c[0]) = two_product(negate, cdy);
349
0
        at_clen = 2;
350
0
    } else {
351
0
        let (adxt_bdy1, adxt_bdy0) = two_product(adxtail, bdy);
352
0
        let (adyt_bdx1, adyt_bdx0) = two_product(adytail, bdx);
353
0
        (at_b[3], at_b[2], at_b[1], at_b[0]) =
354
0
            two_two_diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0);
355
0
        at_blen = 4;
356
0
        let (adyt_cdx1, adyt_cdx0) = two_product(adytail, cdx);
357
0
        let (adxt_cdy1, adxt_cdy0) = two_product(adxtail, cdy);
358
0
        (at_c[3], at_c[2], at_c[1], at_c[0]) =
359
0
            two_two_diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0);
360
0
        at_clen = 4;
361
0
    }
362
0
    if bdxtail == 0.0 {
363
0
        if bdytail == 0.0 {
364
0
            bt_c[0] = 0.0;
365
0
            bt_clen = 1;
366
0
            bt_a[0] = 0.0;
367
0
            bt_alen = 1;
368
0
        } else {
369
0
            let negate = -bdytail;
370
0
            (bt_c[1], bt_c[0]) = two_product(negate, cdx);
371
0
            bt_clen = 2;
372
0
            (bt_a[1], bt_a[0]) = two_product(bdytail, adx);
373
0
            bt_alen = 2;
374
0
        }
375
0
    } else if bdytail == 0.0 {
376
0
        (bt_c[1], bt_c[0]) = two_product(bdxtail, cdy);
377
0
        bt_clen = 2;
378
0
        let negate = -bdxtail;
379
0
        (bt_a[1], bt_a[0]) = two_product(negate, ady);
380
0
        bt_alen = 2;
381
0
    } else {
382
0
        let (bdxt_cdy1, bdxt_cdy0) = two_product(bdxtail, cdy);
383
0
        let (bdyt_cdx1, bdyt_cdx0) = two_product(bdytail, cdx);
384
0
        (bt_c[3], bt_c[2], bt_c[1], bt_c[0]) =
385
0
            two_two_diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0);
386
0
        bt_clen = 4;
387
0
        let (bdyt_adx1, bdyt_adx0) = two_product(bdytail, adx);
388
0
        let (bdxt_ady1, bdxt_ady0) = two_product(bdxtail, ady);
389
0
        (bt_a[3], bt_a[2], bt_a[1], bt_a[0]) =
390
0
            two_two_diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0);
391
0
        bt_alen = 4;
392
0
    }
393
0
    if cdxtail == 0.0 {
394
0
        if cdytail == 0.0 {
395
0
            ct_a[0] = 0.0;
396
0
            ct_alen = 1;
397
0
            ct_b[0] = 0.0;
398
0
            ct_blen = 1;
399
0
        } else {
400
0
            let negate = -cdytail;
401
0
            (ct_a[1], ct_a[0]) = two_product(negate, adx);
402
0
            ct_alen = 2;
403
0
            (ct_b[1], ct_b[0]) = two_product(cdytail, bdx);
404
0
            ct_blen = 2;
405
0
        }
406
0
    } else if cdytail == 0.0 {
407
0
        (ct_a[1], ct_a[0]) = two_product(cdxtail, ady);
408
0
        ct_alen = 2;
409
0
        let negate = -cdxtail;
410
0
        (ct_b[1], ct_b[0]) = two_product(negate, bdy);
411
0
        ct_blen = 2;
412
0
    } else {
413
0
        let (cdxt_ady1, cdxt_ady0) = two_product(cdxtail, ady);
414
0
        let (cdyt_adx1, cdyt_adx0) = two_product(cdytail, adx);
415
0
        (ct_a[3], ct_a[2], ct_a[1], ct_a[0]) =
416
0
            two_two_diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0);
417
0
        ct_alen = 4;
418
0
        let (cdyt_bdx1, cdyt_bdx0) = two_product(cdytail, bdx);
419
0
        let (cdxt_bdy1, cdxt_bdy0) = two_product(cdxtail, bdy);
420
0
        (ct_b[3], ct_b[2], ct_b[1], ct_b[0]) =
421
0
            two_two_diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0);
422
0
        ct_blen = 4;
423
0
    }
424
425
0
    let mut bct = [0f64; 8];
426
0
    let mut cat = [0f64; 8];
427
0
    let mut abt = [0f64; 8];
428
0
    let mut u = [0f64; 4];
429
0
    let mut v = [0f64; 12];
430
0
    let mut w = [0f64; 16];
431
    let mut vlength: usize;
432
    let mut wlength: usize;
433
434
0
    let bctlen = fast_expansion_sum_zeroelim(&bt_c[..bt_clen], &ct_b[..ct_blen], &mut bct);
435
0
    wlength = scale_expansion_zeroelim(&bct[..bctlen], adz, &mut w);
436
0
    let mut finlength =
437
0
        fast_expansion_sum_zeroelim(&finnow[..finlength], &w[..wlength], &mut finother);
438
0
    ::core::mem::swap(&mut finnow, &mut finother);
439
440
0
    let catlen = fast_expansion_sum_zeroelim(&ct_a[..ct_alen], &at_c[..at_clen], &mut cat);
441
0
    wlength = scale_expansion_zeroelim(&cat[..catlen], bdz, &mut w);
442
0
    finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &w[..wlength], &mut finother);
443
0
    ::core::mem::swap(&mut finnow, &mut finother);
444
445
0
    let abtlen = fast_expansion_sum_zeroelim(&at_b[..at_blen], &bt_a[..bt_alen], &mut abt);
446
0
    wlength = scale_expansion_zeroelim(&abt[..abtlen], cdz, &mut w);
447
0
    finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &w[..wlength], &mut finother);
448
0
    ::core::mem::swap(&mut finnow, &mut finother);
449
450
0
    if adztail != 0.0 {
451
0
        vlength = scale_expansion_zeroelim(&bc[..4], adztail, &mut v);
452
0
        finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &v[..vlength], &mut finother);
453
0
        ::core::mem::swap(&mut finnow, &mut finother);
454
0
    }
455
0
    if bdztail != 0.0 {
456
0
        vlength = scale_expansion_zeroelim(&ca[..4], bdztail, &mut v);
457
0
        finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &v[..vlength], &mut finother);
458
0
        ::core::mem::swap(&mut finnow, &mut finother);
459
0
    }
460
0
    if cdztail != 0.0 {
461
0
        vlength = scale_expansion_zeroelim(&ab[..4], cdztail, &mut v);
462
0
        finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &v[..vlength], &mut finother);
463
0
        ::core::mem::swap(&mut finnow, &mut finother);
464
0
    }
465
466
0
    if adxtail != 0.0 {
467
0
        if bdytail != 0.0 {
468
0
            let (adxt_bdyt1, adxt_bdyt0) = two_product(adxtail, bdytail);
469
0
            (u[3], u[2], u[1], u[0]) = two_one_product(adxt_bdyt1, adxt_bdyt0, cdz);
470
0
            finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
471
0
            ::core::mem::swap(&mut finnow, &mut finother);
472
0
            if cdztail != 0.0 {
473
0
                (u[3], u[2], u[1], u[0]) = two_one_product(adxt_bdyt1, adxt_bdyt0, cdztail);
474
0
                finlength =
475
0
                    fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
476
0
                ::core::mem::swap(&mut finnow, &mut finother);
477
0
            }
478
0
        }
479
0
        if cdytail != 0.0 {
480
0
            let negate = -adxtail;
481
0
            let (adxt_cdyt1, adxt_cdyt0) = two_product(negate, cdytail);
482
0
            (u[3], u[2], u[1], u[0]) = two_one_product(adxt_cdyt1, adxt_cdyt0, bdz);
483
0
            finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
484
0
            ::core::mem::swap(&mut finnow, &mut finother);
485
0
            if bdztail != 0.0 {
486
0
                (u[3], u[2], u[1], u[0]) = two_one_product(adxt_cdyt1, adxt_cdyt0, bdztail);
487
0
                finlength =
488
0
                    fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
489
0
                ::core::mem::swap(&mut finnow, &mut finother);
490
0
            }
491
0
        }
492
0
    }
493
0
    if bdxtail != 0.0 {
494
0
        if cdytail != 0.0 {
495
0
            let (bdxt_cdyt1, bdxt_cdyt0) = two_product(bdxtail, cdytail);
496
0
            (u[3], u[2], u[1], u[0]) = two_one_product(bdxt_cdyt1, bdxt_cdyt0, adz);
497
0
            finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
498
0
            ::core::mem::swap(&mut finnow, &mut finother);
499
0
            if adztail != 0.0 {
500
0
                (u[3], u[2], u[1], u[0]) = two_one_product(bdxt_cdyt1, bdxt_cdyt0, adztail);
501
0
                finlength =
502
0
                    fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
503
0
                ::core::mem::swap(&mut finnow, &mut finother);
504
0
            }
505
0
        }
506
0
        if adytail != 0.0 {
507
0
            let negate = -bdxtail;
508
0
            let (bdxt_adyt1, bdxt_adyt0) = two_product(negate, adytail);
509
0
            (u[3], u[2], u[1], u[0]) = two_one_product(bdxt_adyt1, bdxt_adyt0, cdz);
510
0
            finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
511
0
            ::core::mem::swap(&mut finnow, &mut finother);
512
0
            if cdztail != 0.0 {
513
0
                (u[3], u[2], u[1], u[0]) = two_one_product(bdxt_adyt1, bdxt_adyt0, cdztail);
514
0
                finlength =
515
0
                    fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
516
0
                ::core::mem::swap(&mut finnow, &mut finother);
517
0
            }
518
0
        }
519
0
    }
520
0
    if cdxtail != 0.0 {
521
0
        if adytail != 0.0 {
522
0
            let (cdxt_adyt1, cdxt_adyt0) = two_product(cdxtail, adytail);
523
0
            (u[3], u[2], u[1], u[0]) = two_one_product(cdxt_adyt1, cdxt_adyt0, bdz);
524
0
            finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
525
0
            ::core::mem::swap(&mut finnow, &mut finother);
526
0
            if bdztail != 0.0 {
527
0
                (u[3], u[2], u[1], u[0]) = two_one_product(cdxt_adyt1, cdxt_adyt0, bdztail);
528
0
                finlength =
529
0
                    fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
530
0
                ::core::mem::swap(&mut finnow, &mut finother);
531
0
            }
532
0
        }
533
0
        if bdytail != 0.0 {
534
0
            let negate = -cdxtail;
535
0
            let (cdxt_bdyt1, cdxt_bdyt0) = two_product(negate, bdytail);
536
0
            (u[3], u[2], u[1], u[0]) = two_one_product(cdxt_bdyt1, cdxt_bdyt0, adz);
537
0
            finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
538
0
            ::core::mem::swap(&mut finnow, &mut finother);
539
0
            if adztail != 0.0 {
540
0
                (u[3], u[2], u[1], u[0]) = two_one_product(cdxt_bdyt1, cdxt_bdyt0, adztail);
541
0
                finlength =
542
0
                    fast_expansion_sum_zeroelim(&finnow[..finlength], &u[..4], &mut finother);
543
0
                ::core::mem::swap(&mut finnow, &mut finother);
544
0
            }
545
0
        }
546
0
    }
547
548
0
    if adztail != 0.0 {
549
0
        wlength = scale_expansion_zeroelim(&bct[..bctlen], adztail, &mut w);
550
0
        finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &w[..wlength], &mut finother);
551
0
        ::core::mem::swap(&mut finnow, &mut finother);
552
0
    }
553
0
    if bdztail != 0.0 {
554
0
        wlength = scale_expansion_zeroelim(&cat[..catlen], bdztail, &mut w);
555
0
        finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &w[..wlength], &mut finother);
556
0
        ::core::mem::swap(&mut finnow, &mut finother);
557
0
    }
558
0
    if cdztail != 0.0 {
559
0
        wlength = scale_expansion_zeroelim(&abt[..abtlen], cdztail, &mut w);
560
0
        finlength = fast_expansion_sum_zeroelim(&finnow[..finlength], &w[..wlength], &mut finother);
561
0
        ::core::mem::swap(&mut finnow, &mut finother);
562
0
    }
563
564
0
    finnow[finlength - 1]
565
0
}
566
567
/// Returns a positive value if the coordinate `pd` lies **inside** the circle passing through `pa`, `pb`, and `pc`.  
568
/// Returns a negative value if it lies **outside** the circle.  
569
/// Returns `0` if the four points are **cocircular**.  
570
/// **Note**: The points `pa`, `pb`, and `pc` must be in **counterclockwise order**, or the sign of the result will be reversed.
571
0
pub fn incircle<T: Into<f64>>(pa: Coord<T>, pb: Coord<T>, pc: Coord<T>, pd: Coord<T>) -> f64 {
572
0
    let pa = Coord {
573
0
        x: pa.x.into(),
574
0
        y: pa.y.into(),
575
0
    };
576
0
    let pb = Coord {
577
0
        x: pb.x.into(),
578
0
        y: pb.y.into(),
579
0
    };
580
0
    let pc = Coord {
581
0
        x: pc.x.into(),
582
0
        y: pc.y.into(),
583
0
    };
584
0
    let pd = Coord {
585
0
        x: pd.x.into(),
586
0
        y: pd.y.into(),
587
0
    };
588
589
0
    let adx = pa.x - pd.x;
590
0
    let bdx = pb.x - pd.x;
591
0
    let cdx = pc.x - pd.x;
592
0
    let ady = pa.y - pd.y;
593
0
    let bdy = pb.y - pd.y;
594
0
    let cdy = pc.y - pd.y;
595
596
0
    let bdxcdy = bdx * cdy;
597
0
    let cdxbdy = cdx * bdy;
598
0
    let alift = adx * adx + ady * ady;
599
600
0
    let cdxady = cdx * ady;
601
0
    let adxcdy = adx * cdy;
602
0
    let blift = bdx * bdx + bdy * bdy;
603
604
0
    let adxbdy = adx * bdy;
605
0
    let bdxady = bdx * ady;
606
0
    let clift = cdx * cdx + cdy * cdy;
607
608
0
    let det = alift * (bdxcdy - cdxbdy) + blift * (cdxady - adxcdy) + clift * (adxbdy - bdxady);
609
610
0
    let permanent = (abs(bdxcdy) + abs(cdxbdy)) * alift
611
0
        + (abs(cdxady) + abs(adxcdy)) * blift
612
0
        + (abs(adxbdy) + abs(bdxady)) * clift;
613
0
    let errbound = ICCERRBOUND_A * permanent;
614
0
    if det > errbound || -det > errbound {
615
0
        return det;
616
0
    }
617
0
    incircleadapt(pa, pb, pc, pd, permanent)
618
0
}
619
620
0
fn incircleadapt(
621
0
    pa: Coord<f64>,
622
0
    pb: Coord<f64>,
623
0
    pc: Coord<f64>,
624
0
    pd: Coord<f64>,
625
0
    permanent: f64,
626
0
) -> f64 {
627
0
    let mut temp8 = [0f64; 8];
628
0
    let mut temp16a = [0f64; 16];
629
0
    let mut temp16b = [0f64; 16];
630
0
    let mut temp16c = [0f64; 16];
631
0
    let mut temp32a = [0f64; 32];
632
0
    let mut temp32b = [0f64; 32];
633
0
    let mut temp48 = [0f64; 48];
634
0
    let mut temp64 = [0f64; 64];
635
636
0
    let adx = pa.x - pd.x;
637
0
    let bdx = pb.x - pd.x;
638
0
    let cdx = pc.x - pd.x;
639
0
    let ady = pa.y - pd.y;
640
0
    let bdy = pb.y - pd.y;
641
0
    let cdy = pc.y - pd.y;
642
643
0
    let (bdxcdy1, bdxcdy0) = two_product(bdx, cdy);
644
0
    let (cdxbdy1, cdxbdy0) = two_product(cdx, bdy);
645
0
    let (bc3, bc2, bc1, bc0) = two_two_diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0);
646
0
    let bc = [bc0, bc1, bc2, bc3];
647
648
0
    let mut axbc = [0f64; 8];
649
0
    let axbclen = scale_expansion_zeroelim(&bc, adx, &mut axbc);
650
0
    let mut axxbc = [0f64; 16];
651
0
    let axxbclen = scale_expansion_zeroelim(&axbc[..axbclen], adx, &mut axxbc);
652
0
    let mut aybc = [0f64; 8];
653
0
    let aybclen = scale_expansion_zeroelim(&bc, ady, &mut aybc);
654
0
    let mut ayybc = [0f64; 16];
655
0
    let ayybclen = scale_expansion_zeroelim(&aybc[..aybclen], ady, &mut ayybc);
656
0
    let mut adet = [0f64; 32];
657
0
    let alen = fast_expansion_sum_zeroelim(&axxbc[0..axxbclen], &ayybc[0..ayybclen], &mut adet);
658
659
0
    let (cdxady1, cdxady0) = two_product(cdx, ady);
660
0
    let (adxcdy1, adxcdy0) = two_product(adx, cdy);
661
0
    let (c3, c2, c1, c0) = two_two_diff(cdxady1, cdxady0, adxcdy1, adxcdy0);
662
0
    let ca = [c0, c1, c2, c3];
663
664
0
    let mut bxca = [0f64; 8];
665
0
    let bxcalen = scale_expansion_zeroelim(&ca, bdx, &mut bxca);
666
0
    let mut bxxca = [0f64; 16];
667
0
    let bxxcalen = scale_expansion_zeroelim(&bxca[..bxcalen], bdx, &mut bxxca);
668
0
    let mut byca = [0f64; 8];
669
0
    let bycalen = scale_expansion_zeroelim(&ca, bdy, &mut byca);
670
0
    let mut byyca = [0f64; 16];
671
0
    let byycalen = scale_expansion_zeroelim(&byca[..bycalen], bdy, &mut byyca);
672
0
    let mut bdet = [0f64; 32];
673
0
    let blen = fast_expansion_sum_zeroelim(&bxxca[..bxxcalen], &byyca[0..byycalen], &mut bdet);
674
675
0
    let (adxbdy1, adxbdy0) = two_product(adx, bdy);
676
0
    let (bdxady1, bdxady0) = two_product(bdx, ady);
677
0
    let (ab3, ab2, ab1, ab0) = two_two_diff(adxbdy1, adxbdy0, bdxady1, bdxady0);
678
0
    let ab = [ab0, ab1, ab2, ab3];
679
680
0
    let mut cxab = [0f64; 8];
681
0
    let cxablen = scale_expansion_zeroelim(&ab, cdx, &mut cxab);
682
0
    let mut cxxab = [0f64; 16];
683
0
    let cxxablen = scale_expansion_zeroelim(&cxab[..cxablen], cdx, &mut cxxab);
684
0
    let mut cyab = [0f64; 8];
685
0
    let cyablen = scale_expansion_zeroelim(&ab, cdy, &mut cyab);
686
0
    let mut cyyab = [0f64; 16];
687
0
    let cyyablen = scale_expansion_zeroelim(&cyab[..cyablen], cdy, &mut cyyab);
688
0
    let mut cdet = [0f64; 32];
689
0
    let clen = fast_expansion_sum_zeroelim(&cxxab[..cxxablen], &cyyab[..cyyablen], &mut cdet);
690
691
0
    let mut abdet = [0f64; 64];
692
0
    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
693
0
    let mut fin1 = [0f64; 1152];
694
0
    let mut finlength = fast_expansion_sum_zeroelim(&abdet[..ablen], &cdet[..clen], &mut fin1);
695
696
0
    let mut det = estimate(&fin1[..finlength]);
697
0
    let errbound = ICCERRBOUND_B * permanent;
698
0
    if det >= errbound || -det >= errbound {
699
0
        return det;
700
0
    }
701
702
0
    let adxtail = two_diff_tail(pa.x, pd.x, adx);
703
0
    let adytail = two_diff_tail(pa.y, pd.y, ady);
704
0
    let bdxtail = two_diff_tail(pb.x, pd.x, bdx);
705
0
    let bdytail = two_diff_tail(pb.y, pd.y, bdy);
706
0
    let cdxtail = two_diff_tail(pc.x, pd.x, cdx);
707
0
    let cdytail = two_diff_tail(pc.y, pd.y, cdy);
708
0
    if adxtail == 0.0
709
0
        && bdxtail == 0.0
710
0
        && cdxtail == 0.0
711
0
        && adytail == 0.0
712
0
        && bdytail == 0.0
713
0
        && cdytail == 0.0
714
    {
715
0
        return det;
716
0
    }
717
718
0
    let errbound = ICCERRBOUND_C * permanent + RESULTERRBOUND * abs(det);
719
0
    det += ((adx * adx + ady * ady)
720
0
        * ((bdx * cdytail + cdy * bdxtail) - (bdy * cdxtail + cdx * bdytail))
721
0
        + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
722
0
        + ((bdx * bdx + bdy * bdy)
723
0
            * ((cdx * adytail + ady * cdxtail) - (cdy * adxtail + adx * cdytail))
724
0
            + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
725
0
        + ((cdx * cdx + cdy * cdy)
726
0
            * ((adx * bdytail + bdy * adxtail) - (ady * bdxtail + bdx * adytail))
727
0
            + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
728
729
0
    if det >= errbound || -det >= errbound {
730
0
        return det;
731
0
    }
732
733
0
    let mut fin2 = [0f64; 1152];
734
735
0
    let aa = if bdxtail != 0.0 || bdytail != 0.0 || cdxtail != 0.0 || cdytail != 0.0 {
736
0
        let (adxadx1, adxadx0) = square(adx);
737
0
        let (adyady1, adyady0) = square(ady);
738
0
        let (aa3, aa2, aa1, aa0) = two_two_sum(adxadx1, adxadx0, adyady1, adyady0);
739
0
        [aa0, aa1, aa2, aa3]
740
    } else {
741
0
        [0f64; 4]
742
    };
743
744
0
    let bb = if cdxtail != 0.0 || cdytail != 0.0 || adxtail != 0.0 || adytail != 0.0 {
745
0
        let (bdxbdx1, bdxbdx0) = square(bdx);
746
0
        let (bdybdy1, bdybdy0) = square(bdy);
747
0
        let (bb3, bb2, bb1, bb0) = two_two_sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0);
748
0
        [bb0, bb1, bb2, bb3]
749
    } else {
750
0
        [0f64; 4]
751
    };
752
753
0
    let cc = if adxtail != 0.0 || adytail != 0.0 || bdxtail != 0.0 || bdytail != 0.0 {
754
0
        let (cdxcdx1, cdxcdx0) = square(cdx);
755
0
        let (cdycdy1, cdycdy0) = square(cdy);
756
0
        let (cc3, cc2, cc1, cc0) = two_two_sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0);
757
0
        [cc0, cc1, cc2, cc3]
758
    } else {
759
0
        [0f64; 4]
760
    };
761
762
0
    let mut axtbclen = 9;
763
0
    let mut axtbc = [0f64; 8];
764
0
    if adxtail != 0.0 {
765
0
        axtbclen = scale_expansion_zeroelim(&bc, adxtail, &mut axtbc);
766
0
        let mut temp16a = [0f64; 16];
767
0
        let temp16alen = scale_expansion_zeroelim(&axtbc[..axtbclen], 2.0 * adx, &mut temp16a);
768
769
0
        let mut axtcc = [0f64; 8];
770
0
        let axtcclen = scale_expansion_zeroelim(&cc, adxtail, &mut axtcc);
771
0
        let mut temp16b = [0f64; 16];
772
0
        let temp16blen = scale_expansion_zeroelim(&axtcc[..axtcclen], bdy, &mut temp16b);
773
774
0
        let mut axtbb = [0f64; 8];
775
0
        let axtbblen = scale_expansion_zeroelim(&bb, adxtail, &mut axtbb);
776
0
        let mut temp16c = [0f64; 16];
777
0
        let temp16clen = scale_expansion_zeroelim(&axtbb[..axtbblen], -cdy, &mut temp16c);
778
779
0
        let mut temp32a = [0f64; 32];
780
0
        let temp32alen = fast_expansion_sum_zeroelim(
781
0
            &temp16a[..temp16alen],
782
0
            &temp16b[..temp16blen],
783
0
            &mut temp32a,
784
        );
785
0
        let mut temp48 = [0f64; 48];
786
0
        let temp48len = fast_expansion_sum_zeroelim(
787
0
            &temp16c[..temp16clen],
788
0
            &temp32a[..temp32alen],
789
0
            &mut temp48,
790
        );
791
0
        finlength =
792
0
            fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
793
0
        ::core::mem::swap(&mut fin1, &mut fin2)
794
0
    }
795
796
0
    let mut aytbclen = 9;
797
0
    let mut aytbc = [0f64; 8];
798
0
    if adytail != 0.0 {
799
0
        aytbclen = scale_expansion_zeroelim(&bc, adytail, &mut aytbc);
800
0
        let temp16alen = scale_expansion_zeroelim(&aytbc[..aytbclen], 2.0 * ady, &mut temp16a);
801
802
0
        let mut aytbb = [0f64; 8];
803
0
        let aytbblen = scale_expansion_zeroelim(&bb, adytail, &mut aytbb);
804
0
        let temp16blen = scale_expansion_zeroelim(&aytbb[..aytbblen], cdx, &mut temp16b);
805
806
0
        let mut aytcc = [0f64; 8];
807
0
        let aytcclen = scale_expansion_zeroelim(&cc, adytail, &mut aytcc);
808
0
        let temp16clen = scale_expansion_zeroelim(&aytcc[..aytcclen], -bdx, &mut temp16c);
809
810
0
        let temp32alen = fast_expansion_sum_zeroelim(
811
0
            &temp16a[..temp16alen],
812
0
            &temp16b[..temp16blen],
813
0
            &mut temp32a,
814
        );
815
816
0
        let temp48len = fast_expansion_sum_zeroelim(
817
0
            &temp16c[..temp16clen],
818
0
            &temp32a[..temp32alen],
819
0
            &mut temp48,
820
        );
821
0
        finlength =
822
0
            fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
823
0
        ::core::mem::swap(&mut fin1, &mut fin2)
824
0
    }
825
826
0
    let mut bxtcalen = 9;
827
0
    let mut bxtca = [0f64; 8];
828
0
    if bdxtail != 0.0 {
829
0
        bxtcalen = scale_expansion_zeroelim(&ca, bdxtail, &mut bxtca);
830
0
        let temp16alen = scale_expansion_zeroelim(&bxtca[..bxtcalen], 2.0 * bdx, &mut temp16a);
831
832
0
        let mut bxtaa = [0f64; 8];
833
0
        let bxtaalen = scale_expansion_zeroelim(&aa, bdxtail, &mut bxtaa);
834
0
        let temp16blen = scale_expansion_zeroelim(&bxtaa[..bxtaalen], cdy, &mut temp16b);
835
836
0
        let mut bxtcc = [0f64; 8];
837
0
        let bxtcclen = scale_expansion_zeroelim(&cc, bdxtail, &mut bxtcc);
838
0
        let temp16clen = scale_expansion_zeroelim(&bxtcc[..bxtcclen], -ady, &mut temp16c);
839
840
0
        let temp32alen = fast_expansion_sum_zeroelim(
841
0
            &temp16a[..temp16alen],
842
0
            &temp16b[..temp16blen],
843
0
            &mut temp32a,
844
        );
845
0
        let temp48len = fast_expansion_sum_zeroelim(
846
0
            &temp16c[..temp16clen],
847
0
            &temp32a[..temp32alen],
848
0
            &mut temp48,
849
        );
850
0
        finlength =
851
0
            fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
852
0
        ::core::mem::swap(&mut fin1, &mut fin2)
853
0
    }
854
855
0
    let mut bytcalen = 9;
856
0
    let mut bytca = [0f64; 8];
857
0
    if bdytail != 0.0 {
858
0
        bytcalen = scale_expansion_zeroelim(&ca, bdytail, &mut bytca);
859
0
        let temp16alen = scale_expansion_zeroelim(&bytca[..bytcalen], 2.0 * bdy, &mut temp16a);
860
861
0
        let mut bytcc = [0f64; 8];
862
0
        let bytcclen = scale_expansion_zeroelim(&cc, bdytail, &mut bytcc);
863
0
        let temp16blen = scale_expansion_zeroelim(&bytcc[..bytcclen], adx, &mut temp16b);
864
865
0
        let mut bytaa = [0f64; 8];
866
0
        let bytaalen = scale_expansion_zeroelim(&aa, bdytail, &mut bytaa);
867
0
        let temp16clen = scale_expansion_zeroelim(&bytaa[..bytaalen], -cdx, &mut temp16c);
868
869
0
        let temp32alen = fast_expansion_sum_zeroelim(
870
0
            &temp16a[..temp16alen],
871
0
            &temp16b[..temp16blen],
872
0
            &mut temp32a,
873
        );
874
0
        let temp48len = fast_expansion_sum_zeroelim(
875
0
            &temp16c[..temp16clen],
876
0
            &temp32a[..temp32alen],
877
0
            &mut temp48,
878
        );
879
880
0
        finlength =
881
0
            fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
882
0
        ::core::mem::swap(&mut fin1, &mut fin2)
883
0
    }
884
885
0
    let mut cxtab = [0f64; 8];
886
0
    let mut cxtablen = 9;
887
0
    if cdxtail != 0.0 {
888
0
        cxtablen = scale_expansion_zeroelim(&ab, cdxtail, &mut cxtab);
889
0
        let temp16alen = scale_expansion_zeroelim(&cxtab[..cxtablen], 2.0 * cdx, &mut temp16a);
890
0
891
0
        let mut cxtbb = [0f64; 8];
892
0
        let cxtbblen = scale_expansion_zeroelim(&bb, cdxtail, &mut cxtbb);
893
0
        let temp16blen = scale_expansion_zeroelim(&cxtbb[..cxtbblen], ady, &mut temp16b);
894
0
895
0
        let mut cxtaa = [0f64; 8];
896
0
        let cxtaalen = scale_expansion_zeroelim(&aa, cdxtail, &mut cxtaa);
897
0
        let temp16clen = scale_expansion_zeroelim(&cxtaa[..cxtaalen], -bdy, &mut temp16c);
898
0
899
0
        let temp32alen = fast_expansion_sum_zeroelim(
900
0
            &temp16a[..temp16alen],
901
0
            &temp16b[..temp16blen],
902
0
            &mut temp32a,
903
0
        );
904
0
        let temp48len = fast_expansion_sum_zeroelim(
905
0
            &temp16c[..temp16clen],
906
0
            &temp32a[..temp32alen],
907
0
            &mut temp48,
908
0
        );
909
0
        finlength =
910
0
            fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
911
0
        ::core::mem::swap(&mut fin1, &mut fin2);
912
0
    }
913
914
0
    let mut cytab = [0f64; 8];
915
0
    let mut cytablen = 9;
916
0
    if cdytail != 0.0 {
917
0
        cytablen = scale_expansion_zeroelim(&ab, cdytail, &mut cytab);
918
0
        let temp16alen = scale_expansion_zeroelim(&cytab[..cytablen], 2.0 * cdy, &mut temp16a);
919
0
920
0
        let mut cytaa = [0f64; 8];
921
0
        let cytaalen = scale_expansion_zeroelim(&aa, cdytail, &mut cytaa);
922
0
        let temp16blen = scale_expansion_zeroelim(&cytaa[..cytaalen], bdx, &mut temp16b);
923
0
924
0
        let mut cytbb = [0f64; 8];
925
0
        let cytbblen = scale_expansion_zeroelim(&bb, cdytail, &mut cytbb);
926
0
        let temp16clen = scale_expansion_zeroelim(&cytbb[..cytbblen], -adx, &mut temp16c);
927
0
928
0
        let temp32alen = fast_expansion_sum_zeroelim(
929
0
            &temp16a[..temp16alen],
930
0
            &temp16b[..temp16blen],
931
0
            &mut temp32a,
932
0
        );
933
0
        let temp48len = fast_expansion_sum_zeroelim(
934
0
            &temp16c[..temp16clen],
935
0
            &temp32a[..temp32alen],
936
0
            &mut temp48,
937
0
        );
938
0
        finlength =
939
0
            fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
940
0
        ::core::mem::swap(&mut fin1, &mut fin2);
941
0
    }
942
943
0
    if adxtail != 0.0 || adytail != 0.0 {
944
0
        let mut bctt = [0f64; 4];
945
0
        let mut bct = [0f64; 8];
946
        let bcttlen;
947
        let bctlen;
948
0
        if bdxtail != 0.0 || bdytail != 0.0 || cdxtail != 0.0 || cdytail != 0.0 {
949
0
            let (ti1, ti0) = two_product(bdxtail, cdy);
950
0
            let (tj1, tj0) = two_product(bdx, cdytail);
951
0
            let (u3, u2, u1, u0) = two_two_sum(ti1, ti0, tj1, tj0);
952
0
            let u = [u0, u1, u2, u3];
953
0
            let negate = -bdy;
954
0
            let (ti1, ti0) = two_product(cdxtail, negate);
955
0
            let negate = -bdytail;
956
0
            let (tj1, tj0) = two_product(cdx, negate);
957
0
            let (v3, v2, v1, v0) = two_two_sum(ti1, ti0, tj1, tj0);
958
0
            let v = [v0, v1, v2, v3];
959
0
            bctlen = fast_expansion_sum_zeroelim(&u, &v, &mut bct);
960
0
            let (ti1, ti0) = two_product(bdxtail, cdytail);
961
0
            let (tj1, tj0) = two_product(cdxtail, bdytail);
962
0
            let (bctt3, bctt2, bctt1, bctt0) = two_two_diff(ti1, ti0, tj1, tj0);
963
0
            bctt = [bctt0, bctt1, bctt2, bctt3];
964
0
            bcttlen = 4;
965
0
        } else {
966
0
            bct[0] = 0.0;
967
0
            bctlen = 1;
968
0
            bctt[0] = 0.0;
969
0
            bcttlen = 1;
970
0
        }
971
972
0
        if adxtail != 0.0 {
973
0
            let temp16alen = scale_expansion_zeroelim(&axtbc[..axtbclen], adxtail, &mut temp16a);
974
0
            let mut axtbct = [0f64; 16];
975
0
            let axtbctlen = scale_expansion_zeroelim(&bct[..bctlen], adxtail, &mut axtbct);
976
0
            let temp32alen =
977
0
                scale_expansion_zeroelim(&axtbct[..axtbctlen], 2.0 * adx, &mut temp32a);
978
0
            let temp48len = fast_expansion_sum_zeroelim(
979
0
                &temp16a[..temp16alen],
980
0
                &temp32a[..temp32alen],
981
0
                &mut temp48,
982
            );
983
0
            finlength =
984
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
985
0
            ::core::mem::swap(&mut fin1, &mut fin2);
986
987
0
            if bdytail != 0.0 {
988
0
                let temp8len = scale_expansion_zeroelim(&cc, adxtail, &mut temp8);
989
0
                let temp16alen =
990
0
                    scale_expansion_zeroelim(&temp8[..temp8len], bdytail, &mut temp16a);
991
0
                finlength = fast_expansion_sum_zeroelim(
992
0
                    &fin1[..finlength],
993
0
                    &temp16a[..temp16alen],
994
0
                    &mut fin2,
995
0
                );
996
0
                ::core::mem::swap(&mut fin1, &mut fin2);
997
0
            }
998
0
            if cdytail != 0.0 {
999
0
                let temp8len = scale_expansion_zeroelim(&bb, -adxtail, &mut temp8);
1000
0
                let temp16alen =
1001
0
                    scale_expansion_zeroelim(&temp8[..temp8len], cdytail, &mut temp16a);
1002
0
                finlength = fast_expansion_sum_zeroelim(
1003
0
                    &fin1[..finlength],
1004
0
                    &temp16a[..temp16alen],
1005
0
                    &mut fin2,
1006
0
                );
1007
0
                ::core::mem::swap(&mut fin1, &mut fin2);
1008
0
            }
1009
1010
0
            let temp32alen = scale_expansion_zeroelim(&axtbct[..axtbctlen], adxtail, &mut temp32a);
1011
0
            let mut axtbctt = [0f64; 8];
1012
0
            let axtbcttlen = scale_expansion_zeroelim(&bctt[..bcttlen], adxtail, &mut axtbctt);
1013
0
            let temp16alen =
1014
0
                scale_expansion_zeroelim(&axtbctt[..axtbcttlen], 2.0 * adx, &mut temp16a);
1015
0
            let temp16blen =
1016
0
                scale_expansion_zeroelim(&axtbctt[..axtbcttlen], adxtail, &mut temp16b);
1017
0
            let temp32blen = fast_expansion_sum_zeroelim(
1018
0
                &temp16a[..temp16alen],
1019
0
                &temp16b[..temp16blen],
1020
0
                &mut temp32b,
1021
            );
1022
0
            let temp64len = fast_expansion_sum_zeroelim(
1023
0
                &temp32a[..temp32alen],
1024
0
                &temp32b[..temp32blen],
1025
0
                &mut temp64,
1026
            );
1027
0
            finlength =
1028
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp64[..temp64len], &mut fin2);
1029
0
            ::core::mem::swap(&mut fin1, &mut fin2);
1030
0
        }
1031
1032
0
        if adytail != 0.0 {
1033
0
            let temp16alen = scale_expansion_zeroelim(&aytbc[..aytbclen], adytail, &mut temp16a);
1034
0
            let mut aytbct = [0f64; 16];
1035
0
            let aytbctlen = scale_expansion_zeroelim(&bct[..bctlen], adytail, &mut aytbct);
1036
0
            let temp32alen =
1037
0
                scale_expansion_zeroelim(&aytbct[..aytbctlen], 2.0 * ady, &mut temp32a);
1038
0
            let temp48len = fast_expansion_sum_zeroelim(
1039
0
                &temp16a[..temp16alen],
1040
0
                &temp32a[..temp32alen],
1041
0
                &mut temp48,
1042
0
            );
1043
0
            finlength =
1044
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
1045
0
            ::core::mem::swap(&mut fin1, &mut fin2);
1046
0
1047
0
            let temp32alen = scale_expansion_zeroelim(&aytbct[..aytbctlen], adytail, &mut temp32a);
1048
0
            let mut aytbctt = [0f64; 8];
1049
0
            let aytbcttlen = scale_expansion_zeroelim(&bctt[..bcttlen], adytail, &mut aytbctt);
1050
0
            let temp16alen =
1051
0
                scale_expansion_zeroelim(&aytbctt[..aytbcttlen], 2.0 * ady, &mut temp16a);
1052
0
            let temp16blen =
1053
0
                scale_expansion_zeroelim(&aytbctt[..aytbcttlen], adytail, &mut temp16b);
1054
0
            let temp32blen = fast_expansion_sum_zeroelim(
1055
0
                &temp16a[..temp16alen],
1056
0
                &temp16b[..temp16blen],
1057
0
                &mut temp32b,
1058
0
            );
1059
0
            let temp64len = fast_expansion_sum_zeroelim(
1060
0
                &temp32a[..temp32alen],
1061
0
                &temp32b[..temp32blen],
1062
0
                &mut temp64,
1063
0
            );
1064
0
            finlength =
1065
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp64[..temp64len], &mut fin2);
1066
0
            ::core::mem::swap(&mut fin1, &mut fin2);
1067
0
        }
1068
0
    }
1069
1070
0
    if bdxtail != 0.0 || bdytail != 0.0 {
1071
0
        let mut catt = [0f64; 4];
1072
0
        let mut cat = [0f64; 8];
1073
        let cattlen;
1074
        let catlen;
1075
1076
0
        if cdxtail != 0.0 || cdytail != 0.0 || adxtail != 0.0 || adytail != 0.0 {
1077
0
            let (ti1, ti0) = two_product(cdxtail, ady);
1078
0
            let (tj1, tj0) = two_product(cdx, adytail);
1079
0
            let (u3, u2, u1, u0) = two_two_sum(ti1, ti0, tj1, tj0);
1080
0
            let u = [u0, u1, u2, u3];
1081
0
            let negate = -cdy;
1082
0
            let (ti1, ti0) = two_product(adxtail, negate);
1083
0
            let negate = -cdytail;
1084
0
            let (tj1, tj0) = two_product(adx, negate);
1085
0
            let (v3, v2, v1, v0) = two_two_sum(ti1, ti0, tj1, tj0);
1086
0
            let v = [v0, v1, v2, v3];
1087
0
            catlen = fast_expansion_sum_zeroelim(&u, &v, &mut cat);
1088
0
1089
0
            let (ti1, ti0) = two_product(cdxtail, adytail);
1090
0
            let (tj1, tj0) = two_product(adxtail, cdytail);
1091
0
            let (catt3, catt2, catt1, catt0) = two_two_diff(ti1, ti0, tj1, tj0);
1092
0
            catt = [catt0, catt1, catt2, catt3];
1093
0
            cattlen = 4;
1094
0
        } else {
1095
0
            cat[0] = 0.0;
1096
0
            catlen = 1;
1097
0
            catt[0] = 0.0;
1098
0
            cattlen = 1;
1099
0
        }
1100
1101
0
        if bdxtail != 0.0 {
1102
0
            let temp16alen = scale_expansion_zeroelim(&bxtca[..bxtcalen], bdxtail, &mut temp16a);
1103
0
            let mut bxtcat = [0f64; 16];
1104
0
            let bxtcatlen = scale_expansion_zeroelim(&cat[..catlen], bdxtail, &mut bxtcat);
1105
0
            let temp32alen =
1106
0
                scale_expansion_zeroelim(&bxtcat[..bxtcatlen], 2.0 * bdx, &mut temp32a);
1107
0
            let temp48len = fast_expansion_sum_zeroelim(
1108
0
                &temp16a[..temp16alen],
1109
0
                &temp32a[..temp32alen],
1110
0
                &mut temp48,
1111
            );
1112
0
            finlength =
1113
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
1114
0
            ::core::mem::swap(&mut fin1, &mut fin2);
1115
1116
0
            if cdytail != 0.0 {
1117
0
                let temp8len = scale_expansion_zeroelim(&aa, bdxtail, &mut temp8);
1118
0
                let temp16alen =
1119
0
                    scale_expansion_zeroelim(&temp8[..temp8len], cdytail, &mut temp16a);
1120
0
                finlength = fast_expansion_sum_zeroelim(
1121
0
                    &fin1[..finlength],
1122
0
                    &temp16a[..temp16alen],
1123
0
                    &mut fin2,
1124
0
                );
1125
0
                ::core::mem::swap(&mut fin1, &mut fin2);
1126
0
            }
1127
0
            if adytail != 0.0 {
1128
0
                let temp8len = scale_expansion_zeroelim(&cc, -bdxtail, &mut temp8);
1129
0
                let temp16alen =
1130
0
                    scale_expansion_zeroelim(&temp8[..temp8len], adytail, &mut temp16a);
1131
0
                finlength = fast_expansion_sum_zeroelim(
1132
0
                    &fin1[..finlength],
1133
0
                    &temp16a[..temp16alen],
1134
0
                    &mut fin2,
1135
0
                );
1136
0
                ::core::mem::swap(&mut fin1, &mut fin2);
1137
0
            }
1138
1139
0
            let temp32alen = scale_expansion_zeroelim(&bxtcat[..bxtcatlen], bdxtail, &mut temp32a);
1140
0
            let mut bxtcatt = [0f64; 8];
1141
0
            let bxtcattlen = scale_expansion_zeroelim(&catt[..cattlen], bdxtail, &mut bxtcatt);
1142
0
            let temp16alen =
1143
0
                scale_expansion_zeroelim(&bxtcatt[..bxtcattlen], 2.0 * bdx, &mut temp16a);
1144
0
            let temp16blen =
1145
0
                scale_expansion_zeroelim(&bxtcatt[..bxtcattlen], bdxtail, &mut temp16b);
1146
0
            let temp32blen = fast_expansion_sum_zeroelim(
1147
0
                &temp16a[..temp16alen],
1148
0
                &temp16b[..temp16blen],
1149
0
                &mut temp32b,
1150
            );
1151
0
            let temp64len = fast_expansion_sum_zeroelim(
1152
0
                &temp32a[..temp32alen],
1153
0
                &temp32b[..temp32blen],
1154
0
                &mut temp64,
1155
            );
1156
0
            finlength =
1157
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp64[..temp64len], &mut fin2);
1158
0
            ::core::mem::swap(&mut fin1, &mut fin2);
1159
0
        }
1160
0
        if bdytail != 0.0 {
1161
0
            let temp16alen = scale_expansion_zeroelim(&bytca[..bytcalen], bdytail, &mut temp16a);
1162
0
            let mut bytcat = [0f64; 16];
1163
0
            let bytcatlen = scale_expansion_zeroelim(&cat[..catlen], bdytail, &mut bytcat);
1164
0
            let temp32alen =
1165
0
                scale_expansion_zeroelim(&bytcat[..bytcatlen], 2.0 * bdy, &mut temp32a);
1166
0
            let temp48len = fast_expansion_sum_zeroelim(
1167
0
                &temp16a[..temp16alen],
1168
0
                &temp32a[..temp32alen],
1169
0
                &mut temp48,
1170
0
            );
1171
0
            finlength =
1172
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
1173
0
            ::core::mem::swap(&mut fin1, &mut fin2);
1174
0
1175
0
            let temp32alen = scale_expansion_zeroelim(&bytcat[..bytcatlen], bdytail, &mut temp32a);
1176
0
            let mut bytcatt = [0f64; 8];
1177
0
            let bytcattlen = scale_expansion_zeroelim(&catt[..cattlen], bdytail, &mut bytcatt);
1178
0
            let temp16alen =
1179
0
                scale_expansion_zeroelim(&bytcatt[..bytcattlen], 2.0 * bdy, &mut temp16a);
1180
0
            let temp16blen =
1181
0
                scale_expansion_zeroelim(&bytcatt[..bytcattlen], bdytail, &mut temp16b);
1182
0
            let temp32blen = fast_expansion_sum_zeroelim(
1183
0
                &temp16a[..temp16alen],
1184
0
                &temp16b[..temp16blen],
1185
0
                &mut temp32b,
1186
0
            );
1187
0
            let temp64len = fast_expansion_sum_zeroelim(
1188
0
                &temp32a[..temp32alen],
1189
0
                &temp32b[..temp32blen],
1190
0
                &mut temp64,
1191
0
            );
1192
0
            finlength =
1193
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp64[..temp64len], &mut fin2);
1194
0
            ::core::mem::swap(&mut fin1, &mut fin2);
1195
0
        }
1196
0
    }
1197
1198
0
    if cdxtail != 0.0 || cdytail != 0.0 {
1199
0
        let mut abtt = [0f64; 4];
1200
0
        let mut abt = [0f64; 8];
1201
        let abttlen;
1202
        let abtlen;
1203
1204
0
        if adxtail != 0.0 || adytail != 0.0 || bdxtail != 0.0 || bdytail != 0.0 {
1205
0
            let (ti1, ti0) = two_product(adxtail, bdy);
1206
0
            let (tj1, tj0) = two_product(adx, bdytail);
1207
0
            let (u3, u2, u1, u0) = two_two_sum(ti1, ti0, tj1, tj0);
1208
0
            let u = [u0, u1, u2, u3];
1209
0
            let negate = -ady;
1210
0
            let (ti1, ti0) = two_product(bdxtail, negate);
1211
0
            let negate = -adytail;
1212
0
            let (tj1, tj0) = two_product(bdx, negate);
1213
0
            let (v3, v2, v1, v0) = two_two_sum(ti1, ti0, tj1, tj0);
1214
0
            let v = [v0, v1, v2, v3];
1215
0
            abtlen = fast_expansion_sum_zeroelim(&u, &v, &mut abt);
1216
0
1217
0
            let (ti1, ti0) = two_product(adxtail, bdytail);
1218
0
            let (tj1, tj0) = two_product(bdxtail, adytail);
1219
0
            let (abtt3, abtt2, abtt1, abtt0) = two_two_diff(ti1, ti0, tj1, tj0);
1220
0
            abtt = [abtt0, abtt1, abtt2, abtt3];
1221
0
            abttlen = 4;
1222
0
        } else {
1223
0
            abt[0] = 0.0;
1224
0
            abtlen = 1;
1225
0
            abtt[0] = 0.0;
1226
0
            abttlen = 1;
1227
0
        }
1228
1229
0
        if cdxtail != 0.0 {
1230
0
            let temp16alen = scale_expansion_zeroelim(&cxtab[..cxtablen], cdxtail, &mut temp16a);
1231
0
            let mut cxtabt = [0f64; 16];
1232
0
            let cxtabtlen = scale_expansion_zeroelim(&abt[..abtlen], cdxtail, &mut cxtabt);
1233
0
            let temp32alen =
1234
0
                scale_expansion_zeroelim(&cxtabt[..cxtabtlen], 2.0 * cdx, &mut temp32a);
1235
0
            let temp48len = fast_expansion_sum_zeroelim(
1236
0
                &temp16a[..temp16alen],
1237
0
                &temp32a[..temp32alen],
1238
0
                &mut temp48,
1239
            );
1240
0
            finlength =
1241
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
1242
0
            ::core::mem::swap(&mut fin1, &mut fin2);
1243
1244
0
            if adytail != 0.0 {
1245
0
                let temp8len = scale_expansion_zeroelim(&bb, cdxtail, &mut temp8);
1246
0
                let temp16alen =
1247
0
                    scale_expansion_zeroelim(&temp8[..temp8len], adytail, &mut temp16a);
1248
0
                finlength = fast_expansion_sum_zeroelim(
1249
0
                    &fin1[..finlength],
1250
0
                    &temp16a[..temp16alen],
1251
0
                    &mut fin2,
1252
0
                );
1253
0
                ::core::mem::swap(&mut fin1, &mut fin2);
1254
0
            }
1255
0
            if bdytail != 0.0 {
1256
0
                let temp8len = scale_expansion_zeroelim(&aa, -cdxtail, &mut temp8);
1257
0
                let temp16alen =
1258
0
                    scale_expansion_zeroelim(&temp8[..temp8len], bdytail, &mut temp16a);
1259
0
                finlength = fast_expansion_sum_zeroelim(
1260
0
                    &fin1[..finlength],
1261
0
                    &temp16a[..temp16alen],
1262
0
                    &mut fin2,
1263
0
                );
1264
0
                ::core::mem::swap(&mut fin1, &mut fin2);
1265
0
            }
1266
1267
0
            let temp32alen = scale_expansion_zeroelim(&cxtabt[..cxtabtlen], cdxtail, &mut temp32a);
1268
0
            let mut cxtabtt = [0f64; 8];
1269
0
            let cxtabttlen = scale_expansion_zeroelim(&abtt[..abttlen], cdxtail, &mut cxtabtt);
1270
0
            let temp16alen =
1271
0
                scale_expansion_zeroelim(&cxtabtt[..cxtabttlen], 2.0 * cdx, &mut temp16a);
1272
0
            let temp16blen =
1273
0
                scale_expansion_zeroelim(&cxtabtt[..cxtabttlen], cdxtail, &mut temp16b);
1274
0
            let temp32blen = fast_expansion_sum_zeroelim(
1275
0
                &temp16a[..temp16alen],
1276
0
                &temp16b[..temp16blen],
1277
0
                &mut temp32b,
1278
            );
1279
0
            let temp64len = fast_expansion_sum_zeroelim(
1280
0
                &temp32a[..temp32alen],
1281
0
                &temp32b[..temp32blen],
1282
0
                &mut temp64,
1283
            );
1284
0
            finlength =
1285
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp64[..temp64len], &mut fin2);
1286
0
            ::core::mem::swap(&mut fin1, &mut fin2);
1287
0
        }
1288
0
        if cdytail != 0.0 {
1289
0
            let temp16alen = scale_expansion_zeroelim(&cytab[..cytablen], cdytail, &mut temp16a);
1290
0
            let mut cytabt = [0f64; 16];
1291
0
            let cytabtlen = scale_expansion_zeroelim(&abt[..abtlen], cdytail, &mut cytabt);
1292
0
            let temp32alen =
1293
0
                scale_expansion_zeroelim(&cytabt[..cytabtlen], 2.0 * cdy, &mut temp32a);
1294
0
            let temp48len = fast_expansion_sum_zeroelim(
1295
0
                &temp16a[..temp16alen],
1296
0
                &temp32a[..temp32alen],
1297
0
                &mut temp48,
1298
0
            );
1299
0
            finlength =
1300
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp48[..temp48len], &mut fin2);
1301
0
            ::core::mem::swap(&mut fin1, &mut fin2);
1302
0
1303
0
            let temp32alen = scale_expansion_zeroelim(&cytabt[..cytabtlen], cdytail, &mut temp32a);
1304
0
            let mut cytabtt = [0f64; 8];
1305
0
            let cytabttlen = scale_expansion_zeroelim(&abtt[..abttlen], cdytail, &mut cytabtt);
1306
0
            let temp16alen =
1307
0
                scale_expansion_zeroelim(&cytabtt[..cytabttlen], 2.0 * cdy, &mut temp16a);
1308
0
            let temp16blen =
1309
0
                scale_expansion_zeroelim(&cytabtt[..cytabttlen], cdytail, &mut temp16b);
1310
0
            let temp32blen = fast_expansion_sum_zeroelim(
1311
0
                &temp16a[..temp16alen],
1312
0
                &temp16b[..temp16blen],
1313
0
                &mut temp32b,
1314
0
            );
1315
0
            let temp64len = fast_expansion_sum_zeroelim(
1316
0
                &temp32a[..temp32alen],
1317
0
                &temp32b[..temp32blen],
1318
0
                &mut temp64,
1319
0
            );
1320
0
            finlength =
1321
0
                fast_expansion_sum_zeroelim(&fin1[..finlength], &temp64[..temp64len], &mut fin2);
1322
0
            ::core::mem::swap(&mut fin1, &mut fin2);
1323
0
        }
1324
0
    }
1325
0
    fin1[finlength - 1]
1326
0
}
1327
1328
/// Returns a positive value if the point `pe` lies inside the sphere passing through `pa`, `pb`, `pc`, and `pd`.  
1329
/// Returns a negative value if it lies outside.  
1330
/// Returns `0` if the five points are **cospherical**.  
1331
/// **NOTE**: The points `pa`, `pb`, `pc`, and `pd` must be ordered so that they have a positive orientation.
1332
0
pub fn insphere<T: Into<f64>>(
1333
0
    pa: Coord3D<T>,
1334
0
    pb: Coord3D<T>,
1335
0
    pc: Coord3D<T>,
1336
0
    pd: Coord3D<T>,
1337
0
    pe: Coord3D<T>,
1338
0
) -> f64 {
1339
0
    let pa = Coord3D {
1340
0
        x: pa.x.into(),
1341
0
        y: pa.y.into(),
1342
0
        z: pa.z.into(),
1343
0
    };
1344
0
    let pb = Coord3D {
1345
0
        x: pb.x.into(),
1346
0
        y: pb.y.into(),
1347
0
        z: pb.z.into(),
1348
0
    };
1349
0
    let pc = Coord3D {
1350
0
        x: pc.x.into(),
1351
0
        y: pc.y.into(),
1352
0
        z: pc.z.into(),
1353
0
    };
1354
0
    let pd = Coord3D {
1355
0
        x: pd.x.into(),
1356
0
        y: pd.y.into(),
1357
0
        z: pd.z.into(),
1358
0
    };
1359
0
    let pe = Coord3D {
1360
0
        x: pe.x.into(),
1361
0
        y: pe.y.into(),
1362
0
        z: pe.z.into(),
1363
0
    };
1364
1365
0
    let aex = pa.x - pe.x;
1366
0
    let bex = pb.x - pe.x;
1367
0
    let cex = pc.x - pe.x;
1368
0
    let dex = pd.x - pe.x;
1369
0
    let aey = pa.y - pe.y;
1370
0
    let bey = pb.y - pe.y;
1371
0
    let cey = pc.y - pe.y;
1372
0
    let dey = pd.y - pe.y;
1373
0
    let aez = pa.z - pe.z;
1374
0
    let bez = pb.z - pe.z;
1375
0
    let cez = pc.z - pe.z;
1376
0
    let dez = pd.z - pe.z;
1377
1378
0
    let aexbey = aex * bey;
1379
0
    let bexaey = bex * aey;
1380
0
    let ab = aexbey - bexaey;
1381
0
    let bexcey = bex * cey;
1382
0
    let cexbey = cex * bey;
1383
0
    let bc = bexcey - cexbey;
1384
0
    let cexdey = cex * dey;
1385
0
    let dexcey = dex * cey;
1386
0
    let cd = cexdey - dexcey;
1387
0
    let dexaey = dex * aey;
1388
0
    let aexdey = aex * dey;
1389
0
    let da = dexaey - aexdey;
1390
1391
0
    let aexcey = aex * cey;
1392
0
    let cexaey = cex * aey;
1393
0
    let ac = aexcey - cexaey;
1394
0
    let bexdey = bex * dey;
1395
0
    let dexbey = dex * bey;
1396
0
    let bd = bexdey - dexbey;
1397
1398
0
    let abc = aez * bc - bez * ac + cez * ab;
1399
0
    let bcd = bez * cd - cez * bd + dez * bc;
1400
0
    let cda = cez * da + dez * ac + aez * cd;
1401
0
    let dab = dez * ab + aez * bd + bez * da;
1402
1403
0
    let alift = aex * aex + aey * aey + aez * aez;
1404
0
    let blift = bex * bex + bey * bey + bez * bez;
1405
0
    let clift = cex * cex + cey * cey + cez * cez;
1406
0
    let dlift = dex * dex + dey * dey + dez * dez;
1407
1408
0
    let det = (dlift * abc - clift * dab) + (blift * cda - alift * bcd);
1409
1410
0
    let aezplus = abs(aez);
1411
0
    let bezplus = abs(bez);
1412
0
    let cezplus = abs(cez);
1413
0
    let dezplus = abs(dez);
1414
0
    let aexbeyplus = abs(aexbey);
1415
0
    let bexaeyplus = abs(bexaey);
1416
0
    let bexceyplus = abs(bexcey);
1417
0
    let cexbeyplus = abs(cexbey);
1418
0
    let cexdeyplus = abs(cexdey);
1419
0
    let dexceyplus = abs(dexcey);
1420
0
    let dexaeyplus = abs(dexaey);
1421
0
    let aexdeyplus = abs(aexdey);
1422
0
    let aexceyplus = abs(aexcey);
1423
0
    let cexaeyplus = abs(cexaey);
1424
0
    let bexdeyplus = abs(bexdey);
1425
0
    let dexbeyplus = abs(dexbey);
1426
0
    let permanent = ((cexdeyplus + dexceyplus) * bezplus
1427
0
        + (dexbeyplus + bexdeyplus) * cezplus
1428
0
        + (bexceyplus + cexbeyplus) * dezplus)
1429
0
        * alift
1430
0
        + ((dexaeyplus + aexdeyplus) * cezplus
1431
0
            + (aexceyplus + cexaeyplus) * dezplus
1432
0
            + (cexdeyplus + dexceyplus) * aezplus)
1433
0
            * blift
1434
0
        + ((aexbeyplus + bexaeyplus) * dezplus
1435
0
            + (bexdeyplus + dexbeyplus) * aezplus
1436
0
            + (dexaeyplus + aexdeyplus) * bezplus)
1437
0
            * clift
1438
0
        + ((bexceyplus + cexbeyplus) * aezplus
1439
0
            + (cexaeyplus + aexceyplus) * bezplus
1440
0
            + (aexbeyplus + bexaeyplus) * cezplus)
1441
0
            * dlift;
1442
0
    let errbound = ISPERRBOUND_A * permanent;
1443
0
    if det > errbound || -det > errbound {
1444
0
        return det;
1445
0
    }
1446
1447
0
    insphereadapt(pa, pb, pc, pd, pe, permanent)
1448
0
}
1449
1450
0
fn insphereadapt<T: Into<f64>>(
1451
0
    pa: Coord3D<T>,
1452
0
    pb: Coord3D<T>,
1453
0
    pc: Coord3D<T>,
1454
0
    pd: Coord3D<T>,
1455
0
    pe: Coord3D<T>,
1456
0
    permanent: f64,
1457
0
) -> f64 {
1458
0
    let pa = Coord3D {
1459
0
        x: pa.x.into(),
1460
0
        y: pa.y.into(),
1461
0
        z: pa.z.into(),
1462
0
    };
1463
0
    let pb = Coord3D {
1464
0
        x: pb.x.into(),
1465
0
        y: pb.y.into(),
1466
0
        z: pb.z.into(),
1467
0
    };
1468
0
    let pc = Coord3D {
1469
0
        x: pc.x.into(),
1470
0
        y: pc.y.into(),
1471
0
        z: pc.z.into(),
1472
0
    };
1473
0
    let pd = Coord3D {
1474
0
        x: pd.x.into(),
1475
0
        y: pd.y.into(),
1476
0
        z: pd.z.into(),
1477
0
    };
1478
0
    let pe = Coord3D {
1479
0
        x: pe.x.into(),
1480
0
        y: pe.y.into(),
1481
0
        z: pe.z.into(),
1482
0
    };
1483
1484
0
    let aex = pa.x - pe.x;
1485
0
    let bex = pb.x - pe.x;
1486
0
    let cex = pc.x - pe.x;
1487
0
    let dex = pd.x - pe.x;
1488
0
    let aey = pa.y - pe.y;
1489
0
    let bey = pb.y - pe.y;
1490
0
    let cey = pc.y - pe.y;
1491
0
    let dey = pd.y - pe.y;
1492
0
    let aez = pa.z - pe.z;
1493
0
    let bez = pb.z - pe.z;
1494
0
    let cez = pc.z - pe.z;
1495
0
    let dez = pd.z - pe.z;
1496
1497
0
    let (aexbey1, aexbey0) = two_product(aex, bey);
1498
0
    let (bexaey1, bexaey0) = two_product(bex, aey);
1499
0
    let (ab3, ab2, ab1, ab0) = two_two_diff(aexbey1, aexbey0, bexaey1, bexaey0);
1500
0
    let ab = [ab0, ab1, ab2, ab3];
1501
1502
0
    let (bexcey1, bexcey0) = two_product(bex, cey);
1503
0
    let (cexbey1, cexbey0) = two_product(cex, bey);
1504
0
    let (bc3, bc2, bc1, bc0) = two_two_diff(bexcey1, bexcey0, cexbey1, cexbey0);
1505
0
    let bc = [bc0, bc1, bc2, bc3];
1506
1507
0
    let (cexdey1, cexdey0) = two_product(cex, dey);
1508
0
    let (dexcey1, dexcey0) = two_product(dex, cey);
1509
0
    let (cd3, cd2, cd1, cd0) = two_two_diff(cexdey1, cexdey0, dexcey1, dexcey0);
1510
0
    let cd = [cd0, cd1, cd2, cd3];
1511
1512
0
    let (dexaey1, dexaey0) = two_product(dex, aey);
1513
0
    let (aexdey1, aexdey0) = two_product(aex, dey);
1514
0
    let (da3, da2, da1, da0) = two_two_diff(dexaey1, dexaey0, aexdey1, aexdey0);
1515
0
    let da = [da0, da1, da2, da3];
1516
1517
0
    let (aexcey1, aexcey0) = two_product(aex, cey);
1518
0
    let (cexaey1, cexaey0) = two_product(cex, aey);
1519
0
    let (ac3, ac2, ac1, ac0) = two_two_diff(aexcey1, aexcey0, cexaey1, cexaey0);
1520
0
    let ac = [ac0, ac1, ac2, ac3];
1521
1522
0
    let (bexdey1, bexdey0) = two_product(bex, dey);
1523
0
    let (dexbey1, dexbey0) = two_product(dex, bey);
1524
0
    let (bd3, bd2, bd1, bd0) = two_two_diff(bexdey1, bexdey0, dexbey1, dexbey0);
1525
0
    let bd = [bd0, bd1, bd2, bd3];
1526
1527
0
    let mut temp8a = [0f64; 8];
1528
0
    let mut temp8b = [0f64; 8];
1529
0
    let mut temp8c = [0f64; 8];
1530
0
    let mut temp16 = [0f64; 16];
1531
0
    let mut temp24 = [0f64; 24];
1532
0
    let mut temp48 = [0f64; 48];
1533
0
    let mut xdet = [0f64; 96];
1534
0
    let mut ydet = [0f64; 96];
1535
0
    let mut zdet = [0f64; 96];
1536
0
    let mut xydet = [0f64; 192];
1537
0
    let mut adet = [0f64; 288];
1538
0
    let mut bdet = [0f64; 288];
1539
0
    let mut cdet = [0f64; 288];
1540
0
    let mut ddet = [0f64; 288];
1541
0
    let mut abdet = [0f64; 576];
1542
0
    let mut cddet = [0f64; 576];
1543
0
    let mut fin1 = [0f64; 1152];
1544
1545
0
    let mut temp8alen = scale_expansion_zeroelim(&cd[..4], bez, &mut temp8a);
1546
0
    let mut temp8blen = scale_expansion_zeroelim(&bd[..4], -cez, &mut temp8b);
1547
0
    let mut temp8clen = scale_expansion_zeroelim(&bc[..4], dez, &mut temp8c);
1548
0
    let mut temp16len =
1549
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1550
0
    let mut temp24len =
1551
0
        fast_expansion_sum_zeroelim(&temp8c[..temp8clen], &temp16[..temp16len], &mut temp24);
1552
0
    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], aex, &mut temp48);
1553
0
    let mut xlen = scale_expansion_zeroelim(&temp48[..temp48len], -aex, &mut xdet);
1554
0
    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], aey, &mut temp48);
1555
0
    let mut ylen = scale_expansion_zeroelim(&temp48[..temp48len], -aey, &mut ydet);
1556
0
    let mut temp48len = scale_expansion_zeroelim(&temp24[..temp24len], aez, &mut temp48);
1557
0
    let mut zlen = scale_expansion_zeroelim(&temp48[..temp48len], -aez, &mut zdet);
1558
0
    let mut xylen = fast_expansion_sum_zeroelim(&xdet[..xlen], &ydet[..ylen], &mut xydet);
1559
0
    let alen = fast_expansion_sum_zeroelim(&xydet[..xylen], &zdet[..zlen], &mut adet);
1560
1561
0
    temp8alen = scale_expansion_zeroelim(&da[..4], cez, &mut temp8a);
1562
0
    temp8blen = scale_expansion_zeroelim(&ac[..4], dez, &mut temp8b);
1563
0
    temp8clen = scale_expansion_zeroelim(&cd[..4], aez, &mut temp8c);
1564
0
    temp16len =
1565
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1566
0
    temp24len =
1567
0
        fast_expansion_sum_zeroelim(&temp8c[..temp8clen], &temp16[..temp16len], &mut temp24);
1568
0
    temp48len = scale_expansion_zeroelim(&temp24[..temp24len], bex, &mut temp48);
1569
0
    xlen = scale_expansion_zeroelim(&temp48[..temp48len], bex, &mut xdet);
1570
0
    temp48len = scale_expansion_zeroelim(&temp24[..temp24len], bey, &mut temp48);
1571
0
    ylen = scale_expansion_zeroelim(&temp48[..temp48len], bey, &mut ydet);
1572
0
    temp48len = scale_expansion_zeroelim(&temp24[..temp24len], bez, &mut temp48);
1573
0
    zlen = scale_expansion_zeroelim(&temp48[..temp48len], bez, &mut zdet);
1574
0
    xylen = fast_expansion_sum_zeroelim(&xdet[..xlen], &ydet[..ylen], &mut xydet);
1575
0
    let blen = fast_expansion_sum_zeroelim(&xydet[..xylen], &zdet[..zlen], &mut bdet);
1576
1577
0
    temp8alen = scale_expansion_zeroelim(&ab[..4], dez, &mut temp8a);
1578
0
    temp8blen = scale_expansion_zeroelim(&bd[..4], aez, &mut temp8b);
1579
0
    temp8clen = scale_expansion_zeroelim(&da[..4], bez, &mut temp8c);
1580
0
    temp16len =
1581
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1582
0
    temp24len =
1583
0
        fast_expansion_sum_zeroelim(&temp8c[..temp8clen], &temp16[..temp16len], &mut temp24);
1584
0
    temp48len = scale_expansion_zeroelim(&temp24[..temp24len], cex, &mut temp48);
1585
0
    xlen = scale_expansion_zeroelim(&temp48[..temp48len], -cex, &mut xdet);
1586
0
    temp48len = scale_expansion_zeroelim(&temp24[..temp24len], cey, &mut temp48);
1587
0
    ylen = scale_expansion_zeroelim(&temp48[..temp48len], -cey, &mut ydet);
1588
0
    temp48len = scale_expansion_zeroelim(&temp24[..temp24len], cez, &mut temp48);
1589
0
    zlen = scale_expansion_zeroelim(&temp48[..temp48len], -cez, &mut zdet);
1590
0
    xylen = fast_expansion_sum_zeroelim(&xdet[..xlen], &ydet[..ylen], &mut xydet);
1591
0
    let clen = fast_expansion_sum_zeroelim(&xydet[..xylen], &zdet[..zlen], &mut cdet);
1592
1593
0
    temp8alen = scale_expansion_zeroelim(&bc[..4], aez, &mut temp8a);
1594
0
    temp8blen = scale_expansion_zeroelim(&ac[..4], -bez, &mut temp8b);
1595
0
    temp8clen = scale_expansion_zeroelim(&ab[..4], cez, &mut temp8c);
1596
0
    temp16len =
1597
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1598
0
    temp24len =
1599
0
        fast_expansion_sum_zeroelim(&temp8c[..temp8clen], &temp16[..temp16len], &mut temp24);
1600
0
    temp48len = scale_expansion_zeroelim(&temp24[..temp24len], dex, &mut temp48);
1601
0
    xlen = scale_expansion_zeroelim(&temp48[..temp48len], dex, &mut xdet);
1602
0
    temp48len = scale_expansion_zeroelim(&temp24[..temp24len], dey, &mut temp48);
1603
0
    ylen = scale_expansion_zeroelim(&temp48[..temp48len], dey, &mut ydet);
1604
0
    temp48len = scale_expansion_zeroelim(&temp24[..temp24len], dez, &mut temp48);
1605
0
    zlen = scale_expansion_zeroelim(&temp48[..temp48len], dez, &mut zdet);
1606
0
    xylen = fast_expansion_sum_zeroelim(&xdet[..xlen], &ydet[..ylen], &mut xydet);
1607
0
    let dlen = fast_expansion_sum_zeroelim(&xydet[..xylen], &zdet[..zlen], &mut ddet);
1608
1609
0
    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
1610
0
    let cdlen = fast_expansion_sum_zeroelim(&cdet[..clen], &ddet[..dlen], &mut cddet);
1611
0
    let finlength = fast_expansion_sum_zeroelim(&abdet[..ablen], &cddet[..cdlen], &mut fin1);
1612
1613
0
    let mut det = estimate(&fin1[..finlength]);
1614
0
    let mut errbound = ISPERRBOUND_B * permanent;
1615
0
    if det >= errbound || -det >= errbound {
1616
0
        return det;
1617
0
    }
1618
1619
0
    let aextail = two_diff_tail(pa.x, pe.x, aex);
1620
0
    let aeytail = two_diff_tail(pa.y, pe.y, aey);
1621
0
    let aeztail = two_diff_tail(pa.z, pe.z, aez);
1622
0
    let bextail = two_diff_tail(pb.x, pe.x, bex);
1623
0
    let beytail = two_diff_tail(pb.y, pe.y, bey);
1624
0
    let beztail = two_diff_tail(pb.z, pe.z, bez);
1625
0
    let cextail = two_diff_tail(pc.x, pe.x, cex);
1626
0
    let ceytail = two_diff_tail(pc.y, pe.y, cey);
1627
0
    let ceztail = two_diff_tail(pc.z, pe.z, cez);
1628
0
    let dextail = two_diff_tail(pd.x, pe.x, dex);
1629
0
    let deytail = two_diff_tail(pd.y, pe.y, dey);
1630
0
    let deztail = two_diff_tail(pd.z, pe.z, dez);
1631
0
    if (aextail == 0.0)
1632
0
        && (aeytail == 0.0)
1633
0
        && (aeztail == 0.0)
1634
0
        && (bextail == 0.0)
1635
0
        && (beytail == 0.0)
1636
0
        && (beztail == 0.0)
1637
0
        && (cextail == 0.0)
1638
0
        && (ceytail == 0.0)
1639
0
        && (ceztail == 0.0)
1640
0
        && (dextail == 0.0)
1641
0
        && (deytail == 0.0)
1642
0
        && (deztail == 0.0)
1643
    {
1644
0
        return det;
1645
0
    }
1646
1647
0
    errbound = ISPERRBOUND_C * permanent + RESULTERRBOUND * abs(det);
1648
0
    let abeps = (aex * beytail + bey * aextail) - (aey * bextail + bex * aeytail);
1649
0
    let bceps = (bex * ceytail + cey * bextail) - (bey * cextail + cex * beytail);
1650
0
    let cdeps = (cex * deytail + dey * cextail) - (cey * dextail + dex * ceytail);
1651
0
    let daeps = (dex * aeytail + aey * dextail) - (dey * aextail + aex * deytail);
1652
0
    let aceps = (aex * ceytail + cey * aextail) - (aey * cextail + cex * aeytail);
1653
0
    let bdeps = (bex * deytail + dey * bextail) - (bey * dextail + dex * beytail);
1654
0
    det += (((bex * bex + bey * bey + bez * bez)
1655
0
        * ((cez * daeps + dez * aceps + aez * cdeps)
1656
0
            + (ceztail * da3 + deztail * ac3 + aeztail * cd3))
1657
0
        + (dex * dex + dey * dey + dez * dez)
1658
0
            * ((aez * bceps - bez * aceps + cez * abeps)
1659
0
                + (aeztail * bc3 - beztail * ac3 + ceztail * ab3)))
1660
0
        - ((aex * aex + aey * aey + aez * aez)
1661
0
            * ((bez * cdeps - cez * bdeps + dez * bceps)
1662
0
                + (beztail * cd3 - ceztail * bd3 + deztail * bc3))
1663
0
            + (cex * cex + cey * cey + cez * cez)
1664
0
                * ((dez * abeps + aez * bdeps + bez * daeps)
1665
0
                    + (deztail * ab3 + aeztail * bd3 + beztail * da3))))
1666
0
        + 2.0
1667
0
            * (((bex * bextail + bey * beytail + bez * beztail)
1668
0
                * (cez * da3 + dez * ac3 + aez * cd3)
1669
0
                + (dex * dextail + dey * deytail + dez * deztail)
1670
0
                    * (aez * bc3 - bez * ac3 + cez * ab3))
1671
0
                - ((aex * aextail + aey * aeytail + aez * aeztail)
1672
0
                    * (bez * cd3 - cez * bd3 + dez * bc3)
1673
0
                    + (cex * cextail + cey * ceytail + cez * ceztail)
1674
0
                        * (dez * ab3 + aez * bd3 + bez * da3)));
1675
0
    if det >= errbound || -det >= errbound {
1676
0
        return det;
1677
0
    }
1678
1679
0
    insphereexact(pa, pb, pc, pd, pe)
1680
0
}
1681
1682
0
fn insphereexact<T: Into<f64>>(
1683
0
    pa: Coord3D<T>,
1684
0
    pb: Coord3D<T>,
1685
0
    pc: Coord3D<T>,
1686
0
    pd: Coord3D<T>,
1687
0
    pe: Coord3D<T>,
1688
0
) -> f64 {
1689
0
    let pa = Coord3D {
1690
0
        x: pa.x.into(),
1691
0
        y: pa.y.into(),
1692
0
        z: pa.z.into(),
1693
0
    };
1694
0
    let pb = Coord3D {
1695
0
        x: pb.x.into(),
1696
0
        y: pb.y.into(),
1697
0
        z: pb.z.into(),
1698
0
    };
1699
0
    let pc = Coord3D {
1700
0
        x: pc.x.into(),
1701
0
        y: pc.y.into(),
1702
0
        z: pc.z.into(),
1703
0
    };
1704
0
    let pd = Coord3D {
1705
0
        x: pd.x.into(),
1706
0
        y: pd.y.into(),
1707
0
        z: pd.z.into(),
1708
0
    };
1709
0
    let pe = Coord3D {
1710
0
        x: pe.x.into(),
1711
0
        y: pe.y.into(),
1712
0
        z: pe.z.into(),
1713
0
    };
1714
1715
0
    let (axby1, axby0) = two_product(pa.x, pb.y);
1716
0
    let (bxay1, bxay0) = two_product(pb.x, pa.y);
1717
0
    let (ab3, ab2, ab1, ab0) = two_two_diff(axby1, axby0, bxay1, bxay0);
1718
0
    let ab = [ab0, ab1, ab2, ab3];
1719
1720
0
    let (bxcy1, bxcy0) = two_product(pb.x, pc.y);
1721
0
    let (cxby1, cxby0) = two_product(pc.x, pb.y);
1722
0
    let (bc3, bc2, bc1, bc0) = two_two_diff(bxcy1, bxcy0, cxby1, cxby0);
1723
0
    let bc = [bc0, bc1, bc2, bc3];
1724
1725
0
    let (cxdy1, cxdy0) = two_product(pc.x, pd.y);
1726
0
    let (dxcy1, dxcy0) = two_product(pd.x, pc.y);
1727
0
    let (cd3, cd2, cd1, cd0) = two_two_diff(cxdy1, cxdy0, dxcy1, dxcy0);
1728
0
    let cd = [cd0, cd1, cd2, cd3];
1729
1730
0
    let (dxey1, dxey0) = two_product(pd.x, pe.y);
1731
0
    let (exdy1, exdy0) = two_product(pe.x, pd.y);
1732
0
    let (de3, de2, de1, de0) = two_two_diff(dxey1, dxey0, exdy1, exdy0);
1733
0
    let de = [de0, de1, de2, de3];
1734
1735
0
    let (exay1, exay0) = two_product(pe.x, pa.y);
1736
0
    let (axey1, axey0) = two_product(pa.x, pe.y);
1737
0
    let (ea3, ea2, ea1, ea0) = two_two_diff(exay1, exay0, axey1, axey0);
1738
0
    let ea = [ea0, ea1, ea2, ea3];
1739
1740
0
    let (axcy1, axcy0) = two_product(pa.x, pc.y);
1741
0
    let (cxay1, cxay0) = two_product(pc.x, pa.y);
1742
0
    let (ac3, ac2, ac1, ac0) = two_two_diff(axcy1, axcy0, cxay1, cxay0);
1743
0
    let ac = [ac0, ac1, ac2, ac3];
1744
1745
0
    let (bxdy1, bxdy0) = two_product(pb.x, pd.y);
1746
0
    let (dxby1, dxby0) = two_product(pd.x, pb.y);
1747
0
    let (bd3, bd2, bd1, bd0) = two_two_diff(bxdy1, bxdy0, dxby1, dxby0);
1748
0
    let bd = [bd0, bd1, bd2, bd3];
1749
1750
0
    let (cxey1, cxey0) = two_product(pc.x, pe.y);
1751
0
    let (excy1, excy0) = two_product(pe.x, pc.y);
1752
0
    let (ce3, ce2, ce1, ce0) = two_two_diff(cxey1, cxey0, excy1, excy0);
1753
0
    let ce = [ce0, ce1, ce2, ce3];
1754
1755
0
    let (dxay1, dxay0) = two_product(pd.x, pa.y);
1756
0
    let (axdy1, axdy0) = two_product(pa.x, pd.y);
1757
0
    let (da3, da2, da1, da0) = two_two_diff(dxay1, dxay0, axdy1, axdy0);
1758
0
    let da = [da0, da1, da2, da3];
1759
1760
0
    let (exby1, exby0) = two_product(pe.x, pb.y);
1761
0
    let (bxey1, bxey0) = two_product(pb.x, pe.y);
1762
0
    let (eb3, eb2, eb1, eb0) = two_two_diff(exby1, exby0, bxey1, bxey0);
1763
0
    let eb = [eb0, eb1, eb2, eb3];
1764
1765
0
    let mut temp8a = [0f64; 8];
1766
0
    let mut temp8b = [0f64; 8];
1767
0
    let mut temp16 = [0f64; 16];
1768
0
    let mut temp48a = [0f64; 48];
1769
0
    let mut temp48b = [0f64; 48];
1770
1771
0
    let mut abc = [0f64; 24];
1772
0
    let mut bcd = [0f64; 24];
1773
0
    let mut cde = [0f64; 24];
1774
0
    let mut dea = [0f64; 24];
1775
0
    let mut eab = [0f64; 24];
1776
0
    let mut abd = [0f64; 24];
1777
0
    let mut bce = [0f64; 24];
1778
0
    let mut cda = [0f64; 24];
1779
0
    let mut deb = [0f64; 24];
1780
0
    let mut eac = [0f64; 24];
1781
1782
0
    let mut abcd = [0f64; 96];
1783
0
    let mut bcde = [0f64; 96];
1784
0
    let mut cdea = [0f64; 96];
1785
0
    let mut deab = [0f64; 96];
1786
0
    let mut eabc = [0f64; 96];
1787
1788
0
    let mut temp192 = [0f64; 192];
1789
0
    let mut det384x = [0f64; 384];
1790
0
    let mut det384y = [0f64; 384];
1791
0
    let mut det384z = [0f64; 384];
1792
1793
0
    let mut detxy = [0f64; 768];
1794
1795
0
    let mut adet = [0f64; 1152];
1796
0
    let mut bdet = [0f64; 1152];
1797
0
    let mut cdet = [0f64; 1152];
1798
0
    let mut ddet = [0f64; 1152];
1799
0
    let mut edet = [0f64; 1152];
1800
1801
0
    let mut abdet = [0f64; 2304];
1802
0
    let mut cddet = [0f64; 2304];
1803
0
    let mut cdedet = [0f64; 3456];
1804
1805
0
    let mut deter = [0f64; 5760];
1806
1807
0
    let mut temp8alen = scale_expansion_zeroelim(&bc[..4], pa.z, &mut temp8a);
1808
0
    let mut temp8blen = scale_expansion_zeroelim(&ac[..4], -pb.z, &mut temp8b);
1809
0
    let mut temp16len =
1810
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1811
0
    temp8alen = scale_expansion_zeroelim(&ab[..4], pc.z, &mut temp8a);
1812
0
    let abclen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut abc);
1813
1814
0
    temp8alen = scale_expansion_zeroelim(&cd[..4], pb.z, &mut temp8a);
1815
0
    temp8blen = scale_expansion_zeroelim(&bd[..4], -pc.z, &mut temp8b);
1816
0
    temp16len =
1817
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1818
0
    temp8alen = scale_expansion_zeroelim(&bc[..4], pd.z, &mut temp8a);
1819
0
    let bcdlen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut bcd);
1820
1821
0
    temp8alen = scale_expansion_zeroelim(&de[..4], pc.z, &mut temp8a);
1822
0
    temp8blen = scale_expansion_zeroelim(&ce[..4], -pd.z, &mut temp8b);
1823
0
    temp16len =
1824
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1825
0
    temp8alen = scale_expansion_zeroelim(&cd[..4], pe.z, &mut temp8a);
1826
0
    let cdelen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut cde);
1827
1828
0
    temp8alen = scale_expansion_zeroelim(&ea[..4], pd.z, &mut temp8a);
1829
0
    temp8blen = scale_expansion_zeroelim(&da[..4], -pe.z, &mut temp8b);
1830
0
    temp16len =
1831
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1832
0
    temp8alen = scale_expansion_zeroelim(&de[..4], pa.z, &mut temp8a);
1833
0
    let dealen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut dea);
1834
1835
0
    temp8alen = scale_expansion_zeroelim(&ab[..4], pe.z, &mut temp8a);
1836
0
    temp8blen = scale_expansion_zeroelim(&eb[..4], -pa.z, &mut temp8b);
1837
0
    temp16len =
1838
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1839
0
    temp8alen = scale_expansion_zeroelim(&ea[..4], pb.z, &mut temp8a);
1840
0
    let eablen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut eab);
1841
1842
0
    temp8alen = scale_expansion_zeroelim(&bd[..4], pa.z, &mut temp8a);
1843
0
    temp8blen = scale_expansion_zeroelim(&da[..4], pb.z, &mut temp8b);
1844
0
    temp16len =
1845
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1846
0
    temp8alen = scale_expansion_zeroelim(&ab[..4], pd.z, &mut temp8a);
1847
0
    let abdlen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut abd);
1848
1849
0
    temp8alen = scale_expansion_zeroelim(&ce[..4], pb.z, &mut temp8a);
1850
0
    temp8blen = scale_expansion_zeroelim(&eb[..4], pc.z, &mut temp8b);
1851
0
    temp16len =
1852
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1853
0
    temp8alen = scale_expansion_zeroelim(&bc[..4], pe.z, &mut temp8a);
1854
0
    let bcelen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut bce);
1855
1856
0
    temp8alen = scale_expansion_zeroelim(&da[..4], pc.z, &mut temp8a);
1857
0
    temp8blen = scale_expansion_zeroelim(&ac[..4], pd.z, &mut temp8b);
1858
0
    temp16len =
1859
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1860
0
    temp8alen = scale_expansion_zeroelim(&cd[..4], pa.z, &mut temp8a);
1861
0
    let cdalen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut cda);
1862
1863
0
    temp8alen = scale_expansion_zeroelim(&eb[..4], pd.z, &mut temp8a);
1864
0
    temp8blen = scale_expansion_zeroelim(&bd[..4], pe.z, &mut temp8b);
1865
0
    temp16len =
1866
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1867
0
    temp8alen = scale_expansion_zeroelim(&de[..4], pb.z, &mut temp8a);
1868
0
    let deblen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut deb);
1869
1870
0
    temp8alen = scale_expansion_zeroelim(&ac[..4], pe.z, &mut temp8a);
1871
0
    temp8blen = scale_expansion_zeroelim(&ce[..4], pa.z, &mut temp8b);
1872
0
    temp16len =
1873
0
        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
1874
0
    let temp8alen = scale_expansion_zeroelim(&ea[..4], pc.z, &mut temp8a);
1875
0
    let eaclen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut eac);
1876
1877
0
    let mut temp48alen = fast_expansion_sum_zeroelim(&cde[..cdelen], &bce[..bcelen], &mut temp48a);
1878
0
    let mut temp48blen = fast_expansion_sum_zeroelim(&deb[..deblen], &bcd[..bcdlen], &mut temp48b);
1879
0
    for i in 0..temp48blen {
1880
0
        temp48b[i] = -temp48b[i];
1881
0
    }
1882
1883
0
    let bcdelen =
1884
0
        fast_expansion_sum_zeroelim(&temp48a[..temp48alen], &temp48b[..temp48blen], &mut bcde);
1885
0
    let mut xlen = scale_expansion_zeroelim(&bcde[..bcdelen], pa.x, &mut temp192);
1886
0
    xlen = scale_expansion_zeroelim(&temp192[..xlen], pa.x, &mut det384x);
1887
0
    let mut ylen = scale_expansion_zeroelim(&bcde[..bcdelen], pa.y, &mut temp192);
1888
0
    ylen = scale_expansion_zeroelim(&temp192[..ylen], pa.y, &mut det384y);
1889
0
    let mut zlen = scale_expansion_zeroelim(&bcde[..bcdelen], pa.z, &mut temp192);
1890
0
    zlen = scale_expansion_zeroelim(&temp192[..zlen], pa.z, &mut det384z);
1891
0
    let mut xylen = fast_expansion_sum_zeroelim(&det384x[..xlen], &det384y[..ylen], &mut detxy);
1892
0
    let alen = fast_expansion_sum_zeroelim(&detxy[..xylen], &det384z[..zlen], &mut adet);
1893
1894
0
    temp48alen = fast_expansion_sum_zeroelim(&dea[..dealen], &cda[..cdalen], &mut temp48a);
1895
0
    temp48blen = fast_expansion_sum_zeroelim(&eac[..eaclen], &cde[..cdelen], &mut temp48b);
1896
0
    for i in 0..temp48blen {
1897
0
        temp48b[i] = -temp48b[i];
1898
0
    }
1899
0
    let cdealen =
1900
0
        fast_expansion_sum_zeroelim(&temp48a[..temp48alen], &temp48b[..temp48blen], &mut cdea);
1901
0
    xlen = scale_expansion_zeroelim(&cdea[..cdealen], pb.x, &mut temp192);
1902
0
    xlen = scale_expansion_zeroelim(&temp192[..xlen], pb.x, &mut det384x);
1903
0
    ylen = scale_expansion_zeroelim(&cdea[..cdealen], pb.y, &mut temp192);
1904
0
    ylen = scale_expansion_zeroelim(&temp192[..ylen], pb.y, &mut det384y);
1905
0
    zlen = scale_expansion_zeroelim(&cdea[..cdealen], pb.z, &mut temp192);
1906
0
    zlen = scale_expansion_zeroelim(&temp192[..zlen], pb.z, &mut det384z);
1907
0
    xylen = fast_expansion_sum_zeroelim(&det384x[..xlen], &det384y[..ylen], &mut detxy);
1908
0
    let blen = fast_expansion_sum_zeroelim(&detxy[..xylen], &det384z[..zlen], &mut bdet);
1909
1910
0
    temp48alen = fast_expansion_sum_zeroelim(&eab[..eablen], &deb[..deblen], &mut temp48a);
1911
0
    temp48blen = fast_expansion_sum_zeroelim(&abd[..abdlen], &dea[..dealen], &mut temp48b);
1912
0
    for i in 0..temp48blen {
1913
0
        temp48b[i] = -temp48b[i];
1914
0
    }
1915
0
    let deablen =
1916
0
        fast_expansion_sum_zeroelim(&temp48a[..temp48alen], &temp48b[..temp48blen], &mut deab);
1917
0
    xlen = scale_expansion_zeroelim(&deab[..deablen], pc.x, &mut temp192);
1918
0
    xlen = scale_expansion_zeroelim(&temp192[..xlen], pc.x, &mut det384x);
1919
0
    ylen = scale_expansion_zeroelim(&deab[..deablen], pc.y, &mut temp192);
1920
0
    ylen = scale_expansion_zeroelim(&temp192[..ylen], pc.y, &mut det384y);
1921
0
    zlen = scale_expansion_zeroelim(&deab[..deablen], pc.z, &mut temp192);
1922
0
    zlen = scale_expansion_zeroelim(&temp192[..zlen], pc.z, &mut det384z);
1923
0
    xylen = fast_expansion_sum_zeroelim(&det384x[..xlen], &det384y[..ylen], &mut detxy);
1924
0
    let clen = fast_expansion_sum_zeroelim(&detxy[..xylen], &det384z[..zlen], &mut cdet);
1925
1926
0
    temp48alen = fast_expansion_sum_zeroelim(&abc[..abclen], &eac[..eaclen], &mut temp48a);
1927
0
    temp48blen = fast_expansion_sum_zeroelim(&bce[..bcelen], &eab[..eablen], &mut temp48b);
1928
0
    for i in 0..temp48blen {
1929
0
        temp48b[i] = -temp48b[i];
1930
0
    }
1931
0
    let eabclen =
1932
0
        fast_expansion_sum_zeroelim(&temp48a[..temp48alen], &temp48b[..temp48blen], &mut eabc);
1933
0
    xlen = scale_expansion_zeroelim(&eabc[..eabclen], pd.x, &mut temp192);
1934
0
    xlen = scale_expansion_zeroelim(&temp192[..xlen], pd.x, &mut det384x);
1935
0
    ylen = scale_expansion_zeroelim(&eabc[..eabclen], pd.y, &mut temp192);
1936
0
    ylen = scale_expansion_zeroelim(&temp192[..ylen], pd.y, &mut det384y);
1937
0
    zlen = scale_expansion_zeroelim(&eabc[..eabclen], pd.z, &mut temp192);
1938
0
    zlen = scale_expansion_zeroelim(&temp192[..zlen], pd.z, &mut det384z);
1939
0
    xylen = fast_expansion_sum_zeroelim(&det384x[..xlen], &det384y[..ylen], &mut detxy);
1940
0
    let dlen = fast_expansion_sum_zeroelim(&detxy[..xylen], &det384z[..zlen], &mut ddet);
1941
1942
0
    temp48alen = fast_expansion_sum_zeroelim(&bcd[..bcdlen], &abd[..abdlen], &mut temp48a);
1943
0
    temp48blen = fast_expansion_sum_zeroelim(&cda[..cdalen], &abc[..abclen], &mut temp48b);
1944
0
    for i in 0..temp48blen {
1945
0
        temp48b[i] = -temp48b[i];
1946
0
    }
1947
0
    let abcdlen =
1948
0
        fast_expansion_sum_zeroelim(&temp48a[..temp48alen], &temp48b[..temp48blen], &mut abcd);
1949
0
    xlen = scale_expansion_zeroelim(&abcd[..abcdlen], pe.x, &mut temp192);
1950
0
    xlen = scale_expansion_zeroelim(&temp192[..xlen], pe.x, &mut det384x);
1951
0
    ylen = scale_expansion_zeroelim(&abcd[..abcdlen], pe.y, &mut temp192);
1952
0
    ylen = scale_expansion_zeroelim(&temp192[..ylen], pe.y, &mut det384y);
1953
0
    zlen = scale_expansion_zeroelim(&abcd[..abcdlen], pe.z, &mut temp192);
1954
0
    zlen = scale_expansion_zeroelim(&temp192[..zlen], pe.z, &mut det384z);
1955
0
    xylen = fast_expansion_sum_zeroelim(&det384x[..xlen], &det384y[..ylen], &mut detxy);
1956
0
    let elen = fast_expansion_sum_zeroelim(&detxy[..xylen], &det384z[..zlen], &mut edet);
1957
1958
0
    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
1959
0
    let cdlen = fast_expansion_sum_zeroelim(&cdet[..clen], &ddet[..dlen], &mut cddet);
1960
0
    let cdelen = fast_expansion_sum_zeroelim(&cddet[..cdlen], &edet[..elen], &mut cdedet);
1961
0
    let deterlen = fast_expansion_sum_zeroelim(&abdet[..ablen], &cdedet[..cdelen], &mut deter);
1962
1963
0
    deter[deterlen - 1]
1964
0
}
1965
1966
0
fn scale_expansion_zeroelim(e: &[f64], b: f64, h: &mut [f64]) -> usize {
1967
0
    let (bhi, blo) = split(b);
1968
0
    let (mut Q, hh) = two_product_presplit(e[0], b, bhi, blo);
1969
0
    let mut hindex = 0;
1970
0
    if hh != 0.0 {
1971
0
        h[hindex] = hh;
1972
0
        hindex += 1;
1973
0
    }
1974
0
    for eindex in 1..e.len() {
1975
0
        let enow = e[eindex];
1976
0
        let (product1, product0) = two_product_presplit(enow, b, bhi, blo);
1977
0
        let (sum, hh) = two_sum(Q, product0);
1978
0
        if hh != 0.0 {
1979
0
            h[hindex] = hh;
1980
0
            hindex += 1;
1981
0
        }
1982
0
        let (new_q, hh) = fast_two_sum(product1, sum);
1983
0
        Q = new_q;
1984
0
        if hh != 0.0 {
1985
0
            h[hindex] = hh;
1986
0
            hindex += 1;
1987
0
        }
1988
    }
1989
0
    if Q != 0.0 || hindex == 0 {
1990
0
        h[hindex] = Q;
1991
0
        hindex += 1;
1992
0
    }
1993
0
    hindex
1994
0
}
1995
1996
#[inline]
1997
0
fn two_product(a: f64, b: f64) -> (f64, f64) {
1998
0
    let x = a * b;
1999
0
    (x, two_product_tail(a, b, x))
2000
0
}
2001
2002
#[inline]
2003
0
fn two_product_tail(a: f64, b: f64, x: f64) -> f64 {
2004
0
    let (ahi, alo) = split(a);
2005
0
    let (bhi, blo) = split(b);
2006
0
    let err1 = x - (ahi * bhi);
2007
0
    let err2 = err1 - (alo * bhi);
2008
0
    let err3 = err2 - (ahi * blo);
2009
0
    (alo * blo) - err3
2010
0
}
2011
2012
#[inline]
2013
0
fn split(a: f64) -> (f64, f64) {
2014
0
    let c = SPLITTER * a;
2015
0
    let abig = c - a;
2016
0
    let ahi = c - abig;
2017
0
    let alo = a - ahi;
2018
0
    (ahi, alo)
2019
0
}
2020
2021
#[inline]
2022
0
fn two_product_presplit(a: f64, b: f64, bhi: f64, blo: f64) -> (f64, f64) {
2023
0
    let x = a * b;
2024
0
    let (ahi, alo) = split(a);
2025
0
    let err1 = x - ahi * bhi;
2026
0
    let err2 = err1 - alo * bhi;
2027
0
    let err3 = err2 - ahi * blo;
2028
0
    let y = alo * blo - err3;
2029
0
    (x, y)
2030
0
}
2031
2032
#[inline]
2033
0
fn two_two_diff(a1: f64, a0: f64, b1: f64, b0: f64) -> (f64, f64, f64, f64) {
2034
0
    let (j, _r0, x0) = two_one_diff(a1, a0, b0);
2035
0
    let (x3, x2, x1) = two_one_diff(j, _r0, b1);
2036
0
    (x3, x2, x1, x0)
2037
0
}
2038
2039
#[inline]
2040
0
fn two_one_diff(a1: f64, a0: f64, b: f64) -> (f64, f64, f64) {
2041
0
    let (i, x0) = two_diff(a0, b);
2042
0
    let (x2, x1) = two_sum(a1, i);
2043
0
    (x2, x1, x0)
2044
0
}
2045
2046
#[inline]
2047
0
fn two_diff(a: f64, b: f64) -> (f64, f64) {
2048
0
    let x = a - b;
2049
0
    (x, two_diff_tail(a, b, x))
2050
0
}
2051
2052
#[inline]
2053
0
fn two_diff_tail(a: f64, b: f64, x: f64) -> f64 {
2054
0
    let bvirt = a - x;
2055
0
    let avirt = x + bvirt;
2056
0
    let bround = bvirt - b;
2057
0
    let around = a - avirt;
2058
0
    around + bround
2059
0
}
2060
2061
#[inline]
2062
0
fn two_sum(a: f64, b: f64) -> (f64, f64) {
2063
0
    let x = a + b;
2064
0
    (x, two_sum_tail(a, b, x))
2065
0
}
2066
2067
#[inline]
2068
0
fn two_sum_tail(a: f64, b: f64, x: f64) -> f64 {
2069
0
    let bvirt = x - a;
2070
0
    let avirt = x - bvirt;
2071
0
    let bround = b - bvirt;
2072
0
    let around = a - avirt;
2073
0
    around + bround
2074
0
}
2075
2076
0
fn estimate(e: &[f64]) -> f64 {
2077
0
    let mut q = e[0];
2078
0
    for cur in &e[1..] {
2079
0
        q += *cur;
2080
0
    }
2081
0
    q
2082
0
}
2083
2084
0
fn fast_expansion_sum_zeroelim(e: &[f64], f: &[f64], h: &mut [f64]) -> usize {
2085
0
    let mut enow = e[0];
2086
0
    let mut fnow = f[0];
2087
0
    let mut eindex = 0;
2088
0
    let mut findex = 0;
2089
    let mut Qnew;
2090
    let mut hh;
2091
    let mut Q;
2092
0
    if (fnow > enow) == (fnow > -enow) {
2093
0
        Q = enow;
2094
0
        eindex += 1;
2095
0
    } else {
2096
0
        Q = fnow;
2097
0
        findex += 1;
2098
0
    }
2099
2100
0
    let mut hindex = 0;
2101
0
    if eindex < e.len() && findex < f.len() {
2102
0
        enow = e[eindex];
2103
0
        fnow = f[findex];
2104
0
        if (fnow > enow) == (fnow > -enow) {
2105
0
            let r = fast_two_sum(enow, Q);
2106
0
            Qnew = r.0;
2107
0
            hh = r.1;
2108
0
            eindex += 1;
2109
0
        } else {
2110
0
            let r = fast_two_sum(fnow, Q);
2111
0
            Qnew = r.0;
2112
0
            hh = r.1;
2113
0
            findex += 1;
2114
0
        }
2115
0
        Q = Qnew;
2116
0
        if hh != 0.0 {
2117
0
            h[hindex] = hh;
2118
0
            hindex += 1;
2119
0
        }
2120
2121
0
        while eindex < e.len() && findex < f.len() {
2122
0
            enow = e[eindex];
2123
0
            fnow = f[findex];
2124
0
            if (fnow > enow) == (fnow > -enow) {
2125
0
                let r = two_sum(Q, enow);
2126
0
                Qnew = r.0;
2127
0
                hh = r.1;
2128
0
                eindex += 1;
2129
0
            } else {
2130
0
                let r = two_sum(Q, fnow);
2131
0
                Qnew = r.0;
2132
0
                hh = r.1;
2133
0
                findex += 1;
2134
0
            };
2135
0
            Q = Qnew;
2136
0
            if hh != 0.0 {
2137
0
                h[hindex] = hh;
2138
0
                hindex += 1;
2139
0
            }
2140
        }
2141
0
    }
2142
2143
0
    while eindex < e.len() {
2144
0
        enow = e[eindex];
2145
0
        let r = two_sum(Q, enow);
2146
0
        Qnew = r.0;
2147
0
        hh = r.1;
2148
0
        Q = Qnew;
2149
0
        eindex += 1;
2150
0
        if hh != 0.0 {
2151
0
            h[hindex] = hh;
2152
0
            hindex += 1
2153
0
        }
2154
    }
2155
2156
0
    while findex < f.len() {
2157
0
        fnow = f[findex];
2158
0
        let r = two_sum(Q, fnow);
2159
0
        Qnew = r.0;
2160
0
        hh = r.1;
2161
0
        Q = Qnew;
2162
0
        findex += 1;
2163
0
        if hh != 0.0 {
2164
0
            h[hindex] = hh;
2165
0
            hindex += 1
2166
0
        }
2167
    }
2168
2169
0
    if Q != 0.0 || hindex == 0 {
2170
0
        h[hindex] = Q;
2171
0
        hindex += 1;
2172
0
    }
2173
0
    hindex
2174
0
}
2175
2176
#[inline]
2177
0
fn fast_two_sum_tail(a: f64, b: f64, x: f64) -> f64 {
2178
0
    let bvirt = x - a;
2179
0
    b - bvirt
2180
0
}
2181
2182
#[inline]
2183
0
fn fast_two_sum(a: f64, b: f64) -> (f64, f64) {
2184
0
    let x = a + b;
2185
0
    (x, fast_two_sum_tail(a, b, x))
2186
0
}
2187
2188
#[inline]
2189
0
fn square_tail(a: f64, x: f64) -> f64 {
2190
0
    let (ahi, alo) = split(a);
2191
0
    let err1 = x - ahi * ahi;
2192
0
    let err3 = err1 - (ahi + ahi) * alo;
2193
0
    alo * alo - err3
2194
0
}
2195
2196
#[inline]
2197
0
fn square(a: f64) -> (f64, f64) {
2198
0
    let x = a * a;
2199
0
    (x, square_tail(a, x))
2200
0
}
2201
2202
#[inline]
2203
0
fn two_one_sum(a1: f64, a0: f64, b: f64) -> (f64, f64, f64) {
2204
0
    let (_i, x0) = two_sum(a0, b);
2205
0
    let (x2, x1) = two_sum(a1, _i);
2206
0
    (x2, x1, x0)
2207
0
}
2208
2209
#[inline]
2210
0
fn two_two_sum(a1: f64, a0: f64, b1: f64, b0: f64) -> (f64, f64, f64, f64) {
2211
0
    let (_j, _r0, x0) = two_one_sum(a1, a0, b0);
2212
0
    let (x3, x2, x1) = two_one_sum(_j, _r0, b1);
2213
0
    (x3, x2, x1, x0)
2214
0
}
2215
2216
#[inline]
2217
0
fn two_one_product(a1: f64, a0: f64, b: f64) -> (f64, f64, f64, f64) {
2218
0
    let (bhi, blo) = split(b);
2219
0
    let (mut _i, x0) = two_product_presplit(a0, b, bhi, blo);
2220
0
    let (mut _j, _0) = two_product_presplit(a1, b, bhi, blo);
2221
0
    let (_k, x1) = two_sum(_i, _0);
2222
0
    let (x3, x2) = fast_two_sum(_j, _k);
2223
0
    (x3, x2, x1, x0)
2224
0
}