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