geometry_predicates/
predicates.rs

1/// Returns the absolute value of the given number.
2///
3/// This function exists since [`std::f64::abs`](std::f64::abs) is not available in core.
4/// See [#50145](https://github.com/rust-lang/rust/issues/50145)
5///
6/// This implementation is identical to [`std::f64::abs`](std::f64::abs) on x86 but not on ARM at the time of this writing.
7#[inline]
8pub fn abs(a: f64) -> f64 {
9    f64::from_bits(a.to_bits() & 0x7FFF_FFFF_FFFF_FFFF)
10}
11
12#[derive(Debug)]
13struct PredicateParams {
14    // Used to split floats in half.
15    splitter: f64, // = 2^ceiling(p / 2) + 1.
16    /* A set of coefficients used to calculate maximum roundoff errors.          */
17    resulterrbound: f64,
18    ccwerrbound_a: f64,
19    ccwerrbound_b: f64,
20    ccwerrbound_c: f64,
21    o3derrbound_a: f64,
22    o3derrbound_b: f64,
23    o3derrbound_c: f64,
24    iccerrbound_a: f64,
25    iccerrbound_b: f64,
26    iccerrbound_c: f64,
27    isperrbound_a: f64,
28    isperrbound_b: f64,
29    isperrbound_c: f64,
30}
31
32// EPSILON and PARAMS.slitter were pregenerated using exactinit on a machine with IEEE 754 floats.
33// See `exactinit` function below for details.
34
35/// The largest power of two such that 1.0 + epsilon = 1.0 in floating-point
36/// arithmetic.
37///
38/// This number bounds the relative roundoff error. It is used for
39/// floating-point error analysis.
40const EPSILON: f64 = 0.000_000_000_000_000_111_022_302_462_515_65;
41
42///  Constants used in exact arithmetic.
43///
44///  See exactinit() for the function used to generate these values.
45const PARAMS: PredicateParams = PredicateParams {
46    ///  Used to split floating-point numbers into two half-length significands
47    ///  for exact multiplication.
48    splitter: 134_217_729f64,
49    resulterrbound: (3.0 + 8.0 * EPSILON) * EPSILON,
50    ccwerrbound_a: (3.0 + 16.0 * EPSILON) * EPSILON,
51    ccwerrbound_b: (2.0 + 12.0 * EPSILON) * EPSILON,
52    ccwerrbound_c: (9.0 + 64.0 * EPSILON) * EPSILON * EPSILON,
53    o3derrbound_a: (7.0f64 + 56.0f64 * EPSILON) * EPSILON,
54    o3derrbound_b: (3.0f64 + 28.0f64 * EPSILON) * EPSILON,
55    o3derrbound_c: (26.0f64 + 288.0f64 * EPSILON) * EPSILON * EPSILON,
56    iccerrbound_a: (10.0 + 96.0 * EPSILON) * EPSILON,
57    iccerrbound_b: (4.0 + 48.0 * EPSILON) * EPSILON,
58    iccerrbound_c: (44.0 + 576.0 * EPSILON) * EPSILON * EPSILON,
59    isperrbound_a: (16.0f64 + 224.0f64 * EPSILON) * EPSILON,
60    isperrbound_b: (5.0f64 + 72.0f64 * EPSILON) * EPSILON,
61    isperrbound_c: (71.0f64 + 1408.0f64 * EPSILON) * EPSILON * EPSILON,
62};
63
64/* ****************************************************************************/
65/*                                                                           */
66/*  exactinit()   Initialize the variables used for exact arithmetic.        */
67/*                                                                           */
68/*  `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in   */
69/*  floating-point arithmetic.  `epsilon' bounds the relative roundoff       */
70/*  error.  It is used for floating-point error analysis.                    */
71/*                                                                           */
72/*  `splitter' is used to split floating-point numbers into two half-        */
73/*  length significands for exact multiplication.                            */
74/*                                                                           */
75/*  I imagine that a highly optimizing compiler might be too smart for its   */
76/*  own good, and somehow cause this routine to fail, if it pretends that    */
77/*  floating-point arithmetic is too much like real arithmetic.              */
78/*                                                                           */
79/*  Don't change this routine unless you fully understand it.                */
80/*                                                                           */
81/* ****************************************************************************/
82#[allow(dead_code)] // This function is for reference only.
83fn exactinit() -> PredicateParams {
84    let mut check = 1.0_f64;
85    let mut lastcheck;
86    let mut every_other = 1_i32;
87    let mut epsilon = 1.0f64;
88    let mut splitter = 1.0f64;
89    loop {
90        /* Repeatedly divide `epsilon' by two until it is too small to add to    */
91        /*   one without causing roundoff.  (Also check if the sum is equal to   */
92        /*   the previous sum, for machines that round up instead of using exact */
93        /*   rounding.  Not that this library will work on such machines anyway. */
94        lastcheck = check;
95        epsilon *= 0.5;
96        if every_other != 0 {
97            splitter *= 2.0f64
98        }
99        every_other = (every_other == 0) as i32;
100        check = 1.0f64 + epsilon;
101        if !(check != 1.0f64 && check != lastcheck) {
102            break;
103        }
104    }
105    splitter += 1.0f64;
106    PredicateParams {
107        splitter,
108        /* Error bounds for orientation and incircle tests. */
109        resulterrbound: (3.0f64 + 8.0f64 * epsilon) * epsilon,
110        ccwerrbound_a: (3.0f64 + 16.0f64 * epsilon) * epsilon,
111        ccwerrbound_b: (2.0f64 + 12.0f64 * epsilon) * epsilon,
112        ccwerrbound_c: (9.0f64 + 64.0f64 * epsilon) * epsilon * epsilon,
113        o3derrbound_a: (7.0f64 + 56.0f64 * epsilon) * epsilon,
114        o3derrbound_b: (3.0f64 + 28.0f64 * epsilon) * epsilon,
115        o3derrbound_c: (26.0f64 + 288.0f64 * epsilon) * epsilon * epsilon,
116        iccerrbound_a: (10.0f64 + 96.0f64 * epsilon) * epsilon,
117        iccerrbound_b: (4.0f64 + 48.0f64 * epsilon) * epsilon,
118        iccerrbound_c: (44.0f64 + 576.0f64 * epsilon) * epsilon * epsilon,
119        isperrbound_a: (16.0f64 + 224.0f64 * epsilon) * epsilon,
120        isperrbound_b: (5.0f64 + 72.0f64 * epsilon) * epsilon,
121        isperrbound_c: (71.0f64 + 1408.0f64 * epsilon) * epsilon * epsilon,
122    }
123}
124
125/* Many of the operations are broken up into two pieces, a main part that    */
126/*   performs an approximate operation, and a "tail" that computes the       */
127/*   roundoff error of that operation.                                       */
128
129#[inline]
130pub fn fast_two_sum_tail(a: f64, b: f64, x: f64) -> f64 {
131    let bvirt: f64 = x - a;
132    b - bvirt
133}
134
135#[inline]
136pub fn fast_two_sum(a: f64, b: f64) -> [f64; 2] {
137    let x: f64 = a + b;
138    [fast_two_sum_tail(a, b, x), x]
139}
140
141#[inline]
142pub fn fast_two_diff_tail(a: f64, b: f64, x: f64) -> f64 {
143    let bvirt: f64 = a - x;
144    return bvirt - b;
145}
146
147#[inline]
148pub fn fast_two_diff(a: f64, b: f64) -> [f64; 2] {
149    let x: f64 = a - b;
150    [fast_two_diff_tail(a, b, x), x]
151}
152
153#[inline]
154pub fn two_sum_tail(a: f64, b: f64, x: f64) -> f64 {
155    let bvirt: f64 = x - a;
156    let avirt: f64 = x - bvirt;
157    let bround: f64 = b - bvirt;
158    let around: f64 = a - avirt;
159    around + bround
160}
161
162#[inline]
163pub fn two_sum(a: f64, b: f64) -> [f64; 2] {
164    let x: f64 = a + b;
165    [two_sum_tail(a, b, x), x]
166}
167
168#[inline]
169pub fn two_diff_tail(a: f64, b: f64, x: f64) -> f64 {
170    let bvirt: f64 = a - x;
171    let avirt: f64 = x + bvirt;
172    let bround: f64 = bvirt - b;
173    let around: f64 = a - avirt;
174    around + bround
175}
176
177#[inline]
178pub fn two_diff(a: f64, b: f64) -> [f64; 2] {
179    let x: f64 = a - b;
180    [two_diff_tail(a, b, x), x]
181}
182
183#[inline]
184pub fn split(a: f64) -> [f64; 2] {
185    let c: f64 = PARAMS.splitter * a;
186    let abig: f64 = c - a;
187    let ahi = c - abig;
188    let alo = a - ahi;
189    [alo, ahi]
190}
191
192#[inline]
193pub fn two_product_tail(a: f64, b: f64, x: f64) -> f64 {
194    let [alo, ahi] = split(a);
195    let [blo, bhi] = split(b);
196    let err1: f64 = x - ahi * bhi;
197    let err2: f64 = err1 - alo * bhi;
198    let err3: f64 = err2 - ahi * blo;
199    alo * blo - err3
200}
201
202#[inline]
203pub fn two_product(a: f64, b: f64) -> [f64; 2] {
204    let x = a * b;
205    [two_product_tail(a, b, x), x]
206}
207
208/// Same as [`two_product`] where one of the inputs has
209/// already been split.
210///
211/// Avoids redundant splitting.
212#[inline]
213pub fn two_product_presplit(a: f64, b: f64, bhi: f64, blo: f64) -> [f64; 2] {
214    let x = a * b;
215    let [alo, ahi] = split(a);
216    let err1: f64 = x - ahi * bhi;
217    let err2: f64 = err1 - alo * bhi;
218    let err3: f64 = err2 - ahi * blo;
219    [alo * blo - err3, x]
220}
221
222/// Same as [`two_product`] where both of the inputs have
223/// already been split.
224///
225/// Avoids redundant splitting.
226#[inline]
227pub fn two_product_2presplit(a: f64, ahi: f64, alo: f64, b: f64, bhi: f64, blo: f64) -> [f64; 2] {
228    let x = a * b;
229    let err1: f64 = x - ahi * bhi;
230    let err2: f64 = err1 - alo * bhi;
231    let err3: f64 = err2 - ahi * blo;
232    [alo * blo - err3, x]
233}
234
235#[inline]
236pub fn square_tail(a: f64, x: f64) -> f64 {
237    let [alo, ahi] = split(a);
238    let err1: f64 = x - ahi * ahi;
239    let err3: f64 = err1 - (ahi + ahi) * alo;
240    alo * alo - err3
241}
242
243/// Squaring can be done more quickly than [`two_product`].
244#[inline]
245pub fn square(a: f64) -> [f64; 2] {
246    let x = a * a;
247    [square_tail(a, x), x]
248}
249
250// Macros for summing expansions of various fixed lengths.  These are all
251// unrolled versions of expansion_sum().
252
253#[inline]
254pub fn two_one_sum(a1: f64, a0: f64, b: f64) -> [f64; 3] {
255    let [x0, _i] = two_sum(a0, b);
256    let [x1, x2] = two_sum(a1, _i);
257    [x0, x1, x2]
258}
259
260#[inline]
261pub fn two_one_diff(a1: f64, a0: f64, b: f64) -> [f64; 3] {
262    let [x0, _i] = two_diff(a0, b);
263    let [x1, x2] = two_sum(a1, _i);
264    [x2, x1, x0]
265}
266
267#[inline]
268pub fn two_two_sum(a1: f64, a0: f64, b1: f64, b0: f64) -> [f64; 4] {
269    let [x0, _0, _j] = two_one_sum(a1, a0, b0);
270    let [x1, x2, x3] = two_one_sum(_j, _0, b1);
271    [x0, x1, x2, x3]
272}
273
274#[inline]
275pub fn two_two_diff(a1: f64, a0: f64, b1: f64, b0: f64) -> [f64; 4] {
276    let [_j, _0, x0] = two_one_diff(a1, a0, b0);
277    let [x3, x2, x1] = two_one_diff(_j, _0, b1);
278    [x0, x1, x2, x3]
279}
280
281#[inline]
282pub fn four_one_sum(a3: f64, a2: f64, a1: f64, a0: f64, b: f64) -> [f64; 5] {
283    let [x0, x1, _j] = two_one_sum(a1, a0, b);
284    let [x2, x3, x4] = two_one_sum(a3, a2, _j);
285    [x0, x1, x2, x3, x4]
286}
287
288#[inline]
289pub fn four_two_sum(a3: f64, a2: f64, a1: f64, a0: f64, b1: f64, b0: f64) -> [f64; 6] {
290    let [x0, _0, _1, _2, _k] = four_one_sum(a3, a2, a1, a0, b0);
291    let [x1, x2, x3, x4, x5] = four_one_sum(_k, _2, _1, _0, b1);
292    [x0, x1, x2, x3, x4, x5]
293}
294
295#[inline]
296pub fn four_four_sum(
297    a3: f64,
298    a2: f64,
299    a1: f64,
300    a0: f64,
301    b4: f64,
302    b3: f64,
303    b1: f64,
304    b0: f64,
305) -> [f64; 8] {
306    let [x0, x1, _0, _1, _2, _l] = four_two_sum(a3, a2, a1, a0, b1, b0);
307    let [x2, x3, x4, x5, x6, x7] = four_two_sum(_l, _2, _1, _0, b4, b3);
308    [x7, x6, x5, x4, x3, x2, x1, x0]
309}
310
311#[inline]
312pub fn eight_one_sum(
313    a7: f64,
314    a6: f64,
315    a5: f64,
316    a4: f64,
317    a3: f64,
318    a2: f64,
319    a1: f64,
320    a0: f64,
321    b: f64,
322) -> [f64; 9] {
323    let [x0, x1, x2, x3, _j] = four_one_sum(a3, a2, a1, a0, b);
324    let [x4, x5, x6, x7, x8] = four_one_sum(a7, a6, a5, a4, _j);
325    [x0, x1, x2, x3, x4, x5, x6, x7, x8]
326}
327
328#[inline]
329pub fn eight_two_sum(
330    a7: f64,
331    a6: f64,
332    a5: f64,
333    a4: f64,
334    a3: f64,
335    a2: f64,
336    a1: f64,
337    a0: f64,
338    b1: f64,
339    b0: f64,
340) -> [f64; 10] {
341    let [x0, _0, _1, _2, _3, _4, _5, _6, _k] = eight_one_sum(a7, a6, a5, a4, a3, a2, a1, a0, b0);
342    let [x1, x2, x3, x4, x5, x6, x7, x8, x9] = eight_one_sum(_k, _6, _5, _4, _3, _2, _1, _0, b1);
343    [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9]
344}
345
346#[inline]
347pub fn eight_four_sum(
348    a7: f64,
349    a6: f64,
350    a5: f64,
351    a4: f64,
352    a3: f64,
353    a2: f64,
354    a1: f64,
355    a0: f64,
356    b4: f64,
357    b3: f64,
358    b1: f64,
359    b0: f64,
360) -> [f64; 12] {
361    let [x0, x1, _0, _1, _2, _3, _4, _5, _6, _l] =
362        eight_two_sum(a7, a6, a5, a4, a3, a2, a1, a0, b1, b0);
363    let [x2, x3, x4, x5, x6, x7, x8, x9, x10, x11] =
364        eight_two_sum(_l, _6, _5, _4, _3, _2, _1, _0, b4, b3);
365    [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11]
366}
367
368// Macros for multiplying expansions of various fixed lengths.
369
370#[inline]
371pub fn two_one_product(a1: f64, a0: f64, b: f64) -> [f64; 4] {
372    let [blo, bhi] = split(b);
373    let [x0, _i] = two_product_presplit(a0, b, bhi, blo);
374    let [_0, _j] = two_product_presplit(a1, b, bhi, blo);
375    let [x1, _k] = two_sum(_i, _0);
376    let [x2, x3] = fast_two_sum(_j, _k);
377    [x0, x1, x2, x3]
378}
379
380#[inline]
381pub fn four_one_product(a3: f64, a2: f64, a1: f64, a0: f64, b: f64) -> [f64; 8] {
382    let [blo, bhi] = split(b);
383    let [x0, _i] = two_product_presplit(a0, b, bhi, blo);
384    let [_0, _j] = two_product_presplit(a1, b, bhi, blo);
385    let [x1, _k] = two_sum(_i, _0);
386    let [x2, _i] = fast_two_sum(_j, _k);
387    let [_0, _j] = two_product_presplit(a2, b, bhi, blo);
388    let [x3, _k] = two_sum(_i, _0);
389    let [x4, _i] = fast_two_sum(_j, _k);
390    let [_0, _j] = two_product_presplit(a3, b, bhi, blo);
391    let [x5, _k] = two_sum(_i, _0);
392    let [x6, x7] = fast_two_sum(_j, _k);
393    [x0, x1, x2, x3, x4, x5, x6, x7]
394}
395
396#[inline]
397pub fn two_two_product(a1: f64, a0: f64, b1: f64, b0: f64) -> [f64; 8] {
398    let [a0lo, a0hi] = split(a0);
399    let [blo, bhi] = split(b0);
400    let [x0, _i] = two_product_2presplit(a0, a0hi, a0lo, b0, bhi, blo);
401    let [a1lo, a1hi] = split(a1);
402    let [_0, _j] = two_product_2presplit(a1, a1hi, a1lo, b0, bhi, blo);
403    let [_1, _k] = two_sum(_i, _0);
404    let [_2, _l] = fast_two_sum(_j, _k);
405    let [blo, bhi] = split(b1);
406    let [_0, _i] = two_product_2presplit(a0, a0hi, a0lo, b1, bhi, blo);
407    let [x1, _k] = two_sum(_1, _0);
408    let [_1, _j] = two_sum(_2, _k);
409    let [_2, _m] = two_sum(_l, _j);
410    let [_0, _j] = two_product_2presplit(a1, a1hi, a1lo, b1, bhi, blo);
411    let [_0, _n] = two_sum(_i, _0);
412    let [x2, _i] = two_sum(_1, _0);
413    let [_1, _k] = two_sum(_2, _i);
414    let [_2, _l] = two_sum(_m, _k);
415    let [_0, _k] = two_sum(_j, _n);
416    let [x3, _j] = two_sum(_1, _0);
417    let [_1, _i] = two_sum(_2, _j);
418    let [_2, _m] = two_sum(_l, _i);
419    let [x4, _i] = two_sum(_1, _k);
420    let [x5, _k] = two_sum(_2, _i);
421    let [x6, x7] = two_sum(_m, _k);
422    [x0, x1, x2, x3, x4, x5, x6, x7]
423}
424
425// An expansion of length two can be squared more quickly than finding the
426// product of two different expansions of length two, and the result is
427// guaranteed to have no more than six (rather than eight) components.
428
429#[inline]
430pub fn two_square(a1: f64, a0: f64) -> [f64; 6] {
431    let [x0, _j] = square(a0);
432    let _0: f64 = a0 + a0;
433    let [_1, _k] = two_product(a1, _0);
434    let [x1, _2, _l] = two_one_sum(_k, _1, _j);
435    let [_1, _j] = square(a1);
436    let [x2, x3, x4, x5] = two_two_sum(_j, _1, _l, _2);
437    [x0, x1, x2, x3, x4, x5]
438}
439
440///  Adds a scalar to an expansion.
441///
442///  Sets `h = e + b`.  See [the paper](http://www.cs.berkeley.edu/~jrs/papers/robustr.pdf) for details.
443///
444///  Maintains the nonoverlapping property.  If round-to-even is used (as
445///  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent
446///  properties as well.  (That is, if `e` has one of these properties, so
447///  will `h`.)
448#[inline]
449pub fn grow_expansion(e: &[f64], b: f64, h: &mut [f64]) -> usize {
450    let mut q = b;
451    let mut eindex = 0;
452    while eindex < e.len() {
453        let [hnew, q_new] = two_sum(q, e[eindex]);
454        q = q_new;
455        h[eindex] = hnew;
456        eindex += 1;
457    }
458    h[eindex] = q;
459    eindex + 1
460}
461
462///  Adds a scalar to an expansion, eliminating zero components from the output
463///  expansion.
464///                                                                        
465///  Sets `h = e + b`. See [the paper](http://www.cs.berkeley.edu/~jrs/papers/robustr.pdf) for details.        
466///                                                                        
467///  Maintains the nonoverlapping property.  If round-to-even is used (as  
468///  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent
469///  properties as well.  (That is, if `e` has one of these properties, so   
470///  will `h`.)
471#[inline]
472pub fn grow_expansion_zeroelim(e: &[f64], b: f64, h: &mut [f64]) -> usize {
473    let mut hindex = 0;
474    let mut q = b;
475    let mut eindex = 0;
476    while eindex < e.len() {
477        let [hh, q_new] = two_sum(q, e[eindex]);
478        q = q_new;
479        if hh != 0.0f64 {
480            let fresh0 = hindex;
481            hindex = hindex + 1;
482            h[fresh0] = hh;
483        }
484        eindex += 1
485    }
486    if q != 0.0f64 || hindex == 0 {
487        let fresh1 = hindex;
488        hindex = hindex + 1;
489        h[fresh1] = q;
490    }
491    hindex
492}
493
494///  Sums two expansions.
495///                      
496///  Sets `h = e + f`. See [the paper](http://www.cs.berkeley.edu/~jrs/papers/robustr.pdf) for details.
497///                                                                 
498///  Maintains the nonoverlapping property.  If round-to-even is used (as
499///  with IEEE 754), maintains the nonadjacent property as well.  (That is,
500///  if `e` has one of these properties, so will `h`.)  Does NOT maintain the
501///  strongly nonoverlapping property.                                  
502#[inline]
503pub fn expansion_sum(e: &[f64], f: &[f64], h: &mut [f64]) -> usize {
504    let mut q = f[0];
505    let mut hindex = 0;
506    while hindex < e.len() {
507        let [hh, qnew] = two_sum(q, e[hindex]);
508        h[hindex] = hh;
509        q = qnew;
510        hindex += 1
511    }
512    h[hindex] = q;
513    let mut hlast = hindex;
514    let mut findex = 1;
515    while findex < f.len() {
516        q = f[findex];
517        hindex = findex;
518        while hindex <= hlast {
519            let [hh, qnew] = two_sum(q, h[hindex]);
520            h[hindex] = hh;
521            q = qnew;
522            hindex += 1
523        }
524        hlast += 1;
525        h[hlast] = q;
526        findex += 1
527    }
528    hlast + 1
529}
530
531///  Sums two expansions, eliminating zero components from the output expansion.
532///                                                                          
533///  Sets `h = e + f`. See [the
534///  paper](http://www.cs.berkeley.edu/~jrs/papers/robustr.pdf) for details.
535///                                                                        
536///  Maintains the nonoverlapping property.  If round-to-even is used (as  
537///  with IEEE 754), maintains the nonadjacent property as well.  (That is,
538///  if `e` has one of these properties, so will `h`.)  Does NOT maintain the  
539///  strongly nonoverlapping property.                                     
540#[inline]
541pub fn expansion_sum_zeroelim1(e: &[f64], f: &[f64], h: &mut [f64]) -> usize {
542    let mut q = f[0];
543    let mut hindex = 0;
544    while hindex < e.len() {
545        let [hh, qnew] = two_sum(q, e[hindex]);
546        h[hindex] = hh;
547        q = qnew;
548        hindex += 1
549    }
550    h[hindex] = q;
551    let mut hlast = hindex;
552    let mut findex = 1;
553    while findex < f.len() {
554        q = f[findex];
555        hindex = findex;
556        while hindex <= hlast {
557            let [hh, qnew] = two_sum(q, h[hindex]);
558            h[hindex] = hh;
559            q = qnew;
560            hindex += 1
561        }
562        hlast += 1;
563        h[hlast] = q;
564        findex += 1
565    }
566    let mut hindex: isize = -1;
567    let mut index = 0;
568    while index <= hlast {
569        let hnow = h[index];
570        if hnow != 0.0 {
571            hindex += 1;
572            h[hindex as usize] = hnow
573        }
574        index += 1
575    }
576    if hindex == -1 {
577        1
578    } else {
579        hindex as usize + 1
580    }
581}
582///  Sums two expansions, eliminating zero components from the output expansion.
583///                                                                        
584///  Sets `h = e + f`. See [the
585///  paper](http://www.cs.berkeley.edu/~jrs/papers/robustr.pdf) for details.
586///                                                                        
587///  Maintains the nonoverlapping property.  If round-to-even is used (as  
588///  with IEEE 754), maintains the nonadjacent property as well.  (That is,
589///  if `e` has one of these properties, so will `h`.)  Does NOT maintain the  
590///  strongly nonoverlapping property.                                     
591#[inline]
592pub fn expansion_sum_zeroelim2(e: &[f64], f: &[f64], h: &mut [f64]) -> usize {
593    let mut hindex = 0;
594    let mut q = f[0];
595    let mut eindex = 0;
596    while eindex < e.len() {
597        let [hh, qnew] = two_sum(q, e[eindex]);
598        q = qnew;
599        if hh != 0.0 {
600            h[hindex] = hh;
601            hindex += 1;
602        }
603        eindex += 1
604    }
605    h[hindex] = q;
606    let mut hlast = hindex;
607    let mut findex = 1;
608    while findex < f.len() {
609        hindex = 0;
610        q = f[findex];
611        eindex = 0;
612        while eindex <= hlast {
613            let [hh, qnew] = two_sum(q, h[eindex]);
614            q = qnew;
615            if hh != 0.0 {
616                h[hindex] = hh;
617                hindex += 1;
618            }
619            eindex += 1
620        }
621        h[hindex] = q;
622        hlast = hindex;
623        findex += 1
624    }
625    hlast + 1
626}
627
628/* ****************************************************************************/
629/*                                                                           */
630/*  fast_expansion_sum()   Sum two expansions.                               */
631/*                                                                           */
632/*  Sets h = e + f.  See the long version of my paper for details.           */
633/*                                                                           */
634/*  If round-to-even is used (as with IEEE 754), maintains the strongly      */
635/*  nonoverlapping property.  (That is, if e is strongly nonoverlapping, h   */
636/*  will be also.)  Does NOT maintain the nonoverlapping or nonadjacent      */
637/*  properties.                                                              */
638/*                                                                           */
639/* ****************************************************************************/
640/*
641pub unsafe fn fast_expansion_sum(mut elen: i32,
642                                            mut e: *const f64,
643                                            mut flen: i32,
644                                            mut f: *const f64,
645                                            mut h: *mut f64)
646 -> i32 {
647    let mut Q: f64 = 0.;
648    let mut Qnew: f64 = 0.;
649    let mut bvirt: f64 = 0.;
650    let mut avirt: f64 = 0.;
651    let mut bround: f64 = 0.;
652    let mut around: f64 = 0.;
653    let mut eindex: i32 = 0;
654    let mut findex: i32 = 0;
655    let mut hindex: i32 = 0;
656    let mut enow: f64 = 0.;
657    let mut fnow: f64 = 0.;
658    enow = e[0];
659    fnow = f[0];
660    findex = 0 as i32;
661    eindex = findex;
662    if (fnow > enow) as i32 == (fnow > -enow) as i32 {
663        Q = enow;
664        eindex += 1;
665        enow = *e.offset(eindex as isize)
666    } else { Q = fnow; findex += 1; fnow = *f.offset(findex as isize) }
667    hindex = 0 as i32;
668    if eindex < elen && findex < flen {
669        if (fnow > enow) as i32 == (fnow > -enow) as i32 {
670            let [y, x] = Fast_Two_Sum(enow, Q);
671            Qnew = x;
672            h[0] = y;
673            eindex += 1;
674            enow = *e.offset(eindex as isize)
675        } else {
676            let [y, x] = Fast_Two_Sum(fnow, Q);
677            Qnew = x;
678            h[0] = y;
679            findex += 1;
680            fnow = *f.offset(findex as isize)
681        }
682        Q = Qnew;
683        hindex = 1 as i32;
684        while eindex < elen && findex < flen {
685            if (fnow > enow) as i32 == (fnow > -enow) as i32 {
686                Two_Sum(Q, enow, &mut Qnew, &mut *h.offset(hindex as isize));
687                eindex += 1;
688                enow = *e.offset(eindex as isize)
689            } else {
690                Two_Sum(Q, fnow, &mut Qnew, &mut *h.offset(hindex as isize));
691                findex += 1;
692                fnow = *f.offset(findex as isize)
693            }
694            Q = Qnew;
695            hindex += 1
696        }
697    }
698    while eindex < elen {
699        Two_Sum(Q, enow, &mut Qnew, &mut *h.offset(hindex as isize));
700        eindex += 1;
701        enow = *e.offset(eindex as isize);
702        Q = Qnew;
703        hindex += 1
704    }
705    while findex < flen {
706        Two_Sum(Q, fnow, &mut Qnew, &mut *h.offset(hindex as isize));
707        findex += 1;
708        fnow = *f.offset(findex as isize);
709        Q = Qnew;
710        hindex += 1
711    }
712    *h.offset(hindex as isize) = Q;
713    return hindex + 1 as i32;
714}
715*/
716
717///  Sums two expansions, eliminating zero components from the output expansion.
718///                                                                        
719///  Sets `h = e + f`.  See [the
720///  paper](http://www.cs.berkeley.edu/~jrs/papers/robustr.pdf) for details.
721///                                                                        
722///  If round-to-even is used (as with IEEE 754), maintains the strongly   
723///  nonoverlapping property.  (That is, if `e` is strongly nonoverlapping, `h`
724///  will be also.)  Does NOT maintain the nonoverlapping or nonadjacent   
725///  properties.                                                           
726#[inline]
727pub fn fast_expansion_sum_zeroelim(e: &[f64], f: &[f64], h: &mut [f64]) -> usize {
728    let mut q;
729    let mut findex = 0;
730    let mut eindex = findex;
731
732    let enow = e[0];
733    let fnow = f[0];
734    if (fnow > enow) == (fnow > -enow) {
735        q = enow;
736        eindex += 1;
737    } else {
738        q = fnow;
739        findex += 1;
740    }
741
742    let mut hindex = 0;
743    if eindex < e.len() && findex < f.len() {
744        let enow = e[eindex];
745        let fnow = f[findex];
746        let [hh, q_new] = if (fnow > enow) == (fnow > -enow) {
747            eindex += 1;
748            fast_two_sum(enow, q)
749        } else {
750            findex += 1;
751            fast_two_sum(fnow, q)
752        };
753        q = q_new;
754        if hh != 0.0f64 {
755            h[hindex] = hh;
756            hindex += 1;
757        }
758        while eindex < e.len() && findex < f.len() {
759            let enow = e[eindex];
760            let fnow = f[findex];
761            let [hh, q_new] = if (fnow > enow) == (fnow > -enow) {
762                eindex += 1;
763                two_sum(q, enow)
764            } else {
765                findex += 1;
766                two_sum(q, fnow)
767            };
768            q = q_new;
769            if hh != 0.0f64 {
770                h[hindex] = hh;
771                hindex += 1;
772            }
773        }
774    }
775    while eindex < e.len() {
776        let [hh, q_new] = two_sum(q, e[eindex]);
777        eindex += 1;
778        q = q_new;
779        if hh != 0.0f64 {
780            h[hindex] = hh;
781            hindex += 1;
782        }
783    }
784    while findex < f.len() {
785        let [hh, q_new] = two_sum(q, f[findex]);
786        findex += 1;
787        q = q_new;
788        if hh != 0.0f64 {
789            h[hindex] = hh;
790            hindex += 1;
791        }
792    }
793    if q != 0.0f64 || hindex == 0 {
794        h[hindex] = q;
795        hindex += 1;
796    }
797    hindex
798}
799/* ****************************************************************************/
800/*                                                                           */
801/*  linear_expansion_sum()   Sum two expansions.                             */
802/*                                                                           */
803/*  Sets h = e + f.  See either version of my paper for details.             */
804/*                                                                           */
805/*  Maintains the nonoverlapping property.  (That is, if e is                */
806/*  nonoverlapping, h will be also.)                                         */
807/*                                                                           */
808/* ****************************************************************************/
809/*
810pub unsafe fn linear_expansion_sum(mut elen: i32,
811                                              mut e: *const f64,
812                                              mut flen: i32,
813                                              mut f: *const f64,
814                                              mut h: *mut f64)
815 -> i32 {
816    let mut Q: f64 = 0.;
817    let mut q: f64 = 0.;
818    let mut Qnew: f64 = 0.;
819    let mut R: f64 = 0.;
820    let mut bvirt: f64 = 0.;
821    let mut avirt: f64 = 0.;
822    let mut bround: f64 = 0.;
823    let mut around: f64 = 0.;
824    let mut eindex: i32 = 0;
825    let mut findex: i32 = 0;
826    let mut hindex: i32 = 0;
827    let mut enow: f64 = 0.;
828    let mut fnow: f64 = 0.;
829    let mut g0: f64 = 0.;
830    enow = e[0];
831    fnow = f[0];
832    findex = 0 as i32;
833    eindex = findex;
834    if (fnow > enow) as i32 == (fnow > -enow) as i32 {
835        g0 = enow;
836        eindex += 1;
837        enow = *e.offset(eindex as isize)
838    } else { g0 = fnow; findex += 1; fnow = *f.offset(findex as isize) }
839    if eindex < elen &&
840           (findex >= flen ||
841                (fnow > enow) as i32 == (fnow > -enow) as i32)
842       {
843        let [y, x] = Fast_Two_Sum(enow, g0);
844        Qnew = x;
845        q = y;
846        eindex += 1;
847        enow = *e.offset(eindex as isize)
848    } else {
849        let [y, x] = Fast_Two_Sum(fnow, g0);
850        Qnew = x;
851        q = y;
852        findex += 1;
853        fnow = *f.offset(findex as isize)
854    }
855    Q = Qnew;
856    hindex = 0 as i32;
857    while hindex < elen + flen - 2 as i32 {
858        if eindex < elen &&
859               (findex >= flen ||
860                    (fnow > enow) as i32 ==
861                        (fnow > -enow) as i32) {
862            let [y, x] = Fast_Two_Sum(enow, q);
863            R = x;
864            *h.offset(hindex as isize) = y;
865            eindex += 1;
866            enow = *e.offset(eindex as isize)
867        } else {
868            let [y, x] = Fast_Two_Sum(fnow, q);
869            R = x;
870            *h.offset(hindex as isize) = y;
871            findex += 1;
872            fnow = *f.offset(findex as isize)
873        }
874        Two_Sum(Q, R, &mut Qnew, &mut q);
875        Q = Qnew;
876        hindex += 1
877    }
878    *h.offset(hindex as isize) = q;
879    *h.offset((hindex + 1 as i32) as isize) = Q;
880    return hindex + 2 as i32;
881}
882*/
883/* ****************************************************************************/
884/*                                                                           */
885/*  linear_expansion_sum_zeroelim()   Sum two expansions, eliminating zero   */
886/*                                    components from the output expansion.  */
887/*                                                                           */
888/*  Sets h = e + f.  See either version of my paper for details.             */
889/*                                                                           */
890/*  Maintains the nonoverlapping property.  (That is, if e is                */
891/*  nonoverlapping, h will be also.)                                         */
892/*                                                                           */
893/* ****************************************************************************/
894
895/*
896pub unsafe fn linear_expansion_sum_zeroelim(mut elen: i32,
897                                                       mut e:
898                                                           *const f64,
899                                                       mut flen: i32,
900                                                       mut f:
901                                                           *const f64,
902                                                       mut h:
903                                                           *mut f64)
904 -> i32 {
905    let mut Q: f64 = 0.;
906    let mut q: f64 = 0.;
907    let mut hh: f64 = 0.;
908    let mut Qnew: f64 = 0.;
909    let mut R: f64 = 0.;
910    let mut bvirt: f64 = 0.;
911    let mut avirt: f64 = 0.;
912    let mut bround: f64 = 0.;
913    let mut around: f64 = 0.;
914    let mut eindex: i32 = 0;
915    let mut findex: i32 = 0;
916    let mut hindex: i32 = 0;
917    let mut count: i32 = 0;
918    let mut enow: f64 = 0.;
919    let mut fnow: f64 = 0.;
920    let mut g0: f64 = 0.;
921    enow = e[0];
922    fnow = f[0];
923    findex = 0 as i32;
924    eindex = findex;
925    hindex = 0 as i32;
926    if (fnow > enow) as i32 == (fnow > -enow) as i32 {
927        g0 = enow;
928        eindex += 1;
929        enow = *e.offset(eindex as isize)
930    } else { g0 = fnow; findex += 1; fnow = *f.offset(findex as isize) }
931    if eindex < elen &&
932           (findex >= flen ||
933                (fnow > enow) as i32 == (fnow > -enow) as i32)
934       {
935        let [y, x] = Fast_Two_Sum(enow, g0);
936        Qnew = x;
937        q = y;
938        eindex += 1;
939        enow = *e.offset(eindex as isize)
940    } else {
941        let [y, x] = Fast_Two_Sum(fnow, g0);
942        Qnew = x;
943        q = y;
944        findex += 1;
945        fnow = *f.offset(findex as isize)
946    }
947    Q = Qnew;
948    count = 2 as i32;
949    while count < elen + flen {
950        if eindex < elen &&
951               (findex >= flen ||
952                    (fnow > enow) as i32 ==
953                        (fnow > -enow) as i32) {
954            let [y, x] = Fast_Two_Sum(enow, q);
955            R = x;
956            hh = y;
957            eindex += 1;
958            enow = *e.offset(eindex as isize)
959        } else {
960            let [y, x] = Fast_Two_Sum(fnow, q);
961            R = x;
962            hh = y;
963            findex += 1;
964            fnow = *f.offset(findex as isize)
965        }
966        Two_Sum(Q, R, &mut Qnew, &mut q);
967        Q = Qnew;
968        if hh != 0 as i32 as f64 {
969            let fresh9 = hindex;
970            hindex = hindex + 1;
971            *h.offset(fresh9 as isize) = hh
972        }
973        count += 1
974    }
975    if q != 0 as i32 as f64 {
976        let fresh10 = hindex;
977        hindex = hindex + 1;
978        *h.offset(fresh10 as isize) = q
979    }
980    if Q != 0.0f64 || hindex == 0 as i32 {
981        let fresh11 = hindex;
982        hindex = hindex + 1;
983        *h.offset(fresh11 as isize) = Q
984    }
985    return hindex;
986}
987*/
988/* ****************************************************************************/
989/*                                                                           */
990/*  scale_expansion()   Multiply an expansion by a scalar.                   */
991/*                                                                           */
992/*  Sets h = be.  See either version of my paper for details.                */
993/*                                                                           */
994/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
995/*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
996/*  properties as well.  (That is, if e has one of these properties, so      */
997/*  will h.)                                                                 */
998/*                                                                           */
999/* ****************************************************************************/
1000/*
1001pub unsafe fn scale_expansion(mut elen: i32,
1002                                         mut e: *const f64,
1003                                         mut b: f64,
1004                                         mut h: *mut f64)
1005 -> i32 {
1006    let mut Q: f64 = 0.;
1007    let mut sum: f64 = 0.;
1008    let mut product1: f64 = 0.;
1009    let mut product0: f64 = 0.;
1010    let mut eindex: i32 = 0;
1011    let mut hindex: i32 = 0;
1012    let mut enow: f64 = 0.;
1013    let mut bvirt: f64 = 0.;
1014    let mut avirt: f64 = 0.;
1015    let mut bround: f64 = 0.;
1016    let mut around: f64 = 0.;
1017    let mut c: f64 = 0.;
1018    let mut abig: f64 = 0.;
1019    let mut ahi: f64 = 0.;
1020    let mut alo: f64 = 0.;
1021    let mut bhi: f64 = 0.;
1022    let mut blo: f64 = 0.;
1023    let mut err1: f64 = 0.;
1024    let mut err2: f64 = 0.;
1025    let mut err3: f64 = 0.;
1026    Split(b, &mut bhi, &mut blo);
1027    Two_Product_Presplit(e[0], b, bhi, blo,
1028                         &mut Q, &mut h[0]);
1029    hindex = 1 as i32;
1030    eindex = 1 as i32;
1031    while eindex < elen {
1032        enow = *e.offset(eindex as isize);
1033        Two_Product_Presplit(enow, b, bhi, blo, &mut product1, &mut product0);
1034        Two_Sum(Q, product0, &mut sum, &mut *h.offset(hindex as isize));
1035        hindex += 1;
1036        Two_Sum(product1, sum, &mut Q, &mut *h.offset(hindex as isize));
1037        hindex += 1;
1038        eindex += 1
1039    }
1040    *h.offset(hindex as isize) = Q;
1041    return elen + elen;
1042}
1043*/
1044
1045///  Multiply an expansion by a scalar, eliminating zero components from the
1046///  output expansion.
1047///                                                                       
1048///  Sets `h = be`. See either [\[1\]] or [\[2\]] for details.
1049///                                                                       
1050///  Maintains the nonoverlapping property.  If round-to-even is used (as
1051///  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent
1052///  properties as well.  (That is, if `e` has one of these properties, so  
1053///  will `h`.)                                                             
1054///
1055/// [\[1\]]: http://www.cs.berkeley.edu/~jrs/papers/robustr.pdf
1056/// [\[2\]]: http://www.cs.berkeley.edu/~jrs/papers/robust-predicates.pdf
1057pub fn scale_expansion_zeroelim(e: &[f64], b: f64, h: &mut [f64]) -> usize {
1058    let [blo, bhi] = split(b);
1059    let [hh, mut q] = two_product_presplit(e[0], b, bhi, blo);
1060
1061    let mut hindex = 0;
1062    if hh != 0.0f64 {
1063        h[hindex] = hh;
1064        hindex += 1;
1065    }
1066    for &enow in e.iter().skip(1) {
1067        let [product0, product1] = two_product_presplit(enow, b, bhi, blo);
1068        let [hh, sum] = two_sum(q, product0);
1069        if hh != 0.0f64 {
1070            h[hindex] = hh;
1071            hindex += 1;
1072        }
1073        let [hh, q_new] = fast_two_sum(product1, sum);
1074        q = q_new;
1075        if hh != 0.0f64 {
1076            h[hindex] = hh;
1077            hindex += 1;
1078        }
1079    }
1080    if q != 0.0f64 || hindex == 0 {
1081        h[hindex] = q;
1082        hindex += 1;
1083    }
1084    hindex
1085}
1086
1087/* ****************************************************************************/
1088/*                                                                           */
1089/*  compress()   Compress an expansion.                                      */
1090/*                                                                           */
1091/*  See the long version of my paper for details.                            */
1092/*                                                                           */
1093/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
1094/*  with IEEE 754), then any nonoverlapping expansion is converted to a      */
1095/*  nonadjacent expansion.                                                   */
1096/*                                                                           */
1097/* ****************************************************************************/
1098/*
1099pub unsafe fn compress(mut elen: i32,
1100                                  mut e: *const f64,
1101                                  mut h: *mut f64) -> i32 {
1102    let mut Q: f64 = 0.;
1103    let mut q: f64 = 0.;
1104    let mut Qnew: f64 = 0.;
1105    let mut eindex: i32 = 0;
1106    let mut hindex: i32 = 0;
1107    let mut bvirt: f64 = 0.;
1108    let mut enow: f64 = 0.;
1109    let mut hnow: f64 = 0.;
1110    let mut top: i32 = 0;
1111    let mut bottom: i32 = 0;
1112    bottom = elen - 1 as i32;
1113    Q = *e.offset(bottom as isize);
1114    eindex = elen - 2 as i32;
1115    while eindex >= 0 as i32 {
1116        enow = *e.offset(eindex as isize);
1117        let [y, x] = Fast_Two_Sum(Q, enow);
1118        Qnew = x;
1119        q = y;
1120        if q != 0 as i32 as f64 {
1121            let fresh16 = bottom;
1122            bottom = bottom - 1;
1123            *h.offset(fresh16 as isize) = Qnew;
1124            Q = q
1125        } else { Q = Qnew }
1126        eindex -= 1
1127    }
1128    top = 0 as i32;
1129    hindex = bottom + 1 as i32;
1130    while hindex < elen {
1131        hnow = *h.offset(hindex as isize);
1132        let mut sum: [f64; 2] = [0.; 2];
1133        let [y, x] = Fast_Two_Sum(hnow, Q);
1134        Qnew = x;
1135        q = y;
1136        if q != 0 as i32 as f64 {
1137            let fresh17 = top;
1138            top = top + 1;
1139            *h.offset(fresh17 as isize) = q
1140        }
1141        Q = Qnew;
1142        hindex += 1
1143    }
1144    *h.offset(top as isize) = Q;
1145    return top + 1 as i32;
1146}
1147*/
1148
1149/* ****************************************************************************/
1150/*                                                                           */
1151/*  orient2d_fast()   Approximate 2D orientation test.  Nonrobust.            */
1152/*  orient2d_exact()   Exact 2D orientation test.  Robust.                    */
1153/*  orient2d_slow()   Another exact 2D orientation test.  Robust.             */
1154/*  orient2d()   Adaptive exact 2D orientation test.  Robust.                */
1155/*                                                                           */
1156/*               Return a positive value if the points pa, pb, and pc occur  */
1157/*               in counterclockwise order; a negative value if they occur   */
1158/*               in clockwise order; and zero if they are collinear.  The    */
1159/*               result is also a rough approximation of twice the signed    */
1160/*               area of the triangle defined by the three points.           */
1161/*                                                                           */
1162/*  Only the first and last routine should be used; the middle two are for   */
1163/*  timings.                                                                 */
1164/*                                                                           */
1165/*  The last three use exact arithmetic to ensure a correct answer.  The     */
1166/*  result returned is the determinant of a matrix.  In orient2d() only,     */
1167/*  this determinant is computed adaptively, in the sense that exact         */
1168/*  arithmetic is used only to the degree it is needed to ensure that the    */
1169/*  returned value has the correct sign.  Hence, orient2d() is usually quite */
1170/*  fast, but will run more slowly when the input points are collinear or    */
1171/*  nearly so.                                                               */
1172/*                                                                           */
1173/* ****************************************************************************/
1174
1175/// Approximate 2D orientation test. Non-robust version of [`orient2d`].
1176#[inline]
1177pub fn orient2d_fast(pa: [f64; 2], pb: [f64; 2], pc: [f64; 2]) -> f64 {
1178    let acx = pa[0] - pc[0];
1179    let bcx = pb[0] - pc[0];
1180    let acy = pa[1] - pc[1];
1181    let bcy = pb[1] - pc[1];
1182    acx * bcy - acy * bcx
1183}
1184
1185#[inline]
1186pub fn orient2d_exact(pa: [f64; 2], pb: [f64; 2], pc: [f64; 2]) -> f64 {
1187    let [axby0, axby1] = two_product(pa[0], pb[1]);
1188    let [axcy0, axcy1] = two_product(pa[0], pc[1]);
1189    let aterms = two_two_diff(axby1, axby0, axcy1, axcy0);
1190    let [bxcy0, bxcy1] = two_product(pb[0], pc[1]);
1191    let [bxay0, bxay1] = two_product(pb[0], pa[1]);
1192    let bterms = two_two_diff(bxcy1, bxcy0, bxay1, bxay0);
1193    let [cxay0, cxay1] = two_product(pc[0], pa[1]);
1194    let [cxby0, cxby1] = two_product(pc[0], pb[1]);
1195    let cterms = two_two_diff(cxay1, cxay0, cxby1, cxby0);
1196    let mut v = [0.; 8];
1197    let vlength = fast_expansion_sum_zeroelim(&aterms, &bterms, &mut v);
1198    let mut w = [0.; 12];
1199    let wlength = fast_expansion_sum_zeroelim(&v[..vlength], &cterms, &mut w);
1200    w[wlength - 1]
1201}
1202
1203#[inline]
1204pub fn orient2d_slow(pa: [f64; 2], pb: [f64; 2], pc: [f64; 2]) -> f64 {
1205    let [acxtail, acx] = two_diff(pa[0], pc[0]);
1206    let [acytail, acy] = two_diff(pa[1], pc[1]);
1207    let [bcxtail, bcx] = two_diff(pb[0], pc[0]);
1208    let [bcytail, bcy] = two_diff(pb[1], pc[1]);
1209    let axby = two_two_product(acx, acxtail, bcy, bcytail);
1210    let negate = -acy;
1211    let negatetail = -acytail;
1212    let bxay = two_two_product(bcx, bcxtail, negate, negatetail);
1213    let mut deter = [0.; 16];
1214    let deterlen = fast_expansion_sum_zeroelim(&axby, &bxay, &mut deter);
1215    deter[deterlen - 1]
1216}
1217
1218#[inline]
1219pub fn orient2dadapt(pa: [f64; 2], pb: [f64; 2], pc: [f64; 2], detsum: f64) -> f64 {
1220    let acx = pa[0] - pc[0];
1221    let bcx = pb[0] - pc[0];
1222    let acy = pa[1] - pc[1];
1223    let bcy = pb[1] - pc[1];
1224    let [detlefttail, detleft] = two_product(acx, bcy);
1225    let [detrighttail, detright] = two_product(acy, bcx);
1226    let b = two_two_diff(detleft, detlefttail, detright, detrighttail);
1227    let mut det: f64 = b.iter().sum();
1228    let errbound = PARAMS.ccwerrbound_b * detsum;
1229    if det >= errbound || -det >= errbound {
1230        return det;
1231    }
1232    let acxtail = two_diff_tail(pa[0], pc[0], acx);
1233    let bcxtail = two_diff_tail(pb[0], pc[0], bcx);
1234    let acytail = two_diff_tail(pa[1], pc[1], acy);
1235    let bcytail = two_diff_tail(pb[1], pc[1], bcy);
1236    if acxtail == 0.0 && acytail == 0.0 && bcxtail == 0.0 && bcytail == 0.0 {
1237        return det;
1238    }
1239    let errbound = PARAMS.ccwerrbound_c * detsum + PARAMS.resulterrbound * abs(det);
1240    det += acx * bcytail + bcy * acxtail - (acy * bcxtail + bcx * acytail);
1241    if det >= errbound || -det >= errbound {
1242        return det;
1243    }
1244    let [s0, s1] = two_product(acxtail, bcy);
1245    let [t0, t1] = two_product(acytail, bcx);
1246    let u = two_two_diff(s1, s0, t1, t0);
1247    let mut c1: [f64; 8] = [0.; 8];
1248    let c1length = fast_expansion_sum_zeroelim(&b, &u, &mut c1);
1249    let [s0, s1] = two_product(acx, bcytail);
1250    let [t0, t1] = two_product(acy, bcxtail);
1251    let u = two_two_diff(s1, s0, t1, t0);
1252    let mut c2: [f64; 12] = [0.; 12];
1253    let c2length = fast_expansion_sum_zeroelim(&c1[..c1length], &u, &mut c2);
1254    let [s0, s1] = two_product(acxtail, bcytail);
1255    let [t0, t1] = two_product(acytail, bcxtail);
1256    let u = two_two_diff(s1, s0, t1, t0);
1257    let mut d: [f64; 16] = [0.; 16];
1258    let dlength = fast_expansion_sum_zeroelim(&c2[..c2length], &u, &mut d);
1259    d[dlength - 1]
1260}
1261
1262/**
1263 * Adaptive exact 2D orientation test.  Robust.
1264 *
1265 * Return a positive value if the points `pa`, `pb`, and `pc` occur
1266 * in counterclockwise order; a negative value if they occur
1267 * in clockwise order; and zero if they are collinear.  The
1268 * result is also a rough approximation of twice the signed
1269 * area of the triangle defined by the three points.
1270 *
1271 * The result returned is the determinant of a matrix.
1272 * This determinant is computed adaptively, in the sense that exact
1273 * arithmetic is used only to the degree it is needed to ensure that the
1274 * returned value has the correct sign.  Hence, `orient2d()` is usually quite
1275 * fast, but will run more slowly when the input points are collinear or
1276 * nearly so.
1277 */
1278#[inline]
1279pub fn orient2d(pa: [f64; 2], pb: [f64; 2], pc: [f64; 2]) -> f64 {
1280    let detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
1281    let detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
1282    let det = detleft - detright;
1283    let detsum = if detleft > 0.0 {
1284        if detright <= 0.0 {
1285            return det;
1286        } else {
1287            detleft + detright
1288        }
1289    } else if detleft < 0.0 {
1290        if detright >= 0.0 {
1291            return det;
1292        } else {
1293            -detleft - detright
1294        }
1295    } else {
1296        return det;
1297    };
1298    let errbound = PARAMS.ccwerrbound_a * detsum;
1299    if det >= errbound || -det >= errbound {
1300        return det;
1301    }
1302    orient2dadapt(pa, pb, pc, detsum)
1303}
1304
1305/* ****************************************************************************/
1306/*                                                                           */
1307/*  orient3d_fast()   Approximate 3D orientation test.  Nonrobust.            */
1308/*  orient3d_exact()   Exact 3D orientation test.  Robust.                    */
1309/*  orient3d_slow()   Another exact 3D orientation test.  Robust.             */
1310/*  orient3d()   Adaptive exact 3D orientation test.  Robust.                */
1311/*                                                                           */
1312/*               Return a positive value if the point pd lies below the      */
1313/*               plane passing through pa, pb, and pc; "below" is defined so */
1314/*               that pa, pb, and pc appear in counterclockwise order when   */
1315/*               viewed from above the plane.  Returns a negative value if   */
1316/*               pd lies above the plane.  Returns zero if the points are    */
1317/*               coplanar.  The result is also a rough approximation of six  */
1318/*               times the signed volume of the tetrahedron defined by the   */
1319/*               four points.                                                */
1320/*                                                                           */
1321/*  Only the first and last routine should be used; the middle two are for   */
1322/*  timings.                                                                 */
1323/*                                                                           */
1324/*  The last three use exact arithmetic to ensure a correct answer.  The     */
1325/*  result returned is the determinant of a matrix.  In orient3d() only,     */
1326/*  this determinant is computed adaptively, in the sense that exact         */
1327/*  arithmetic is used only to the degree it is needed to ensure that the    */
1328/*  returned value has the correct sign.  Hence, orient3d() is usually quite */
1329/*  fast, but will run more slowly when the input points are coplanar or     */
1330/*  nearly so.                                                               */
1331/*                                                                           */
1332/* ****************************************************************************/
1333
1334/// Approximate 3D orientation test. Non-robust version of [`orient3d`].
1335#[inline]
1336pub fn orient3d_fast(pa: [f64; 3], pb: [f64; 3], pc: [f64; 3], pd: [f64; 3]) -> f64 {
1337    let adx = pa[0] - pd[0];
1338    let bdx = pb[0] - pd[0];
1339    let cdx = pc[0] - pd[0];
1340    let ady = pa[1] - pd[1];
1341    let bdy = pb[1] - pd[1];
1342    let cdy = pc[1] - pd[1];
1343    let adz = pa[2] - pd[2];
1344    let bdz = pb[2] - pd[2];
1345    let cdz = pc[2] - pd[2];
1346    adx * (bdy * cdz - bdz * cdy) + bdx * (cdy * adz - cdz * ady) + cdx * (ady * bdz - adz * bdy)
1347}
1348
1349#[inline]
1350pub fn orient3d_exact(pa: [f64; 3], pb: [f64; 3], pc: [f64; 3], pd: [f64; 3]) -> f64 {
1351    let [axby0, axby1] = two_product(pa[0], pb[1]);
1352    let [bxay0, bxay1] = two_product(pb[0], pa[1]);
1353    let ab = two_two_diff(axby1, axby0, bxay1, bxay0);
1354    let [bxcy0, bxcy1] = two_product(pb[0], pc[1]);
1355    let [cxby0, cxby1] = two_product(pc[0], pb[1]);
1356    let bc = two_two_diff(bxcy1, bxcy0, cxby1, cxby0);
1357    let [cxdy0, cxdy1] = two_product(pc[0], pd[1]);
1358    let [dxcy0, dxcy1] = two_product(pd[0], pc[1]);
1359    let cd = two_two_diff(cxdy1, cxdy0, dxcy1, dxcy0);
1360    let [dxay0, dxay1] = two_product(pd[0], pa[1]);
1361    let [axdy0, axdy1] = two_product(pa[0], pd[1]);
1362    let da = two_two_diff(dxay1, dxay0, axdy1, axdy0);
1363    let [axcy0, axcy1] = two_product(pa[0], pc[1]);
1364    let [cxay0, cxay1] = two_product(pc[0], pa[1]);
1365    let mut ac = two_two_diff(axcy1, axcy0, cxay1, cxay0);
1366    let [bxdy0, bxdy1] = two_product(pb[0], pd[1]);
1367    let [dxby0, dxby1] = two_product(pd[0], pb[1]);
1368    let mut bd = two_two_diff(bxdy1, bxdy0, dxby1, dxby0);
1369
1370    let mut temp8 = [0.; 8];
1371    let mut abc = [0.; 12];
1372    let mut bcd = [0.; 12];
1373    let mut cda = [0.; 12];
1374    let mut dab = [0.; 12];
1375    let mut adet = [0.; 24];
1376    let mut bdet = [0.; 24];
1377    let mut cdet = [0.; 24];
1378    let mut ddet = [0.; 24];
1379    let mut abdet = [0.; 48];
1380    let mut cddet = [0.; 48];
1381    let mut deter = [0.; 96];
1382
1383    let templen = fast_expansion_sum_zeroelim(&cd, &da, &mut temp8);
1384    let cdalen = fast_expansion_sum_zeroelim(&temp8[..templen], &ac, &mut cda);
1385    let templen = fast_expansion_sum_zeroelim(&da, &ab, &mut temp8);
1386    let dablen = fast_expansion_sum_zeroelim(&temp8[..templen], &bd, &mut dab);
1387    bd.iter_mut().for_each(|x| *x = -*x);
1388    ac.iter_mut().for_each(|x| *x = -*x);
1389    let templen = fast_expansion_sum_zeroelim(&ab, &bc, &mut temp8);
1390    let abclen = fast_expansion_sum_zeroelim(&temp8[..templen], &ac, &mut abc);
1391    let templen = fast_expansion_sum_zeroelim(&bc, &cd, &mut temp8);
1392    let bcdlen = fast_expansion_sum_zeroelim(&temp8[..templen], &bd, &mut bcd);
1393    let alen = scale_expansion_zeroelim(&bcd[..bcdlen], pa[2], &mut adet);
1394    let blen = scale_expansion_zeroelim(&cda[..cdalen], -pb[2], &mut bdet);
1395    let clen = scale_expansion_zeroelim(&dab[..dablen], pc[2], &mut cdet);
1396    let dlen = scale_expansion_zeroelim(&abc[..abclen], -pd[2], &mut ddet);
1397    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
1398    let cdlen = fast_expansion_sum_zeroelim(&cdet[..clen], &ddet[..dlen], &mut cddet);
1399    let deterlen = fast_expansion_sum_zeroelim(&abdet[..ablen], &cddet[..cdlen], &mut deter);
1400    deter[deterlen - 1]
1401}
1402
1403#[inline]
1404pub fn orient3d_slow(pa: [f64; 3], pb: [f64; 3], pc: [f64; 3], pd: [f64; 3]) -> f64 {
1405    let mut temp16: [f64; 16] = [0.; 16];
1406    let mut temp32: [f64; 32] = [0.; 32];
1407    let mut temp32t: [f64; 32] = [0.; 32];
1408    let mut adet: [f64; 64] = [0.; 64];
1409    let mut bdet: [f64; 64] = [0.; 64];
1410    let mut cdet: [f64; 64] = [0.; 64];
1411    let mut abdet: [f64; 128] = [0.; 128];
1412    let mut deter: [f64; 192] = [0.; 192];
1413    let [adxtail, adx] = two_diff(pa[0], pd[0]);
1414    let [adytail, ady] = two_diff(pa[1], pd[1]);
1415    let [adztail, adz] = two_diff(pa[2], pd[2]);
1416    let [bdxtail, bdx] = two_diff(pb[0], pd[0]);
1417    let [bdytail, bdy] = two_diff(pb[1], pd[1]);
1418    let [bdztail, bdz] = two_diff(pb[2], pd[2]);
1419    let [cdxtail, cdx] = two_diff(pc[0], pd[0]);
1420    let [cdytail, cdy] = two_diff(pc[1], pd[1]);
1421    let [cdztail, cdz] = two_diff(pc[2], pd[2]);
1422    let axby = two_two_product(adx, adxtail, bdy, bdytail);
1423    let negate = -ady;
1424    let negatetail = -adytail;
1425    let bxay = two_two_product(bdx, bdxtail, negate, negatetail);
1426    let bxcy = two_two_product(bdx, bdxtail, cdy, cdytail);
1427    let negate = -bdy;
1428    let negatetail = -bdytail;
1429    let cxby = two_two_product(cdx, cdxtail, negate, negatetail);
1430    let cxay = two_two_product(cdx, cdxtail, ady, adytail);
1431    let negate = -cdy;
1432    let negatetail = -cdytail;
1433    let axcy = two_two_product(adx, adxtail, negate, negatetail);
1434    let temp16len = fast_expansion_sum_zeroelim(&bxcy, &cxby, &mut temp16);
1435    let temp32len = scale_expansion_zeroelim(&temp16[..temp16len], adz, &mut temp32);
1436    let temp32tlen = scale_expansion_zeroelim(&temp16[..temp16len], adztail, &mut temp32t);
1437    let alen = fast_expansion_sum_zeroelim(&temp32[..temp32len], &temp32t[..temp32tlen], &mut adet);
1438    let temp16len = fast_expansion_sum_zeroelim(&cxay, &axcy, &mut temp16);
1439    let temp32len = scale_expansion_zeroelim(&temp16[..temp16len], bdz, &mut temp32);
1440    let temp32tlen = scale_expansion_zeroelim(&temp16[..temp16len], bdztail, &mut temp32t);
1441    let blen = fast_expansion_sum_zeroelim(&temp32[..temp32len], &temp32t[..temp32tlen], &mut bdet);
1442    let temp16len = fast_expansion_sum_zeroelim(&axby, &bxay, &mut temp16);
1443    let temp32len = scale_expansion_zeroelim(&temp16[..temp16len], cdz, &mut temp32);
1444    let temp32tlen = scale_expansion_zeroelim(&temp16[..temp16len], cdztail, &mut temp32t);
1445    let clen = fast_expansion_sum_zeroelim(&temp32[..temp32len], &temp32t[..temp32tlen], &mut cdet);
1446    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
1447    let deterlen = fast_expansion_sum_zeroelim(&abdet[..ablen], &cdet[..clen], &mut deter);
1448    deter[deterlen - 1]
1449}
1450
1451#[inline]
1452pub fn orient3dadapt(
1453    pa: [f64; 3],
1454    pb: [f64; 3],
1455    pc: [f64; 3],
1456    pd: [f64; 3],
1457    permanent: f64,
1458) -> f64 {
1459    let adx = pa[0] - pd[0];
1460    let bdx = pb[0] - pd[0];
1461    let cdx = pc[0] - pd[0];
1462    let ady = pa[1] - pd[1];
1463    let bdy = pb[1] - pd[1];
1464    let cdy = pc[1] - pd[1];
1465    let adz = pa[2] - pd[2];
1466    let bdz = pb[2] - pd[2];
1467    let cdz = pc[2] - pd[2];
1468
1469    let [bdxcdy0, bdxcdy1] = two_product(bdx, cdy);
1470    let [cdxbdy0, cdxbdy1] = two_product(cdx, bdy);
1471    let bc = two_two_diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0);
1472    let mut adet = [0.; 8];
1473    let alen = scale_expansion_zeroelim(&bc, adz, &mut adet);
1474
1475    let [cdxady0, cdxady1] = two_product(cdx, ady);
1476    let [adxcdy0, adxcdy1] = two_product(adx, cdy);
1477    let ca = two_two_diff(cdxady1, cdxady0, adxcdy1, adxcdy0);
1478    let mut bdet = [0.; 8];
1479    let blen = scale_expansion_zeroelim(&ca, bdz, &mut bdet);
1480
1481    let [adxbdy0, adxbdy1] = two_product(adx, bdy);
1482    let [bdxady0, bdxady1] = two_product(bdx, ady);
1483    let ab = two_two_diff(adxbdy1, adxbdy0, bdxady1, bdxady0);
1484    let mut cdet = [0.; 8];
1485    let clen = scale_expansion_zeroelim(&ab, cdz, &mut cdet);
1486
1487    let mut abdet = [0.; 16];
1488    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
1489    let mut fin1 = [0.; 192];
1490    let mut finlength = fast_expansion_sum_zeroelim(&abdet[..ablen], &cdet[..clen], &mut fin1);
1491
1492    let mut det: f64 = fin1[..finlength].iter().sum();
1493    let errbound = PARAMS.o3derrbound_b * permanent;
1494    if det >= errbound || -det >= errbound {
1495        return det;
1496    }
1497
1498    let adxtail = two_diff_tail(pa[0], pd[0], adx);
1499    let bdxtail = two_diff_tail(pb[0], pd[0], bdx);
1500    let cdxtail = two_diff_tail(pc[0], pd[0], cdx);
1501    let adytail = two_diff_tail(pa[1], pd[1], ady);
1502    let bdytail = two_diff_tail(pb[1], pd[1], bdy);
1503    let cdytail = two_diff_tail(pc[1], pd[1], cdy);
1504    let adztail = two_diff_tail(pa[2], pd[2], adz);
1505    let bdztail = two_diff_tail(pb[2], pd[2], bdz);
1506    let cdztail = two_diff_tail(pc[2], pd[2], cdz);
1507    if adxtail == 0.0
1508        && bdxtail == 0.0
1509        && cdxtail == 0.0
1510        && adytail == 0.0
1511        && bdytail == 0.0
1512        && cdytail == 0.0
1513        && adztail == 0.0
1514        && bdztail == 0.0
1515        && cdztail == 0.0
1516    {
1517        return det;
1518    }
1519    let errbound = PARAMS.o3derrbound_c * permanent + PARAMS.resulterrbound * abs(det);
1520    det += adz * (bdx * cdytail + cdy * bdxtail - (bdy * cdxtail + cdx * bdytail))
1521        + adztail * (bdx * cdy - bdy * cdx)
1522        + (bdz * (cdx * adytail + ady * cdxtail - (cdy * adxtail + adx * cdytail))
1523            + bdztail * (cdx * ady - cdy * adx))
1524        + (cdz * (adx * bdytail + bdy * adxtail - (ady * bdxtail + bdx * adytail))
1525            + cdztail * (adx * bdy - ady * bdx));
1526
1527    if det >= errbound || -det >= errbound {
1528        return det;
1529    }
1530
1531    let at_blen;
1532    let at_clen;
1533    let at_b;
1534    let at_c;
1535    if adxtail == 0.0 {
1536        if adytail == 0.0 {
1537            at_b = [0.; 4];
1538            at_blen = 1;
1539            at_c = [0.; 4];
1540            at_clen = 1;
1541        } else {
1542            let negate = -adytail;
1543            let [at_b0, at_blarge] = two_product(negate, bdx);
1544            at_b = [at_b0, at_blarge, 0., 0.];
1545            at_blen = 2;
1546            let [at_c0, at_clarge] = two_product(adytail, cdx);
1547            at_c = [at_c0, at_clarge, 0., 0.];
1548            at_clen = 2;
1549        }
1550    } else if adytail == 0.0 {
1551        let [at_b0, at_blarge] = two_product(adxtail, bdy);
1552        at_b = [at_b0, at_blarge, 0., 0.];
1553        at_blen = 2;
1554        let negate = -adxtail;
1555        let [at_c0, at_clarge] = two_product(negate, cdy);
1556        at_c = [at_c0, at_clarge, 0., 0.];
1557        at_clen = 2;
1558    } else {
1559        let [adxt_bdy0, adxt_bdy1] = two_product(adxtail, bdy);
1560        let [adyt_bdx0, adyt_bdx1] = two_product(adytail, bdx);
1561        at_b = two_two_diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0);
1562        at_blen = 4;
1563        let [adyt_cdx0, adyt_cdx1] = two_product(adytail, cdx);
1564        let [adxt_cdy0, adxt_cdy1] = two_product(adxtail, cdy);
1565        at_c = two_two_diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0);
1566        at_clen = 4;
1567    }
1568    let bt_clen;
1569    let bt_alen;
1570    let bt_c;
1571    let bt_a;
1572    if bdxtail == 0.0 {
1573        if bdytail == 0.0 {
1574            bt_c = [0.0; 4];
1575            bt_clen = 1;
1576            bt_a = [0.0; 4];
1577            bt_alen = 1;
1578        } else {
1579            let negate = -bdytail;
1580            let [bt_c0, bt_clarge] = two_product(negate, cdx);
1581            bt_c = [bt_c0, bt_clarge, 0., 0.];
1582            bt_clen = 2;
1583            let [bt_a0, bt_alarge] = two_product(bdytail, adx);
1584            bt_a = [bt_a0, bt_alarge, 0., 0.];
1585            bt_alen = 2;
1586        }
1587    } else if bdytail == 0.0 {
1588        let [bt_c0, bt_clarge] = two_product(bdxtail, cdy);
1589        bt_c = [bt_c0, bt_clarge, 0., 0.];
1590        bt_clen = 2;
1591        let negate = -bdxtail;
1592        let [bt_a0, bt_alarge] = two_product(negate, ady);
1593        bt_a = [bt_a0, bt_alarge, 0., 0.];
1594        bt_alen = 2
1595    } else {
1596        let [bdxt_cdy0, bdxt_cdy1] = two_product(bdxtail, cdy);
1597        let [bdyt_cdx0, bdyt_cdx1] = two_product(bdytail, cdx);
1598        bt_c = two_two_diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0);
1599        bt_clen = 4;
1600        let [bdyt_adx0, bdyt_adx1] = two_product(bdytail, adx);
1601        let [bdxt_ady0, bdxt_ady1] = two_product(bdxtail, ady);
1602        bt_a = two_two_diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0);
1603        bt_alen = 4;
1604    }
1605    let ct_alen;
1606    let ct_blen;
1607    let ct_a;
1608    let ct_b;
1609    if cdxtail == 0.0 {
1610        if cdytail == 0.0 {
1611            ct_a = [0.; 4];
1612            ct_alen = 1;
1613            ct_b = [0.; 4];
1614            ct_blen = 1;
1615        } else {
1616            let negate = -cdytail;
1617            let [ct_a0, ct_alarge] = two_product(negate, adx);
1618            ct_a = [ct_a0, ct_alarge, 0., 0.];
1619            ct_alen = 2;
1620            let [ct_b0, ct_blarge] = two_product(cdytail, bdx);
1621            ct_b = [ct_b0, ct_blarge, 0., 0.];
1622            ct_blen = 2;
1623        }
1624    } else if cdytail == 0.0 {
1625        let [ct_a0, ct_alarge] = two_product(cdxtail, ady);
1626        ct_a = [ct_a0, ct_alarge, 0., 0.];
1627        ct_alen = 2;
1628        let negate = -cdxtail;
1629        let [ct_b0, ct_blarge] = two_product(negate, bdy);
1630        ct_b = [ct_b0, ct_blarge, 0., 0.];
1631        ct_blen = 2;
1632    } else {
1633        let [cdxt_ady0, cdxt_ady1] = two_product(cdxtail, ady);
1634        let [cdyt_adx0, cdyt_adx1] = two_product(cdytail, adx);
1635        ct_a = two_two_diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0);
1636        ct_alen = 4;
1637        let [cdyt_bdx0, cdyt_bdx1] = two_product(cdytail, bdx);
1638        let [cdxt_bdy0, cdxt_bdy1] = two_product(cdxtail, bdy);
1639        ct_b = two_two_diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0);
1640        ct_blen = 4;
1641    }
1642
1643    let mut fin2 = [0.; 192];
1644
1645    let mut w = [0.; 16];
1646
1647    let mut bct = [0.; 8];
1648    let bctlen = fast_expansion_sum_zeroelim(&bt_c[..bt_clen], &ct_b[..ct_blen], &mut bct);
1649    let wlength = scale_expansion_zeroelim(&bct[..bctlen], adz, &mut w);
1650    finlength = fast_expansion_sum_zeroelim(&fin1[..finlength], &w[..wlength], &mut fin2);
1651
1652    let mut cat = [0.; 8];
1653    let catlen = fast_expansion_sum_zeroelim(&ct_a[..ct_alen], &at_c[..at_clen], &mut cat);
1654    let wlength = scale_expansion_zeroelim(&cat[..catlen], bdz, &mut w);
1655    finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &w[..wlength], &mut fin1);
1656
1657    let mut abt = [0.; 8];
1658    let abtlen = fast_expansion_sum_zeroelim(&at_b[..at_blen], &bt_a[..bt_alen], &mut abt);
1659    let wlength = scale_expansion_zeroelim(&abt[..abtlen], cdz, &mut w);
1660    finlength = fast_expansion_sum_zeroelim(&fin1[..finlength], &w[..wlength], &mut fin2);
1661
1662    let mut v = [0.; 12];
1663
1664    // TODO: replace these swaps with destructuring assignment when it is stable;
1665    // https://github.com/rust-lang/rfcs/pull/2909
1666    let (mut fin1, fin2) = if adztail != 0.0 {
1667        let vlength = scale_expansion_zeroelim(&bc, adztail, &mut v);
1668        finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &v[..vlength], &mut fin1);
1669        (fin2, fin1)
1670    } else {
1671        (fin1, fin2)
1672    };
1673    let (mut fin1, fin2) = if bdztail != 0.0 {
1674        let vlength = scale_expansion_zeroelim(&ca, bdztail, &mut v);
1675        finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &v[..vlength], &mut fin1);
1676        (fin2, fin1)
1677    } else {
1678        (fin1, fin2)
1679    };
1680    let (mut fin1, fin2) = if cdztail != 0.0 {
1681        let vlength = scale_expansion_zeroelim(&ab, cdztail, &mut v);
1682        finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &v[..vlength], &mut fin1);
1683        (fin2, fin1)
1684    } else {
1685        (fin1, fin2)
1686    };
1687    let (mut fin1, fin2) = if adxtail != 0.0 {
1688        let (mut fin1, fin2) = if bdytail != 0.0 {
1689            let [adxt_bdyt0, adxt_bdyt1] = two_product(adxtail, bdytail);
1690            let u = two_one_product(adxt_bdyt1, adxt_bdyt0, cdz);
1691            finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1692            let (mut fin1, fin2) = (fin2, fin1);
1693            if cdztail != 0.0 {
1694                let u = two_one_product(adxt_bdyt1, adxt_bdyt0, cdztail);
1695                finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1696                (fin2, fin1)
1697            } else {
1698                (fin1, fin2)
1699            }
1700        } else {
1701            (fin1, fin2)
1702        };
1703        if cdytail != 0.0 {
1704            let negate = -adxtail;
1705            let [adxt_cdyt0, adxt_cdyt1] = two_product(negate, cdytail);
1706            let u = two_one_product(adxt_cdyt1, adxt_cdyt0, bdz);
1707            finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1708            let (mut fin1, fin2) = (fin2, fin1);
1709            if bdztail != 0.0 {
1710                let u = two_one_product(adxt_cdyt1, adxt_cdyt0, bdztail);
1711                finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1712                (fin2, fin1)
1713            } else {
1714                (fin1, fin2)
1715            }
1716        } else {
1717            (fin1, fin2)
1718        }
1719    } else {
1720        (fin1, fin2)
1721    };
1722    let (mut fin1, fin2) = if bdxtail != 0.0 {
1723        let (mut fin1, fin2) = if cdytail != 0.0 {
1724            let [bdxt_cdyt0, bdxt_cdyt1] = two_product(bdxtail, cdytail);
1725            let u = two_one_product(bdxt_cdyt1, bdxt_cdyt0, adz);
1726            finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1727            let (mut fin1, fin2) = (fin2, fin1);
1728            if adztail != 0.0 {
1729                let u = two_one_product(bdxt_cdyt1, bdxt_cdyt0, adztail);
1730                finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1731                (fin2, fin1)
1732            } else {
1733                (fin1, fin2)
1734            }
1735        } else {
1736            (fin1, fin2)
1737        };
1738        if adytail != 0.0 {
1739            let negate = -bdxtail;
1740            let [bdxt_adyt0, bdxt_adyt1] = two_product(negate, adytail);
1741            let u = two_one_product(bdxt_adyt1, bdxt_adyt0, cdz);
1742            finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1743            let (mut fin1, fin2) = (fin2, fin1);
1744            if cdztail != 0.0 {
1745                let u = two_one_product(bdxt_adyt1, bdxt_adyt0, cdztail);
1746                finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1747                (fin2, fin1)
1748            } else {
1749                (fin1, fin2)
1750            }
1751        } else {
1752            (fin1, fin2)
1753        }
1754    } else {
1755        (fin1, fin2)
1756    };
1757    let (mut fin1, fin2) = if cdxtail != 0.0 {
1758        let (mut fin1, fin2) = if adytail != 0.0 {
1759            let [cdxt_adyt0, cdxt_adyt1] = two_product(cdxtail, adytail);
1760            let u = two_one_product(cdxt_adyt1, cdxt_adyt0, bdz);
1761            finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1762            let (mut fin1, fin2) = (fin2, fin1);
1763            if bdztail != 0.0 {
1764                let u = two_one_product(cdxt_adyt1, cdxt_adyt0, bdztail);
1765                finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1766                (fin2, fin1)
1767            } else {
1768                (fin1, fin2)
1769            }
1770        } else {
1771            (fin1, fin2)
1772        };
1773        if bdytail != 0.0 {
1774            let negate = -cdxtail;
1775            let [cdxt_bdyt0, cdxt_bdyt1] = two_product(negate, bdytail);
1776            let u = two_one_product(cdxt_bdyt1, cdxt_bdyt0, adz);
1777            finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1778            let (mut fin1, fin2) = (fin2, fin1);
1779            if adztail != 0.0 {
1780                let u = two_one_product(cdxt_bdyt1, cdxt_bdyt0, adztail);
1781                finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &u, &mut fin1);
1782                (fin2, fin1)
1783            } else {
1784                (fin1, fin2)
1785            }
1786        } else {
1787            (fin1, fin2)
1788        }
1789    } else {
1790        (fin1, fin2)
1791    };
1792    let (mut fin1, fin2) = if adztail != 0.0 {
1793        let wlength = scale_expansion_zeroelim(&bct[..bctlen], adztail, &mut w);
1794        finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &w[..wlength], &mut fin1);
1795        (fin2, fin1)
1796    } else {
1797        (fin1, fin2)
1798    };
1799    let (mut fin1, fin2) = if bdztail != 0.0 {
1800        let wlength = scale_expansion_zeroelim(&cat[..catlen], bdztail, &mut w);
1801        finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &w[..wlength], &mut fin1);
1802        (fin2, fin1)
1803    } else {
1804        (fin1, fin2)
1805    };
1806    let fin2 = if cdztail != 0.0 {
1807        let wlength = scale_expansion_zeroelim(&abt[..abtlen], cdztail, &mut w);
1808        finlength = fast_expansion_sum_zeroelim(&fin2[..finlength], &w[..wlength], &mut fin1);
1809        fin1
1810    } else {
1811        fin2
1812    };
1813    fin2[finlength - 1]
1814}
1815
1816/**
1817 * Adaptive exact 3D orientation test. Robust.
1818 *
1819 * Returns a positive value if the point `pd` lies below the
1820 * plane passing through `pa`, `pb`, and `pc`; "below" is defined so
1821 * that `pa`, `pb`, and `pc` appear in counterclockwise order when
1822 * viewed from above the plane.  Returns a negative value if
1823 * pd lies above the plane.  Returns zero if the points are
1824 * coplanar.  The result is also a rough approximation of six
1825 * times the signed volume of the tetrahedron defined by the
1826 * four points.
1827 *
1828 * The result returned is the determinant of a matrix.
1829 * This determinant is computed adaptively, in the sense that exact
1830 * arithmetic is used only to the degree it is needed to ensure that the
1831 * returned value has the correct sign.  Hence, orient3d() is usually quite
1832 * fast, but will run more slowly when the input points are coplanar or
1833 * nearly so.
1834 */
1835#[inline]
1836pub fn orient3d(pa: [f64; 3], pb: [f64; 3], pc: [f64; 3], pd: [f64; 3]) -> f64 {
1837    let adx = pa[0] - pd[0];
1838    let bdx = pb[0] - pd[0];
1839    let cdx = pc[0] - pd[0];
1840    let ady = pa[1] - pd[1];
1841    let bdy = pb[1] - pd[1];
1842    let cdy = pc[1] - pd[1];
1843    let adz = pa[2] - pd[2];
1844    let bdz = pb[2] - pd[2];
1845    let cdz = pc[2] - pd[2];
1846    let bdxcdy = bdx * cdy;
1847    let cdxbdy = cdx * bdy;
1848    let cdxady = cdx * ady;
1849    let adxcdy = adx * cdy;
1850    let adxbdy = adx * bdy;
1851    let bdxady = bdx * ady;
1852    let det = adz * (bdxcdy - cdxbdy) + bdz * (cdxady - adxcdy) + cdz * (adxbdy - bdxady);
1853    let permanent = (abs(bdxcdy) + abs(cdxbdy)) * abs(adz)
1854        + (abs(cdxady) + abs(adxcdy)) * abs(bdz)
1855        + (abs(adxbdy) + abs(bdxady)) * abs(cdz);
1856    let errbound = PARAMS.o3derrbound_a * permanent;
1857    if det > errbound || -det > errbound {
1858        return det;
1859    }
1860    orient3dadapt(pa, pb, pc, pd, permanent)
1861}
1862
1863/* ****************************************************************************/
1864/*                                                                           */
1865/*  incircle_fast()   Approximate 2D incircle test.  Nonrobust.               */
1866/*  incircle_exact()   Exact 2D incircle test.  Robust.                       */
1867/*  incircle_slow()   Another exact 2D incircle test.  Robust.                */
1868/*  incircle()   Adaptive exact 2D incircle test.  Robust.                   */
1869/*                                                                           */
1870/*               Return a positive value if the point pd lies inside the     */
1871/*               circle passing through pa, pb, and pc; a negative value if  */
1872/*               it lies outside; and zero if the four points are cocircular.*/
1873/*               The points pa, pb, and pc must be in counterclockwise       */
1874/*               order, or the sign of the result will be reversed.          */
1875/*                                                                           */
1876/*  Only the first and last routine should be used; the middle two are for   */
1877/*  timings.                                                                 */
1878/*                                                                           */
1879/*  The last three use exact arithmetic to ensure a correct answer.  The     */
1880/*  result returned is the determinant of a matrix.  In incircle() only,     */
1881/*  this determinant is computed adaptively, in the sense that exact         */
1882/*  arithmetic is used only to the degree it is needed to ensure that the    */
1883/*  returned value has the correct sign.  Hence, incircle() is usually quite */
1884/*  fast, but will run more slowly when the input points are cocircular or   */
1885/*  nearly so.                                                               */
1886/*                                                                           */
1887/* ****************************************************************************/
1888
1889/// Approximate 2D incircle test. Non-robust version of [`incircle`].
1890#[inline]
1891pub fn incircle_fast(pa: [f64; 2], pb: [f64; 2], pc: [f64; 2], pd: [f64; 2]) -> f64 {
1892    let adx = pa[0] - pd[0];
1893    let ady = pa[1] - pd[1];
1894    let bdx = pb[0] - pd[0];
1895    let bdy = pb[1] - pd[1];
1896    let cdx = pc[0] - pd[0];
1897    let cdy = pc[1] - pd[1];
1898    let abdet = adx * bdy - bdx * ady;
1899    let bcdet = bdx * cdy - cdx * bdy;
1900    let cadet = cdx * ady - adx * cdy;
1901    let alift = adx * adx + ady * ady;
1902    let blift = bdx * bdx + bdy * bdy;
1903    let clift = cdx * cdx + cdy * cdy;
1904    alift * bcdet + blift * cadet + clift * abdet
1905}
1906
1907#[inline]
1908pub fn incircle_exact(pa: [f64; 2], pb: [f64; 2], pc: [f64; 2], pd: [f64; 2]) -> f64 {
1909    let [axby0, axby1] = two_product(pa[0], pb[1]);
1910    let [bxay0, bxay1] = two_product(pb[0], pa[1]);
1911    let ab = two_two_diff(axby1, axby0, bxay1, bxay0);
1912    let [bxcy0, bxcy1] = two_product(pb[0], pc[1]);
1913    let [cxby0, cxby1] = two_product(pc[0], pb[1]);
1914    let bc = two_two_diff(bxcy1, bxcy0, cxby1, cxby0);
1915    let [cxdy0, cxdy1] = two_product(pc[0], pd[1]);
1916    let [dxcy0, dxcy1] = two_product(pd[0], pc[1]);
1917    let cd = two_two_diff(cxdy1, cxdy0, dxcy1, dxcy0);
1918    let [dxay0, dxay1] = two_product(pd[0], pa[1]);
1919    let [axdy0, axdy1] = two_product(pa[0], pd[1]);
1920    let da = two_two_diff(dxay1, dxay0, axdy1, axdy0);
1921    let [axcy0, axcy1] = two_product(pa[0], pc[1]);
1922    let [cxay0, cxay1] = two_product(pc[0], pa[1]);
1923    let mut ac = two_two_diff(axcy1, axcy0, cxay1, cxay0);
1924    let [bxdy0, bxdy1] = two_product(pb[0], pd[1]);
1925    let [dxby0, dxby1] = two_product(pd[0], pb[1]);
1926    let mut bd = two_two_diff(bxdy1, bxdy0, dxby1, dxby0);
1927    let mut temp8 = [0.; 8];
1928    let templen = fast_expansion_sum_zeroelim(&cd, &da, &mut temp8);
1929    let mut cda = [0.; 12];
1930    let cdalen = fast_expansion_sum_zeroelim(&temp8[..templen], &ac, &mut cda);
1931    let templen = fast_expansion_sum_zeroelim(&da, &ab, &mut temp8);
1932    let mut dab = [0.; 12];
1933    let dablen = fast_expansion_sum_zeroelim(&temp8[..templen], &bd, &mut dab);
1934    bd.iter_mut().for_each(|x| *x = -*x);
1935    ac.iter_mut().for_each(|x| *x = -*x);
1936    let templen = fast_expansion_sum_zeroelim(&ab, &bc, &mut temp8);
1937    let mut abc = [0.; 12];
1938    let abclen = fast_expansion_sum_zeroelim(&temp8[..templen], &ac, &mut abc);
1939    let templen = fast_expansion_sum_zeroelim(&bc, &cd, &mut temp8);
1940    let mut bcd = [0.; 12];
1941    let bcdlen = fast_expansion_sum_zeroelim(&temp8[..templen], &bd, &mut bcd);
1942    let mut det24x = [0.; 24];
1943    let xlen = scale_expansion_zeroelim(&bcd[..bcdlen], pa[0], &mut det24x);
1944    let mut det48x = [0.; 48];
1945    let xlen = scale_expansion_zeroelim(&det24x[..xlen], pa[0], &mut det48x);
1946    let mut det24y = [0.; 24];
1947    let ylen = scale_expansion_zeroelim(&bcd[..bcdlen], pa[1], &mut det24y);
1948    let mut det48y = [0.; 48];
1949    let ylen = scale_expansion_zeroelim(&det24y[..ylen], pa[1], &mut det48y);
1950    let mut adet = [0.; 96];
1951    let alen = fast_expansion_sum_zeroelim(&det48x[..xlen], &det48y[..ylen], &mut adet);
1952    let xlen = scale_expansion_zeroelim(&cda[..cdalen], pb[0], &mut det24x);
1953    let xlen = scale_expansion_zeroelim(&det24x[..xlen], -pb[0], &mut det48x);
1954    let ylen = scale_expansion_zeroelim(&cda[..cdalen], pb[1], &mut det24y);
1955    let ylen = scale_expansion_zeroelim(&det24y[..ylen], -pb[1], &mut det48y);
1956    let mut bdet = [0.; 96];
1957    let blen = fast_expansion_sum_zeroelim(&det48x[..xlen], &det48y[..ylen], &mut bdet);
1958    let xlen = scale_expansion_zeroelim(&dab[..dablen], pc[0], &mut det24x);
1959    let xlen = scale_expansion_zeroelim(&det24x[..xlen], pc[0], &mut det48x);
1960    let ylen = scale_expansion_zeroelim(&dab[..dablen], pc[1], &mut det24y);
1961    let ylen = scale_expansion_zeroelim(&det24y[..ylen], pc[1], &mut det48y);
1962    let mut cdet = [0.; 96];
1963    let clen = fast_expansion_sum_zeroelim(&det48x[..xlen], &det48y[..ylen], &mut cdet);
1964    let xlen = scale_expansion_zeroelim(&abc[..abclen], pd[0], &mut det24x);
1965    let xlen = scale_expansion_zeroelim(&det24x[..xlen], -pd[0], &mut det48x);
1966    let ylen = scale_expansion_zeroelim(&abc[..abclen], pd[1], &mut det24y);
1967    let ylen = scale_expansion_zeroelim(&det24y[..ylen], -pd[1], &mut det48y);
1968    let mut ddet = [0.; 96];
1969    let dlen = fast_expansion_sum_zeroelim(&det48x[..xlen], &det48y[..ylen], &mut ddet);
1970    let mut abdet = [0.; 192];
1971    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
1972    let mut cddet = [0.; 192];
1973    let cdlen = fast_expansion_sum_zeroelim(&cdet[..clen], &ddet[..dlen], &mut cddet);
1974    let mut deter = [0.; 384];
1975    let deterlen = fast_expansion_sum_zeroelim(&abdet[..ablen], &cddet[..cdlen], &mut deter);
1976    deter[deterlen - 1]
1977}
1978
1979#[inline]
1980pub fn incircle_slow(pa: [f64; 2], pb: [f64; 2], pc: [f64; 2], pd: [f64; 2]) -> f64 {
1981    let [adxtail, adx] = two_diff(pa[0], pd[0]);
1982    let [adytail, ady] = two_diff(pa[1], pd[1]);
1983    let [bdxtail, bdx] = two_diff(pb[0], pd[0]);
1984    let [bdytail, bdy] = two_diff(pb[1], pd[1]);
1985    let [cdxtail, cdx] = two_diff(pc[0], pd[0]);
1986    let [cdytail, cdy] = two_diff(pc[1], pd[1]);
1987    let axby = two_two_product(adx, adxtail, bdy, bdytail);
1988    let negate = -ady;
1989    let negatetail = -adytail;
1990    let bxay = two_two_product(bdx, bdxtail, negate, negatetail);
1991    let bxcy = two_two_product(bdx, bdxtail, cdy, cdytail);
1992    let negate = -bdy;
1993    let negatetail = -bdytail;
1994    let cxby = two_two_product(cdx, cdxtail, negate, negatetail);
1995    let cxay = two_two_product(cdx, cdxtail, ady, adytail);
1996    let negate = -cdy;
1997    let negatetail = -cdytail;
1998    let axcy = two_two_product(adx, adxtail, negate, negatetail);
1999    let mut temp16 = [0.; 16];
2000    let temp16len = fast_expansion_sum_zeroelim(&bxcy, &cxby, &mut temp16);
2001    let mut detx = [0.; 32];
2002    let xlen = scale_expansion_zeroelim(&temp16[..temp16len], adx, &mut detx);
2003    let mut detxx = [0.; 64];
2004    let xxlen = scale_expansion_zeroelim(&detx[..xlen], adx, &mut detxx);
2005    let mut detxt = [0.; 32];
2006    let xtlen = scale_expansion_zeroelim(&temp16[..temp16len], adxtail, &mut detxt);
2007    let mut detxxt = [0.; 64];
2008    let xxtlen = scale_expansion_zeroelim(&detxt[..xtlen], adx, &mut detxxt);
2009    detxxt[..xxtlen].iter_mut().for_each(|x| *x *= 2.0);
2010    let mut detxtxt = [0.; 64];
2011    let xtxtlen = scale_expansion_zeroelim(&detxt[..xtlen], adxtail, &mut detxtxt);
2012    let mut x1 = [0.; 128];
2013    let x1len = fast_expansion_sum_zeroelim(&detxx[..xxlen], &detxxt[..xxtlen], &mut x1);
2014    let mut x2 = [0.; 192];
2015    let x2len = fast_expansion_sum_zeroelim(&x1[..x1len], &detxtxt[..xtxtlen], &mut x2);
2016    let mut dety = [0.; 32];
2017    let ylen = scale_expansion_zeroelim(&temp16[..temp16len], ady, &mut dety);
2018    let mut detyy = [0.; 64];
2019    let yylen = scale_expansion_zeroelim(&dety[..ylen], ady, &mut detyy);
2020    let mut detyt = [0.; 32];
2021    let ytlen = scale_expansion_zeroelim(&temp16[..temp16len], adytail, &mut detyt);
2022    let mut detyyt = [0.; 64];
2023    let yytlen = scale_expansion_zeroelim(&detyt[..ytlen], ady, &mut detyyt);
2024    detyyt[..yytlen].iter_mut().for_each(|x| *x *= 2.0);
2025    let mut detytyt = [0.; 64];
2026    let ytytlen = scale_expansion_zeroelim(&detyt[..ytlen], adytail, &mut detytyt);
2027    let mut y1 = [0.; 128];
2028    let y1len = fast_expansion_sum_zeroelim(&detyy[..yylen], &detyyt[..yytlen], &mut y1);
2029    let mut y2 = [0.; 192];
2030    let y2len = fast_expansion_sum_zeroelim(&y1[..y1len], &detytyt[..ytytlen], &mut y2);
2031    let mut adet = [0.; 384];
2032    let alen = fast_expansion_sum_zeroelim(&x2[..x2len], &y2[..y2len], &mut adet);
2033    let temp16len = fast_expansion_sum_zeroelim(&cxay, &axcy, &mut temp16);
2034    let xlen = scale_expansion_zeroelim(&temp16[..temp16len], bdx, &mut detx);
2035    let xxlen = scale_expansion_zeroelim(&detx[..xlen], bdx, &mut detxx);
2036    let xtlen = scale_expansion_zeroelim(&temp16[..temp16len], bdxtail, &mut detxt);
2037    let xxtlen = scale_expansion_zeroelim(&detxt[..xtlen], bdx, &mut detxxt);
2038    detxxt[..xxtlen].iter_mut().for_each(|x| *x *= 2.0);
2039    let xtxtlen = scale_expansion_zeroelim(&detxt[..xtlen], bdxtail, &mut detxtxt);
2040    let x1len = fast_expansion_sum_zeroelim(&detxx[..xxlen], &detxxt[..xxtlen], &mut x1);
2041    let x2len = fast_expansion_sum_zeroelim(&x1[..x1len], &detxtxt[..xtxtlen], &mut x2);
2042    let ylen = scale_expansion_zeroelim(&temp16[..temp16len], bdy, &mut dety);
2043    let yylen = scale_expansion_zeroelim(&dety[..ylen], bdy, &mut detyy);
2044    let ytlen = scale_expansion_zeroelim(&temp16[..temp16len], bdytail, &mut detyt);
2045    let yytlen = scale_expansion_zeroelim(&detyt[..ytlen], bdy, &mut detyyt);
2046    detyyt[..yytlen].iter_mut().for_each(|x| *x *= 2.0);
2047    let ytytlen = scale_expansion_zeroelim(&detyt[..ytlen], bdytail, &mut detytyt);
2048    let y1len = fast_expansion_sum_zeroelim(&detyy[..yylen], &detyyt[..yytlen], &mut y1);
2049    let y2len = fast_expansion_sum_zeroelim(&y1[..y1len], &detytyt[..ytytlen], &mut y2);
2050    let mut bdet = [0.; 384];
2051    let blen = fast_expansion_sum_zeroelim(&x2[..x2len], &y2[..y2len], &mut bdet);
2052    let temp16len = fast_expansion_sum_zeroelim(&axby, &bxay, &mut temp16);
2053    let xlen = scale_expansion_zeroelim(&temp16[..temp16len], cdx, &mut detx);
2054    let xxlen = scale_expansion_zeroelim(&detx[..xlen], cdx, &mut detxx);
2055    let xtlen = scale_expansion_zeroelim(&temp16[..temp16len], cdxtail, &mut detxt);
2056    let xxtlen = scale_expansion_zeroelim(&detxt[..xtlen], cdx, &mut detxxt);
2057    detxxt[..xxtlen].iter_mut().for_each(|x| *x *= 2.0);
2058    let xtxtlen = scale_expansion_zeroelim(&detxt[..xtlen], cdxtail, &mut detxtxt);
2059    let x1len = fast_expansion_sum_zeroelim(&detxx[..xxlen], &detxxt[..xxtlen], &mut x1);
2060    let x2len = fast_expansion_sum_zeroelim(&x1[..x1len], &detxtxt[..xtxtlen], &mut x2);
2061    let ylen = scale_expansion_zeroelim(&temp16[..temp16len], cdy, &mut dety);
2062    let yylen = scale_expansion_zeroelim(&dety[..ylen], cdy, &mut detyy);
2063    let ytlen = scale_expansion_zeroelim(&temp16[..temp16len], cdytail, &mut detyt);
2064    let yytlen = scale_expansion_zeroelim(&detyt[..ytlen], cdy, &mut detyyt);
2065    detyyt[..yytlen].iter_mut().for_each(|x| *x *= 2.0);
2066    let ytytlen = scale_expansion_zeroelim(&detyt[..ytlen], cdytail, &mut detytyt);
2067    let y1len = fast_expansion_sum_zeroelim(&detyy[..yylen], &detyyt[..yytlen], &mut y1);
2068    let y2len = fast_expansion_sum_zeroelim(&y1[..y1len], &detytyt[..ytytlen], &mut y2);
2069    let mut cdet = [0.; 384];
2070    let clen = fast_expansion_sum_zeroelim(&x2[..x2len], &y2[..y2len], &mut cdet);
2071    let mut abdet = [0.; 768];
2072    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
2073    let mut deter = [0.; 1152];
2074    let deterlen = fast_expansion_sum_zeroelim(&abdet[..ablen], &cdet[..clen], &mut deter);
2075    deter[deterlen - 1]
2076}
2077
2078#[inline]
2079pub fn incircleadapt(
2080    pa: [f64; 2],
2081    pb: [f64; 2],
2082    pc: [f64; 2],
2083    pd: [f64; 2],
2084    permanent: f64,
2085) -> f64 {
2086    let mut axbc = [0.; 8];
2087    let mut axxbc = [0.; 16];
2088    let mut aybc = [0.; 8];
2089    let mut ayybc = [0.; 16];
2090    let mut adet = [0.; 32];
2091    let mut bxca = [0.; 8];
2092    let mut bxxca = [0.; 16];
2093    let mut byca = [0.; 8];
2094    let mut byyca = [0.; 16];
2095    let mut bdet = [0.; 32];
2096    let mut cxab = [0.; 8];
2097    let mut cxxab = [0.; 16];
2098    let mut cyab = [0.; 8];
2099    let mut cyyab = [0.; 16];
2100    let mut cdet = [0.; 32];
2101    let mut abdet = [0.; 64];
2102    let mut fin1 = [0.; 1152];
2103    let mut fin2 = [0.; 1152];
2104    let mut finnow: &mut [f64];
2105    let mut finother: &mut [f64];
2106    let mut temp8 = [0.; 8];
2107    let mut temp16a = [0.; 16];
2108    let mut temp16b = [0.; 16];
2109    let mut temp16c = [0.; 16];
2110    let mut temp32a = [0.; 32];
2111    let mut temp32b = [0.; 32];
2112    let mut temp48 = [0.; 48];
2113    let mut temp64 = [0.; 64];
2114    let mut axtbb = [0.; 8];
2115    let mut axtcc = [0.; 8];
2116    let mut aytbb = [0.; 8];
2117    let mut aytcc = [0.; 8];
2118    let mut bxtaa = [0.; 8];
2119    let mut bxtcc = [0.; 8];
2120    let mut bytaa = [0.; 8];
2121    let mut bytcc = [0.; 8];
2122    let mut cxtaa = [0.; 8];
2123    let mut cxtbb = [0.; 8];
2124    let mut cytaa = [0.; 8];
2125    let mut cytbb = [0.; 8];
2126    let mut axtbct = [0.; 16];
2127    let mut aytbct = [0.; 16];
2128    let mut bxtcat = [0.; 16];
2129    let mut bytcat = [0.; 16];
2130    let mut cxtabt = [0.; 16];
2131    let mut cytabt = [0.; 16];
2132    let mut axtbctt = [0.; 8];
2133    let mut aytbctt = [0.; 8];
2134    let mut bxtcatt = [0.; 8];
2135    let mut bytcatt = [0.; 8];
2136    let mut cxtabtt = [0.; 8];
2137    let mut cytabtt = [0.; 8];
2138    let adx = pa[0] - pd[0];
2139    let bdx = pb[0] - pd[0];
2140    let cdx = pc[0] - pd[0];
2141    let ady = pa[1] - pd[1];
2142    let bdy = pb[1] - pd[1];
2143    let cdy = pc[1] - pd[1];
2144    let [bdxcdy0, bdxcdy1] = two_product(bdx, cdy);
2145    let [cdxbdy0, cdxbdy1] = two_product(cdx, bdy);
2146    let bc = two_two_diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0);
2147    let axbclen = scale_expansion_zeroelim(&bc, adx, &mut axbc);
2148    let axxbclen = scale_expansion_zeroelim(&axbc[..axbclen], adx, &mut axxbc);
2149    let aybclen = scale_expansion_zeroelim(&bc, ady, &mut aybc);
2150    let ayybclen = scale_expansion_zeroelim(&aybc[..aybclen], ady, &mut ayybc);
2151    let alen = fast_expansion_sum_zeroelim(&axxbc[..axxbclen], &ayybc[..ayybclen], &mut adet);
2152    let [cdxady0, cdxady1] = two_product(cdx, ady);
2153    let [adxcdy0, adxcdy1] = two_product(adx, cdy);
2154    let ca = two_two_diff(cdxady1, cdxady0, adxcdy1, adxcdy0);
2155    let bxcalen = scale_expansion_zeroelim(&ca, bdx, &mut bxca);
2156    let bxxcalen = scale_expansion_zeroelim(&bxca[..bxcalen], bdx, &mut bxxca);
2157    let bycalen = scale_expansion_zeroelim(&ca, bdy, &mut byca);
2158    let byycalen = scale_expansion_zeroelim(&byca[..bycalen], bdy, &mut byyca);
2159    let blen = fast_expansion_sum_zeroelim(&bxxca[..bxxcalen], &byyca[..byycalen], &mut bdet);
2160    let [adxbdy0, adxbdy1] = two_product(adx, bdy);
2161    let [bdxady0, bdxady1] = two_product(bdx, ady);
2162    let ab = two_two_diff(adxbdy1, adxbdy0, bdxady1, bdxady0);
2163    let cxablen = scale_expansion_zeroelim(&ab, cdx, &mut cxab);
2164    let cxxablen = scale_expansion_zeroelim(&cxab[..cxablen], cdx, &mut cxxab);
2165    let cyablen = scale_expansion_zeroelim(&ab, cdy, &mut cyab);
2166    let cyyablen = scale_expansion_zeroelim(&cyab[..cyablen], cdy, &mut cyyab);
2167    let clen = fast_expansion_sum_zeroelim(&cxxab[..cxxablen], &cyyab[..cyyablen], &mut cdet);
2168    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
2169    let mut finlength = fast_expansion_sum_zeroelim(&abdet[..ablen], &cdet[..clen], &mut fin1);
2170    let mut det: f64 = fin1[..finlength].iter().sum();
2171    let errbound = PARAMS.iccerrbound_b * permanent;
2172    if det >= errbound || -det >= errbound {
2173        return det;
2174    }
2175    let adxtail = two_diff_tail(pa[0], pd[0], adx);
2176    let adytail = two_diff_tail(pa[1], pd[1], ady);
2177    let bdxtail = two_diff_tail(pb[0], pd[0], bdx);
2178    let bdytail = two_diff_tail(pb[1], pd[1], bdy);
2179    let cdxtail = two_diff_tail(pc[0], pd[0], cdx);
2180    let cdytail = two_diff_tail(pc[1], pd[1], cdy);
2181    if adxtail == 0.0
2182        && bdxtail == 0.0
2183        && cdxtail == 0.0
2184        && adytail == 0.0
2185        && bdytail == 0.0
2186        && cdytail == 0.0
2187    {
2188        return det;
2189    }
2190    let errbound = PARAMS.iccerrbound_c * permanent + PARAMS.resulterrbound * abs(det);
2191    det += (adx * adx + ady * ady)
2192        * (bdx * cdytail + cdy * bdxtail - (bdy * cdxtail + cdx * bdytail))
2193        + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx)
2194        + ((bdx * bdx + bdy * bdy)
2195            * (cdx * adytail + ady * cdxtail - (cdy * adxtail + adx * cdytail))
2196            + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
2197        + ((cdx * cdx + cdy * cdy)
2198            * (adx * bdytail + bdy * adxtail - (ady * bdxtail + bdx * adytail))
2199            + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
2200    if det >= errbound || -det >= errbound {
2201        return det;
2202    }
2203    finnow = &mut fin1;
2204    finother = &mut fin2;
2205    let aa = if bdxtail != 0.0 || bdytail != 0.0 || cdxtail != 0.0 || cdytail != 0.0 {
2206        let [adxadx0, adxadx1] = square(adx);
2207        let [adyady0, adyady1] = square(ady);
2208        two_two_sum(adxadx1, adxadx0, adyady1, adyady0)
2209    } else {
2210        [0.; 4]
2211    };
2212    let bb = if cdxtail != 0.0 || cdytail != 0.0 || adxtail != 0.0 || adytail != 0.0 {
2213        let [bdxbdx0, bdxbdx1] = square(bdx);
2214        let [bdybdy0, bdybdy1] = square(bdy);
2215        two_two_sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0)
2216    } else {
2217        [0.; 4]
2218    };
2219    let cc = if adxtail != 0.0 || adytail != 0.0 || bdxtail != 0.0 || bdytail != 0.0 {
2220        let [cdxcdx0, cdxcdx1] = square(cdx);
2221        let [cdycdy0, cdycdy1] = square(cdy);
2222        two_two_sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0)
2223    } else {
2224        [0.; 4]
2225    };
2226    let mut axtbclen = 8;
2227    let mut axtbc = [0.; 8];
2228    if adxtail != 0.0 {
2229        axtbclen = scale_expansion_zeroelim(&bc, adxtail, &mut axtbc);
2230        let temp16alen = scale_expansion_zeroelim(&axtbc[..axtbclen], 2.0 * adx, &mut temp16a);
2231        let axtcclen = scale_expansion_zeroelim(&cc, adxtail, &mut axtcc);
2232        let temp16blen = scale_expansion_zeroelim(&axtcc[..axtcclen], bdy, &mut temp16b);
2233        let axtbblen = scale_expansion_zeroelim(&bb, adxtail, &mut axtbb);
2234        let temp16clen = scale_expansion_zeroelim(&axtbb[..axtbblen], -cdy, &mut temp16c);
2235        let temp32alen = fast_expansion_sum_zeroelim(
2236            &temp16a[..temp16alen],
2237            &temp16b[..temp16blen],
2238            &mut temp32a,
2239        );
2240        let temp48len = fast_expansion_sum_zeroelim(
2241            &temp16c[..temp16clen],
2242            &temp32a[..temp32alen],
2243            &mut temp48,
2244        );
2245        finlength =
2246            fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2247        core::mem::swap(&mut finnow, &mut finother);
2248    }
2249    let mut aytbclen = 8;
2250    let mut aytbc = [0.; 8];
2251    if adytail != 0.0 {
2252        aytbclen = scale_expansion_zeroelim(&bc, adytail, &mut aytbc);
2253        let temp16alen = scale_expansion_zeroelim(&aytbc[..aytbclen], 2.0 * ady, &mut temp16a);
2254        let aytbblen = scale_expansion_zeroelim(&bb, adytail, &mut aytbb);
2255        let temp16blen = scale_expansion_zeroelim(&aytbb[..aytbblen], cdx, &mut temp16b);
2256        let aytcclen = scale_expansion_zeroelim(&cc, adytail, &mut aytcc);
2257        let temp16clen = scale_expansion_zeroelim(&aytcc[..aytcclen], -bdx, &mut temp16c);
2258        let temp32alen = fast_expansion_sum_zeroelim(
2259            &temp16a[..temp16alen],
2260            &temp16b[..temp16blen],
2261            &mut temp32a,
2262        );
2263        let temp48len = fast_expansion_sum_zeroelim(
2264            &temp16c[..temp16clen],
2265            &temp32a[..temp32alen],
2266            &mut temp48,
2267        );
2268        finlength =
2269            fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2270        core::mem::swap(&mut finnow, &mut finother);
2271    }
2272    let mut bxtcalen = 8;
2273    let mut bxtca = [0.; 8];
2274    if bdxtail != 0.0 {
2275        bxtcalen = scale_expansion_zeroelim(&ca, bdxtail, &mut bxtca);
2276        let temp16alen = scale_expansion_zeroelim(&bxtca[..bxtcalen], 2.0 * bdx, &mut temp16a);
2277        let bxtaalen = scale_expansion_zeroelim(&aa, bdxtail, &mut bxtaa);
2278        let temp16blen = scale_expansion_zeroelim(&bxtaa[..bxtaalen], cdy, &mut temp16b);
2279        let bxtcclen = scale_expansion_zeroelim(&cc, bdxtail, &mut bxtcc);
2280        let temp16clen = scale_expansion_zeroelim(&bxtcc[..bxtcclen], -ady, &mut temp16c);
2281        let temp32alen = fast_expansion_sum_zeroelim(
2282            &temp16a[..temp16alen],
2283            &temp16b[..temp16blen],
2284            &mut temp32a,
2285        );
2286        let temp48len = fast_expansion_sum_zeroelim(
2287            &temp16c[..temp16clen],
2288            &temp32a[..temp32alen],
2289            &mut temp48,
2290        );
2291        finlength =
2292            fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2293        core::mem::swap(&mut finnow, &mut finother);
2294    }
2295    let mut bytcalen = 8;
2296    let mut bytca = [0.; 8];
2297    if bdytail != 0.0 {
2298        bytcalen = scale_expansion_zeroelim(&ca, bdytail, &mut bytca);
2299        let temp16alen = scale_expansion_zeroelim(&bytca[..bytcalen], 2.0 * bdy, &mut temp16a);
2300        let bytcclen = scale_expansion_zeroelim(&cc, bdytail, &mut bytcc);
2301        let temp16blen = scale_expansion_zeroelim(&bytcc[..bytcclen], adx, &mut temp16b);
2302        let bytaalen = scale_expansion_zeroelim(&aa, bdytail, &mut bytaa);
2303        let temp16clen = scale_expansion_zeroelim(&bytaa[..bytaalen], -cdx, &mut temp16c);
2304        let temp32alen = fast_expansion_sum_zeroelim(
2305            &temp16a[..temp16alen],
2306            &temp16b[..temp16blen],
2307            &mut temp32a,
2308        );
2309        let temp48len = fast_expansion_sum_zeroelim(
2310            &temp16c[..temp16clen],
2311            &temp32a[..temp32alen],
2312            &mut temp48,
2313        );
2314        finlength =
2315            fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2316        core::mem::swap(&mut finnow, &mut finother);
2317    }
2318    let cxtablen = 8;
2319    let mut cxtab = [0.; 8];
2320    if cdxtail != 0.0 {
2321        let cxtablen = scale_expansion_zeroelim(&ab, cdxtail, &mut cxtab);
2322        let temp16alen = scale_expansion_zeroelim(&cxtab[..cxtablen], 2.0 * cdx, &mut temp16a);
2323        let cxtbblen = scale_expansion_zeroelim(&bb, cdxtail, &mut cxtbb);
2324        let temp16blen = scale_expansion_zeroelim(&cxtbb[..cxtbblen], ady, &mut temp16b);
2325        let cxtaalen = scale_expansion_zeroelim(&aa, cdxtail, &mut cxtaa);
2326        let temp16clen = scale_expansion_zeroelim(&cxtaa[..cxtaalen], -bdy, &mut temp16c);
2327        let temp32alen = fast_expansion_sum_zeroelim(
2328            &temp16a[..temp16alen],
2329            &temp16b[..temp16blen],
2330            &mut temp32a,
2331        );
2332        let temp48len = fast_expansion_sum_zeroelim(
2333            &temp16c[..temp16clen],
2334            &temp32a[..temp32alen],
2335            &mut temp48,
2336        );
2337        finlength =
2338            fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2339        core::mem::swap(&mut finnow, &mut finother);
2340    }
2341    let mut cytablen = 8;
2342    let mut cytab = [0.; 8];
2343    if cdytail != 0.0 {
2344        cytablen = scale_expansion_zeroelim(&ab, cdytail, &mut cytab);
2345        let temp16alen = scale_expansion_zeroelim(&cytab[..cytablen], 2.0 * cdy, &mut temp16a);
2346        let cytaalen = scale_expansion_zeroelim(&aa, cdytail, &mut cytaa);
2347        let temp16blen = scale_expansion_zeroelim(&cytaa[..cytaalen], bdx, &mut temp16b);
2348        let cytbblen = scale_expansion_zeroelim(&bb, cdytail, &mut cytbb);
2349        let temp16clen = scale_expansion_zeroelim(&cytbb[..cytbblen], -adx, &mut temp16c);
2350        let temp32alen = fast_expansion_sum_zeroelim(
2351            &temp16a[..temp16alen],
2352            &temp16b[..temp16blen],
2353            &mut temp32a,
2354        );
2355        let temp48len = fast_expansion_sum_zeroelim(
2356            &temp16c[..temp16clen],
2357            &temp32a[..temp32alen],
2358            &mut temp48,
2359        );
2360        finlength =
2361            fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2362        core::mem::swap(&mut finnow, &mut finother);
2363    }
2364    if adxtail != 0.0 || adytail != 0.0 {
2365        let mut bctlen = 1;
2366        let mut bcttlen = 1;
2367        let mut bct: [f64; 8] = [0.; 8];
2368        let mut bctt: [f64; 4] = [0.; 4];
2369        if bdxtail != 0.0 || bdytail != 0.0 || cdxtail != 0.0 || cdytail != 0.0 {
2370            let [ti0, ti1] = two_product(bdxtail, cdy);
2371            let [tj0, tj1] = two_product(bdx, cdytail);
2372            let u = two_two_sum(ti1, ti0, tj1, tj0);
2373            let negate = -bdy;
2374            let [ti0, ti1] = two_product(cdxtail, negate);
2375            let negate = -bdytail;
2376            let [tj0, tj1] = two_product(cdx, negate);
2377            let v = two_two_sum(ti1, ti0, tj1, tj0);
2378            bctlen = fast_expansion_sum_zeroelim(&u, &v, &mut bct);
2379            let [ti0, ti1] = two_product(bdxtail, cdytail);
2380            let [tj0, tj1] = two_product(cdxtail, bdytail);
2381            bctt = two_two_diff(ti1, ti0, tj1, tj0);
2382            bcttlen = 4;
2383        }
2384        if adxtail != 0.0 {
2385            let temp16alen = scale_expansion_zeroelim(&axtbc[..axtbclen], adxtail, &mut temp16a);
2386            let axtbctlen = scale_expansion_zeroelim(&bct[..bctlen], adxtail, &mut axtbct);
2387            let temp32alen =
2388                scale_expansion_zeroelim(&axtbct[..axtbctlen], 2.0 * adx, &mut temp32a);
2389            let temp48len = fast_expansion_sum_zeroelim(
2390                &temp16a[..temp16alen],
2391                &temp32a[..temp32alen],
2392                &mut temp48,
2393            );
2394            finlength =
2395                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2396            core::mem::swap(&mut finnow, &mut finother);
2397            if bdytail != 0.0 {
2398                let temp8len = scale_expansion_zeroelim(&cc, adxtail, &mut temp8);
2399                let temp16alen =
2400                    scale_expansion_zeroelim(&temp8[..temp8len], bdytail, &mut temp16a);
2401                finlength = fast_expansion_sum_zeroelim(
2402                    &finnow[..finlength],
2403                    &temp16a[..temp16alen],
2404                    finother,
2405                );
2406                core::mem::swap(&mut finnow, &mut finother);
2407            }
2408            if cdytail != 0.0 {
2409                let temp8len = scale_expansion_zeroelim(&bb, -adxtail, &mut temp8);
2410                let temp16alen =
2411                    scale_expansion_zeroelim(&temp8[..temp8len], cdytail, &mut temp16a);
2412                finlength = fast_expansion_sum_zeroelim(
2413                    &finnow[..finlength],
2414                    &temp16a[..temp16alen],
2415                    finother,
2416                );
2417                core::mem::swap(&mut finnow, &mut finother);
2418            }
2419            let temp32alen = scale_expansion_zeroelim(&axtbct[..axtbctlen], adxtail, &mut temp32a);
2420            let axtbcttlen = scale_expansion_zeroelim(&bctt[..bcttlen], adxtail, &mut axtbctt);
2421            let temp16alen =
2422                scale_expansion_zeroelim(&axtbctt[..axtbcttlen], 2.0 * adx, &mut temp16a);
2423            let temp16blen =
2424                scale_expansion_zeroelim(&axtbctt[..axtbcttlen], adxtail, &mut temp16b);
2425            let temp32blen = fast_expansion_sum_zeroelim(
2426                &temp16a[..temp16alen],
2427                &temp16b[..temp16blen],
2428                &mut temp32b,
2429            );
2430            let temp64len = fast_expansion_sum_zeroelim(
2431                &temp32a[..temp32alen],
2432                &temp32b[..temp32blen],
2433                &mut temp64,
2434            );
2435            finlength =
2436                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp64[..temp64len], finother);
2437            core::mem::swap(&mut finnow, &mut finother);
2438        }
2439        if adytail != 0.0 {
2440            let temp16alen = scale_expansion_zeroelim(&aytbc[..aytbclen], adytail, &mut temp16a);
2441            let aytbctlen = scale_expansion_zeroelim(&bct[..bctlen], adytail, &mut aytbct);
2442            let temp32alen =
2443                scale_expansion_zeroelim(&aytbct[..aytbctlen], 2.0 * ady, &mut temp32a);
2444            let temp48len = fast_expansion_sum_zeroelim(
2445                &temp16a[..temp16alen],
2446                &temp32a[..temp32alen],
2447                &mut temp48,
2448            );
2449            finlength =
2450                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2451            core::mem::swap(&mut finnow, &mut finother);
2452            let temp32alen = scale_expansion_zeroelim(&aytbct[..aytbctlen], adytail, &mut temp32a);
2453            let aytbcttlen = scale_expansion_zeroelim(&bctt[..bcttlen], adytail, &mut aytbctt);
2454            let temp16alen =
2455                scale_expansion_zeroelim(&aytbctt[..aytbcttlen], 2.0 * ady, &mut temp16a);
2456            let temp16blen =
2457                scale_expansion_zeroelim(&aytbctt[..aytbcttlen], adytail, &mut temp16b);
2458            let temp32blen = fast_expansion_sum_zeroelim(
2459                &temp16a[..temp16alen],
2460                &temp16b[..temp16blen],
2461                &mut temp32b,
2462            );
2463            let temp64len = fast_expansion_sum_zeroelim(
2464                &temp32a[..temp32alen],
2465                &temp32b[..temp32blen],
2466                &mut temp64,
2467            );
2468            finlength =
2469                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp64[..temp64len], finother);
2470            core::mem::swap(&mut finnow, &mut finother);
2471        }
2472    }
2473    if bdxtail != 0.0 || bdytail != 0.0 {
2474        let mut catlen = 1;
2475        let mut cattlen = 1;
2476        let mut cat: [f64; 8] = [0.; 8];
2477        let mut catt: [f64; 4] = [0.; 4];
2478        if cdxtail != 0.0 || cdytail != 0.0 || adxtail != 0.0 || adytail != 0.0 {
2479            let [ti0, ti1] = two_product(cdxtail, ady);
2480            let [tj0, tj1] = two_product(cdx, adytail);
2481            let u = two_two_sum(ti1, ti0, tj1, tj0);
2482            let negate = -cdy;
2483            let [ti0, ti1] = two_product(adxtail, negate);
2484            let negate = -cdytail;
2485            let [tj0, tj1] = two_product(adx, negate);
2486            let v = two_two_sum(ti1, ti0, tj1, tj0);
2487            catlen = fast_expansion_sum_zeroelim(&u, &v, &mut cat);
2488            let [ti0, ti1] = two_product(cdxtail, adytail);
2489            let [tj0, tj1] = two_product(adxtail, cdytail);
2490            catt = two_two_diff(ti1, ti0, tj1, tj0);
2491            cattlen = 4;
2492        }
2493        if bdxtail != 0.0 {
2494            let temp16alen = scale_expansion_zeroelim(&bxtca[..bxtcalen], bdxtail, &mut temp16a);
2495            let bxtcatlen = scale_expansion_zeroelim(&cat[..catlen], bdxtail, &mut bxtcat);
2496            let temp32alen =
2497                scale_expansion_zeroelim(&bxtcat[..bxtcatlen], 2.0 * bdx, &mut temp32a);
2498            let temp48len = fast_expansion_sum_zeroelim(
2499                &temp16a[..temp16alen],
2500                &temp32a[..temp32alen],
2501                &mut temp48,
2502            );
2503            finlength =
2504                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2505            core::mem::swap(&mut finnow, &mut finother);
2506            if cdytail != 0.0 {
2507                let temp8len = scale_expansion_zeroelim(&aa, bdxtail, &mut temp8);
2508                let temp16alen =
2509                    scale_expansion_zeroelim(&temp8[..temp8len], cdytail, &mut temp16a);
2510                finlength = fast_expansion_sum_zeroelim(
2511                    &finnow[..finlength],
2512                    &temp16a[..temp16alen],
2513                    finother,
2514                );
2515                core::mem::swap(&mut finnow, &mut finother);
2516            }
2517            if adytail != 0.0 {
2518                let temp8len = scale_expansion_zeroelim(&cc, -bdxtail, &mut temp8);
2519                let temp16alen =
2520                    scale_expansion_zeroelim(&temp8[..temp8len], adytail, &mut temp16a);
2521                finlength = fast_expansion_sum_zeroelim(
2522                    &finnow[..finlength],
2523                    &temp16a[..temp16alen],
2524                    finother,
2525                );
2526                core::mem::swap(&mut finnow, &mut finother);
2527            }
2528            let temp32alen = scale_expansion_zeroelim(&bxtcat[..bxtcatlen], bdxtail, &mut temp32a);
2529            let bxtcattlen = scale_expansion_zeroelim(&catt[..cattlen], bdxtail, &mut bxtcatt);
2530            let temp16alen =
2531                scale_expansion_zeroelim(&bxtcatt[..bxtcattlen], 2.0 * bdx, &mut temp16a);
2532            let temp16blen =
2533                scale_expansion_zeroelim(&bxtcatt[..bxtcattlen], bdxtail, &mut temp16b);
2534            let temp32blen = fast_expansion_sum_zeroelim(
2535                &temp16a[..temp16alen],
2536                &temp16b[..temp16blen],
2537                &mut temp32b,
2538            );
2539            let temp64len = fast_expansion_sum_zeroelim(
2540                &temp32a[..temp32alen],
2541                &temp32b[..temp32blen],
2542                &mut temp64,
2543            );
2544            finlength =
2545                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp64[..temp64len], finother);
2546            core::mem::swap(&mut finnow, &mut finother);
2547        }
2548        if bdytail != 0.0 {
2549            let temp16alen = scale_expansion_zeroelim(&bytca[..bytcalen], bdytail, &mut temp16a);
2550            let bytcatlen = scale_expansion_zeroelim(&cat[..catlen], bdytail, &mut bytcat);
2551            let temp32alen =
2552                scale_expansion_zeroelim(&bytcat[..bytcatlen], 2.0 * bdy, &mut temp32a);
2553            let temp48len = fast_expansion_sum_zeroelim(
2554                &temp16a[..temp16alen],
2555                &temp32a[..temp32alen],
2556                &mut temp48,
2557            );
2558            finlength =
2559                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2560            core::mem::swap(&mut finnow, &mut finother);
2561            let temp32alen = scale_expansion_zeroelim(&bytcat[..bytcatlen], bdytail, &mut temp32a);
2562            let bytcattlen = scale_expansion_zeroelim(&catt[..cattlen], bdytail, &mut bytcatt);
2563            let temp16alen =
2564                scale_expansion_zeroelim(&bytcatt[..bytcattlen], 2.0 * bdy, &mut temp16a);
2565            let temp16blen =
2566                scale_expansion_zeroelim(&bytcatt[..bytcattlen], bdytail, &mut temp16b);
2567            let temp32blen = fast_expansion_sum_zeroelim(
2568                &temp16a[..temp16alen],
2569                &temp16b[..temp16blen],
2570                &mut temp32b,
2571            );
2572            let temp64len = fast_expansion_sum_zeroelim(
2573                &temp32a[..temp32alen],
2574                &temp32b[..temp32blen],
2575                &mut temp64,
2576            );
2577            finlength =
2578                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp64[..temp64len], finother);
2579            core::mem::swap(&mut finnow, &mut finother);
2580        }
2581    }
2582    if cdxtail != 0.0 || cdytail != 0.0 {
2583        let mut abtlen = 1;
2584        let mut abttlen = 1;
2585        let mut abt: [f64; 8] = [0.; 8];
2586        let mut abtt: [f64; 4] = [0.; 4];
2587        if adxtail != 0.0 || adytail != 0.0 || bdxtail != 0.0 || bdytail != 0.0 {
2588            let [ti0, ti1] = two_product(adxtail, bdy);
2589            let [tj0, tj1] = two_product(adx, bdytail);
2590            let u = two_two_sum(ti1, ti0, tj1, tj0);
2591            let negate = -ady;
2592            let [ti0, ti1] = two_product(bdxtail, negate);
2593            let negate = -adytail;
2594            let [tj0, tj1] = two_product(bdx, negate);
2595            let v = two_two_sum(ti1, ti0, tj1, tj0);
2596            abtlen = fast_expansion_sum_zeroelim(&u, &v, &mut abt);
2597            let [ti0, ti1] = two_product(adxtail, bdytail);
2598            let [tj0, tj1] = two_product(bdxtail, adytail);
2599            abtt = two_two_diff(ti1, ti0, tj1, tj0);
2600            abttlen = 4;
2601        }
2602        if cdxtail != 0.0 {
2603            let temp16alen = scale_expansion_zeroelim(&cxtab[..cxtablen], cdxtail, &mut temp16a);
2604            let cxtabtlen = scale_expansion_zeroelim(&abt[..abtlen], cdxtail, &mut cxtabt);
2605            let temp32alen =
2606                scale_expansion_zeroelim(&cxtabt[..cxtabtlen], 2.0 * cdx, &mut temp32a);
2607            let temp48len = fast_expansion_sum_zeroelim(
2608                &temp16a[..temp16alen],
2609                &temp32a[..temp32alen],
2610                &mut temp48,
2611            );
2612            finlength =
2613                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2614            core::mem::swap(&mut finnow, &mut finother);
2615            if adytail != 0.0 {
2616                let temp8len = scale_expansion_zeroelim(&bb, cdxtail, &mut temp8);
2617                let temp16alen =
2618                    scale_expansion_zeroelim(&temp8[..temp8len], adytail, &mut temp16a);
2619                finlength = fast_expansion_sum_zeroelim(
2620                    &finnow[..finlength],
2621                    &temp16a[..temp16alen],
2622                    finother,
2623                );
2624                core::mem::swap(&mut finnow, &mut finother);
2625            }
2626            if bdytail != 0.0 {
2627                let temp8len = scale_expansion_zeroelim(&aa, -cdxtail, &mut temp8);
2628                let temp16alen =
2629                    scale_expansion_zeroelim(&temp8[..temp8len], bdytail, &mut temp16a);
2630                finlength = fast_expansion_sum_zeroelim(
2631                    &finnow[..finlength],
2632                    &temp16a[..temp16alen],
2633                    finother,
2634                );
2635                core::mem::swap(&mut finnow, &mut finother);
2636            }
2637            let temp32alen = scale_expansion_zeroelim(&cxtabt[..cxtabtlen], cdxtail, &mut temp32a);
2638            let cxtabttlen = scale_expansion_zeroelim(&abtt[..abttlen], cdxtail, &mut cxtabtt);
2639            let temp16alen =
2640                scale_expansion_zeroelim(&cxtabtt[..cxtabttlen], 2.0 * cdx, &mut temp16a);
2641            let temp16blen =
2642                scale_expansion_zeroelim(&cxtabtt[..cxtabttlen], cdxtail, &mut temp16b);
2643            let temp32blen = fast_expansion_sum_zeroelim(
2644                &temp16a[..temp16alen],
2645                &temp16b[..temp16blen],
2646                &mut temp32b,
2647            );
2648            let temp64len = fast_expansion_sum_zeroelim(
2649                &temp32a[..temp32alen],
2650                &temp32b[..temp32blen],
2651                &mut temp64,
2652            );
2653            finlength =
2654                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp64[..temp64len], finother);
2655            core::mem::swap(&mut finnow, &mut finother);
2656        }
2657        if cdytail != 0.0 {
2658            let temp16alen = scale_expansion_zeroelim(&cytab[..cytablen], cdytail, &mut temp16a);
2659            let cytabtlen = scale_expansion_zeroelim(&abt[..abtlen], cdytail, &mut cytabt);
2660            let temp32alen =
2661                scale_expansion_zeroelim(&cytabt[..cytabtlen], 2.0 * cdy, &mut temp32a);
2662            let temp48len = fast_expansion_sum_zeroelim(
2663                &temp16a[..temp16alen],
2664                &temp32a[..temp32alen],
2665                &mut temp48,
2666            );
2667            finlength =
2668                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp48[..temp48len], finother);
2669            core::mem::swap(&mut finnow, &mut finother);
2670            let temp32alen = scale_expansion_zeroelim(&cytabt[..cytabtlen], cdytail, &mut temp32a);
2671            let cytabttlen = scale_expansion_zeroelim(&abtt[..abttlen], cdytail, &mut cytabtt);
2672            let temp16alen =
2673                scale_expansion_zeroelim(&cytabtt[..cytabttlen], 2.0 * cdy, &mut temp16a);
2674            let temp16blen =
2675                scale_expansion_zeroelim(&cytabtt[..cytabttlen], cdytail, &mut temp16b);
2676            let temp32blen = fast_expansion_sum_zeroelim(
2677                &temp16a[..temp16alen],
2678                &temp16b[..temp16blen],
2679                &mut temp32b,
2680            );
2681            let temp64len = fast_expansion_sum_zeroelim(
2682                &temp32a[..temp32alen],
2683                &temp32b[..temp32blen],
2684                &mut temp64,
2685            );
2686            finlength =
2687                fast_expansion_sum_zeroelim(&finnow[..finlength], &temp64[..temp64len], finother);
2688            core::mem::swap(&mut finnow, &mut finother);
2689        }
2690    }
2691    finnow[finlength - 1]
2692}
2693
2694/**
2695 * Adaptive exact 2D incircle test. Robust.
2696 *
2697 * Return a positive value if the point `pd` lies inside the
2698 * circle passing through `pa`, `pb`, and `pc`; a negative value if
2699 * it lies outside; and zero if the four points are cocircular.
2700 * The points `pa`, `pb`, and `pc` must be in counterclockwise
2701 * order, or the sign of the result will be reversed.
2702 *
2703 * The result returned is the determinant of a matrix.
2704 * This determinant is computed adaptively, in the sense that exact
2705 * arithmetic is used only to the degree it is needed to ensure that the
2706 * returned value has the correct sign.  Hence, `incircle()` is usually quite
2707 * fast, but will run more slowly when the input points are cocircular or
2708 * nearly so.
2709 */
2710#[inline]
2711pub fn incircle(pa: [f64; 2], pb: [f64; 2], pc: [f64; 2], pd: [f64; 2]) -> f64 {
2712    let adx = pa[0] - pd[0];
2713    let bdx = pb[0] - pd[0];
2714    let cdx = pc[0] - pd[0];
2715    let ady = pa[1] - pd[1];
2716    let bdy = pb[1] - pd[1];
2717    let cdy = pc[1] - pd[1];
2718    let bdxcdy = bdx * cdy;
2719    let cdxbdy = cdx * bdy;
2720    let alift = adx * adx + ady * ady;
2721    let cdxady = cdx * ady;
2722    let adxcdy = adx * cdy;
2723    let blift = bdx * bdx + bdy * bdy;
2724    let adxbdy = adx * bdy;
2725    let bdxady = bdx * ady;
2726    let clift = cdx * cdx + cdy * cdy;
2727    let det = alift * (bdxcdy - cdxbdy) + blift * (cdxady - adxcdy) + clift * (adxbdy - bdxady);
2728    let permanent = (abs(bdxcdy) + abs(cdxbdy)) * alift
2729        + (abs(cdxady) + abs(adxcdy)) * blift
2730        + (abs(adxbdy) + abs(bdxady)) * clift;
2731    let errbound = PARAMS.iccerrbound_a * permanent;
2732    if det > errbound || -det > errbound {
2733        return det;
2734    }
2735    incircleadapt(pa, pb, pc, pd, permanent)
2736}
2737
2738/* ****************************************************************************/
2739/*                                                                           */
2740/*  insphere_fast()   Approximate 3D insphere test.  Nonrobust.               */
2741/*  insphere_exact()   Exact 3D insphere test.  Robust.                       */
2742/*  insphere_slow()   Another exact 3D insphere test.  Robust.                */
2743/*  insphere()   Adaptive exact 3D insphere test.  Robust.                   */
2744/*                                                                           */
2745/*               Return a positive value if the point pe lies inside the     */
2746/*               sphere passing through pa, pb, pc, and pd; a negative value */
2747/*               if it lies outside; and zero if the five points are         */
2748/*               cospherical.  The points pa, pb, pc, and pd must be ordered */
2749/*               so that they have a positive orientation (as defined by     */
2750/*               orient3d()), or the sign of the result will be reversed.    */
2751/*                                                                           */
2752/*  Only the first and last routine should be used; the middle two are for   */
2753/*  timings.                                                                 */
2754/*                                                                           */
2755/*  The last three use exact arithmetic to ensure a correct answer.  The     */
2756/*  result returned is the determinant of a matrix.  In insphere() only,     */
2757/*  this determinant is computed adaptively, in the sense that exact         */
2758/*  arithmetic is used only to the degree it is needed to ensure that the    */
2759/*  returned value has the correct sign.  Hence, insphere() is usually quite */
2760/*  fast, but will run more slowly when the input points are cospherical or  */
2761/*  nearly so.                                                               */
2762/*                                                                           */
2763/* ****************************************************************************/
2764
2765/// Approximate 3D insphere test. Non-robust version of [`insphere`].
2766#[inline]
2767pub fn insphere_fast(pa: [f64; 3], pb: [f64; 3], pc: [f64; 3], pd: [f64; 3], pe: [f64; 3]) -> f64 {
2768    let aex = pa[0] - pe[0];
2769    let bex = pb[0] - pe[0];
2770    let cex = pc[0] - pe[0];
2771    let dex = pd[0] - pe[0];
2772    let aey = pa[1] - pe[1];
2773    let bey = pb[1] - pe[1];
2774    let cey = pc[1] - pe[1];
2775    let dey = pd[1] - pe[1];
2776    let aez = pa[2] - pe[2];
2777    let bez = pb[2] - pe[2];
2778    let cez = pc[2] - pe[2];
2779    let dez = pd[2] - pe[2];
2780    let ab = aex * bey - bex * aey;
2781    let bc = bex * cey - cex * bey;
2782    let cd = cex * dey - dex * cey;
2783    let da = dex * aey - aex * dey;
2784    let ac = aex * cey - cex * aey;
2785    let bd = bex * dey - dex * bey;
2786    let abc = aez * bc - bez * ac + cez * ab;
2787    let bcd = bez * cd - cez * bd + dez * bc;
2788    let cda = cez * da + dez * ac + aez * cd;
2789    let dab = dez * ab + aez * bd + bez * da;
2790    let alift = aex * aex + aey * aey + aez * aez;
2791    let blift = bex * bex + bey * bey + bez * bez;
2792    let clift = cex * cex + cey * cey + cez * cez;
2793    let dlift = dex * dex + dey * dey + dez * dez;
2794    dlift * abc - clift * dab + (blift * cda - alift * bcd)
2795}
2796
2797#[inline]
2798pub fn insphere_exact(pa: [f64; 3], pb: [f64; 3], pc: [f64; 3], pd: [f64; 3], pe: [f64; 3]) -> f64 {
2799    let mut temp8a = [0.; 8];
2800    let mut temp8b = [0.; 8];
2801    let mut temp16 = [0.; 16];
2802    let mut abc = [0.; 24];
2803    let mut bcd = [0.; 24];
2804    let mut cde = [0.; 24];
2805    let mut dea = [0.; 24];
2806    let mut eab = [0.; 24];
2807    let mut abd = [0.; 24];
2808    let mut bce = [0.; 24];
2809    let mut cda = [0.; 24];
2810    let mut deb = [0.; 24];
2811    let mut eac = [0.; 24];
2812    let mut temp48a = [0.; 48];
2813    let mut temp48b = [0.; 48];
2814    let mut abcd = [0.; 96];
2815    let mut bcde = [0.; 96];
2816    let mut cdea = [0.; 96];
2817    let mut deab = [0.; 96];
2818    let mut eabc = [0.; 96];
2819    let mut temp192 = [0.; 192];
2820    let mut det384x = [0.; 384];
2821    let mut det384y = [0.; 384];
2822    let mut det384z = [0.; 384];
2823    let mut detxy = [0.; 768];
2824    let mut adet = [0.; 1152];
2825    let mut bdet = [0.; 1152];
2826    let mut cdet = [0.; 1152];
2827    let mut ddet = [0.; 1152];
2828    let mut edet = [0.; 1152];
2829    let mut abdet = [0.; 2304];
2830    let mut cddet = [0.; 2304];
2831    let mut cdedet = [0.; 3456];
2832    let [axby0, axby1] = two_product(pa[0], pb[1]);
2833    let [bxay0, bxay1] = two_product(pb[0], pa[1]);
2834    let ab = two_two_diff(axby1, axby0, bxay1, bxay0);
2835    let [bxcy0, bxcy1] = two_product(pb[0], pc[1]);
2836    let [cxby0, cxby1] = two_product(pc[0], pb[1]);
2837    let bc = two_two_diff(bxcy1, bxcy0, cxby1, cxby0);
2838    let [cxdy0, cxdy1] = two_product(pc[0], pd[1]);
2839    let [dxcy0, dxcy1] = two_product(pd[0], pc[1]);
2840    let cd = two_two_diff(cxdy1, cxdy0, dxcy1, dxcy0);
2841    let [dxey0, dxey1] = two_product(pd[0], pe[1]);
2842    let [exdy0, exdy1] = two_product(pe[0], pd[1]);
2843    let de = two_two_diff(dxey1, dxey0, exdy1, exdy0);
2844    let [exay0, exay1] = two_product(pe[0], pa[1]);
2845    let [axey0, axey1] = two_product(pa[0], pe[1]);
2846    let ea = two_two_diff(exay1, exay0, axey1, axey0);
2847    let [axcy0, axcy1] = two_product(pa[0], pc[1]);
2848    let [cxay0, cxay1] = two_product(pc[0], pa[1]);
2849    let ac = two_two_diff(axcy1, axcy0, cxay1, cxay0);
2850    let [bxdy0, bxdy1] = two_product(pb[0], pd[1]);
2851    let [dxby0, dxby1] = two_product(pd[0], pb[1]);
2852    let bd = two_two_diff(bxdy1, bxdy0, dxby1, dxby0);
2853    let [cxey0, cxey1] = two_product(pc[0], pe[1]);
2854    let [excy0, excy1] = two_product(pe[0], pc[1]);
2855    let ce = two_two_diff(cxey1, cxey0, excy1, excy0);
2856    let [dxay0, dxay1] = two_product(pd[0], pa[1]);
2857    let [axdy0, axdy1] = two_product(pa[0], pd[1]);
2858    let da = two_two_diff(dxay1, dxay0, axdy1, axdy0);
2859    let [exby0, exby1] = two_product(pe[0], pb[1]);
2860    let [bxey0, bxey1] = two_product(pb[0], pe[1]);
2861    let eb = two_two_diff(exby1, exby0, bxey1, bxey0);
2862    let temp8alen = scale_expansion_zeroelim(&bc, pa[2], &mut temp8a);
2863    let temp8blen = scale_expansion_zeroelim(&ac, -pb[2], &mut temp8b);
2864    let temp16len =
2865        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
2866    let temp8alen = scale_expansion_zeroelim(&ab, pc[2], &mut temp8a);
2867    let abclen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut abc);
2868    let temp8alen = scale_expansion_zeroelim(&cd, pb[2], &mut temp8a);
2869    let temp8blen = scale_expansion_zeroelim(&bd, -pc[2], &mut temp8b);
2870    let temp16len =
2871        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
2872    let temp8alen = scale_expansion_zeroelim(&bc, pd[2], &mut temp8a);
2873    let bcdlen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut bcd);
2874    let temp8alen = scale_expansion_zeroelim(&de, pc[2], &mut temp8a);
2875    let temp8blen = scale_expansion_zeroelim(&ce, -pd[2], &mut temp8b);
2876    let temp16len =
2877        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
2878    let temp8alen = scale_expansion_zeroelim(&cd, pe[2], &mut temp8a);
2879    let cdelen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut cde);
2880    let temp8alen = scale_expansion_zeroelim(&ea, pd[2], &mut temp8a);
2881    let temp8blen = scale_expansion_zeroelim(&da, -pe[2], &mut temp8b);
2882    let temp16len =
2883        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
2884    let temp8alen = scale_expansion_zeroelim(&de, pa[2], &mut temp8a);
2885    let dealen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut dea);
2886    let temp8alen = scale_expansion_zeroelim(&ab, pe[2], &mut temp8a);
2887    let temp8blen = scale_expansion_zeroelim(&eb, -pa[2], &mut temp8b);
2888    let temp16len =
2889        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
2890    let temp8alen = scale_expansion_zeroelim(&ea, pb[2], &mut temp8a);
2891    let eablen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut eab);
2892    let temp8alen = scale_expansion_zeroelim(&bd, pa[2], &mut temp8a);
2893    let temp8blen = scale_expansion_zeroelim(&da, pb[2], &mut temp8b);
2894    let temp16len =
2895        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
2896    let temp8alen = scale_expansion_zeroelim(&ab, pd[2], &mut temp8a);
2897    let abdlen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut abd);
2898    let temp8alen = scale_expansion_zeroelim(&ce, pb[2], &mut temp8a);
2899    let temp8blen = scale_expansion_zeroelim(&eb, pc[2], &mut temp8b);
2900    let temp16len =
2901        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
2902    let temp8alen = scale_expansion_zeroelim(&bc, pe[2], &mut temp8a);
2903    let bcelen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut bce);
2904    let temp8alen = scale_expansion_zeroelim(&da, pc[2], &mut temp8a);
2905    let temp8blen = scale_expansion_zeroelim(&ac, pd[2], &mut temp8b);
2906    let temp16len =
2907        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
2908    let temp8alen = scale_expansion_zeroelim(&cd, pa[2], &mut temp8a);
2909    let cdalen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut cda);
2910    let temp8alen = scale_expansion_zeroelim(&eb, pd[2], &mut temp8a);
2911    let temp8blen = scale_expansion_zeroelim(&bd, pe[2], &mut temp8b);
2912    let temp16len =
2913        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
2914    let temp8alen = scale_expansion_zeroelim(&de, pb[2], &mut temp8a);
2915    let deblen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut deb);
2916    let temp8alen = scale_expansion_zeroelim(&ac, pe[2], &mut temp8a);
2917    let temp8blen = scale_expansion_zeroelim(&ce, pa[2], &mut temp8b);
2918    let temp16len =
2919        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
2920    let temp8alen = scale_expansion_zeroelim(&ea, pc[2], &mut temp8a);
2921    let eaclen = fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp16[..temp16len], &mut eac);
2922    let temp48alen = fast_expansion_sum_zeroelim(&cde[..cdelen], &bce[..bcelen], &mut temp48a);
2923    let temp48blen = fast_expansion_sum_zeroelim(&deb[..deblen], &bcd[..bcdlen], &mut temp48b);
2924    temp48b[..temp48blen].iter_mut().for_each(|x| *x = -*x);
2925    let bcdelen =
2926        fast_expansion_sum_zeroelim(&temp48a[..temp48alen], &temp48b[..temp48blen], &mut bcde);
2927    let xlen = scale_expansion_zeroelim(&bcde[..bcdelen], pa[0], &mut temp192);
2928    let xlen = scale_expansion_zeroelim(&temp192[..xlen], pa[0], &mut det384x);
2929    let ylen = scale_expansion_zeroelim(&bcde[..bcdelen], pa[1], &mut temp192);
2930    let ylen = scale_expansion_zeroelim(&temp192[..ylen], pa[1], &mut det384y);
2931    let zlen = scale_expansion_zeroelim(&bcde[..bcdelen], pa[2], &mut temp192);
2932    let zlen = scale_expansion_zeroelim(&temp192[..zlen], pa[2], &mut det384z);
2933    let xylen = fast_expansion_sum_zeroelim(&det384x[..xlen], &det384y[..ylen], &mut detxy);
2934    let alen = fast_expansion_sum_zeroelim(&detxy[..xylen], &det384z[..zlen], &mut adet);
2935    let temp48alen = fast_expansion_sum_zeroelim(&dea[..dealen], &cda[..cdalen], &mut temp48a);
2936    let temp48blen = fast_expansion_sum_zeroelim(&eac[..eaclen], &cde[..cdelen], &mut temp48b);
2937    temp48b[..temp48blen].iter_mut().for_each(|x| *x = -*x);
2938    let cdealen =
2939        fast_expansion_sum_zeroelim(&temp48a[..temp48alen], &temp48b[..temp48blen], &mut cdea);
2940    let xlen = scale_expansion_zeroelim(&cdea[..cdealen], pb[0], &mut temp192);
2941    let xlen = scale_expansion_zeroelim(&temp192[..xlen], pb[0], &mut det384x);
2942    let ylen = scale_expansion_zeroelim(&cdea[..cdealen], pb[1], &mut temp192);
2943    let ylen = scale_expansion_zeroelim(&temp192[..ylen], pb[1], &mut det384y);
2944    let zlen = scale_expansion_zeroelim(&cdea[..cdealen], pb[2], &mut temp192);
2945    let zlen = scale_expansion_zeroelim(&temp192[..zlen], pb[2], &mut det384z);
2946    let xylen = fast_expansion_sum_zeroelim(&det384x[..xlen], &det384y[..ylen], &mut detxy);
2947    let blen = fast_expansion_sum_zeroelim(&detxy[..xylen], &det384z[..zlen], &mut bdet);
2948    let temp48alen = fast_expansion_sum_zeroelim(&eab[..eablen], &deb[..deblen], &mut temp48a);
2949    let temp48blen = fast_expansion_sum_zeroelim(&abd[..abdlen], &dea[..dealen], &mut temp48b);
2950    temp48b[..temp48blen].iter_mut().for_each(|x| *x = -*x);
2951    let deablen =
2952        fast_expansion_sum_zeroelim(&temp48a[..temp48alen], &temp48b[..temp48blen], &mut deab);
2953    let xlen = scale_expansion_zeroelim(&deab[..deablen], pc[0], &mut temp192);
2954    let xlen = scale_expansion_zeroelim(&temp192[..xlen], pc[0], &mut det384x);
2955    let ylen = scale_expansion_zeroelim(&deab[..deablen], pc[1], &mut temp192);
2956    let ylen = scale_expansion_zeroelim(&temp192[..ylen], pc[1], &mut det384y);
2957    let zlen = scale_expansion_zeroelim(&deab[..deablen], pc[2], &mut temp192);
2958    let zlen = scale_expansion_zeroelim(&temp192[..zlen], pc[2], &mut det384z);
2959    let xylen = fast_expansion_sum_zeroelim(&det384x[..xlen], &det384y[..ylen], &mut detxy);
2960    let clen = fast_expansion_sum_zeroelim(&detxy[..xylen], &det384z[..zlen], &mut cdet);
2961    let temp48alen = fast_expansion_sum_zeroelim(&abc[..abclen], &eac[..eaclen], &mut temp48a);
2962    let temp48blen = fast_expansion_sum_zeroelim(&bce[..bcelen], &eab[..eablen], &mut temp48b);
2963    temp48b[..temp48blen].iter_mut().for_each(|x| *x = -*x);
2964    let eabclen =
2965        fast_expansion_sum_zeroelim(&temp48a[..temp48alen], &temp48b[..temp48blen], &mut eabc);
2966    let xlen = scale_expansion_zeroelim(&eabc[..eabclen], pd[0], &mut temp192);
2967    let xlen = scale_expansion_zeroelim(&temp192[..xlen], pd[0], &mut det384x);
2968    let ylen = scale_expansion_zeroelim(&eabc[..eabclen], pd[1], &mut temp192);
2969    let ylen = scale_expansion_zeroelim(&temp192[..ylen], pd[1], &mut det384y);
2970    let zlen = scale_expansion_zeroelim(&eabc[..eabclen], pd[2], &mut temp192);
2971    let zlen = scale_expansion_zeroelim(&temp192[..zlen], pd[2], &mut det384z);
2972    let xylen = fast_expansion_sum_zeroelim(&det384x[..xlen], &det384y[..ylen], &mut detxy);
2973    let dlen = fast_expansion_sum_zeroelim(&detxy[..xylen], &det384z[..zlen], &mut ddet);
2974    let temp48alen = fast_expansion_sum_zeroelim(&bcd[..bcdlen], &abd[..abdlen], &mut temp48a);
2975    let temp48blen = fast_expansion_sum_zeroelim(&cda[..cdalen], &abc[..abclen], &mut temp48b);
2976    temp48b[..temp48blen].iter_mut().for_each(|x| *x = -*x);
2977    let abcdlen =
2978        fast_expansion_sum_zeroelim(&temp48a[..temp48alen], &temp48b[..temp48blen], &mut abcd);
2979    let xlen = scale_expansion_zeroelim(&abcd[..abcdlen], pe[0], &mut temp192);
2980    let xlen = scale_expansion_zeroelim(&temp192[..xlen], pe[0], &mut det384x);
2981    let ylen = scale_expansion_zeroelim(&abcd[..abcdlen], pe[1], &mut temp192);
2982    let ylen = scale_expansion_zeroelim(&temp192[..ylen], pe[1], &mut det384y);
2983    let zlen = scale_expansion_zeroelim(&abcd[..abcdlen], pe[2], &mut temp192);
2984    let zlen = scale_expansion_zeroelim(&temp192[..zlen], pe[2], &mut det384z);
2985    let xylen = fast_expansion_sum_zeroelim(&det384x[..xlen], &det384y[..ylen], &mut detxy);
2986    let elen = fast_expansion_sum_zeroelim(&detxy[..xylen], &det384z[..zlen], &mut edet);
2987    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
2988    let cdlen = fast_expansion_sum_zeroelim(&cdet[..clen], &ddet[..dlen], &mut cddet);
2989    let cdelen = fast_expansion_sum_zeroelim(&cddet[..cdlen], &edet[..elen], &mut cdedet);
2990    let mut deter = [0.; 5760];
2991    let deterlen = fast_expansion_sum_zeroelim(&abdet[..ablen], &cdedet[..cdelen], &mut deter);
2992    deter[deterlen - 1]
2993}
2994
2995#[inline]
2996pub fn insphere_slow(pa: [f64; 3], pb: [f64; 3], pc: [f64; 3], pd: [f64; 3], pe: [f64; 3]) -> f64 {
2997    let mut ab = [0.; 16];
2998    let mut bc = [0.; 16];
2999    let mut cd = [0.; 16];
3000    let mut da = [0.; 16];
3001    let mut ac = [0.; 16];
3002    let mut bd = [0.; 16];
3003    let mut temp32a = [0.; 32];
3004    let mut temp32b = [0.; 32];
3005    let mut temp64a = [0.; 64];
3006    let mut temp64b = [0.; 64];
3007    let mut temp64c = [0.; 64];
3008    let mut temp128 = [0.; 128];
3009    let mut temp192 = [0.; 192];
3010    let mut detx = [0.; 384];
3011    let mut detxx = [0.; 768];
3012    let mut detxt = [0.; 384];
3013    let mut detxxt = [0.; 768];
3014    let mut detxtxt = [0.; 768];
3015    let mut x1 = [0.; 1536];
3016    let mut x2 = [0.; 2304];
3017    let mut dety = [0.; 384];
3018    let mut detyy = [0.; 768];
3019    let mut detyt = [0.; 384];
3020    let mut detyyt = [0.; 768];
3021    let mut detytyt = [0.; 768];
3022    let mut y1 = [0.; 1536];
3023    let mut y2 = [0.; 2304];
3024    let mut detz = [0.; 384];
3025    let mut detzz = [0.; 768];
3026    let mut detzt = [0.; 384];
3027    let mut detzzt = [0.; 768];
3028    let mut detztzt = [0.; 768];
3029    let mut z1 = [0.; 1536];
3030    let mut z2 = [0.; 2304];
3031    let mut detxy = [0.; 4608];
3032    let mut adet = [0.; 6912];
3033    let mut bdet = [0.; 6912];
3034    let mut cdet = [0.; 6912];
3035    let mut ddet = [0.; 6912];
3036    let mut abdet = [0.; 13824];
3037    let mut cddet = [0.; 13824];
3038    let mut deter = [0.; 27648];
3039    let [aextail, aex] = two_diff(pa[0], pe[0]);
3040    let [aeytail, aey] = two_diff(pa[1], pe[1]);
3041    let [aeztail, aez] = two_diff(pa[2], pe[2]);
3042    let [bextail, bex] = two_diff(pb[0], pe[0]);
3043    let [beytail, bey] = two_diff(pb[1], pe[1]);
3044    let [beztail, bez] = two_diff(pb[2], pe[2]);
3045    let [cextail, cex] = two_diff(pc[0], pe[0]);
3046    let [ceytail, cey] = two_diff(pc[1], pe[1]);
3047    let [ceztail, cez] = two_diff(pc[2], pe[2]);
3048    let [dextail, dex] = two_diff(pd[0], pe[0]);
3049    let [deytail, dey] = two_diff(pd[1], pe[1]);
3050    let [deztail, dez] = two_diff(pd[2], pe[2]);
3051    let axby = two_two_product(aex, aextail, bey, beytail);
3052    let negate = -aey;
3053    let negatetail = -aeytail;
3054    let bxay = two_two_product(bex, bextail, negate, negatetail);
3055    let ablen = fast_expansion_sum_zeroelim(&axby, &bxay, &mut ab);
3056    let bxcy = two_two_product(bex, bextail, cey, ceytail);
3057    let negate = -bey;
3058    let negatetail = -beytail;
3059    let cxby = two_two_product(cex, cextail, negate, negatetail);
3060    let bclen = fast_expansion_sum_zeroelim(&bxcy, &cxby, &mut bc);
3061    let cxdy = two_two_product(cex, cextail, dey, deytail);
3062    let negate = -cey;
3063    let negatetail = -ceytail;
3064    let dxcy = two_two_product(dex, dextail, negate, negatetail);
3065    let cdlen = fast_expansion_sum_zeroelim(&cxdy, &dxcy, &mut cd);
3066    let dxay = two_two_product(dex, dextail, aey, aeytail);
3067    let negate = -dey;
3068    let negatetail = -deytail;
3069    let axdy = two_two_product(aex, aextail, negate, negatetail);
3070    let dalen = fast_expansion_sum_zeroelim(&dxay, &axdy, &mut da);
3071    let axcy = two_two_product(aex, aextail, cey, ceytail);
3072    let negate = -aey;
3073    let negatetail = -aeytail;
3074    let cxay = two_two_product(cex, cextail, negate, negatetail);
3075    let aclen = fast_expansion_sum_zeroelim(&axcy, &cxay, &mut ac);
3076    let bxdy = two_two_product(bex, bextail, dey, deytail);
3077    let negate = -bey;
3078    let negatetail = -beytail;
3079    let dxby = two_two_product(dex, dextail, negate, negatetail);
3080    let bdlen = fast_expansion_sum_zeroelim(&bxdy, &dxby, &mut bd);
3081    let temp32alen = scale_expansion_zeroelim(&cd[..cdlen], -bez, &mut temp32a);
3082    let temp32blen = scale_expansion_zeroelim(&cd[..cdlen], -beztail, &mut temp32b);
3083    let temp64alen =
3084        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64a);
3085    let temp32alen = scale_expansion_zeroelim(&bd[..bdlen], cez, &mut temp32a);
3086    let temp32blen = scale_expansion_zeroelim(&bd[..bdlen], ceztail, &mut temp32b);
3087    let temp64blen =
3088        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64b);
3089    let temp32alen = scale_expansion_zeroelim(&bc[..bclen], -dez, &mut temp32a);
3090    let temp32blen = scale_expansion_zeroelim(&bc[..bclen], -deztail, &mut temp32b);
3091    let temp64clen =
3092        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64c);
3093    let temp128len =
3094        fast_expansion_sum_zeroelim(&temp64a[..temp64alen], &temp64b[..temp64blen], &mut temp128);
3095    let temp192len =
3096        fast_expansion_sum_zeroelim(&temp64c[..temp64clen], &temp128[..temp128len], &mut temp192);
3097    let xlen = scale_expansion_zeroelim(&temp192[..temp192len], aex, &mut detx);
3098    let xxlen = scale_expansion_zeroelim(&detx[..xlen], aex, &mut detxx);
3099    let xtlen = scale_expansion_zeroelim(&temp192[..temp192len], aextail, &mut detxt);
3100    let xxtlen = scale_expansion_zeroelim(&detxt[..xtlen], aex, &mut detxxt);
3101    detxxt[..xxtlen].iter_mut().for_each(|x| *x *= 2.0);
3102    let xtxtlen = scale_expansion_zeroelim(&detxt[..xtlen], aextail, &mut detxtxt);
3103    let x1len = fast_expansion_sum_zeroelim(&detxx[..xxlen], &detxxt[..xxtlen], &mut x1);
3104    let x2len = fast_expansion_sum_zeroelim(&x1[..x1len], &detxtxt[..xtxtlen], &mut x2);
3105    let ylen = scale_expansion_zeroelim(&temp192[..temp192len], aey, &mut dety);
3106    let yylen = scale_expansion_zeroelim(&dety[..ylen], aey, &mut detyy);
3107    let ytlen = scale_expansion_zeroelim(&temp192[..temp192len], aeytail, &mut detyt);
3108    let yytlen = scale_expansion_zeroelim(&detyt[..ytlen], aey, &mut detyyt);
3109    detyyt[..yytlen].iter_mut().for_each(|x| *x *= 2.0);
3110    let ytytlen = scale_expansion_zeroelim(&detyt[..ytlen], aeytail, &mut detytyt);
3111    let y1len = fast_expansion_sum_zeroelim(&detyy[..yylen], &detyyt[..yytlen], &mut y1);
3112    let y2len = fast_expansion_sum_zeroelim(&y1[..y1len], &detytyt[..ytytlen], &mut y2);
3113    let zlen = scale_expansion_zeroelim(&temp192[..temp192len], aez, &mut detz);
3114    let zzlen = scale_expansion_zeroelim(&detz[..zlen], aez, &mut detzz);
3115    let ztlen = scale_expansion_zeroelim(&temp192[..temp192len], aeztail, &mut detzt);
3116    let zztlen = scale_expansion_zeroelim(&detzt[..ztlen], aez, &mut detzzt);
3117    detzzt[..zztlen].iter_mut().for_each(|x| *x *= 2.0);
3118    let ztztlen = scale_expansion_zeroelim(&detzt[..ztlen], aeztail, &mut detztzt);
3119    let z1len = fast_expansion_sum_zeroelim(&detzz[..zzlen], &detzzt[..zztlen], &mut z1);
3120    let z2len = fast_expansion_sum_zeroelim(&z1[..z1len], &detztzt[..ztztlen], &mut z2);
3121    let xylen = fast_expansion_sum_zeroelim(&x2[..x2len], &y2[..y2len], &mut detxy);
3122    let alen = fast_expansion_sum_zeroelim(&z2[..z2len], &detxy[..xylen], &mut adet);
3123    let temp32alen = scale_expansion_zeroelim(&da[..dalen], cez, &mut temp32a);
3124    let temp32blen = scale_expansion_zeroelim(&da[..dalen], ceztail, &mut temp32b);
3125    let temp64alen =
3126        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64a);
3127    let temp32alen = scale_expansion_zeroelim(&ac[..aclen], dez, &mut temp32a);
3128    let temp32blen = scale_expansion_zeroelim(&ac[..aclen], deztail, &mut temp32b);
3129    let temp64blen =
3130        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64b);
3131    let temp32alen = scale_expansion_zeroelim(&cd[..cdlen], aez, &mut temp32a);
3132    let temp32blen = scale_expansion_zeroelim(&cd[..cdlen], aeztail, &mut temp32b);
3133    let temp64clen =
3134        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64c);
3135    let temp128len =
3136        fast_expansion_sum_zeroelim(&temp64a[..temp64alen], &temp64b[..temp64blen], &mut temp128);
3137    let temp192len =
3138        fast_expansion_sum_zeroelim(&temp64c[..temp64clen], &temp128[..temp128len], &mut temp192);
3139    let xlen = scale_expansion_zeroelim(&temp192[..temp192len], bex, &mut detx);
3140    let xxlen = scale_expansion_zeroelim(&detx[..xlen], bex, &mut detxx);
3141    let xtlen = scale_expansion_zeroelim(&temp192[..temp192len], bextail, &mut detxt);
3142    let xxtlen = scale_expansion_zeroelim(&detxt[..xtlen], bex, &mut detxxt);
3143    detxxt[..xxtlen].iter_mut().for_each(|x| *x *= 2.0);
3144    let xtxtlen = scale_expansion_zeroelim(&detxt[..xtlen], bextail, &mut detxtxt);
3145    let x1len = fast_expansion_sum_zeroelim(&detxx[..xxlen], &detxxt[..xxtlen], &mut x1);
3146    let x2len = fast_expansion_sum_zeroelim(&x1[..x1len], &detxtxt[..xtxtlen], &mut x2);
3147    let ylen = scale_expansion_zeroelim(&temp192[..temp192len], bey, &mut dety);
3148    let yylen = scale_expansion_zeroelim(&dety[..ylen], bey, &mut detyy);
3149    let ytlen = scale_expansion_zeroelim(&temp192[..temp192len], beytail, &mut detyt);
3150    let yytlen = scale_expansion_zeroelim(&detyt[..ytlen], bey, &mut detyyt);
3151    detyyt[..yytlen].iter_mut().for_each(|x| *x *= 2.0);
3152    let ytytlen = scale_expansion_zeroelim(&detyt[..ytlen], beytail, &mut detytyt);
3153    let y1len = fast_expansion_sum_zeroelim(&detyy[..yylen], &detyyt[..yytlen], &mut y1);
3154    let y2len = fast_expansion_sum_zeroelim(&y1[..y1len], &detytyt[..ytytlen], &mut y2);
3155    let zlen = scale_expansion_zeroelim(&temp192[..temp192len], bez, &mut detz);
3156    let zzlen = scale_expansion_zeroelim(&detz[..zlen], bez, &mut detzz);
3157    let ztlen = scale_expansion_zeroelim(&temp192[..temp192len], beztail, &mut detzt);
3158    let zztlen = scale_expansion_zeroelim(&detzt[..ztlen], bez, &mut detzzt);
3159    detzzt[..zztlen].iter_mut().for_each(|x| *x *= 2.0);
3160    let ztztlen = scale_expansion_zeroelim(&detzt[..ztlen], beztail, &mut detztzt);
3161    let z1len = fast_expansion_sum_zeroelim(&detzz[..zzlen], &detzzt[..zztlen], &mut z1);
3162    let z2len = fast_expansion_sum_zeroelim(&z1[..z1len], &detztzt[..ztztlen], &mut z2);
3163    let xylen = fast_expansion_sum_zeroelim(&x2[..x2len], &y2[..y2len], &mut detxy);
3164    let blen = fast_expansion_sum_zeroelim(&z2[..z2len], &detxy[..xylen], &mut bdet);
3165    let temp32alen = scale_expansion_zeroelim(&ab[..ablen], -dez, &mut temp32a);
3166    let temp32blen = scale_expansion_zeroelim(&ab[..ablen], -deztail, &mut temp32b);
3167    let temp64alen =
3168        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64a);
3169    let temp32alen = scale_expansion_zeroelim(&bd[..bdlen], -aez, &mut temp32a);
3170    let temp32blen = scale_expansion_zeroelim(&bd[..bdlen], -aeztail, &mut temp32b);
3171    let temp64blen =
3172        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64b);
3173    let temp32alen = scale_expansion_zeroelim(&da[..dalen], -bez, &mut temp32a);
3174    let temp32blen = scale_expansion_zeroelim(&da[..dalen], -beztail, &mut temp32b);
3175    let temp64clen =
3176        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64c);
3177    let temp128len =
3178        fast_expansion_sum_zeroelim(&temp64a[..temp64alen], &temp64b[..temp64blen], &mut temp128);
3179    let temp192len =
3180        fast_expansion_sum_zeroelim(&temp64c[..temp64clen], &temp128[..temp128len], &mut temp192);
3181    let xlen = scale_expansion_zeroelim(&temp192[..temp192len], cex, &mut detx);
3182    let xxlen = scale_expansion_zeroelim(&detx[..xlen], cex, &mut detxx);
3183    let xtlen = scale_expansion_zeroelim(&temp192[..temp192len], cextail, &mut detxt);
3184    let xxtlen = scale_expansion_zeroelim(&detxt[..xtlen], cex, &mut detxxt);
3185    detxxt[..xxtlen].iter_mut().for_each(|x| *x *= 2.0);
3186    let xtxtlen = scale_expansion_zeroelim(&detxt[..xtlen], cextail, &mut detxtxt);
3187    let x1len = fast_expansion_sum_zeroelim(&detxx[..xxlen], &detxxt[..xxtlen], &mut x1);
3188    let x2len = fast_expansion_sum_zeroelim(&x1[..x1len], &detxtxt[..xtxtlen], &mut x2);
3189    let ylen = scale_expansion_zeroelim(&temp192[..temp192len], cey, &mut dety);
3190    let yylen = scale_expansion_zeroelim(&dety[..ylen], cey, &mut detyy);
3191    let ytlen = scale_expansion_zeroelim(&temp192[..temp192len], ceytail, &mut detyt);
3192    let yytlen = scale_expansion_zeroelim(&detyt[..ytlen], cey, &mut detyyt);
3193    detyyt[..yytlen].iter_mut().for_each(|x| *x *= 2.0);
3194    let ytytlen = scale_expansion_zeroelim(&detyt[..ytlen], ceytail, &mut detytyt);
3195    let y1len = fast_expansion_sum_zeroelim(&detyy[..yylen], &detyyt[..yytlen], &mut y1);
3196    let y2len = fast_expansion_sum_zeroelim(&y1[..y1len], &detytyt[..ytytlen], &mut y2);
3197    let zlen = scale_expansion_zeroelim(&temp192[..temp192len], cez, &mut detz);
3198    let zzlen = scale_expansion_zeroelim(&detz[..zlen], cez, &mut detzz);
3199    let ztlen = scale_expansion_zeroelim(&temp192[..temp192len], ceztail, &mut detzt);
3200    let zztlen = scale_expansion_zeroelim(&detzt[..ztlen], cez, &mut detzzt);
3201    detzzt[..zztlen].iter_mut().for_each(|x| *x *= 2.0);
3202    let ztztlen = scale_expansion_zeroelim(&detzt[..ztlen], ceztail, &mut detztzt);
3203    let z1len = fast_expansion_sum_zeroelim(&detzz[..zzlen], &detzzt[..zztlen], &mut z1);
3204    let z2len = fast_expansion_sum_zeroelim(&z1[..z1len], &detztzt[..ztztlen], &mut z2);
3205    let xylen = fast_expansion_sum_zeroelim(&x2[..x2len], &y2[..y2len], &mut detxy);
3206    let clen = fast_expansion_sum_zeroelim(&z2[..z2len], &detxy[..xylen], &mut cdet);
3207    let temp32alen = scale_expansion_zeroelim(&bc[..bclen], aez, &mut temp32a);
3208    let temp32blen = scale_expansion_zeroelim(&bc[..bclen], aeztail, &mut temp32b);
3209    let temp64alen =
3210        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64a);
3211    let temp32alen = scale_expansion_zeroelim(&ac[..aclen], -bez, &mut temp32a);
3212    let temp32blen = scale_expansion_zeroelim(&ac[..aclen], -beztail, &mut temp32b);
3213    let temp64blen =
3214        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64b);
3215    let temp32alen = scale_expansion_zeroelim(&ab[..ablen], cez, &mut temp32a);
3216    let temp32blen = scale_expansion_zeroelim(&ab[..ablen], ceztail, &mut temp32b);
3217    let temp64clen =
3218        fast_expansion_sum_zeroelim(&temp32a[..temp32alen], &temp32b[..temp32blen], &mut temp64c);
3219    let temp128len =
3220        fast_expansion_sum_zeroelim(&temp64a[..temp64alen], &temp64b[..temp64blen], &mut temp128);
3221    let temp192len =
3222        fast_expansion_sum_zeroelim(&temp64c[..temp64clen], &temp128[..temp128len], &mut temp192);
3223    let xlen = scale_expansion_zeroelim(&temp192[..temp192len], dex, &mut detx);
3224    let xxlen = scale_expansion_zeroelim(&detx[..xlen], dex, &mut detxx);
3225    let xtlen = scale_expansion_zeroelim(&temp192[..temp192len], dextail, &mut detxt);
3226    let xxtlen = scale_expansion_zeroelim(&detxt[..xtlen], dex, &mut detxxt);
3227    detxxt[..xxtlen].iter_mut().for_each(|x| *x *= 2.0);
3228    let xtxtlen = scale_expansion_zeroelim(&detxt[..xtlen], dextail, &mut detxtxt);
3229    let x1len = fast_expansion_sum_zeroelim(&detxx[..xxlen], &detxxt[..xxtlen], &mut x1);
3230    let x2len = fast_expansion_sum_zeroelim(&x1[..x1len], &detxtxt[..xtxtlen], &mut x2);
3231    let ylen = scale_expansion_zeroelim(&temp192[..temp192len], dey, &mut dety);
3232    let yylen = scale_expansion_zeroelim(&dety[..ylen], dey, &mut detyy);
3233    let ytlen = scale_expansion_zeroelim(&temp192[..temp192len], deytail, &mut detyt);
3234    let yytlen = scale_expansion_zeroelim(&detyt[..ytlen], dey, &mut detyyt);
3235    detyyt[..yytlen].iter_mut().for_each(|x| *x *= 2.0);
3236    let ytytlen = scale_expansion_zeroelim(&detyt[..ytlen], deytail, &mut detytyt);
3237    let y1len = fast_expansion_sum_zeroelim(&detyy[..yylen], &detyyt[..yytlen], &mut y1);
3238    let y2len = fast_expansion_sum_zeroelim(&y1[..y1len], &detytyt[..ytytlen], &mut y2);
3239    let zlen = scale_expansion_zeroelim(&temp192[..temp192len], dez, &mut detz);
3240    let zzlen = scale_expansion_zeroelim(&detz[..zlen], dez, &mut detzz);
3241    let ztlen = scale_expansion_zeroelim(&temp192[..temp192len], deztail, &mut detzt);
3242    let zztlen = scale_expansion_zeroelim(&detzt[..ztlen], dez, &mut detzzt);
3243    detzzt[..zztlen].iter_mut().for_each(|x| *x *= 2.0);
3244    let ztztlen = scale_expansion_zeroelim(&detzt[..ztlen], deztail, &mut detztzt);
3245    let z1len = fast_expansion_sum_zeroelim(&detzz[..zzlen], &detzzt[..zztlen], &mut z1);
3246    let z2len = fast_expansion_sum_zeroelim(&z1[..z1len], &detztzt[..ztztlen], &mut z2);
3247    let xylen = fast_expansion_sum_zeroelim(&x2[..x2len], &y2[..y2len], &mut detxy);
3248    let dlen = fast_expansion_sum_zeroelim(&z2[..z2len], &detxy[..xylen], &mut ddet);
3249    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
3250    let cdlen = fast_expansion_sum_zeroelim(&cdet[..clen], &ddet[..dlen], &mut cddet);
3251    let deterlen = fast_expansion_sum_zeroelim(&abdet[..ablen], &cddet[..cdlen], &mut deter);
3252    deter[deterlen - 1]
3253}
3254
3255#[inline]
3256pub fn insphereadapt(
3257    pa: [f64; 3],
3258    pb: [f64; 3],
3259    pc: [f64; 3],
3260    pd: [f64; 3],
3261    pe: [f64; 3],
3262    permanent: f64,
3263) -> f64 {
3264    let mut temp8a: [f64; 8] = [0.; 8];
3265    let mut temp8b: [f64; 8] = [0.; 8];
3266    let mut temp8c: [f64; 8] = [0.; 8];
3267    let mut temp16: [f64; 16] = [0.; 16];
3268    let mut temp24: [f64; 24] = [0.; 24];
3269    let mut temp48: [f64; 48] = [0.; 48];
3270    let mut xdet: [f64; 96] = [0.; 96];
3271    let mut ydet: [f64; 96] = [0.; 96];
3272    let mut zdet: [f64; 96] = [0.; 96];
3273    let mut xydet: [f64; 192] = [0.; 192];
3274    let mut adet: [f64; 288] = [0.; 288];
3275    let mut bdet: [f64; 288] = [0.; 288];
3276    let mut cdet: [f64; 288] = [0.; 288];
3277    let mut ddet: [f64; 288] = [0.; 288];
3278    let mut abdet: [f64; 576] = [0.; 576];
3279    let mut cddet: [f64; 576] = [0.; 576];
3280    let mut fin1: [f64; 1152] = [0.; 1152];
3281    let aex = pa[0] - pe[0];
3282    let bex = pb[0] - pe[0];
3283    let cex = pc[0] - pe[0];
3284    let dex = pd[0] - pe[0];
3285    let aey = pa[1] - pe[1];
3286    let bey = pb[1] - pe[1];
3287    let cey = pc[1] - pe[1];
3288    let dey = pd[1] - pe[1];
3289    let aez = pa[2] - pe[2];
3290    let bez = pb[2] - pe[2];
3291    let cez = pc[2] - pe[2];
3292    let dez = pd[2] - pe[2];
3293    let [aexbey0, aexbey1] = two_product(aex, bey);
3294    let [bexaey0, bexaey1] = two_product(bex, aey);
3295    let ab = two_two_diff(aexbey1, aexbey0, bexaey1, bexaey0);
3296    let [bexcey0, bexcey1] = two_product(bex, cey);
3297    let [cexbey0, cexbey1] = two_product(cex, bey);
3298    let bc = two_two_diff(bexcey1, bexcey0, cexbey1, cexbey0);
3299    let [cexdey0, cexdey1] = two_product(cex, dey);
3300    let [dexcey0, dexcey1] = two_product(dex, cey);
3301    let cd = two_two_diff(cexdey1, cexdey0, dexcey1, dexcey0);
3302    let [dexaey0, dexaey1] = two_product(dex, aey);
3303    let [aexdey0, aexdey1] = two_product(aex, dey);
3304    let da = two_two_diff(dexaey1, dexaey0, aexdey1, aexdey0);
3305    let [aexcey0, aexcey1] = two_product(aex, cey);
3306    let [cexaey0, cexaey1] = two_product(cex, aey);
3307    let ac = two_two_diff(aexcey1, aexcey0, cexaey1, cexaey0);
3308    let [bexdey0, bexdey1] = two_product(bex, dey);
3309    let [dexbey0, dexbey1] = two_product(dex, bey);
3310    let bd = two_two_diff(bexdey1, bexdey0, dexbey1, dexbey0);
3311    let temp8alen = scale_expansion_zeroelim(&cd, bez, &mut temp8a);
3312    let temp8blen = scale_expansion_zeroelim(&bd, -cez, &mut temp8b);
3313    let temp8clen = scale_expansion_zeroelim(&bc, dez, &mut temp8c);
3314    let temp16len =
3315        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
3316    let temp24len =
3317        fast_expansion_sum_zeroelim(&temp8c[..temp8clen], &temp16[..temp16len], &mut temp24);
3318    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], aex, &mut temp48);
3319    let xlen = scale_expansion_zeroelim(&temp48[..temp48len], -aex, &mut xdet);
3320    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], aey, &mut temp48);
3321    let ylen = scale_expansion_zeroelim(&temp48[..temp48len], -aey, &mut ydet);
3322    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], aez, &mut temp48);
3323    let zlen = scale_expansion_zeroelim(&temp48[..temp48len], -aez, &mut zdet);
3324    let xylen = fast_expansion_sum_zeroelim(&xdet[..xlen], &ydet[..ylen], &mut xydet);
3325    let alen = fast_expansion_sum_zeroelim(&xydet[..xylen], &zdet[..zlen], &mut adet);
3326    let temp8alen = scale_expansion_zeroelim(&da, cez, &mut temp8a);
3327    let temp8blen = scale_expansion_zeroelim(&ac, dez, &mut temp8b);
3328    let temp8clen = scale_expansion_zeroelim(&cd, aez, &mut temp8c);
3329    let temp16len =
3330        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
3331    let temp24len =
3332        fast_expansion_sum_zeroelim(&temp8c[..temp8clen], &temp16[..temp16len], &mut temp24);
3333    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], bex, &mut temp48);
3334    let xlen = scale_expansion_zeroelim(&temp48[..temp48len], bex, &mut xdet);
3335    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], bey, &mut temp48);
3336    let ylen = scale_expansion_zeroelim(&temp48[..temp48len], bey, &mut ydet);
3337    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], bez, &mut temp48);
3338    let zlen = scale_expansion_zeroelim(&temp48[..temp48len], bez, &mut zdet);
3339    let xylen = fast_expansion_sum_zeroelim(&xdet[..xlen], &ydet[..ylen], &mut xydet);
3340    let blen = fast_expansion_sum_zeroelim(&xydet[..xylen], &zdet[..zlen], &mut bdet);
3341    let temp8alen = scale_expansion_zeroelim(&ab, dez, &mut temp8a);
3342    let temp8blen = scale_expansion_zeroelim(&bd, aez, &mut temp8b);
3343    let temp8clen = scale_expansion_zeroelim(&da, bez, &mut temp8c);
3344    let temp16len =
3345        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
3346    let temp24len =
3347        fast_expansion_sum_zeroelim(&temp8c[..temp8clen], &temp16[..temp16len], &mut temp24);
3348    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], cex, &mut temp48);
3349    let xlen = scale_expansion_zeroelim(&temp48[..temp48len], -cex, &mut xdet);
3350    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], cey, &mut temp48);
3351    let ylen = scale_expansion_zeroelim(&temp48[..temp48len], -cey, &mut ydet);
3352    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], cez, &mut temp48);
3353    let zlen = scale_expansion_zeroelim(&temp48[..temp48len], -cez, &mut zdet);
3354    let xylen = fast_expansion_sum_zeroelim(&xdet[..xlen], &ydet[..ylen], &mut xydet);
3355    let clen = fast_expansion_sum_zeroelim(&xydet[..xylen], &zdet[..zlen], &mut cdet);
3356    let temp8alen = scale_expansion_zeroelim(&bc, aez, &mut temp8a);
3357    let temp8blen = scale_expansion_zeroelim(&ac, -bez, &mut temp8b);
3358    let temp8clen = scale_expansion_zeroelim(&ab, cez, &mut temp8c);
3359    let temp16len =
3360        fast_expansion_sum_zeroelim(&temp8a[..temp8alen], &temp8b[..temp8blen], &mut temp16);
3361    let temp24len =
3362        fast_expansion_sum_zeroelim(&temp8c[..temp8clen], &temp16[..temp16len], &mut temp24);
3363    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], dex, &mut temp48);
3364    let xlen = scale_expansion_zeroelim(&temp48[..temp48len], dex, &mut xdet);
3365    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], dey, &mut temp48);
3366    let ylen = scale_expansion_zeroelim(&temp48[..temp48len], dey, &mut ydet);
3367    let temp48len = scale_expansion_zeroelim(&temp24[..temp24len], dez, &mut temp48);
3368    let zlen = scale_expansion_zeroelim(&temp48[..temp48len], dez, &mut zdet);
3369    let xylen = fast_expansion_sum_zeroelim(&xdet[..xlen], &ydet[..ylen], &mut xydet);
3370    let dlen = fast_expansion_sum_zeroelim(&xydet[..xylen], &zdet[..zlen], &mut ddet);
3371    let ablen = fast_expansion_sum_zeroelim(&adet[..alen], &bdet[..blen], &mut abdet);
3372    let cdlen = fast_expansion_sum_zeroelim(&cdet[..clen], &ddet[..dlen], &mut cddet);
3373    let finlength = fast_expansion_sum_zeroelim(&abdet[..ablen], &cddet[..cdlen], &mut fin1);
3374    let mut det: f64 = fin1[..finlength].iter().sum();
3375    let errbound = PARAMS.isperrbound_b * permanent;
3376    if det >= errbound || -det >= errbound {
3377        return det;
3378    }
3379    let aextail = two_diff_tail(pa[0], pe[0], aex);
3380    let aeytail = two_diff_tail(pa[1], pe[1], aey);
3381    let aeztail = two_diff_tail(pa[2], pe[2], aez);
3382    let bextail = two_diff_tail(pb[0], pe[0], bex);
3383    let beytail = two_diff_tail(pb[1], pe[1], bey);
3384    let beztail = two_diff_tail(pb[2], pe[2], bez);
3385    let cextail = two_diff_tail(pc[0], pe[0], cex);
3386    let ceytail = two_diff_tail(pc[1], pe[1], cey);
3387    let ceztail = two_diff_tail(pc[2], pe[2], cez);
3388    let dextail = two_diff_tail(pd[0], pe[0], dex);
3389    let deytail = two_diff_tail(pd[1], pe[1], dey);
3390    let deztail = two_diff_tail(pd[2], pe[2], dez);
3391    if aextail == 0.0
3392        && aeytail == 0.0
3393        && aeztail == 0.0
3394        && bextail == 0.0
3395        && beytail == 0.0
3396        && beztail == 0.0
3397        && cextail == 0.0
3398        && ceytail == 0.0
3399        && ceztail == 0.0
3400        && dextail == 0.0
3401        && deytail == 0.0
3402        && deztail == 0.0
3403    {
3404        return det;
3405    }
3406    let errbound = PARAMS.isperrbound_c * permanent + PARAMS.resulterrbound * abs(det);
3407    let abeps = aex * beytail + bey * aextail - (aey * bextail + bex * aeytail);
3408    let bceps = bex * ceytail + cey * bextail - (bey * cextail + cex * beytail);
3409    let cdeps = cex * deytail + dey * cextail - (cey * dextail + dex * ceytail);
3410    let daeps = dex * aeytail + aey * dextail - (dey * aextail + aex * deytail);
3411    let aceps = aex * ceytail + cey * aextail - (aey * cextail + cex * aeytail);
3412    let bdeps = bex * deytail + dey * bextail - (bey * dextail + dex * beytail);
3413    det += (bex * bex + bey * bey + bez * bez)
3414        * (cez * daeps
3415            + dez * aceps
3416            + aez * cdeps
3417            + (ceztail * da[3] + deztail * ac[3] + aeztail * cd[3]))
3418        + (dex * dex + dey * dey + dez * dez)
3419            * (aez * bceps - bez * aceps
3420                + cez * abeps
3421                + (aeztail * bc[3] - beztail * ac[3] + ceztail * ab[3]))
3422        - ((aex * aex + aey * aey + aez * aez)
3423            * (bez * cdeps - cez * bdeps
3424                + dez * bceps
3425                + (beztail * cd[3] - ceztail * bd[3] + deztail * bc[3]))
3426            + (cex * cex + cey * cey + cez * cez)
3427                * (dez * abeps
3428                    + aez * bdeps
3429                    + bez * daeps
3430                    + (deztail * ab[3] + aeztail * bd[3] + beztail * da[3])))
3431        + 2.0
3432            * ((bex * bextail + bey * beytail + bez * beztail)
3433                * (cez * da[3] + dez * ac[3] + aez * cd[3])
3434                + (dex * dextail + dey * deytail + dez * deztail)
3435                    * (aez * bc[3] - bez * ac[3] + cez * ab[3])
3436                - ((aex * aextail + aey * aeytail + aez * aeztail)
3437                    * (bez * cd[3] - cez * bd[3] + dez * bc[3])
3438                    + (cex * cextail + cey * ceytail + cez * ceztail)
3439                        * (dez * ab[3] + aez * bd[3] + bez * da[3])));
3440    if det >= errbound || -det >= errbound {
3441        return det;
3442    }
3443    insphere_exact(pa, pb, pc, pd, pe)
3444}
3445
3446/**
3447 * Adaptive exact 3D insphere test. Robust.
3448 *
3449 * Return a positive value if the point `pe` lies inside the
3450 * sphere passing through `pa`, `pb`, `pc`, and `pd`; a negative value
3451 * if it lies outside; and zero if the five points are
3452 * cospherical.  The points `pa`, `pb`, `pc`, and `pd` must be ordered
3453 * so that they have a positive orientation (as defined by
3454 * `orient3d()`), or the sign of the result will be reversed.
3455 *
3456 * The result returned is the determinant of a matrix.
3457 * this determinant is computed adaptively, in the sense that exact
3458 * arithmetic is used only to the degree it is needed to ensure that the
3459 * returned value has the correct sign.  Hence, `insphere()` is usually quite
3460 * fast, but will run more slowly when the input points are cospherical or
3461 * nearly so.
3462 */
3463#[inline]
3464pub fn insphere(pa: [f64; 3], pb: [f64; 3], pc: [f64; 3], pd: [f64; 3], pe: [f64; 3]) -> f64 {
3465    let aex = pa[0] - pe[0];
3466    let bex = pb[0] - pe[0];
3467    let cex = pc[0] - pe[0];
3468    let dex = pd[0] - pe[0];
3469    let aey = pa[1] - pe[1];
3470    let bey = pb[1] - pe[1];
3471    let cey = pc[1] - pe[1];
3472    let dey = pd[1] - pe[1];
3473    let aez = pa[2] - pe[2];
3474    let bez = pb[2] - pe[2];
3475    let cez = pc[2] - pe[2];
3476    let dez = pd[2] - pe[2];
3477    let aexbey = aex * bey;
3478    let bexaey = bex * aey;
3479    let ab = aexbey - bexaey;
3480    let bexcey = bex * cey;
3481    let cexbey = cex * bey;
3482    let bc = bexcey - cexbey;
3483    let cexdey = cex * dey;
3484    let dexcey = dex * cey;
3485    let cd = cexdey - dexcey;
3486    let dexaey = dex * aey;
3487    let aexdey = aex * dey;
3488    let da = dexaey - aexdey;
3489    let aexcey = aex * cey;
3490    let cexaey = cex * aey;
3491    let ac = aexcey - cexaey;
3492    let bexdey = bex * dey;
3493    let dexbey = dex * bey;
3494    let bd = bexdey - dexbey;
3495    let abc = aez * bc - bez * ac + cez * ab;
3496    let bcd = bez * cd - cez * bd + dez * bc;
3497    let cda = cez * da + dez * ac + aez * cd;
3498    let dab = dez * ab + aez * bd + bez * da;
3499    let alift = aex * aex + aey * aey + aez * aez;
3500    let blift = bex * bex + bey * bey + bez * bez;
3501    let clift = cex * cex + cey * cey + cez * cez;
3502    let dlift = dex * dex + dey * dey + dez * dez;
3503    let det = dlift * abc - clift * dab + (blift * cda - alift * bcd);
3504    let aezplus = abs(aez);
3505    let bezplus = abs(bez);
3506    let cezplus = abs(cez);
3507    let dezplus = abs(dez);
3508    let aexbeyplus = abs(aexbey);
3509    let bexaeyplus = abs(bexaey);
3510    let bexceyplus = abs(bexcey);
3511    let cexbeyplus = abs(cexbey);
3512    let cexdeyplus = abs(cexdey);
3513    let dexceyplus = abs(dexcey);
3514    let dexaeyplus = abs(dexaey);
3515    let aexdeyplus = abs(aexdey);
3516    let aexceyplus = abs(aexcey);
3517    let cexaeyplus = abs(cexaey);
3518    let bexdeyplus = abs(bexdey);
3519    let dexbeyplus = abs(dexbey);
3520    let permanent = ((cexdeyplus + dexceyplus) * bezplus
3521        + (dexbeyplus + bexdeyplus) * cezplus
3522        + (bexceyplus + cexbeyplus) * dezplus)
3523        * alift
3524        + ((dexaeyplus + aexdeyplus) * cezplus
3525            + (aexceyplus + cexaeyplus) * dezplus
3526            + (cexdeyplus + dexceyplus) * aezplus)
3527            * blift
3528        + ((aexbeyplus + bexaeyplus) * dezplus
3529            + (bexdeyplus + dexbeyplus) * aezplus
3530            + (dexaeyplus + aexdeyplus) * bezplus)
3531            * clift
3532        + ((bexceyplus + cexbeyplus) * aezplus
3533            + (cexaeyplus + aexceyplus) * bezplus
3534            + (aexbeyplus + bexaeyplus) * cezplus)
3535            * dlift;
3536    let errbound = PARAMS.isperrbound_a * permanent;
3537    if det > errbound || -det > errbound {
3538        return det;
3539    }
3540    insphereadapt(pa, pb, pc, pd, pe, permanent)
3541}