├── LICENSE.md
├── README.md
├── basebase.hpp
├── example.cpp
├── expansion
├── dd_float.hpp
├── ia_float.hpp
├── mp_basic.hpp
├── mp_float.hpp
└── mp_utils.hpp
├── geompred.hpp
├── mpfloats.hpp
└── predicate
├── bisect_k.hpp
├── inball_k.hpp
├── orient_k.hpp
└── predicate_k.hpp
/LICENSE.md:
--------------------------------------------------------------------------------
1 | `Robust-Predicate` is licensed under the following terms:
2 |
3 | This program may be freely redistributed under the condition that the copyright notices (including this entire header) are not removed, and no compensation is received through use of the software. Private, research, and institutional use is free. You may distribute modified versions of this code `UNDER THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR NOTICE IS GIVEN OF THE MODIFICATIONS`. Distribution of this code as part of a commercial system is permissible `ONLY BY DIRECT ARRANGEMENT WITH THE AUTHOR`. (If you are not directly supplying this code to a customer, and you are instead telling them how they can obtain it for free, then you are not required to make any arrangement with me.)
4 |
5 | `DISCLAIMER`: Neither I nor: Columbia University, the Massachusetts Institute of Technology, the University of Sydney, nor the National Aeronautics and Space Administration warrant this code in any way whatsoever. This code is provided "as-is" to be used at your own risk.
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## `Robust geometric predicates (without the agonising pain)`
2 |
3 | Evaluating "geometric predicates" (`orientation`, `incircle`, etc) using standard floating-point arithmetic is a well-known nightmare, with floating-point round-off errors leading to ambiguities, non-convergence, and program crashes. A standard remedy is to employ "exact" computation via multi-precision techniques; eliminating floating-point round-off errors through operations on arbitrary bit-length number types.
4 |
5 | This package is a `C++` framework for the construction of such predicates; encapsulating Jonathan Shewchuk's seminal arbitrary precision library *without the agonising pain* of the original hand-rolled `C89` code.
6 |
7 | This package aims to implement a "zero-overhead" abstraction; leveraging various `C++` template- and compile-time patterns to avoid run-time stack/heap manipulation or pointer indirection. Timing analysis suggests the new templated `C++` predicates perform favourably compared to the original hand-rolled `C89` implementation.
8 |
9 | The following predicates are currently available:
10 | ````
11 | orient2d: orientation of 3 points in E^2, or a point wrt. a line.
12 | bisect2d: orientation of point wrt. half-space in E^2.
13 | bisect2w: orientation of point wrt. half-space in E^2 (weighted).
14 | inball2d: point-in-circumball (Delaunay-Voronoi tessellations) in E^2.
15 | inball2w: point-in-ortho-ball (Regular-Laguerre tessellations) in E^2.
16 |
17 | orient3d: orientation of 4 points in E^3, or a point wrt. a plane.
18 | bisect3d: orientation of point wrt. half-space in E^3.
19 | bisect3w: orientation of point wrt. half-space in E^3 (weighted).
20 | inball3d: point-in-circumball (Delaunay-Voronoi tessellations) in E^3.
21 | inball3w: point-in-ortho-ball (Regular-Laguerre tessellations) in E^3.
22 | ````
23 | A simplified two-stage variation on Shewchuk's original arithmetic is employed, adopting standard (fast!) floating-point approximations when results are unambiguous and falling back onto (slower) arbitrary precision evaluations as necessary to guarantee "sign-correctness". Semi-static filters are used to toggle between floating-point and arbitrary precision kernels. An optional third (intermediate) stage based on interval arithmetic is also available.
24 |
25 | In addition to support for multi-precision expansions, a simplified "double-double" precision number type is also provided, enabling construction of geometric primitives with approximately twice the precision of standard floating-point evaluations.
26 |
27 | ### `License`
28 |
29 | This program may be freely redistributed under the condition that the copyright notices (including this entire header) are not removed, and no compensation is received through use of the software. Private, research, and institutional use is free. You may distribute modified versions of this code `UNDER THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR NOTICE IS GIVEN OF THE MODIFICATIONS`. Distribution of this code as part of a commercial system is permissible `ONLY BY DIRECT ARRANGEMENT WITH THE AUTHOR`. (If you are not directly supplying this code to a customer, and you are instead telling them how they can obtain it for free, then you are not required to make any arrangement with me.)
30 |
31 | `DISCLAIMER`: Neither I nor: Columbia University, the Massachusetts Institute of Technology, the University of Sydney, nor the National Aeronautics and Space Administration warrant this code in any way whatsoever. This code is provided "as-is" to be used at your own risk.
32 |
33 | ### `References`
34 |
35 | `[1]` - J. R. Shewchuk (1997), Adaptive Precision Floating-Point Arithmetic & Fast Robust Geometric Predicates. Discrete & Computational Geometry, 18, pp. 305-363.
36 |
37 | `[2]` - B. Lévy (2016), Robustness and efficiency of geometric programs: The Predicate Construction Kit (PCK). Computer-Aided Design, 72, pp. 03-12.
38 |
39 | `[3]` - C. Burnikel, S. Funke, and M. Seel (2001), Exact geometric computation using cascading. IJCGA (Special issue) 11 (3), pp. 245–266.
40 |
41 | `[4]` - M. Joldes, J-M. Muller, V. Popescu (2017): Tight and rigorous error bounds for basic building blocks of double-word arithmetic. ACM Transactions on Mathematical Software, ACM, 44 (2), pp. 1-27.
42 |
43 | `[5]` - Y. Hida, X. Li, and D. Bailey (2000): Quad-double arithmetic: Algorithms, implementation, and application. In the 15th IEEE Symposium on Computer Arithmetic, pp. 155-162.
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/basebase.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | ------------------------------------------------------------
4 | * basic types, macros, compiler-settings, etc...
5 | ------------------------------------------------------------
6 | *
7 | * This program may be freely redistributed under the
8 | * condition that the copyright notices (including this
9 | * entire header) are not removed, and no compensation
10 | * is received through use of the software. Private,
11 | * research, and institutional use is free. You may
12 | * distribute modified versions of this code UNDER THE
13 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
14 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
15 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
16 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
17 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
18 | * of this code as part of a commercial system is
19 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
20 | * AUTHOR. (If you are not directly supplying this
21 | * code to a customer, and you are instead telling them
22 | * how they can obtain it for free, then you are not
23 | * required to make any arrangement with me.)
24 | *
25 | * Disclaimer: Neither I nor: Columbia University, The
26 | * Massachusetts Institute of Technology, The
27 | * University of Sydney, nor The National Aeronautics
28 | * and Space Administration warrant this code in any
29 | * way whatsoever. This code is provided "as-is" to be
30 | * used at your own risk.
31 | *
32 | ------------------------------------------------------------
33 | *
34 | * Last updated: 02 March, 2020
35 | *
36 | * Copyright 2013-2020
37 | * Darren Engwirda
38 | * de2363@columbia.edu
39 | * https://github.com/dengwirda/
40 | *
41 | ------------------------------------------------------------
42 | */
43 |
44 | # pragma once
45 |
46 | # ifndef __BASEBASE__
47 | # define __BASEBASE__
48 |
49 | # include
50 | # include
51 | # include
52 |
53 | /*
54 | ------------------------------------------------------------
55 | * push compiler settings
56 | ------------------------------------------------------------
57 | */
58 |
59 | # if defined(_MSC_VER)
60 | # pragma warning(disable:4127) // constant conditionals
61 | # pragma warning(disable:4503) // decorated name length
62 |
63 | # elif defined(__LLVM__)
64 |
65 | # elif defined(__GNUC__)
66 |
67 | # endif
68 |
69 | # define __assert assert
70 |
71 | /*
72 | ------------------------------------------------------------
73 | * global data type alias
74 | ------------------------------------------------------------
75 | */
76 |
77 | typedef void void_type ;
78 | typedef bool bool_type ;
79 | typedef char char_type ;
80 |
81 | /*
82 | ------------------------------------------------------------
83 | * function call decorator
84 | ------------------------------------------------------------
85 | */
86 |
87 | # define __inline_call inline
88 | # define __normal_call
89 | # define __static_call static
90 | # define __friend_call friend
91 | # define __nocast_call explicit
92 |
93 | /*
94 | ------------------------------------------------------------
95 | * copy // move forwarding
96 | ------------------------------------------------------------
97 | */
98 |
99 | # define __copy(T, x) std::forward(x)
100 | # define __move(T, x) std::forward(x)
101 |
102 | /*
103 | ------------------------------------------------------------
104 | * unused parameter macros
105 | ------------------------------------------------------------
106 | */
107 |
108 | # define __unreferenced(x) ((void) x)
109 |
110 | /*
111 | ------------------------------------------------------------
112 | * no--alias pointer types
113 | ------------------------------------------------------------
114 | */
115 |
116 | # define __const_ptr(T) T const *__restrict
117 | # define __write_ptr(T) T *__restrict
118 |
119 | # define __const_ref(T) T const &__restrict
120 | # define __write_ref(T) T &__restrict
121 |
122 | /*
123 | ------------------------------------------------------------
124 | * integer "flip" routines
125 | ------------------------------------------------------------
126 | */
127 |
128 | # define __isflip(__i) ( (__i) < 0)
129 |
130 | # define __doflip(__i) (-(__i) - 2)
131 |
132 | # define __unflip(__i) (((__i) < 0) \
133 | ? __doflip(__i) : (__i) )
134 |
135 | /*
136 | ------------------------------------------------------------
137 | * integer "flip" routines
138 | ------------------------------------------------------------
139 | */
140 |
141 | # define __setbit(x,b) ((x)|= (1ULL<<(b)))
142 |
143 | # define __popbit(x,b) ((x)&= ~(1ULL<<(b)))
144 |
145 | # define __flpbit(x,b) ((x)^= (1ULL<<(b)))
146 |
147 | # define __chkbit(x,b) (!!((x)&(1ULL<<(b))) )
148 |
149 |
150 | # endif//__BASEBASE__
151 |
152 |
153 |
154 |
--------------------------------------------------------------------------------
/example.cpp:
--------------------------------------------------------------------------------
1 |
2 | // g++ -std=c++17 -pedantic -Wall -O3 -flto -DNDEBUG
3 | // example.cpp -oexample
4 |
5 | #include
6 |
7 | #include "geompred.hpp"
8 |
9 | int main () {
10 |
11 | // Initialise the internal library state. Call at the
12 | // start of any program.
13 |
14 | mp_float::exactinit() ;
15 |
16 | /*-------------------------------- test prediactes in E^2 */
17 |
18 | double _pa[3] = { // (d+1) coord. is weight
19 | +0.0, +0.0, +0.0
20 | } ;
21 | double _pb[3] = {
22 | +1.0, +0.0, +0.1
23 | } ;
24 | double _pc[3] = {
25 | +1.0, +1.0, +0.2
26 | } ;
27 |
28 | double _qq[3] = {
29 | +0.5, +0.5, +0.0
30 | } ;
31 |
32 | double _rr ;
33 |
34 | // Test the orienation of the point QQ wrt. the line
35 | // PA, PB in E^2.
36 |
37 | _rr = geompred::orient2d (
38 | _pa, _pb, _qq
39 | ) ;
40 |
41 | std::cout << std::showpos;
42 |
43 | std::cout << "orient2d: " << _rr;
44 | std::cout << std::endl;
45 |
46 | // Test the orienation of the point QQ wrt. the half-
47 | // space of PA, PB.
48 |
49 | // This is the unweighted case in E^2.
50 |
51 | _rr = geompred::bisect2d (
52 | _pa, _pb, _qq
53 | ) ;
54 |
55 | std::cout << "bisect2d: " << _rr;
56 | std::cout << std::endl;
57 |
58 | // Test the orienation of the point QQ wrt. the half-
59 | // space of PA, PB.
60 |
61 | // This is the "weighted" case in E^2.
62 |
63 | _rr = geompred::bisect2w (
64 | _pa, _pb, _qq
65 | ) ;
66 |
67 | std::cout << "bisect2w: " << _rr;
68 | std::cout << std::endl;
69 |
70 | // Test whether the point QQ is contained within the
71 | // circumscribing ball associated with the unweighted
72 | // simplex PA, PB, PC in E^2.
73 |
74 | // This is the unweighted case, so only the geometric
75 | // coordinates PP[0..1] are used.
76 |
77 | _rr = geompred::inball2d (
78 | _pa, _pb, _pc, _qq
79 | ) ;
80 |
81 | std::cout << "inball2d: " << _rr;
82 | std::cout << std::endl;
83 |
84 | // Test whether the point QQ is contained within the
85 | // "orthogonal" ball associated with the weighted
86 | // simplex PA, PB, PC in E^2.
87 |
88 | // This is the "weighted" case, so the full (x, y, w)
89 | // coordinates PP[0..2] are used.
90 |
91 | _rr = geompred::inball2w (
92 | _pa, _pb, _pc, _qq
93 | ) ;
94 |
95 | std::cout << "inball2w: " << _rr;
96 | std::cout << std::endl;
97 |
98 | /*-------------------------------- test prediactes in E^3 */
99 |
100 | double _PA[4] = { // (d+1) coord. is weight
101 | +0.0, +0.0, +0.0, +0.0
102 | } ;
103 | double _PB[4] = {
104 | +1.0, +0.0, +0.0, +0.1
105 | } ;
106 | double _PC[4] = {
107 | +1.0, +1.0, +0.0, +0.2
108 | } ;
109 | double _PD[4] = {
110 | +1.0, +1.0, +1.0, +0.3
111 | } ;
112 |
113 | double _QQ[4] = {
114 | +0.5, +0.5, +0.5, +0.0
115 | } ;
116 |
117 | // Test the orienation of the point QQ wrt. the plane
118 | // PA, PB, PC in E^3.
119 |
120 | _rr = geompred::orient3d (
121 | _PA, _PB, _PC, _QQ
122 | ) ;
123 |
124 | std::cout << "orient3d: " << _rr;
125 | std::cout << std::endl;
126 |
127 | // Test the orienation of the point QQ wrt. the half-
128 | // space of PA, PB.
129 |
130 | // This is the unweighted case in E^3.
131 |
132 | _rr = geompred::bisect3d (
133 | _PA, _PB, _QQ
134 | ) ;
135 |
136 | std::cout << "bisect3d: " << _rr;
137 | std::cout << std::endl;
138 |
139 | // Test the orienation of the point QQ wrt. the half-
140 | // space of PA, PB.
141 |
142 | // This is the "weighted" case in E^3.
143 |
144 | _rr = geompred::bisect3w (
145 | _PA, _PB, _QQ
146 | ) ;
147 |
148 | std::cout << "bisect3w: " << _rr;
149 | std::cout << std::endl;
150 |
151 | // Test whether the point QQ is contained within the
152 | // circumscribing ball associated with the unweighted
153 | // simplex PA, PB, PC, PD in E^3.
154 |
155 | // This is the unweighted case, so only the geometric
156 | // coordinates PP[0..2] are used.
157 |
158 | _rr = geompred::inball3d (
159 | _PA, _PB, _PC, _PD, _QQ
160 | ) ;
161 |
162 | std::cout << "inball3d: " << _rr;
163 | std::cout << std::endl;
164 |
165 | // Test whether the point QQ is contained within the
166 | // "orthogonal" ball associated with the weighted
167 | // simplex PA, PB, PC, PD in E^3.
168 |
169 | // This is the "weighted" case, so the full (x,y,z,w)
170 | // coordinates PP[0..3] are used.
171 |
172 | _rr = geompred::inball3w (
173 | _PA, _PB, _PC, _PD, _QQ
174 | ) ;
175 |
176 | std::cout << "inball3w: " << _rr;
177 | std::cout << std::endl;
178 |
179 | return 0 ;
180 | }
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/expansion/dd_float.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | --------------------------------------------------------
4 | * MPFLOAT: multi-precision floating-point arithmetic.
5 | --------------------------------------------------------
6 | *
7 | * "double-double" arithmetic. Here mp-expansion size
8 | * is capped at 2, with subsequent bits truncated:
9 | *
10 | * M. Joldes, J-M. Muller, V. Popescu (2017): Tight &
11 | * rigourous error bounds for basic building blocks of
12 | * double-word arithmetic. ACM Transactions on
13 | * Mathematical Software, ACM, 44 (2), pp. 1-27.
14 | *
15 | * Y. Hida, X. Li, and D. Bailey (2000): Quad-double
16 | * arithmetic: Algorithms, implementation, and
17 | * application. In the 15th IEEE Symposium on Computer
18 | * Arithmetic, pp. 155-162.
19 | *
20 | --------------------------------------------------------
21 | *
22 | * This program may be freely redistributed under the
23 | * condition that the copyright notices (including this
24 | * entire header) are not removed, and no compensation
25 | * is received through use of the software. Private,
26 | * research, and institutional use is free. You may
27 | * distribute modified versions of this code UNDER THE
28 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
29 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
30 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
31 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
32 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
33 | * of this code as part of a commercial system is
34 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
35 | * AUTHOR. (If you are not directly supplying this
36 | * code to a customer, and you are instead telling them
37 | * how they can obtain it for free, then you are not
38 | * required to make any arrangement with me.)
39 | *
40 | * Disclaimer: Neither I nor: Columbia University, The
41 | * Massachusetts Institute of Technology, The
42 | * University of Sydney, nor The National Aeronautics
43 | * and Space Administration warrant this code in any
44 | * way whatsoever. This code is provided "as-is" to be
45 | * used at your own risk.
46 | *
47 | --------------------------------------------------------
48 | *
49 | * Last updated: 16 April, 2020
50 | *
51 | * Copyright 2020--
52 | * Darren Engwirda
53 | * de2363@columbia.edu
54 | * https://github.com/dengwirda/
55 | *
56 | --------------------------------------------------------
57 | */
58 |
59 | # pragma once
60 |
61 | # ifndef __DD_FLOAT__
62 | # define __DD_FLOAT__
63 |
64 | # include "mp_basic.hpp"
65 |
66 | // namespace mp_float { // hmmm no...
67 |
68 | /*
69 | --------------------------------------------------------
70 | * DD_FLT: (double-double) precision numbers
71 | --------------------------------------------------------
72 | */
73 |
74 | # define REAL_TYPE mp_float::real_type
75 | # define INDX_TYPE mp_float::indx_type
76 |
77 | class dd_flt;
78 |
79 | __inline_call dd_flt operator + ( // fwd. dec's
80 | dd_flt const&,
81 | REAL_TYPE ) ;
82 | __inline_call dd_flt operator + (
83 | REAL_TYPE ,
84 | dd_flt const&) ;
85 | __inline_call dd_flt operator + (
86 | dd_flt const&,
87 | dd_flt const&) ;
88 |
89 | __inline_call dd_flt operator - (
90 | dd_flt const&,
91 | REAL_TYPE ) ;
92 | __inline_call dd_flt operator - (
93 | REAL_TYPE ,
94 | dd_flt const&) ;
95 | __inline_call dd_flt operator - (
96 | dd_flt const&,
97 | dd_flt const&) ;
98 |
99 | __inline_call dd_flt operator * (
100 | dd_flt const&,
101 | REAL_TYPE ) ;
102 | __inline_call dd_flt operator * (
103 | REAL_TYPE ,
104 | dd_flt const&) ;
105 | __inline_call dd_flt operator * (
106 | dd_flt const&,
107 | dd_flt const&) ;
108 |
109 | __inline_call dd_flt operator / (
110 | dd_flt const&,
111 | REAL_TYPE ) ;
112 | __inline_call dd_flt operator / (
113 | REAL_TYPE ,
114 | dd_flt const&) ;
115 | __inline_call dd_flt operator / (
116 | dd_flt const&,
117 | dd_flt const&) ;
118 |
119 | class dd_flt
120 | {
121 | /*------------------------------ doubledouble number type */
122 | public :
123 | typedef REAL_TYPE real_type;
124 | typedef INDX_TYPE indx_type;
125 |
126 | indx_type static constexpr _size = 2 ;
127 | indx_type static constexpr _xlen = 2 ;
128 |
129 | real_type _xdat [ 2 ] ;
130 |
131 | public :
132 | /*------------------------------ access to expansion bits */
133 | __inline_call real_type& hi (
134 | )
135 | { return this->_xdat[1] ;
136 | }
137 | __inline_call real_type& lo (
138 | )
139 | { return this->_xdat[0] ;
140 | }
141 |
142 | __inline_call real_type const&hi (
143 | ) const
144 | { return this->_xdat[1] ;
145 | }
146 | __inline_call real_type const&lo (
147 | ) const
148 | { return this->_xdat[0] ;
149 | }
150 |
151 | /*------------------------------ initialising constructor */
152 | __inline_call dd_flt (
153 | real_type _hi = real_type(+0.) ,
154 | real_type _lo = real_type(+0.)
155 | )
156 | { this->_xdat[0] = _lo ;
157 | this->_xdat[1] = _hi ;
158 | }
159 |
160 | __inline_call dd_flt ( // copy c'tor
161 | dd_flt const& _aa
162 | )
163 | {
164 | this->_xdat[0] = _aa.lo();
165 | this->_xdat[1] = _aa.hi();
166 | }
167 |
168 | __inline_call dd_flt& operator = ( // assignment
169 | dd_flt const& _aa
170 | )
171 | {
172 | this->_xdat[0] = _aa.lo();
173 | this->_xdat[1] = _aa.hi();
174 |
175 | return ( *this ) ;
176 | }
177 | __inline_call dd_flt& operator = ( // assignment
178 | real_type _aa
179 | )
180 | {
181 | this->_xdat[0] = +0. ;
182 | this->_xdat[1] = (real_type)_aa;
183 |
184 | return ( *this ) ;
185 | }
186 |
187 | /*---------------------------------------- cast operators */
188 | __inline_call operator real_type (
189 | ) const
190 | { return (real_type)(hi()+lo());
191 | }
192 |
193 | __inline_call operator indx_type (
194 | ) const
195 | { return (indx_type)(hi()+lo());
196 | }
197 |
198 | /*---------------------------------------- math operators */
199 | __inline_call dd_flt operator + (
200 | ) const
201 | { return dd_flt(+hi(), +lo());
202 | }
203 |
204 | __inline_call dd_flt operator - (
205 | ) const
206 | { return dd_flt(-hi(), -lo());
207 | }
208 |
209 | /*------------------------------ helper: init. from a + b */
210 | __inline_call void from_add (
211 | real_type _aa, real_type _bb
212 | )
213 | {
214 | mp_float::one_one_add_full(_aa, _bb,
215 | this->_xdat[1],
216 | this->_xdat[0]) ;
217 | }
218 |
219 | /*------------------------------ helper: init. from a - b */
220 | __inline_call void from_sub (
221 | real_type _aa, real_type _bb
222 | )
223 | {
224 | mp_float::one_one_sub_full(_aa, _bb,
225 | this->_xdat[1],
226 | this->_xdat[0]) ;
227 | }
228 |
229 | /*------------------------------ helper: init. from a * a */
230 | __inline_call void from_sqr (
231 | real_type _aa
232 | )
233 | {
234 | mp_float::one_one_sqr_full(_aa,
235 | this->_xdat[1],
236 | this->_xdat[0]) ;
237 | }
238 |
239 | /*------------------------------ helper: init. from a * b */
240 | __inline_call void from_mul (
241 | real_type _aa, real_type _bb
242 | )
243 | {
244 | mp_float::one_one_mul_full(_aa, _bb,
245 | this->_xdat[1],
246 | this->_xdat[0]) ;
247 | }
248 |
249 | __inline_call dd_flt& operator+= ( // via double
250 | real_type _aa
251 | )
252 | {
253 | dd_flt _tt = *this + _aa ;
254 |
255 | hi() = _tt.hi();
256 | lo() = _tt.lo();
257 |
258 | return ( *this ) ;
259 | }
260 | __inline_call dd_flt& operator-= (
261 | real_type _aa
262 | )
263 | {
264 | dd_flt _tt = *this - _aa ;
265 |
266 | hi() = _tt.hi();
267 | lo() = _tt.lo();
268 |
269 | return ( *this ) ;
270 | }
271 | __inline_call dd_flt& operator*= (
272 | real_type _aa
273 | )
274 | {
275 | dd_flt _tt = *this * _aa ;
276 |
277 | hi() = _tt.hi();
278 | lo() = _tt.lo();
279 |
280 | return ( *this ) ;
281 | }
282 | __inline_call dd_flt& operator/= (
283 | real_type _aa
284 | )
285 | {
286 | dd_flt _tt = *this / _aa ;
287 |
288 | hi() = _tt.hi();
289 | lo() = _tt.lo();
290 |
291 | return ( *this ) ;
292 | }
293 |
294 | __inline_call dd_flt& operator+= ( // via dd_flt
295 | dd_flt const& _aa
296 | )
297 | {
298 | dd_flt _tt = *this + _aa ;
299 |
300 | hi() = _tt.hi();
301 | lo() = _tt.lo();
302 |
303 | return ( *this ) ;
304 | }
305 | __inline_call dd_flt& operator-= (
306 | dd_flt const& _aa
307 | )
308 | {
309 | dd_flt _tt = *this - _aa ;
310 |
311 | hi() = _tt.hi();
312 | lo() = _tt.lo();
313 |
314 | return ( *this ) ;
315 | }
316 | __inline_call dd_flt& operator*= (
317 | dd_flt const& _aa
318 | )
319 | {
320 | dd_flt _tt = *this * _aa ;
321 |
322 | hi() = _tt.hi();
323 | lo() = _tt.lo();
324 |
325 | return ( *this ) ;
326 | }
327 | __inline_call dd_flt& operator/= (
328 | dd_flt const& _aa
329 | )
330 | {
331 | dd_flt _tt = *this / _aa ;
332 |
333 | hi() = _tt.hi();
334 | lo() = _tt.lo();
335 |
336 | return ( *this ) ;
337 | }
338 |
339 | } ;
340 |
341 | /*
342 | --------------------------------------------------------
343 | * double-double a + b operators
344 | --------------------------------------------------------
345 | */
346 |
347 | __inline_call dd_flt operator + (
348 | dd_flt const& _aa,
349 | REAL_TYPE _bb
350 | )
351 | {
352 | REAL_TYPE _x0, _x1;
353 | mp_float::two_one_add_clip(
354 | _aa.hi(), _aa.lo(), _bb, _x1, _x0
355 | ) ;
356 |
357 | return ( dd_flt(_x1, _x0) ) ;
358 | }
359 |
360 | __inline_call dd_flt operator + (
361 | REAL_TYPE _aa,
362 | dd_flt const& _bb
363 | )
364 | { return ( +(_bb + _aa) ) ;
365 | }
366 |
367 | __inline_call dd_flt operator + (
368 | dd_flt const& _aa,
369 | dd_flt const& _bb
370 | )
371 | {
372 | REAL_TYPE _x0, _x1;
373 | mp_float::two_two_add_clip(
374 | _aa.hi(), _aa.lo(),
375 | _bb.hi(), _bb.lo(), _x1, _x0
376 | ) ;
377 |
378 | return ( dd_flt(_x1, _x0) ) ;
379 | }
380 |
381 | /*
382 | --------------------------------------------------------
383 | * double-double a - b operators
384 | --------------------------------------------------------
385 | */
386 |
387 | __inline_call dd_flt operator - (
388 | dd_flt const& _aa,
389 | REAL_TYPE _bb
390 | )
391 | {
392 | REAL_TYPE _x0, _x1;
393 | mp_float::two_one_sub_clip(
394 | _aa.hi(), _aa.lo(), _bb, _x1, _x0
395 | ) ;
396 |
397 | return ( dd_flt(_x1, _x0) ) ;
398 | }
399 |
400 | __inline_call dd_flt operator - (
401 | REAL_TYPE _aa,
402 | dd_flt const& _bb
403 | )
404 | { return ( -(_bb - _aa) ) ;
405 | }
406 |
407 | __inline_call dd_flt operator - (
408 | dd_flt const& _aa,
409 | dd_flt const& _bb
410 | )
411 | {
412 | REAL_TYPE _x0, _x1;
413 | mp_float::two_two_sub_clip(
414 | _aa.hi(), _aa.lo(),
415 | _bb.hi(), _bb.lo(), _x1, _x0
416 | ) ;
417 |
418 | return ( dd_flt(_x1, _x0) ) ;
419 | }
420 |
421 | /*
422 | --------------------------------------------------------
423 | * double-double a * b operators
424 | --------------------------------------------------------
425 | */
426 |
427 | __inline_call dd_flt operator * (
428 | dd_flt const& _aa,
429 | REAL_TYPE _bb
430 | )
431 | {
432 | REAL_TYPE _x0, _x1;
433 | mp_float::two_one_mul_clip(
434 | _aa.hi(), _aa.lo(), _bb, _x1, _x0
435 | ) ;
436 |
437 | return ( dd_flt(_x1, _x0) ) ;
438 | }
439 |
440 | __inline_call dd_flt operator * (
441 | REAL_TYPE _aa,
442 | dd_flt const& _bb
443 | )
444 | { return ( _bb * _aa ) ;
445 | }
446 |
447 | __inline_call dd_flt operator * (
448 | dd_flt const& _aa,
449 | dd_flt const& _bb
450 | )
451 | {
452 | REAL_TYPE _x0, _x1;
453 | mp_float::two_two_mul_clip(
454 | _aa.hi(), _aa.lo(),
455 | _bb.hi(), _bb.lo(), _x1, _x0
456 | ) ;
457 |
458 | return ( dd_flt(_x1, _x0) ) ;
459 | }
460 |
461 | /*
462 | --------------------------------------------------------
463 | * double-double a / b operators
464 | --------------------------------------------------------
465 | */
466 |
467 | __inline_call dd_flt operator / (
468 | dd_flt const& _aa,
469 | REAL_TYPE _bb
470 | )
471 | {
472 | REAL_TYPE _x0, _x1;
473 | mp_float::two_one_div_clip(
474 | _aa.hi(), _aa.lo(), _bb, _x1, _x0
475 | ) ;
476 |
477 | return ( dd_flt(_x1, _x0) ) ;
478 | }
479 |
480 | __inline_call dd_flt operator / (
481 | REAL_TYPE _aa,
482 | dd_flt const& _bb
483 | )
484 | { return ( dd_flt(_aa) / _bb ) ;
485 | }
486 |
487 | __inline_call dd_flt operator / (
488 | dd_flt const& _aa,
489 | dd_flt const& _bb
490 | )
491 | {
492 | REAL_TYPE _x0, _x1;
493 | mp_float::two_two_div_clip(
494 | _aa.hi(), _aa.lo(),
495 | _bb.hi(), _bb.lo(), _x1, _x0
496 | ) ;
497 |
498 | return ( dd_flt(_x1, _x0) ) ;
499 | }
500 |
501 | /*
502 | --------------------------------------------------------
503 | * double-double equal operators
504 | --------------------------------------------------------
505 | */
506 |
507 | __inline_call bool operator == (
508 | dd_flt const& _aa,
509 | dd_flt const& _bb
510 | )
511 | { return _aa.hi() == _bb.hi() &&
512 | _aa.lo() == _bb.lo() ;
513 | }
514 |
515 | __inline_call bool operator != (
516 | dd_flt const& _aa,
517 | dd_flt const& _bb
518 | )
519 | { return _aa.hi() != _bb.hi() ||
520 | _aa.lo() != _bb.lo() ;
521 | }
522 |
523 | __inline_call bool operator < (
524 | dd_flt const& _aa,
525 | dd_flt const& _bb
526 | )
527 | { return _aa.hi() != _bb.hi() ?
528 | _aa.hi() < _bb.hi() :
529 | _aa.lo() < _bb.lo() ;
530 | }
531 |
532 | __inline_call bool operator > (
533 | dd_flt const& _aa,
534 | dd_flt const& _bb
535 | )
536 | { return _aa.hi() != _bb.hi() ?
537 | _aa.hi() > _bb.hi() :
538 | _aa.lo() > _bb.lo() ;
539 | }
540 |
541 | # undef REAL_TYPE
542 | # undef INDX_TYPE
543 |
544 |
545 | // }
546 |
547 | # endif//__DD_FLOAT__
548 |
549 |
550 |
551 |
--------------------------------------------------------------------------------
/expansion/ia_float.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | --------------------------------------------------------
4 | * MPFLOAT: multi-precision floating-point arithmetic.
5 | --------------------------------------------------------
6 | *
7 | * This program may be freely redistributed under the
8 | * condition that the copyright notices (including this
9 | * entire header) are not removed, and no compensation
10 | * is received through use of the software. Private,
11 | * research, and institutional use is free. You may
12 | * distribute modified versions of this code UNDER THE
13 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
14 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
15 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
16 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
17 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
18 | * of this code as part of a commercial system is
19 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
20 | * AUTHOR. (If you are not directly supplying this
21 | * code to a customer, and you are instead telling them
22 | * how they can obtain it for free, then you are not
23 | * required to make any arrangement with me.)
24 | *
25 | * Disclaimer: Neither I nor: Columbia University, The
26 | * Massachusetts Institute of Technology, The
27 | * University of Sydney, nor The National Aeronautics
28 | * and Space Administration warrant this code in any
29 | * way whatsoever. This code is provided "as-is" to be
30 | * used at your own risk.
31 | *
32 | --------------------------------------------------------
33 | *
34 | * Last updated: 10 April, 2020
35 | *
36 | * Copyright 2020--
37 | * Darren Engwirda
38 | * de2363@columbia.edu
39 | * https://github.com/dengwirda/
40 | *
41 | --------------------------------------------------------
42 | */
43 |
44 | // very simple, light-weight interval arithmetic for the
45 | // construction of "filtered" numerical predicates. Only
46 | // OP = {+, -, *,} implemented...
47 |
48 |
49 | # pragma once
50 |
51 | # ifndef __IA_FLOAT__
52 | # define __IA_FLOAT__
53 |
54 | # include "mp_basic.hpp"
55 |
56 | // namespace mp_float { // hmmm no...
57 |
58 | /*
59 | --------------------------------------------------------
60 | * IA-FLT: interval arithmetic
61 | --------------------------------------------------------
62 | */
63 |
64 | # define REAL_TYPE mp_float::real_type
65 | # define INDX_TYPE mp_float::indx_type
66 |
67 | // silliness with "volatile" to try to stop the compiler
68 | // from spuriously(!) optimising floating-point op's and
69 | // breaking rounding-mode behaviour...
70 |
71 | // really, proper compiler support is needed instead and
72 | // it's unclear whether this is actually reliable or not
73 |
74 | __normal_call REAL_TYPE add_up ( // for rnd up
75 | REAL_TYPE _aa, REAL_TYPE _bb
76 | )
77 | { REAL_TYPE volatile _cc = (+_aa) + (+_bb) ;
78 | return +_cc ;
79 | }
80 |
81 | __normal_call REAL_TYPE add_dn (
82 | REAL_TYPE _aa, REAL_TYPE _bb
83 | )
84 | { REAL_TYPE volatile _cc = (-_aa) + (-_bb) ;
85 | return -_cc ;
86 | }
87 |
88 | __normal_call REAL_TYPE sub_up (
89 | REAL_TYPE _aa, REAL_TYPE _bb
90 | )
91 | { REAL_TYPE volatile _cc = (+_aa) - (+_bb) ;
92 | return +_cc ;
93 | }
94 |
95 | __normal_call REAL_TYPE sub_dn (
96 | REAL_TYPE _aa, REAL_TYPE _bb
97 | )
98 | { REAL_TYPE volatile _cc = (+_bb) - (+_aa) ;
99 | return -_cc ;
100 | }
101 |
102 | __normal_call REAL_TYPE mul_up (
103 | REAL_TYPE _aa, REAL_TYPE _bb
104 | )
105 | { REAL_TYPE volatile _cc = (+_aa) * (+_bb) ;
106 | return +_cc ;
107 | }
108 |
109 | __normal_call REAL_TYPE mul_dn (
110 | REAL_TYPE _aa, REAL_TYPE _bb
111 | )
112 | { REAL_TYPE volatile _cc = (+_aa) * (-_bb) ;
113 | return -_cc ;
114 | }
115 |
116 | class ia_flt;
117 |
118 | __inline_call ia_flt operator + ( // fwd. dec's
119 | ia_flt const&,
120 | REAL_TYPE ) ;
121 | __inline_call ia_flt operator + (
122 | REAL_TYPE ,
123 | ia_flt const&) ;
124 | __inline_call ia_flt operator + (
125 | ia_flt const&,
126 | ia_flt const&) ;
127 |
128 | __inline_call ia_flt operator - (
129 | ia_flt const&,
130 | REAL_TYPE ) ;
131 | __inline_call ia_flt operator - (
132 | REAL_TYPE ,
133 | ia_flt const&) ;
134 | __inline_call ia_flt operator - (
135 | ia_flt const&,
136 | ia_flt const&) ;
137 |
138 | __inline_call ia_flt operator * (
139 | ia_flt const&,
140 | REAL_TYPE ) ;
141 | __inline_call ia_flt operator * (
142 | REAL_TYPE ,
143 | ia_flt const&) ;
144 | __inline_call ia_flt operator * (
145 | ia_flt const&,
146 | ia_flt const&) ;
147 |
148 | class ia_rnd
149 | {
150 | /*---------------------------------- interval FP-rnd type */
151 | public :
152 | int volatile _rndstate = 0;
153 |
154 | public :
155 | /*---------------------------------- floating pt rounding */
156 | __normal_call ia_rnd (
157 | )
158 | {
159 | _rndstate=fegetround();
160 |
161 | fesetround (FE_UPWARD);
162 | }
163 | __normal_call ~ia_rnd (
164 | )
165 | {
166 | fesetround (_rndstate);
167 | }
168 | } ;
169 |
170 | class ia_flt
171 | {
172 | /*---------------------------------- interval number type */
173 | public :
174 | typedef REAL_TYPE real_type;
175 | typedef INDX_TYPE indx_type;
176 |
177 | indx_type static constexpr _size = 2 ;
178 | indx_type static constexpr _xlen = 2 ;
179 |
180 | real_type _xdat [ 2 ] ;
181 |
182 | public :
183 | /*------------------------------ access to expansion bits */
184 | __inline_call real_type& up (
185 | )
186 | { return this->_xdat[1] ;
187 | }
188 | __inline_call real_type& lo (
189 | )
190 | { return this->_xdat[0] ;
191 | }
192 |
193 | __inline_call real_type const&up (
194 | ) const
195 | { return this->_xdat[1] ;
196 | }
197 | __inline_call real_type const&lo (
198 | ) const
199 | { return this->_xdat[0] ;
200 | }
201 |
202 | /*------------------------------ initialising constructor */
203 | __inline_call ia_flt (
204 | real_type _lo = real_type(+0.) ,
205 | real_type _up = real_type(+0.)
206 | )
207 | { this->_xdat[0] = _lo ;
208 | this->_xdat[1] = _up ;
209 | }
210 |
211 | __inline_call ia_flt ( // copy c'tor
212 | ia_flt const& _aa
213 | )
214 | {
215 | this->_xdat[0] = _aa.lo();
216 | this->_xdat[1] = _aa.up();
217 | }
218 |
219 | __inline_call ia_flt& operator = ( // assignment
220 | ia_flt const& _aa
221 | )
222 | {
223 | this->_xdat[0] = _aa.lo();
224 | this->_xdat[1] = _aa.up();
225 |
226 | return ( *this ) ;
227 | }
228 | __inline_call ia_flt& operator = ( // assignment
229 | real_type _aa
230 | )
231 | {
232 | this->_xdat[0] = (real_type)_aa;
233 | this->_xdat[1] = (real_type)_aa;
234 |
235 | return ( *this ) ;
236 | }
237 |
238 | /*---------------------------------------- set from float */
239 | __inline_call void_type from_add (
240 | real_type _aa,
241 | real_type _bb
242 | )
243 | {
244 | lo() = add_dn(_aa, _bb) ;
245 | up() = add_up(_aa, _bb) ;
246 | }
247 |
248 | __inline_call void_type from_sub (
249 | real_type _aa,
250 | real_type _bb
251 | )
252 | {
253 | lo() = sub_dn(_aa, _bb) ;
254 | up() = sub_up(_aa, _bb) ;
255 | }
256 |
257 | __inline_call void_type from_mul (
258 | real_type _aa,
259 | real_type _bb
260 | )
261 | {
262 | lo() = mul_dn(_aa, _bb) ;
263 | up() = mul_up(_aa, _bb) ;
264 | }
265 |
266 | /*---------------------------------------- math operators */
267 | __inline_call ia_flt operator + (
268 | ) const
269 | { return ia_flt(+lo(), +up());
270 | }
271 |
272 | __inline_call ia_flt operator - (
273 | ) const
274 | { return ia_flt(-lo(), -up());
275 | }
276 |
277 | __inline_call ia_flt& operator+= ( // via double
278 | real_type _aa
279 | )
280 | {
281 | ia_flt _tt = *this + _aa ;
282 |
283 | up() = _tt.up();
284 | lo() = _tt.lo();
285 |
286 | return ( *this ) ;
287 | }
288 | __inline_call ia_flt& operator-= (
289 | real_type _aa
290 | )
291 | {
292 | ia_flt _tt = *this - _aa ;
293 |
294 | up() = _tt.up();
295 | lo() = _tt.lo();
296 |
297 | return ( *this ) ;
298 | }
299 | __inline_call ia_flt& operator*= (
300 | real_type _aa
301 | )
302 | {
303 | ia_flt _tt = *this * _aa ;
304 |
305 | up() = _tt.up();
306 | lo() = _tt.lo();
307 |
308 | return ( *this ) ;
309 | }
310 |
311 | __inline_call ia_flt& operator+= ( // via ia_flt
312 | ia_flt const& _aa
313 | )
314 | {
315 | ia_flt _tt = *this + _aa ;
316 |
317 | up() = _tt.up();
318 | lo() = _tt.lo();
319 |
320 | return ( *this ) ;
321 | }
322 | __inline_call ia_flt& operator-= (
323 | ia_flt const& _aa
324 | )
325 | {
326 | ia_flt _tt = *this - _aa ;
327 |
328 | up() = _tt.up();
329 | lo() = _tt.lo();
330 |
331 | return ( *this ) ;
332 | }
333 | __inline_call ia_flt& operator*= (
334 | ia_flt const& _aa
335 | )
336 | {
337 | ia_flt _tt = *this * _aa ;
338 |
339 | up() = _tt.up();
340 | lo() = _tt.lo();
341 |
342 | return ( *this ) ;
343 | }
344 |
345 | /*---------------------------------------- mid-rad. forms */
346 | __inline_call real_type mid (
347 | ) const
348 | {
349 | real_type _mm = lo() + up() ;
350 |
351 | if (!std::isfinite(_mm))
352 | {
353 | _mm =
354 | (lo() / (real_type)+2.)+
355 | (up() / (real_type)+2.);
356 | }
357 | else
358 | {
359 | _mm /= (real_type)+2. ;
360 | }
361 |
362 | return _mm ;
363 | }
364 |
365 | __inline_call real_type rad (
366 | ) const
367 | {
368 | real_type _r1 = up() - mid() ;
369 | real_type _r2 = mid() - lo() ;
370 |
371 | return std::max(_r1, _r2) ;
372 | }
373 |
374 | } ;
375 |
376 | /*
377 | --------------------------------------------------------
378 | * interval-float a + b operators
379 | --------------------------------------------------------
380 | */
381 |
382 | __inline_call ia_flt operator + (
383 | ia_flt const& _aa,
384 | REAL_TYPE _bb
385 | )
386 | {
387 | REAL_TYPE _lo, _up;
388 |
389 | _lo = add_dn(_aa.lo(), _bb) ;
390 | _up = add_up(_aa.up(), _bb) ;
391 |
392 | return ( ia_flt(_lo, _up) ) ;
393 | }
394 |
395 | __inline_call ia_flt operator + (
396 | REAL_TYPE _aa,
397 | ia_flt const& _bb
398 | )
399 | {
400 | REAL_TYPE _lo, _up;
401 |
402 | _lo = add_dn(_aa, _bb.lo()) ;
403 | _up = add_up(_aa, _bb.up()) ;
404 |
405 | return ( ia_flt(_lo, _up) ) ;
406 | }
407 |
408 | __inline_call ia_flt operator + (
409 | ia_flt const& _aa,
410 | ia_flt const& _bb
411 | )
412 | {
413 | REAL_TYPE _lo, _up;
414 |
415 | _lo = add_dn(_aa.lo(), _bb.lo()) ;
416 | _up = add_up(_aa.up(), _bb.up()) ;
417 |
418 | return ( ia_flt(_lo, _up) ) ;
419 | }
420 |
421 | /*
422 | --------------------------------------------------------
423 | * interval-float a - b operators
424 | --------------------------------------------------------
425 | */
426 |
427 | __inline_call ia_flt operator - (
428 | ia_flt const& _aa,
429 | REAL_TYPE _bb
430 | )
431 | {
432 | REAL_TYPE _lo, _up;
433 |
434 | _lo = sub_dn(_aa.lo(), _bb) ;
435 | _up = sub_up(_aa.up(), _bb) ;
436 |
437 | return ( ia_flt(_lo, _up) ) ;
438 | }
439 |
440 | __inline_call ia_flt operator - (
441 | REAL_TYPE _aa,
442 | ia_flt const& _bb
443 | )
444 | {
445 | REAL_TYPE _lo, _up;
446 |
447 | _lo = sub_dn(_aa, _bb.up()) ;
448 | _up = sub_up(_aa, _bb.lo()) ;
449 |
450 | return ( ia_flt(_lo, _up) ) ;
451 | }
452 |
453 | __inline_call ia_flt operator - (
454 | ia_flt const& _aa,
455 | ia_flt const& _bb
456 | )
457 | {
458 | REAL_TYPE _lo, _up;
459 |
460 | _lo = sub_dn(_aa.lo(), _bb.up()) ;
461 | _up = sub_up(_aa.up(), _bb.lo()) ;
462 |
463 | return ( ia_flt(_lo, _up) ) ;
464 | }
465 |
466 | /*
467 | --------------------------------------------------------
468 | * interval-float a * b operators
469 | --------------------------------------------------------
470 | */
471 |
472 | __inline_call ia_flt operator * (
473 | ia_flt const& _aa,
474 | REAL_TYPE _bb
475 | )
476 | {
477 | REAL_TYPE _lo, _up;
478 |
479 | if (_bb > (REAL_TYPE) +0.)
480 | {
481 | _lo = mul_dn(_aa.lo(), _bb) ;
482 | _up = mul_up(_aa.up(), _bb) ;
483 | }
484 | else
485 | if (_bb < (REAL_TYPE)+0.)
486 | {
487 | _lo = mul_dn(_aa.up(), _bb) ;
488 | _up = mul_up(_aa.lo(), _bb) ;
489 | }
490 | else
491 | {
492 | _lo = (REAL_TYPE)+0. ;
493 | _up = (REAL_TYPE)+0. ;
494 | }
495 |
496 | return ( ia_flt(_lo, _up) ) ;
497 | }
498 |
499 | __inline_call ia_flt operator * (
500 | REAL_TYPE _aa,
501 | ia_flt const& _bb
502 | )
503 | { return ( _bb * _aa ) ;
504 | }
505 |
506 | __normal_call ia_flt operator * (
507 | ia_flt const& _aa,
508 | ia_flt const& _bb
509 | )
510 | {
511 | REAL_TYPE _lo, _up;
512 |
513 | if (_aa.lo() < (REAL_TYPE)+0.)
514 | {
515 | if (_aa.up() > (REAL_TYPE)+0.)
516 | {
517 | if (_bb.lo() < (REAL_TYPE)+0.)
518 | {
519 | if (_bb.up() > (REAL_TYPE)+0.) // mix * mix
520 | {
521 | REAL_TYPE _l1, _l2;
522 | _l1 = mul_dn(_aa.lo(), _bb.up());
523 | _l2 = mul_dn(_aa.up(), _bb.lo());
524 | _lo = std::min(_l1, _l2);
525 |
526 | REAL_TYPE _u1, _u2;
527 | _u1 = mul_up(_aa.lo(), _bb.lo());
528 | _u2 = mul_up(_aa.up(), _bb.up());
529 | _up = std::min(_u1, _u2);
530 | }
531 | else // mix * -ve
532 | {
533 | _lo = mul_dn(_aa.up(), _bb.lo());
534 | _up = mul_up(_aa.lo(), _bb.lo());
535 | }
536 | }
537 | else
538 | {
539 | if (_bb.up() > (REAL_TYPE)+0.) // mix * +ve
540 | {
541 | _lo = mul_dn(_aa.lo(), _bb.up());
542 | _up = mul_up(_aa.up(), _bb.up());
543 | }
544 | else // mix * +0.
545 | {
546 | _lo = (REAL_TYPE)+0. ;
547 | _up = (REAL_TYPE)+0. ;
548 | }
549 | }
550 | }
551 | else
552 | {
553 | if (_bb.lo() < (REAL_TYPE)+0.)
554 | {
555 | if (_bb.up() > (REAL_TYPE)+0.) // -ve * mix
556 | {
557 | _lo = mul_dn(_aa.lo(), _bb.up());
558 | _up = mul_up(_aa.lo(), _bb.lo());
559 | }
560 | else // -ve * -ve
561 | {
562 | _lo = mul_dn(_aa.up(), _bb.up());
563 | _up = mul_up(_aa.lo(), _bb.lo());
564 | }
565 | }
566 | else
567 | {
568 | if (_bb.up() > (REAL_TYPE)+0.) // -ve * +ve
569 | {
570 | _lo = mul_dn(_aa.lo(), _bb.up());
571 | _up = mul_up(_aa.up(), _bb.lo());
572 | }
573 | else // -ve * +0.
574 | {
575 | _lo = (REAL_TYPE)+0. ;
576 | _up = (REAL_TYPE)+0. ;
577 | }
578 | }
579 | }
580 | }
581 | else
582 | {
583 | if (_aa.up() > (REAL_TYPE)+0.)
584 | {
585 | if (_bb.lo() < (REAL_TYPE)+0.)
586 | {
587 | if (_bb.up() > (REAL_TYPE)+0.) // +ve * mix
588 | {
589 | _lo = mul_dn(_aa.up(), _bb.lo());
590 | _up = mul_up(_aa.up(), _bb.up());
591 | }
592 | else // +ve * -ve
593 | {
594 | _lo = mul_dn(_aa.up(), _bb.lo());
595 | _up = mul_up(_aa.lo(), _bb.up());
596 | }
597 | }
598 | else
599 | {
600 | if (_bb.up() > (REAL_TYPE)+0.) // +ve * +ve
601 | {
602 | _lo = mul_dn(_aa.lo(), _bb.lo());
603 | _up = mul_up(_aa.up(), _bb.up());
604 | }
605 | else // +ve * +0.
606 | {
607 | _lo = (REAL_TYPE)+0. ;
608 | _up = (REAL_TYPE)+0. ;
609 | }
610 | }
611 | }
612 | else // -ve * ???
613 | {
614 | _lo = (REAL_TYPE)+0. ;
615 | _up = (REAL_TYPE)+0. ;
616 | }
617 | }
618 |
619 | return ( ia_flt(_lo, _up) ) ;
620 | }
621 |
622 | /*
623 | --------------------------------------------------------
624 | * interval-float a ^ 2 operators
625 | --------------------------------------------------------
626 | */
627 |
628 | __normal_call ia_flt sqr (
629 | ia_flt const& _aa
630 | )
631 | {
632 | REAL_TYPE _lo, _up;
633 |
634 | if (_aa.up() < (REAL_TYPE)+0.)
635 | {
636 | _lo = mul_dn(_aa.up(), _aa.up());
637 | _up = mul_up(_aa.lo(), _aa.lo());
638 | }
639 | else
640 | if (_aa.lo() > (REAL_TYPE)+0.)
641 | {
642 | _lo = mul_dn(_aa.lo(), _aa.lo());
643 | _up = mul_up(_aa.up(), _aa.up());
644 | }
645 | else
646 | {
647 | if (-_aa.lo() > +_aa.up())
648 | {
649 | _lo = (REAL_TYPE)+0.;
650 | _up = mul_up(_aa.lo(), _aa.lo());
651 | }
652 | else
653 | {
654 | _lo = (REAL_TYPE)+0.;
655 | _up = mul_up(_aa.up(), _aa.up());
656 | }
657 | }
658 |
659 | return ( ia_flt(_lo, _up) ) ;
660 | }
661 |
662 | # undef REAL_TYPE
663 | # undef INDX_TYPE
664 |
665 |
666 | // }
667 |
668 | # endif//__IA_FLOAT__
669 |
670 |
671 |
672 |
--------------------------------------------------------------------------------
/expansion/mp_basic.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | --------------------------------------------------------
4 | * MPFLOAT: multi-precision floating-point arithmetic.
5 | --------------------------------------------------------
6 | *
7 | * These are the low-level multi-precision kernels ---
8 | * computing elementary operations on "expansions" of
9 | * floating-point numbers such that rounding error is
10 | * eliminated. See Shewchuk for more detail:
11 | *
12 | * J. R. Shewchuk (1997): Adaptive Precision Floating-
13 | * Point Arithmetic & Fast Robust Geometric Predicates
14 | * Discrete & Computational Geometry, 18, pp. 305-363.
15 | *
16 | * This header is adapted from Shewchuk's original C89
17 | * source (predicates.c).
18 | *
19 | * Related "clipped" operations for "double-double"
20 | * arithmetic are also included. Here expansion length
21 | * is capped at 2, with subsequent bits truncated:
22 | *
23 | * M. Joldes, J-M. Muller, V. Popescu (2017): Tight &
24 | * rigourous error bounds for basic building blocks of
25 | * double-word arithmetic. ACM Transactions on
26 | * Mathematical Software, ACM, 44 (2), pp. 1-27.
27 | *
28 | * Y. Hida, X. Li, and D. Bailey (2000): Quad-double
29 | * arithmetic: Algorithms, implementation, and
30 | * application. In the 15th IEEE Symposium on Computer
31 | * Arithmetic, pp. 155-162.
32 | *
33 | --------------------------------------------------------
34 | *
35 | * This program may be freely redistributed under the
36 | * condition that the copyright notices (including this
37 | * entire header) are not removed, and no compensation
38 | * is received through use of the software. Private,
39 | * research, and institutional use is free. You may
40 | * distribute modified versions of this code UNDER THE
41 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
42 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
43 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
44 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
45 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
46 | * of this code as part of a commercial system is
47 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
48 | * AUTHOR. (If you are not directly supplying this
49 | * code to a customer, and you are instead telling them
50 | * how they can obtain it for free, then you are not
51 | * required to make any arrangement with me.)
52 | *
53 | * Disclaimer: Neither I nor: Columbia University, The
54 | * Massachusetts Institute of Technology, The
55 | * University of Sydney, nor The National Aeronautics
56 | * and Space Administration warrant this code in any
57 | * way whatsoever. This code is provided "as-is" to be
58 | * used at your own risk.
59 | *
60 | --------------------------------------------------------
61 | *
62 | * Last updated: 16 April, 2020
63 | *
64 | * Copyright 2020--
65 | * Darren Engwirda
66 | * de2363@columbia.edu
67 | * https://github.com/dengwirda/
68 | *
69 | --------------------------------------------------------
70 | */
71 |
72 | # pragma once
73 |
74 | # ifndef __MP_BASIC__
75 | # define __MP_BASIC__
76 |
77 | namespace mp_float {
78 |
79 | # define REAL_TYPE mp_float::real_type
80 | # define INDX_TYPE mp_float::indx_type
81 |
82 | /*------------------------ have hardware FMA support? */
83 |
84 | # if defined(FP_FAST_FMA)
85 | bool constexpr _has_fma =
86 | std::is_same::value;
87 | # elif defined(FP_FAST_FMAF)
88 | bool constexpr _has_fma =
89 | std::is_same::value;
90 | # else
91 | bool constexpr _has_fma = false;
92 | # endif
93 |
94 | /*
95 | --------------------------------------------------------
96 | * multi-precision initialisation, a'la shewchuk
97 | --------------------------------------------------------
98 | */
99 |
100 | REAL_TYPE _splitter;
101 | REAL_TYPE _epsilon ;
102 |
103 | __normal_call void exactinit (
104 | )
105 | {
106 | /*-------------- find machine eps, etc, a'la shewchuk */
107 | INDX_TYPE _alternate = +1 ;
108 | REAL_TYPE _lastcheck ;
109 | REAL_TYPE _halve = +0.5;
110 | REAL_TYPE _check = +1.0;
111 |
112 | /*-------------- find eps: bisect until 1. + eps ~ 1. */
113 |
114 | _epsilon = _splitter = +1.00 ;
115 |
116 | do {
117 | _lastcheck = _check;
118 | _epsilon *= _halve;
119 |
120 | if (_alternate)
121 | _splitter *= +2.00 ;
122 |
123 | _alternate = !_alternate ;
124 |
125 | _check = 1.00 + _epsilon ;
126 | }
127 | while (_check != +1.00 &&
128 | _check != _lastcheck) ;
129 |
130 | _splitter += 1.00 ;
131 | }
132 |
133 | /*
134 | --------------------------------------------------------
135 | * multi-precision "add" routines, a'la shewchuk
136 | --------------------------------------------------------
137 | */
138 |
139 | __inline_call void one_one_add_fast (
140 | REAL_TYPE _aa, REAL_TYPE _bb,
141 | REAL_TYPE &_x1, REAL_TYPE &_x0
142 | )
143 | {
144 | REAL_TYPE _bvirt;
145 | _x1 = _aa + _bb;
146 | _bvirt = _x1 - _aa;
147 | _x0 = _bb - _bvirt;
148 | }
149 |
150 | __inline_call void one_one_add_full (
151 | REAL_TYPE _aa, REAL_TYPE _bb,
152 | REAL_TYPE &_x1, REAL_TYPE &_x0
153 | )
154 | {
155 | REAL_TYPE _bvirt, _avirt;
156 | _x1 = _aa + _bb;
157 | _bvirt = _x1 - _aa;
158 | _avirt = _x1 - _bvirt;
159 |
160 | REAL_TYPE _bround, _around;
161 | _bround = _bb - _bvirt;
162 | _around = _aa - _avirt;
163 | _x0 = _around + _bround;
164 | }
165 |
166 | __inline_call void two_one_add_full (
167 | REAL_TYPE _a1, REAL_TYPE _a0,
168 | REAL_TYPE _bb,
169 | REAL_TYPE &_x2, REAL_TYPE &_x1,
170 | REAL_TYPE &_x0
171 | )
172 | {
173 | REAL_TYPE _tt;
174 | one_one_add_full(_a0, _bb, _tt, _x0
175 | ) ;
176 | one_one_add_full(_a1, _tt, _x2, _x1
177 | ) ;
178 | }
179 |
180 | __inline_call void two_one_add_clip ( // dd_flt
181 | REAL_TYPE _a1, REAL_TYPE _a0,
182 | REAL_TYPE _bb,
183 | REAL_TYPE &_x1, REAL_TYPE &_x0
184 | )
185 | {
186 | REAL_TYPE _t0, _t1 ;
187 | one_one_add_full(_a1, _bb, _t1, _t0
188 | ) ;
189 |
190 | _t0 = _t0 + _a0 ;
191 |
192 | one_one_add_fast(_t1, _t0, _x1, _x0
193 | ) ;
194 | }
195 |
196 | __inline_call void two_two_add_full (
197 | REAL_TYPE _a1, REAL_TYPE _a0,
198 | REAL_TYPE _b1, REAL_TYPE _b0,
199 | REAL_TYPE &_x3, REAL_TYPE &_x2,
200 | REAL_TYPE &_x1, REAL_TYPE &_x0
201 | )
202 | {
203 | REAL_TYPE _t1, _t0 ;
204 | two_one_add_full(_a1, _a0, _b0, _t1,
205 | _t0, _x0
206 | ) ;
207 | two_one_add_full(_t1, _t0, _b1, _x3,
208 | _x2, _x1
209 | ) ;
210 | }
211 |
212 | __inline_call void two_two_add_clip ( // dd_flt
213 | REAL_TYPE _a1, REAL_TYPE _a0,
214 | REAL_TYPE _b1, REAL_TYPE _b0,
215 | REAL_TYPE &_x1, REAL_TYPE &_x0
216 | )
217 | {
218 | REAL_TYPE _t1, _t0 ;
219 | REAL_TYPE _s1, _s0 ;
220 | REAL_TYPE _w1, _w0 ;
221 | one_one_add_full(_a1, _b1, _s1, _s0
222 | ) ;
223 | one_one_add_full(_a0, _b0, _t1, _t0
224 | ) ;
225 |
226 | _s0 = _s0 + _t1 ;
227 |
228 | one_one_add_fast(_s1, _s0, _w1, _w0
229 | ) ;
230 |
231 | _w0 = _w0 + _t0 ;
232 |
233 | one_one_add_fast(_w1, _w0, _x1, _x0
234 | ) ;
235 | }
236 |
237 | /*
238 | --------------------------------------------------------
239 | * multi-precision "sub" routines, a'la shewchuk
240 | --------------------------------------------------------
241 | */
242 |
243 | __inline_call void one_one_sub_fast (
244 | REAL_TYPE _aa, REAL_TYPE _bb,
245 | REAL_TYPE &_x1, REAL_TYPE &_x0
246 | )
247 | {
248 | REAL_TYPE _bvirt;
249 | _x1 = _aa - _bb;
250 | _bvirt = _aa - _x1;
251 | _x0 = _bvirt - _bb;
252 | }
253 |
254 | __inline_call void one_one_sub_full (
255 | REAL_TYPE _aa, REAL_TYPE _bb,
256 | REAL_TYPE &_x1, REAL_TYPE &_x0
257 | )
258 | {
259 | REAL_TYPE _bvirt, _avirt;
260 | _x1 = _aa - _bb;
261 | _bvirt = _aa - _x1;
262 | _avirt = _x1 + _bvirt;
263 |
264 | REAL_TYPE _bround, _around;
265 | _bround = _bvirt - _bb;
266 | _around = _aa - _avirt;
267 | _x0 = _around + _bround;
268 | }
269 |
270 | __inline_call void two_one_sub_full (
271 | REAL_TYPE _a1, REAL_TYPE _a0,
272 | REAL_TYPE _bb,
273 | REAL_TYPE &_x2, REAL_TYPE &_x1,
274 | REAL_TYPE &_x0
275 | )
276 | {
277 | REAL_TYPE _tt;
278 | one_one_sub_full(_a0, _bb, _tt, _x0
279 | ) ;
280 | one_one_add_full(_a1, _tt, _x2, _x1
281 | ) ;
282 | }
283 |
284 | __inline_call void two_one_sub_clip ( // dd_flt
285 | REAL_TYPE _a1, REAL_TYPE _a0,
286 | REAL_TYPE _bb,
287 | REAL_TYPE &_x1, REAL_TYPE &_x0
288 | )
289 | {
290 | REAL_TYPE _t0, _t1 ;
291 | one_one_sub_full(_a1, _bb, _t1, _t0
292 | ) ;
293 |
294 | _t0 = _t0 + _a0 ;
295 |
296 | one_one_add_fast(_t1, _t0, _x1, _x0
297 | ) ;
298 | }
299 |
300 | __inline_call void two_two_sub_full (
301 | REAL_TYPE _a1, REAL_TYPE _a0,
302 | REAL_TYPE _b1, REAL_TYPE _b0,
303 | REAL_TYPE &_x3, REAL_TYPE &_x2,
304 | REAL_TYPE &_x1, REAL_TYPE &_x0
305 | )
306 | {
307 | REAL_TYPE _t1, _t0 ;
308 | two_one_sub_full(_a1, _a0, _b0, _t1,
309 | _t0, _x0
310 | ) ;
311 | two_one_sub_full(_t1, _t0, _b1, _x3,
312 | _x2, _x1
313 | ) ;
314 | }
315 |
316 | __inline_call void two_two_sub_clip ( // dd_flt
317 | REAL_TYPE _a1, REAL_TYPE _a0,
318 | REAL_TYPE _b1, REAL_TYPE _b0,
319 | REAL_TYPE &_x1, REAL_TYPE &_x0
320 | )
321 | {
322 | REAL_TYPE _s0, _s1 ;
323 | REAL_TYPE _t0, _t1 ;
324 | REAL_TYPE _w0, _w1 ;
325 | one_one_sub_full(_a1, _b1, _s1, _s0
326 | ) ;
327 | one_one_sub_full(_a0, _b0, _t1, _t0
328 | ) ;
329 |
330 | _s0 = _s0 + _t1 ;
331 |
332 | one_one_add_fast(_s1, _s0, _w1, _w0
333 | ) ;
334 |
335 | _w0 = _w0 + _t0 ;
336 |
337 | one_one_add_fast(_w1, _w0, _x1, _x0
338 | ) ;
339 | }
340 |
341 | /*
342 | --------------------------------------------------------
343 | * multi-precision "mul" routines, a'la shewchuk
344 | --------------------------------------------------------
345 | */
346 |
347 | __inline_call void one_split (
348 | REAL_TYPE _aa,
349 | REAL_TYPE &_x1, REAL_TYPE &_x0
350 | )
351 | {
352 | REAL_TYPE _cc, _ab ;
353 | _cc = _aa * _splitter;
354 | _ab = _cc - _aa;
355 | _x1 = _cc - _ab;
356 | _x0 = _aa - _x1;
357 | }
358 |
359 | __inline_call void one_one_mul_full (
360 | REAL_TYPE _aa, REAL_TYPE _bb,
361 | REAL_TYPE &_x1, REAL_TYPE &_x0
362 | )
363 | {
364 | if constexpr (_has_fma)
365 | {
366 | _x1 = _aa * _bb;
367 | _x0 = fma(_aa, _bb, -_x1);
368 | }
369 | else // use fpu
370 | {
371 | REAL_TYPE _ah, _al, _bh, _bl;
372 | _x1 = _aa * _bb;
373 | one_split (_aa, _ah, _al);
374 | one_split (_bb, _bh, _bl);
375 |
376 | REAL_TYPE _err1, _err2, _err3;
377 | _err1 = _x1 - (_ah * _bh);
378 | _err2 = _err1 - (_al * _bh);
379 | _err3 = _err2 - (_ah * _bl);
380 | _x0 = (_al * _bl) - _err3;
381 | }
382 | }
383 |
384 | __inline_call void one_one_mul_full (
385 | REAL_TYPE _aa,
386 | REAL_TYPE _bb, REAL_TYPE _bh,
387 | REAL_TYPE _bl,
388 | REAL_TYPE &_x1, REAL_TYPE &_x0
389 | )
390 | {
391 | if constexpr (_has_fma)
392 | {
393 | _x1 = _aa * _bb;
394 | _x0 = fma(_aa, _bb, -_x1);
395 | }
396 | else // use fpu
397 | {
398 | REAL_TYPE _ah, _al;
399 | _x1 = _aa * _bb;
400 | one_split (_aa, _ah, _al);
401 |
402 | REAL_TYPE _err1, _err2, _err3;
403 | _err1 = _x1 - (_ah * _bh);
404 | _err2 = _err1 - (_al * _bh);
405 | _err3 = _err2 - (_ah * _bl);
406 | _x0 = (_al * _bl) - _err3;
407 | }
408 | }
409 |
410 | __inline_call void one_one_mul_full (
411 | REAL_TYPE _aa, REAL_TYPE _ah,
412 | REAL_TYPE _al,
413 | REAL_TYPE _bb, REAL_TYPE _bh,
414 | REAL_TYPE _bl,
415 | REAL_TYPE &_x1, REAL_TYPE &_x0
416 | )
417 | {
418 | if constexpr (_has_fma)
419 | {
420 | _x1 = _aa * _bb;
421 | _x0 = fma(_aa, _bb, -_x1);
422 | }
423 | else // use fpu
424 | {
425 | _x1 = _aa * _bb;
426 |
427 | REAL_TYPE _err1, _err2, _err3;
428 | _err1 = _x1 - (_ah * _bh);
429 | _err2 = _err1 - (_al * _bh);
430 | _err3 = _err2 - (_ah * _bl);
431 | _x0 = (_al * _bl) - _err3;
432 | }
433 | }
434 |
435 | __inline_call void one_one_sqr_full (
436 | REAL_TYPE _aa,
437 | REAL_TYPE &_x1, REAL_TYPE &_x0
438 | )
439 | {
440 | if constexpr (_has_fma)
441 | {
442 | _x1 = _aa * _aa;
443 | _x0 = fma(_aa, _aa, -_x1);
444 | }
445 | else // use fpu
446 | {
447 | REAL_TYPE _ah, _al;
448 | _x1 = _aa * _aa;
449 | one_split (_aa, _ah, _al);
450 |
451 | REAL_TYPE _err1, _err3;
452 | _err1 = _x1 - (_ah * _ah);
453 | _err3 = _err1 - ((_ah + _ah) * _al);
454 | _x0 = (_al * _al) - _err3;
455 | }
456 | }
457 |
458 | __inline_call void one_one_sqr_full (
459 | REAL_TYPE _aa, REAL_TYPE _ah,
460 | REAL_TYPE _al,
461 | REAL_TYPE &_x1, REAL_TYPE &_x0
462 | )
463 | {
464 | if constexpr (_has_fma)
465 | {
466 | _x1 = _aa * _aa;
467 | _x0 = fma(_aa, _aa, -_x1);
468 | }
469 | else // use fpu
470 | {
471 | _x1 = _aa * _aa;
472 |
473 | REAL_TYPE _err1, _err3;
474 | _err1 = _x1 - (_ah * _ah);
475 | _err3 = _err1 - ((_ah + _ah) * _al);
476 | _x0 = (_al * _al) - _err3;
477 | }
478 | }
479 |
480 | __inline_call void two_one_mul_full (
481 | REAL_TYPE _a1, REAL_TYPE _a0,
482 | REAL_TYPE _bb,
483 | REAL_TYPE &_x3, REAL_TYPE &_x2,
484 | REAL_TYPE &_x1, REAL_TYPE &_x0
485 | )
486 | {
487 | if constexpr (_has_fma)
488 | {
489 | REAL_TYPE _t0, _t1, _t2, _t3 ;
490 | one_one_mul_full(_a0, _bb, _t2, _x0
491 | ) ;
492 | one_one_mul_full(_a1, _bb, _t1, _t0
493 | ) ;
494 |
495 | one_one_add_full(_t2, _t0, _t3, _x1
496 | ) ;
497 | one_one_add_fast(_t1, _t3, _x3, _x2
498 | ) ;
499 | }
500 | else // use fpu
501 | {
502 | REAL_TYPE _bh, _bl;
503 | REAL_TYPE _t0, _t1, _t2, _t3 ;
504 | one_split(_bb, _bh, _bl) ;
505 |
506 | one_one_mul_full(_a0, _bb, _bh, _bl,
507 | _t2, _x0
508 | ) ;
509 | one_one_mul_full(_a1, _bb, _bh, _bl,
510 | _t1, _t0
511 | ) ;
512 |
513 | one_one_add_full(_t2, _t0, _t3, _x1
514 | ) ;
515 | one_one_add_fast(_t1, _t3, _x3, _x2
516 | ) ;
517 | }
518 | }
519 |
520 | __inline_call void two_one_mul_clip ( // dd_flt
521 | REAL_TYPE _a1, REAL_TYPE _a0,
522 | REAL_TYPE _bb,
523 | REAL_TYPE &_x1, REAL_TYPE &_x0
524 | )
525 | {
526 | if constexpr (_has_fma)
527 | {
528 | REAL_TYPE _t0, _t1;
529 | one_one_mul_full(_a1, _bb, _t1, _t0
530 | ) ;
531 |
532 | _t0 = fma(_a0, _bb, _t0);
533 |
534 | one_one_add_fast(_t1, _t0, _x1, _x0
535 | ) ;
536 | }
537 | else // use fpu
538 | {
539 | REAL_TYPE _t0, _t1, _ss ;
540 | one_one_mul_full(_a1, _bb, _t1, _t0
541 | ) ;
542 |
543 | _ss = _a0 * _bb ;
544 | _t0 = _t0 + _ss ;
545 |
546 | one_one_add_fast(_t1, _t0, _x1, _x0
547 | ) ;
548 | }
549 | }
550 |
551 | __inline_call void two_two_mul_clip ( // dd_flt
552 | REAL_TYPE _a1, REAL_TYPE _a0,
553 | REAL_TYPE _b1, REAL_TYPE _b0,
554 | REAL_TYPE &_x1, REAL_TYPE &_x0
555 | )
556 | {
557 | if constexpr (_has_fma)
558 | {
559 | REAL_TYPE _t0, _t1, _ss;
560 | one_one_mul_full(_a1, _b1, _t1, _t0
561 | ) ;
562 |
563 | _ss = _a0 * _b0 ;
564 | _ss = fma(_a1, _b0, _ss);
565 | _ss = fma(_a0, _b0, _ss);
566 |
567 | _t0 = _t0 + _ss ;
568 |
569 | one_one_add_fast(_t1, _t0, _x1, _x0
570 | ) ;
571 | }
572 | else
573 | {
574 | REAL_TYPE _t0, _t1;
575 | REAL_TYPE _ss, _s1, _s2, _s3;
576 | one_one_mul_full(_a1, _b1, _t1, _t0
577 | ) ;
578 |
579 | _s1 = _a0 * _b0 ;
580 | _s2 = _a1 * _b0 ;
581 | _s3 = _a0 * _b1 ;
582 | _ss = _s1 + _s2 + _s3 ;
583 |
584 | _t0 = _t0 + _ss ;
585 |
586 | one_one_add_fast(_t1, _t0, _x1, _x0
587 | ) ;
588 | }
589 | }
590 |
591 | __inline_call void two_one_div_clip ( // dd_flt
592 | REAL_TYPE _a1, REAL_TYPE _a0,
593 | REAL_TYPE _bb,
594 | REAL_TYPE &_x1, REAL_TYPE &_x0
595 | )
596 | {
597 | REAL_TYPE _t0, _t1, _p1, _p0, _dd;
598 | _t1 = _a1 / _bb;
599 |
600 | one_one_mul_full(_t1, _bb, _p1, _p0
601 | ) ;
602 |
603 | _dd = _a1 - _p1;
604 | _dd = _dd - _p0;
605 | _dd = _dd + _a0;
606 |
607 | _t0 = _dd / _bb;
608 |
609 | one_one_add_fast(_t1, _t0, _x1, _x0
610 | ) ;
611 | }
612 |
613 | __inline_call void two_two_div_clip ( // dd_flt
614 | REAL_TYPE _a1, REAL_TYPE _a0,
615 | REAL_TYPE _b1, REAL_TYPE _b0,
616 | REAL_TYPE &_x1, REAL_TYPE &_x0
617 | )
618 | {
619 | REAL_TYPE _t0, _t1, _ee;
620 | _t1 = _a1 / _b1 ;
621 |
622 | REAL_TYPE _r0, _r1 ;
623 | REAL_TYPE _w0, _w1 ;
624 | two_one_mul_clip(_b1, _b0, _t1,
625 | _r1, _r0 // rr = bb * t1
626 | ) ;
627 | two_two_sub_clip(_a1, _a0, _r1, _r0,
628 | _w1, _w0 // ww = aa - rr
629 | ) ;
630 |
631 | _t0 = _w1 / _b1 ;
632 |
633 | REAL_TYPE _u0, _u1 ;
634 | two_one_mul_clip(_b1, _b0, _t0,
635 | _r1, _r0 // rr = bb * t0
636 | ) ;
637 | two_two_sub_clip(_w1, _w0, _r1, _r0,
638 | _u1, _u0 // uu = ww - rr
639 | ) ;
640 |
641 | _ee = _u1 / _b1 ;
642 |
643 | REAL_TYPE _q0, _q1 ; // t1 + t0 + ee
644 | one_one_add_fast(_t1, _t0, _q1, _q0
645 | ) ;
646 | two_one_add_clip(_q1, _q0, _ee,
647 | _x1, _x0
648 | ) ;
649 | }
650 |
651 | # undef REAL_TYPE
652 | # undef INDX_TYPE
653 |
654 |
655 | }
656 |
657 | # endif//__MP_BASIC__
658 |
659 |
660 |
661 |
--------------------------------------------------------------------------------
/expansion/mp_float.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | --------------------------------------------------------
4 | * MPFLOAT: multi-precision floating-point arithmetic.
5 | --------------------------------------------------------
6 | *
7 | * These are the high-level multi-precision objects ---
8 | * computing elementary operations on "expansions" of
9 | * floating-point numbers such that rounding error is
10 | * eliminated. See Shewchuk for more detail:
11 | *
12 | * J. R. Shewchuk (1997), Adaptive Precision Floating-
13 | * Point Arithmetic & Fast Robust Geometric Predicates
14 | * Discrete & Computational Geometry, 18, pp. 305-363.
15 | *
16 | * This header provides a stack allocated, compile-time
17 | * "expansion" object that wraps Shewchuk's operators,
18 | * inspired by similar run-time constructs, e.g. Lévy:
19 | *
20 | * B. Lévy (2016), Robustness and efficiency of
21 | * geometric programs: The Predicate Construction Kit
22 | * (PCK). Computer-Aided Design, 72, pp. 03-12.
23 | *
24 | * Here, various compile-time techniques and template
25 | * patterns are used to build a "zero-overhead"
26 | * framework that doesn't require run-time stack/heap
27 | * manipulation or pointer indirection.
28 | *
29 | --------------------------------------------------------
30 | *
31 | * This program may be freely redistributed under the
32 | * condition that the copyright notices (including this
33 | * entire header) are not removed, and no compensation
34 | * is received through use of the software. Private,
35 | * research, and institutional use is free. You may
36 | * distribute modified versions of this code UNDER THE
37 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
38 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
39 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
40 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
41 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
42 | * of this code as part of a commercial system is
43 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
44 | * AUTHOR. (If you are not directly supplying this
45 | * code to a customer, and you are instead telling them
46 | * how they can obtain it for free, then you are not
47 | * required to make any arrangement with me.)
48 | *
49 | * Disclaimer: Neither I nor: Columbia University, The
50 | * Massachusetts Institute of Technology, The
51 | * University of Sydney, nor The National Aeronautics
52 | * and Space Administration warrant this code in any
53 | * way whatsoever. This code is provided "as-is" to be
54 | * used at your own risk.
55 | *
56 | --------------------------------------------------------
57 | *
58 | * Last updated: 07 April, 2020
59 | *
60 | * Copyright 2020--
61 | * Darren Engwirda
62 | * de2363@columbia.edu
63 | * https://github.com/dengwirda/
64 | *
65 | --------------------------------------------------------
66 | */
67 |
68 | # pragma once
69 |
70 | # ifndef __MP_FLOAT__
71 | # define __MP_FLOAT__
72 |
73 | # include "mp_basic.hpp"
74 |
75 | namespace mp_float {
76 |
77 | /*
78 | --------------------------------------------------------
79 | * EXPANSION: multi-precision floating-point numbers.
80 | --------------------------------------------------------
81 | */
82 |
83 | # define REAL_TYPE mp_float::real_type
84 | # define INDX_TYPE mp_float::indx_type
85 |
86 | template <
87 | size_t N = +1 // max. floats in expansion
88 | >
89 | class expansion
90 | {
91 | /*-------------- a compile-time multi-precision expansion */
92 | public :
93 | typedef REAL_TYPE real_type;
94 | typedef INDX_TYPE indx_type;
95 |
96 | indx_type static constexpr _size = N ;
97 |
98 | real_type _xdat [ N ] ;
99 | indx_type _xlen = 0 ;
100 |
101 | public :
102 | /*------------------------------ initialising constructor */
103 | __inline_call expansion ()
104 | { // just default...
105 | }
106 | __inline_call expansion (
107 | REAL_TYPE _xx
108 | )
109 | { this->push(_xx) ;
110 | }
111 |
112 | /*------------------------------ append bits to expansion */
113 | __inline_call void push (
114 | real_type _xx
115 | )
116 | { this->_xdat[this->_xlen++] = _xx ;
117 | }
118 |
119 | /*------------------------------ query the expansion size */
120 | __inline_call indx_type count (
121 | ) const
122 | { return this->_xlen ;
123 | }
124 | __inline_call indx_type alloc (
125 | ) const
126 | { return this->_size ;
127 | }
128 | __inline_call bool empty (
129 | ) const
130 | { return this->_xlen == +0 ;
131 | }
132 |
133 | /*------------------------------ access to expansion bits */
134 | __inline_call real_type & operator[] (
135 | indx_type _ii
136 | )
137 | {
138 | assert ( _ii < this->_size &&
139 | "expansion: index out of bounds") ;
140 |
141 | return ( this->_xdat[_ii] ) ;
142 | }
143 |
144 | __inline_call real_type const& operator[] (
145 | indx_type _ii
146 | ) const
147 | {
148 | assert ( _ii<= this->_size &&
149 | "expansion: index out of bounds") ;
150 |
151 | return ( this->_xdat[_ii] ) ;
152 | }
153 |
154 | public :
155 | /*------------------------------ helper: init. from a + b */
156 | __inline_call void from_add (
157 | real_type _aa, real_type _bb
158 | )
159 | {
160 | static_assert( _size >= 2,
161 | "from-add: insufficient alloc.!") ;
162 |
163 | this->_xlen = +2 ;
164 |
165 | one_one_add_full(_aa, _bb,
166 | this->_xdat[1],
167 | this->_xdat[0]) ;
168 | }
169 |
170 | /*------------------------------ helper: init. from a - b */
171 | __inline_call void from_sub (
172 | real_type _aa, real_type _bb
173 | )
174 | {
175 | static_assert( _size >= 2,
176 | "from-sub: insufficient alloc.!") ;
177 |
178 | this->_xlen = +2 ;
179 |
180 | one_one_sub_full(_aa, _bb,
181 | this->_xdat[1],
182 | this->_xdat[0]) ;
183 | }
184 |
185 | /*------------------------------ helper: init. from a * a */
186 | __inline_call void from_sqr (
187 | real_type _aa
188 | )
189 | {
190 | static_assert( _size >= 2,
191 | "from-sqr: insufficient alloc.!") ;
192 |
193 | this->_xlen = +2 ;
194 |
195 | one_one_sqr_full(_aa,
196 | this->_xdat[1],
197 | this->_xdat[0]) ;
198 | }
199 |
200 | /*------------------------------ helper: init. from a * b */
201 | __inline_call void from_mul (
202 | real_type _aa, real_type _bb
203 | )
204 | {
205 | static_assert( _size >= 2,
206 | "from-mul: insufficient alloc.!") ;
207 |
208 | this->_xlen = +2 ;
209 |
210 | one_one_mul_full(_aa, _bb,
211 | this->_xdat[1],
212 | this->_xdat[0]) ;
213 | }
214 |
215 | } ;
216 |
217 | /*
218 | --------------------------------------------------------
219 | * shortcut utilities to construct basic expansions
220 | --------------------------------------------------------
221 | */
222 |
223 | __inline_call
224 | expansion<2> expansion_from_add (
225 | REAL_TYPE _aa, REAL_TYPE _bb
226 | )
227 | {
228 | expansion<2> _ex; _ex.from_add(_aa, _bb) ;
229 | return _ex;
230 | }
231 |
232 | __inline_call
233 | expansion<2> expansion_from_sub (
234 | REAL_TYPE _aa, REAL_TYPE _bb
235 | )
236 | {
237 | expansion<2> _ex; _ex.from_sub(_aa, _bb) ;
238 | return _ex;
239 | }
240 |
241 | __inline_call
242 | expansion<2> expansion_from_sqr (
243 | REAL_TYPE _aa
244 | )
245 | {
246 | expansion<2> _ex; _ex.from_sqr(_aa) ;
247 | return _ex;
248 | }
249 |
250 | __inline_call
251 | expansion<2> expansion_from_mul (
252 | REAL_TYPE _aa, REAL_TYPE _bb
253 | )
254 | {
255 | expansion<2> _ex; _ex.from_mul(_aa, _bb) ;
256 | return _ex;
257 | }
258 |
259 | /*
260 | --------------------------------------------------------
261 | * alloc. requirements for operations on expansions
262 | --------------------------------------------------------
263 | */
264 |
265 | __inline_call INDX_TYPE constexpr add_alloc (
266 | INDX_TYPE _na,
267 | INDX_TYPE _nb
268 | )
269 | { return _na + _nb ;
270 | }
271 |
272 | __inline_call INDX_TYPE constexpr sub_alloc (
273 | INDX_TYPE _na,
274 | INDX_TYPE _nb
275 | )
276 | { return _na + _nb ;
277 | }
278 |
279 | __inline_call INDX_TYPE constexpr mul_alloc (
280 | INDX_TYPE _na,
281 | INDX_TYPE _nb
282 | )
283 | { return _na * _nb * +2 ;
284 | }
285 |
286 | /*
287 | --------------------------------------------------------
288 | * add two multi-precision expansion, a'la shewchuk
289 | --------------------------------------------------------
290 | */
291 |
292 | template <
293 | size_t NE, size_t NF, size_t NH
294 | >
295 | __normal_call void fast_expansion_add_zeroelim (
296 | expansion const& _ee ,
297 | expansion const& _ff ,
298 | expansion & _hh
299 | ) // adapted from: fast_expansion_sum_zeroelim
300 | {
301 | REAL_TYPE _qq, _qn, _hx;
302 | REAL_TYPE _ex = _ee [0];
303 | REAL_TYPE _fx = _ff [0];
304 | INDX_TYPE _ei = +0, _fi = +0 ;
305 |
306 | _hh._xlen = 0;
307 |
308 | if((_fx > _ex) == (_fx > -_ex))
309 | {
310 | _qq = _ex;
311 | _ex = _ee[++_ei];
312 | }
313 | else
314 | {
315 | _qq = _fx;
316 | _fx = _ff[++_fi];
317 | }
318 |
319 | if((_ei < _ee._xlen) && (_fi < _ff._xlen))
320 | {
321 | if((_fx > _ex) == (_fx > -_ex))
322 | {
323 | one_one_add_fast(
324 | _ex, _qq, _qn, _hx);
325 | _qq = _qn;
326 | _ex = _ee[++_ei];
327 | }
328 | else
329 | {
330 | one_one_add_fast(
331 | _fx, _qq, _qn, _hx);
332 | _qq = _qn;
333 | _fx = _ff[++_fi];
334 | }
335 | if (_hx != +0.0) _hh.push (_hx) ;
336 |
337 | while ((_ei < _ee._xlen) &&
338 | (_fi < _ff._xlen) )
339 | {
340 | if((_fx > _ex) == (_fx > -_ex))
341 | {
342 | one_one_add_full(
343 | _qq, _ex, _qn, _hx);
344 | _qq = _qn;
345 | _ex = _ee[++_ei] ;
346 | }
347 | else
348 | {
349 | one_one_add_full(
350 | _qq, _fx, _qn, _hx);
351 | _qq = _qn;
352 | _fx = _ff[++_fi] ;
353 | }
354 | if (_hx != +0.0) _hh.push (_hx) ;
355 | }
356 | }
357 |
358 | while (_ei < _ee._xlen)
359 | {
360 | one_one_add_full(_qq, _ex, _qn, _hx);
361 | _qq = _qn;
362 | _ex = _ee[++_ei];
363 | if (_hx != +0.0) _hh.push (_hx) ;
364 | }
365 |
366 | while (_fi < _ff._xlen)
367 | {
368 | one_one_add_full(_qq, _fx, _qn, _hx);
369 | _qq = _qn;
370 | _fx = _ff[++_fi];
371 | if (_hx != +0.0) _hh.push (_hx) ;
372 | }
373 |
374 | if((_qq != +0.0) || (_hh._xlen == +0))
375 | {
376 | _hh.push(_qq) ;
377 | }
378 | }
379 |
380 | template <
381 | size_t NA, size_t NB, size_t NC
382 | >
383 | __inline_call void expansion_add (
384 | expansion const& _aa ,
385 | expansion const& _bb ,
386 | expansion & _cc
387 | ) // adapted from: fast_expansion_sum_zeroelim
388 | {
389 | static_assert ( NC >= NA + NB ,
390 | "expansion-add: insufficient alloc.!");
391 |
392 | if (_aa._xlen == +1 && // 1-to-1 unrolling
393 | _bb._xlen == +1)
394 | {
395 | REAL_TYPE _t1, _t0;
396 |
397 | _cc._xlen = +0 ;
398 |
399 | one_one_add_full(
400 | _aa[0], _bb[0], _t1, _t0);
401 |
402 | if (_t0 != +0.0) _cc.push (_t0) ;
403 | if (_t1 != +0.0) _cc.push (_t1) ;
404 | if (_cc.empty()) _cc.push (+0.) ;
405 | }
406 | else
407 | if (_aa._xlen == +2 && // 2-to-1 unrolling
408 | _bb._xlen == +1)
409 | {
410 | REAL_TYPE _t2, _t1, _t0;
411 |
412 | _cc._xlen = +0 ;
413 |
414 | two_one_add_full(
415 | _aa[1], _aa[0], _bb[0], _t2, _t1, _t0);
416 |
417 | if (_t0 != +0.0) _cc.push (_t0) ;
418 | if (_t1 != +0.0) _cc.push (_t1) ;
419 | if (_t2 != +0.0) _cc.push (_t2) ;
420 | if (_cc.empty()) _cc.push (+0.) ;
421 | }
422 | else
423 | if (_aa._xlen == +1 && // 1-to-2 unrolling
424 | _bb._xlen == +2)
425 | {
426 | REAL_TYPE _t2, _t1, _t0;
427 |
428 | _cc._xlen = +0 ;
429 |
430 | two_one_add_full(
431 | _bb[1], _bb[0], _aa[0], _t2, _t1, _t0);
432 |
433 | if (_t0 != +0.0) _cc.push (_t0) ;
434 | if (_t1 != +0.0) _cc.push (_t1) ;
435 | if (_t2 != +0.0) _cc.push (_t2) ;
436 | if (_cc.empty()) _cc.push (+0.) ;
437 | }
438 | else
439 | if (_aa._xlen == +2 && // 2-to-2 unrolling
440 | _bb._xlen == +2)
441 | {
442 | REAL_TYPE _t3, _t2, _t1, _t0;
443 |
444 | _cc._xlen = +0 ;
445 |
446 | two_two_add_full(
447 | _aa[1], _aa[0],
448 | _bb[1], _bb[0], _t3, _t2, _t1, _t0);
449 |
450 | if (_t0 != +0.0) _cc.push (_t0) ;
451 | if (_t1 != +0.0) _cc.push (_t1) ;
452 | if (_t2 != +0.0) _cc.push (_t2) ;
453 | if (_t3 != +0.0) _cc.push (_t3) ;
454 | if (_cc.empty()) _cc.push (+0.) ;
455 | }
456 | else // the n-to-m loops
457 | {
458 | fast_expansion_add_zeroelim(_aa, _bb, _cc);
459 | }
460 | }
461 |
462 | /*
463 | --------------------------------------------------------
464 | * sub two multi-precision expansion, a'la shewchuk
465 | --------------------------------------------------------
466 | */
467 |
468 | template <
469 | size_t NE, size_t NF, size_t NH
470 | >
471 | __normal_call void fast_expansion_sub_zeroelim (
472 | expansion const& _ee ,
473 | expansion const& _ff ,
474 | expansion & _hh
475 | ) // adapted from: fast_expansion_diff_zeroelim
476 | {
477 | REAL_TYPE _qq, _qn, _hx;
478 | REAL_TYPE _ex = _ee [0];
479 | REAL_TYPE _fx =-_ff [0];
480 | INDX_TYPE _ei = +0, _fi = +0 ;
481 |
482 | _hh._xlen = 0;
483 |
484 | if((_fx > _ex) == (_fx > -_ex))
485 | {
486 | _qq = _ex;
487 | _ex = _ee[++_ei];
488 | }
489 | else
490 | {
491 | _qq = _fx;
492 | _fx =-_ff[++_fi];
493 | }
494 |
495 | if((_ei < _ee._xlen) && (_fi < _ff._xlen))
496 | {
497 | if((_fx > _ex) == (_fx > -_ex))
498 | {
499 | one_one_add_fast(
500 | _ex, _qq, _qn, _hx);
501 | _qq = _qn;
502 | _ex = _ee[++_ei];
503 | }
504 | else
505 | {
506 | one_one_add_fast(
507 | _fx, _qq, _qn, _hx);
508 | _qq = _qn;
509 | _fx =-_ff[++_fi];
510 | }
511 | if (_hx != +0.0) _hh.push (_hx) ;
512 |
513 | while ((_ei < _ee._xlen) &&
514 | (_fi < _ff._xlen) )
515 | {
516 | if((_fx > _ex) == (_fx > -_ex))
517 | {
518 | one_one_add_full(
519 | _qq, _ex, _qn, _hx);
520 | _qq = _qn;
521 | _ex = _ee[++_ei] ;
522 | }
523 | else
524 | {
525 | one_one_add_full(
526 | _qq, _fx, _qn, _hx);
527 | _qq = _qn;
528 | _fx =-_ff[++_fi] ;
529 | }
530 | if (_hx != +0.0) _hh.push (_hx) ;
531 | }
532 | }
533 |
534 | while (_ei < _ee._xlen)
535 | {
536 | one_one_add_full(_qq, _ex, _qn, _hx);
537 | _qq = _qn;
538 | _ex = _ee[++_ei];
539 | if (_hx != +0.0) _hh.push (_hx) ;
540 | }
541 |
542 | while (_fi < _ff._xlen)
543 | {
544 | one_one_add_full(_qq, _fx, _qn, _hx);
545 | _qq = _qn;
546 | _fx =-_ff[++_fi];
547 | if (_hx != +0.0) _hh.push (_hx) ;
548 | }
549 |
550 | if((_qq != +0.0) || (_hh._xlen == +0))
551 | {
552 | _hh.push(_qq) ;
553 | }
554 | }
555 |
556 | template <
557 | size_t NA, size_t NB, size_t NC
558 | >
559 | __inline_call void expansion_sub (
560 | expansion const& _aa ,
561 | expansion const& _bb ,
562 | expansion & _cc
563 | ) // adapted from: fast_expansion_diff_zeroelim
564 | {
565 | static_assert ( NC >= NA + NB ,
566 | "expansion-sub: insufficient alloc.!");
567 |
568 | if (_aa._xlen == +1 && // 1-to-1 unrolling
569 | _bb._xlen == +1)
570 | {
571 | REAL_TYPE _t1, _t0;
572 |
573 | _cc._xlen = +0 ;
574 |
575 | one_one_sub_full(
576 | _aa[0], _bb[0], _t1, _t0);
577 |
578 | if (_t0 != +0.0) _cc.push (_t0) ;
579 | if (_t1 != +0.0) _cc.push (_t1) ;
580 | if (_cc.empty()) _cc.push (+0.) ;
581 | }
582 | else
583 | if (_aa._xlen == +2 && // 2-to-1 unrolling
584 | _bb._xlen == +1)
585 | {
586 | REAL_TYPE _t2, _t1, _t0;
587 |
588 | _cc._xlen = +0 ;
589 |
590 | two_one_sub_full(
591 | _aa[1], _aa[0], _bb[0], _t2, _t1, _t0);
592 |
593 | if (_t0 != +0.0) _cc.push (_t0) ;
594 | if (_t1 != +0.0) _cc.push (_t1) ;
595 | if (_t2 != +0.0) _cc.push (_t2) ;
596 | if (_cc.empty()) _cc.push (+0.) ;
597 | }
598 | else
599 | if (_aa._xlen == +2 && // 2-to-2 unrolling
600 | _bb._xlen == +2)
601 | {
602 | REAL_TYPE _t3, _t2, _t1, _t0;
603 |
604 | _cc._xlen = +0 ;
605 |
606 | two_two_sub_full(
607 | _aa[1], _aa[0],
608 | _bb[1], _bb[0], _t3, _t2, _t1, _t0);
609 |
610 | if (_t0 != +0.0) _cc.push (_t0) ;
611 | if (_t1 != +0.0) _cc.push (_t1) ;
612 | if (_t2 != +0.0) _cc.push (_t2) ;
613 | if (_t3 != +0.0) _cc.push (_t3) ;
614 | if (_cc.empty()) _cc.push (+0.) ;
615 | }
616 | else // the n-to-m loops
617 | {
618 | fast_expansion_sub_zeroelim(_aa, _bb, _cc);
619 | }
620 | }
621 |
622 | /*
623 | --------------------------------------------------------
624 | * add/sub multi-precision expansion utilities
625 | --------------------------------------------------------
626 | */
627 |
628 | template <
629 | size_t NA, size_t NC
630 | >
631 | __inline_call void expansion_add (
632 | expansion const& _aa ,
633 | REAL_TYPE _bb ,
634 | expansion & _cc
635 | ) // add --- from-one
636 | {
637 | expansion_add(
638 | _aa, expansion<1>(_bb), _cc ) ;
639 | }
640 |
641 | template <
642 | size_t NA, size_t NC
643 | >
644 | __inline_call void expansion_sub (
645 | expansion const& _aa ,
646 | REAL_TYPE _bb ,
647 | expansion & _cc
648 | ) // sub --- from-one
649 | {
650 | expansion_sub(
651 | _aa, expansion<1>(_bb), _cc ) ;
652 | }
653 |
654 | template <
655 | size_t NA, size_t NB, size_t NC,
656 | size_t ND
657 | >
658 | __inline_call void expansion_add (
659 | expansion const& _aa,
660 | expansion const& _bb,
661 | expansion const& _cc,
662 | expansion & _dd
663 | ) // 3-way add kernel
664 | {
665 | expansion _ab ;
666 | expansion_add(_aa, _bb, _ab);
667 |
668 | expansion_add(_ab, _cc, _dd);
669 | }
670 |
671 | template <
672 | size_t NA, size_t NB, size_t NC,
673 | size_t ND, size_t NE
674 | >
675 | __inline_call void expansion_add (
676 | expansion const& _aa,
677 | expansion const& _bb,
678 | expansion const& _cc,
679 | expansion const& _dd,
680 | expansion & _ee
681 | ) // 4-way add kernel
682 | {
683 | expansion _ab ;
684 | expansion_add(_aa, _bb, _ab);
685 |
686 | expansion _cd ;
687 | expansion_add(_cc, _dd, _cd);
688 |
689 | expansion_add(_ab, _cd, _ee);
690 | }
691 |
692 | /*
693 | --------------------------------------------------------
694 | * scale a multi-precision expansion, a'la shewchuk
695 | --------------------------------------------------------
696 | */
697 |
698 | template <
699 | size_t NE, size_t NH
700 | >
701 | __normal_call void scale_expansion_zeroelim (
702 | expansion const& _ee,
703 | REAL_TYPE _bb,
704 | expansion & _hh
705 | ) // adapted from: scale_expansion_zeroelim
706 | {
707 | REAL_TYPE _bh, _bl, _t1, _t0 , _ss, _hx, _qq;
708 | one_split(_bb, _bh, _bl) ;
709 |
710 | _hh._xlen = +0 ;
711 |
712 | one_one_mul_full(
713 | _ee[ 0 ], _bb, _bh, _bl, _qq, _hx) ;
714 |
715 | if (_hx != +0.0) _hh.push (_hx) ;
716 |
717 | INDX_TYPE _ei;
718 | for (_ei = +1; _ei < _ee._xlen; ++_ei)
719 | {
720 | one_one_mul_full(_ee[_ei], _bb, _bh, _bl,
721 | _t1, _t0) ;
722 |
723 | one_one_add_full(
724 | _qq, _t0, _ss, _hx);
725 |
726 | if (_hx != +0.0) _hh.push (_hx) ;
727 |
728 | one_one_add_fast(
729 | _t1, _ss, _qq, _hx);
730 |
731 | if (_hx != +0.0) _hh.push (_hx) ;
732 | }
733 | if((_qq != +0.0) || (_hh._xlen == +0))
734 | {
735 | _hh.push(_qq) ;
736 | }
737 | }
738 |
739 | template <
740 | size_t NA, size_t NC
741 | >
742 | __inline_call void expansion_mul (
743 | expansion const& _aa ,
744 | REAL_TYPE _bb,
745 | expansion & _cc
746 | ) // adapted from: scale_expansion_zeroelim
747 | {
748 | static_assert ( NC >= NA * +2 ,
749 | "expansion-mul: insufficient alloc.!");
750 |
751 | if (_aa._xlen == +1) // 1-to-1 unrolling
752 | {
753 | REAL_TYPE _t1, _t0;
754 |
755 | _cc._xlen = +0 ;
756 |
757 | one_one_mul_full(
758 | _aa[0], _bb, _t1, _t0);
759 |
760 | if (_t0 != +0.0) _cc.push (_t0) ;
761 | if (_t1 != +0.0) _cc.push (_t1) ;
762 | if (_cc.empty()) _cc.push (+0.) ;
763 | }
764 | else
765 | if (_aa._xlen == +2) // 2-to-1 unrolling
766 | {
767 | REAL_TYPE _t3, _t2, _t1, _t0;
768 |
769 | _cc._xlen = +0 ;
770 |
771 | two_one_mul_full(
772 | _aa[1], _aa[0], _bb, _t3, _t2, _t1, _t0);
773 |
774 | if (_t0 != +0.0) _cc.push (_t0) ;
775 | if (_t1 != +0.0) _cc.push (_t1) ;
776 | if (_t2 != +0.0) _cc.push (_t2) ;
777 | if (_t3 != +0.0) _cc.push (_t3) ;
778 | if (_cc.empty()) _cc.push (+0.) ;
779 | }
780 | else // the n-to-1 loops
781 | {
782 | scale_expansion_zeroelim (_aa, _bb, _cc);
783 | }
784 | }
785 |
786 | /*
787 | --------------------------------------------------------
788 | * multi-precision expansion product, a'la shewchuk
789 | --------------------------------------------------------
790 | */
791 |
792 | template <
793 | size_t NA, size_t NB, size_t NC,
794 | size_t NR
795 | >
796 | __normal_call void expansion_mul (
797 | expansion const& _aa ,
798 | expansion const& _bb ,
799 | INDX_TYPE _i1, INDX_TYPE _i2 ,
800 | expansion & _cc
801 | ) // see shewchuk: block-wise "distillation"
802 | {
803 | INDX_TYPE _nr = _i2 - _i1 + 1;
804 | if (_nr >= +3) // recursive splits
805 | {
806 | if constexpr ( NR >= +3 )
807 | {
808 | INDX_TYPE _im = _i1 + _nr / 2 ;
809 |
810 | INDX_TYPE constexpr R1 = NR / 2 ;
811 | INDX_TYPE constexpr R2 = NR - R1;
812 |
813 | INDX_TYPE constexpr
814 | N1 = mul_alloc (R1, NA) ;
815 | INDX_TYPE constexpr
816 | N2 = mul_alloc (R2, NA) ;
817 |
818 | expansion _c1;
819 | expansion_mul(
820 | _aa, _bb, _i1, _im - 1, _c1);
821 |
822 | expansion _c2;
823 | expansion_mul(
824 | _aa, _bb, _im + 0, _i2, _c2);
825 |
826 | expansion_add(_c1, _c2, _cc) ;
827 | }
828 | else
829 | {
830 | assert( false &&
831 | "expansion-mul: distill fail");
832 | }
833 | }
834 | else
835 | if (_nr == +2)
836 | {
837 | if constexpr ( NR >= +2 )
838 | {
839 | expansion _c1 ;
840 | expansion _c2 ;
841 | expansion_mul(
842 | _aa, _bb [_i1 + 0], _c1) ;
843 | expansion_mul(
844 | _aa, _bb [_i1 + 1], _c2) ;
845 |
846 | expansion_add(_c1, _c2, _cc) ;
847 | }
848 | else
849 | {
850 | assert( false &&
851 | "expansion-mul: distill fail");
852 | }
853 | }
854 | else
855 | if (_nr == +1) // do 1-by-n direct
856 | {
857 | expansion_mul(_aa, _bb [_i1], _cc);
858 | }
859 | }
860 |
861 | template <
862 | size_t NA, size_t NB, size_t NC
863 | >
864 | __inline_call void expansion_mul (
865 | expansion const& _aa ,
866 | expansion const& _bb ,
867 | expansion & _cc
868 | ) // see shewchuk: block-wise "distillation"
869 | {
870 | if (_aa._xlen < _bb._xlen)
871 | {
872 | expansion_mul (
873 | _bb, _aa, 0, _aa._xlen-1, _cc);
874 | }
875 | else
876 | {
877 | expansion_mul (
878 | _aa, _bb, 0, _bb._xlen-1, _cc);
879 | }
880 | }
881 |
882 | /*
883 | --------------------------------------------------------
884 | * -ve for multi-precision expansion, a'la shewchuk
885 | --------------------------------------------------------
886 | */
887 |
888 | template <
889 | size_t NN
890 | >
891 | __normal_call void expansion_neg (
892 | expansion & _aa
893 | )
894 | {
895 | INDX_TYPE _ii;
896 | for (_ii = +0; _ii < _aa._xlen; ++_ii)
897 | {
898 | _aa[_ii] *= -1 ;
899 | }
900 | }
901 |
902 | /*
903 | --------------------------------------------------------
904 | * est. of multi-precision expansion, a'la shewchuk
905 | --------------------------------------------------------
906 | */
907 |
908 | template <
909 | size_t NN
910 | >
911 | __normal_call REAL_TYPE expansion_est (
912 | expansion const& _aa
913 | )
914 | {
915 | REAL_TYPE _rr = +0.;
916 | INDX_TYPE _ii;
917 | for (_ii = +0; _ii < _aa._xlen; ++_ii)
918 | {
919 | _rr += _aa[_ii];
920 | }
921 |
922 | return _rr ;
923 | }
924 |
925 | /*
926 | --------------------------------------------------------
927 | * form dot-products for multi-precision expansions
928 | --------------------------------------------------------
929 | */
930 |
931 | template <
932 | size_t AX, size_t BX, size_t AY,
933 | size_t BY, size_t NP
934 | >
935 | __inline_call void expansion_dot (
936 | expansion const& _xa,
937 | expansion const& _xb,
938 | expansion const& _ya,
939 | expansion const& _yb,
940 | expansion & _dp
941 | ) // 2-dim dotproduct
942 | {
943 | expansion _xp ;
944 | expansion_mul(_xa, _xb, _xp);
945 |
946 | expansion _yp ;
947 | expansion_mul(_ya, _yb, _yp);
948 |
949 | expansion_add(_xp, _yp, _dp);
950 | }
951 |
952 | template <
953 | size_t AX, size_t BX, size_t AY,
954 | size_t BY, size_t AZ, size_t BZ,
955 | size_t NP
956 | >
957 | __inline_call void expansion_dot (
958 | expansion const& _xa,
959 | expansion const& _xb,
960 | expansion const& _ya,
961 | expansion const& _yb,
962 | expansion const& _za,
963 | expansion const& _zb,
964 | expansion & _dp
965 | ) // 3-dim dotproduct
966 | {
967 | expansion _xp ;
968 | expansion_mul(_xa, _xb, _xp);
969 |
970 | expansion _yp ;
971 | expansion_mul(_ya, _yb, _yp);
972 |
973 | expansion _zp ;
974 | expansion_mul(_za, _zb, _zp);
975 |
976 | expansion_add(_xp, _yp, _zp, _dp);
977 | }
978 |
979 |
980 | # undef REAL_TYPE
981 | # undef INDX_TYPE
982 |
983 |
984 | }
985 |
986 | # endif//__MP_FLOAT__
987 |
988 |
989 |
990 |
--------------------------------------------------------------------------------
/expansion/mp_utils.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | --------------------------------------------------------
4 | * MPFLOAT: multi-precision floating-point arithmetic.
5 | --------------------------------------------------------
6 | *
7 | * This program may be freely redistributed under the
8 | * condition that the copyright notices (including this
9 | * entire header) are not removed, and no compensation
10 | * is received through use of the software. Private,
11 | * research, and institutional use is free. You may
12 | * distribute modified versions of this code UNDER THE
13 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
14 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
15 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
16 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
17 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
18 | * of this code as part of a commercial system is
19 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
20 | * AUTHOR. (If you are not directly supplying this
21 | * code to a customer, and you are instead telling them
22 | * how they can obtain it for free, then you are not
23 | * required to make any arrangement with me.)
24 | *
25 | * Disclaimer: Neither I nor: Columbia University, The
26 | * Massachusetts Institute of Technology, The
27 | * University of Sydney, nor The National Aeronautics
28 | * and Space Administration warrant this code in any
29 | * way whatsoever. This code is provided "as-is" to be
30 | * used at your own risk.
31 | *
32 | --------------------------------------------------------
33 | *
34 | * Last updated: 03 March, 2020
35 | *
36 | * Copyright 2020--
37 | * Darren Engwirda
38 | * de2363@columbia.edu
39 | * https://github.com/dengwirda/
40 | *
41 | --------------------------------------------------------
42 | */
43 |
44 | # pragma once
45 |
46 | # ifndef __MP_UTILS__
47 | # define __MP_UTILS__
48 |
49 | namespace mp_float {
50 |
51 | # define REAL_TYPE mp_float::real_type
52 | # define INDX_TYPE mp_float::indx_type
53 |
54 | /*---------------- compute an exact 2 x 2 determinant */
55 |
56 | template <
57 | size_t NN
58 | >
59 | __inline_call void compute_det_2x2 (
60 | REAL_TYPE _aa, REAL_TYPE _bb ,
61 | REAL_TYPE _cc, REAL_TYPE _dd ,
62 | expansion & _final
63 | )
64 | {
65 | expansion< 2 >_mulad, _mulbc ;
66 | _mulad.from_mul (_aa, _dd);
67 | _mulbc.from_mul (_bb, _cc);
68 |
69 | expansion_sub(_mulad, _mulbc, _final);
70 | }
71 |
72 | /*
73 | --------------------------------------------------------
74 | *
75 | * Compute an exact 3 x 3 determinant.
76 | *
77 | * | a1 a2 v1 |
78 | * | b1 b2 v2 |
79 | * | c1 c2 v3 |
80 | *
81 | * as the product of 2 x 2 minors about a pivot column
82 | * P, shown here for P = 3. The entry V1 is associated
83 | * with the minor
84 | *
85 | * | b1 b2 | = D1
86 | * | c1 c2 |
87 | *
88 | * and so on for (V2,D2), (V3,D3) etc.
89 | *
90 | --------------------------------------------------------
91 | */
92 |
93 | template <
94 | size_t NA, size_t NB, size_t NC,
95 | size_t ND, size_t NE, size_t NF,
96 | size_t NG
97 | >
98 | __inline_call void compute_det_3x3 (
99 | expansion const& _det1p ,
100 | expansion const& _val1p ,
101 | expansion const& _det2p ,
102 | expansion const& _val2p ,
103 | expansion const& _det3p ,
104 | expansion const& _val3p ,
105 | expansion & _final ,
106 | INDX_TYPE _pivot
107 | )
108 | {
109 | /*---------------------------------- products Vi * Di */
110 | INDX_TYPE
111 | constexpr N1 = mul_alloc (NA, NB) ;
112 | expansion _mul1p;
113 | expansion_mul(_det1p, _val1p, _mul1p);
114 |
115 | INDX_TYPE
116 | constexpr N2 = mul_alloc (NC, ND) ;
117 | expansion _mul2p;
118 | expansion_mul(_det2p, _val2p, _mul2p);
119 |
120 | INDX_TYPE
121 | constexpr N3 = mul_alloc (NE, NF) ;
122 | expansion _mul3p;
123 | expansion_mul(_det3p, _val3p, _mul3p);
124 |
125 | /*---------------------------------- sum (-1)^P * VDi */
126 | INDX_TYPE
127 | constexpr MM = sub_alloc (N1, N2) ;
128 | expansion _sum_1;
129 |
130 | if (_pivot % 2 == +0)
131 | {
132 | expansion_sub(_mul2p, _mul1p, _sum_1);
133 | expansion_sub(_sum_1, _mul3p, _final);
134 | }
135 | else
136 | {
137 | expansion_sub(_mul1p, _mul2p, _sum_1);
138 | expansion_add(_sum_1, _mul3p, _final);
139 | }
140 | }
141 |
142 | /*--------------------- "unitary" case, with Vi = +1. */
143 |
144 | template <
145 | size_t NA, size_t NB, size_t NC,
146 | size_t ND
147 | >
148 | __inline_call void unitary_det_3x3 (
149 | expansion const& _det1p ,
150 | expansion const& _det2p ,
151 | expansion const& _det3p ,
152 | expansion & _final ,
153 | INDX_TYPE _pivot
154 | )
155 | {
156 | INDX_TYPE
157 | constexpr MM = sub_alloc (NA, NB) ;
158 | expansion _sum_1;
159 |
160 | if (_pivot % 2 == +0)
161 | {
162 | expansion_sub(_det2p, _det1p, _sum_1);
163 | expansion_sub(_sum_1, _det3p, _final);
164 | }
165 | else
166 | {
167 | expansion_sub(_det1p, _det2p, _sum_1);
168 | expansion_add(_sum_1, _det3p, _final);
169 | }
170 | }
171 |
172 | /*
173 | --------------------------------------------------------
174 | *
175 | * Compute an exact 4 x 4 determinant.
176 | *
177 | * | a1 a2 a3 v1 |
178 | * | b1 b2 b2 v2 |
179 | * | c1 c2 c3 v3 |
180 | * | d1 d2 d3 v4 |
181 | *
182 | * as the product of 3 x 3 minors about a pivot column
183 | * P, shown here for P = 4. The entry V1 is associated
184 | * with the minor
185 | *
186 | * | b1 b2 b3 |
187 | * | c1 c2 c3 | = D1
188 | * | d1 d2 d3 |
189 | *
190 | * and so on for (V2,D2), (V3,D3) etc.
191 | *
192 | --------------------------------------------------------
193 | */
194 |
195 | template <
196 | size_t NA, size_t NB, size_t NC,
197 | size_t ND, size_t NE, size_t NF,
198 | size_t NG, size_t NH, size_t NI
199 | >
200 | __inline_call void compute_det_4x4 (
201 | expansion const& _det1p ,
202 | expansion const& _val1p ,
203 | expansion const& _det2p ,
204 | expansion const& _val2p ,
205 | expansion const& _det3p ,
206 | expansion const& _val3p ,
207 | expansion const& _det4p ,
208 | expansion const& _val4p ,
209 | expansion & _final ,
210 | INDX_TYPE _pivot
211 | )
212 | {
213 | /*---------------------------------- products Vi * Di */
214 | INDX_TYPE
215 | constexpr N1 = mul_alloc (NA, NB) ;
216 | expansion _mul1p;
217 | expansion_mul(_det1p, _val1p, _mul1p);
218 |
219 | INDX_TYPE
220 | constexpr N2 = mul_alloc (NC, ND) ;
221 | expansion _mul2p;
222 | expansion_mul(_det2p, _val2p, _mul2p);
223 |
224 | INDX_TYPE
225 | constexpr N3 = mul_alloc (NE, NF) ;
226 | expansion _mul3p;
227 | expansion_mul(_det3p, _val3p, _mul3p);
228 |
229 | INDX_TYPE
230 | constexpr N4 = mul_alloc (NG, NH) ;
231 | expansion _mul4p;
232 | expansion_mul(_det4p, _val4p, _mul4p);
233 |
234 | /*---------------------------------- sum (-1)^P * VDi */
235 | INDX_TYPE
236 | constexpr M1 = sub_alloc (N1, N2) ;
237 | expansion _sum_1;
238 |
239 | INDX_TYPE
240 | constexpr M2 = sub_alloc (N3, N4) ;
241 | expansion _sum_2;
242 |
243 | if (_pivot % 2 == +0)
244 | {
245 | expansion_sub(_mul2p, _mul1p, _sum_1);
246 | expansion_sub(_mul4p, _mul3p, _sum_2);
247 | }
248 | else
249 | {
250 | expansion_sub(_mul1p, _mul2p, _sum_1);
251 | expansion_sub(_mul3p, _mul4p, _sum_2);
252 | }
253 |
254 | expansion_add(_sum_1, _sum_2, _final);
255 | }
256 |
257 | /*--------------------- "unitary" case, with Vi = +1. */
258 |
259 | template <
260 | size_t NA, size_t NB, size_t NC,
261 | size_t ND, size_t NE
262 | >
263 | __inline_call void unitary_det_4x4 (
264 | expansion const& _det1p ,
265 | expansion const& _det2p ,
266 | expansion const& _det3p ,
267 | expansion const& _det4p ,
268 | expansion & _final ,
269 | INDX_TYPE _pivot
270 | )
271 | {
272 | INDX_TYPE
273 | constexpr M1 = sub_alloc (NA, NB) ;
274 | expansion _sum_1;
275 |
276 | INDX_TYPE
277 | constexpr M2 = sub_alloc (NC, ND) ;
278 | expansion _sum_2;
279 |
280 | if (_pivot % 2 == +0)
281 | {
282 | expansion_sub(_det2p, _det1p, _sum_1);
283 | expansion_sub(_det4p, _det3p, _sum_2);
284 | }
285 | else
286 | {
287 | expansion_sub(_det2p, _det1p, _sum_1);
288 | expansion_sub(_det4p, _det3p, _sum_2);
289 | }
290 |
291 | expansion_add(_sum_1, _sum_2, _final);
292 | }
293 |
294 | /*
295 | --------------------------------------------------------
296 | *
297 | * Compute an exact 5 x 5 determinant.
298 | *
299 | * | a1 a2 a3 a4 v1 |
300 | * | b1 b2 b3 b4 v2 |
301 | * | c1 c2 c3 c4 v3 |
302 | * | d1 d2 d3 d4 v4 |
303 | * | e1 e2 e3 e4 v5 |
304 | *
305 | * as the product of 4 x 4 minors about a pivot column
306 | * P, shown here for P = 5. The entry V1 is associated
307 | * with the minor
308 | *
309 | * | b1 b2 b3 b4 |
310 | * | c1 c2 c3 c4 | = D1
311 | * | d1 d2 d3 d4 |
312 | * | e1 e2 e3 e4 |
313 | *
314 | * and so on for (V2,D2), (V3,D3) etc.
315 | *
316 | --------------------------------------------------------
317 | */
318 |
319 | template <
320 | size_t NA, size_t NB, size_t NC,
321 | size_t ND, size_t NE, size_t NF,
322 | size_t NG, size_t NH, size_t NI,
323 | size_t NJ, size_t NK
324 | >
325 | __inline_call void compute_det_5x5 (
326 | expansion const& _det1p ,
327 | expansion const& _val1p ,
328 | expansion const& _det2p ,
329 | expansion const& _val2p ,
330 | expansion const& _det3p ,
331 | expansion const& _val3p ,
332 | expansion const& _det4p ,
333 | expansion const& _val4p ,
334 | expansion const& _det5p ,
335 | expansion const& _val5p ,
336 | expansion & _final ,
337 | INDX_TYPE _pivot
338 | )
339 | {
340 | /*---------------------------------- products Vi * Di */
341 | INDX_TYPE
342 | constexpr N1 = mul_alloc (NA, NB) ;
343 | expansion _mul1p;
344 | expansion_mul(_det1p, _val1p, _mul1p);
345 |
346 | INDX_TYPE
347 | constexpr N2 = mul_alloc (NC, ND) ;
348 | expansion _mul2p;
349 | expansion_mul(_det2p, _val2p, _mul2p);
350 |
351 | INDX_TYPE
352 | constexpr N3 = mul_alloc (NE, NF) ;
353 | expansion _mul3p;
354 | expansion_mul(_det3p, _val3p, _mul3p);
355 |
356 | INDX_TYPE
357 | constexpr N4 = mul_alloc (NG, NH) ;
358 | expansion _mul4p;
359 | expansion_mul(_det4p, _val4p, _mul4p);
360 |
361 | INDX_TYPE
362 | constexpr N5 = mul_alloc (NI, NJ) ;
363 | expansion _mul5p;
364 | expansion_mul(_det5p, _val5p, _mul5p);
365 |
366 | /*---------------------------------- sum (-1)^P * VDi */
367 | INDX_TYPE
368 | constexpr M1 = sub_alloc (N1, N2) ;
369 | expansion _sum_1;
370 |
371 | INDX_TYPE
372 | constexpr M2 = sub_alloc (N3, N4) ;
373 | expansion _sum_2;
374 |
375 | INDX_TYPE
376 | constexpr M3 = sub_alloc (M1, N5) ;
377 | expansion _sum_3;
378 |
379 | if (_pivot % 2 == +0)
380 | {
381 | expansion_sub(_mul2p, _mul1p, _sum_1);
382 | expansion_sub(_mul4p, _mul3p, _sum_2);
383 | expansion_sub(_sum_1, _mul5p, _sum_3);
384 | }
385 | else
386 | {
387 | expansion_sub(_mul1p, _mul2p, _sum_1);
388 | expansion_sub(_mul3p, _mul4p, _sum_2);
389 | expansion_add(_sum_1, _mul5p, _sum_3);
390 | }
391 |
392 | expansion_add(_sum_3, _sum_2, _final);
393 | }
394 |
395 | /*--------------------- "unitary" case, with Vi = +1. */
396 |
397 | template <
398 | size_t NA, size_t NB, size_t NC,
399 | size_t ND, size_t NE, size_t NF
400 | >
401 | __inline_call void unitary_det_5x5 (
402 | expansion const& _det1p ,
403 | expansion const& _det2p ,
404 | expansion const& _det3p ,
405 | expansion const& _det4p ,
406 | expansion const& _det5p ,
407 | expansion & _final ,
408 | INDX_TYPE _pivot
409 | )
410 | {
411 | INDX_TYPE
412 | constexpr N1 = sub_alloc (NA, NB) ;
413 | expansion _sum_1;
414 |
415 | INDX_TYPE
416 | constexpr N2 = sub_alloc (NC, ND) ;
417 | expansion _sum_2;
418 |
419 | INDX_TYPE
420 | constexpr N3 = sub_alloc (N1, NE) ;
421 | expansion _sum_3;
422 |
423 | if (_pivot % 2 == +0)
424 | {
425 | expansion_sub(_det2p, _det1p, _sum_1);
426 | expansion_sub(_det4p, _det3p, _sum_2);
427 | expansion_sub(_sum_1, _det5p, _sum_3);
428 | }
429 | else
430 | {
431 | expansion_sub(_det1p, _det2p, _sum_1);
432 | expansion_sub(_det3p, _det4p, _sum_2);
433 | expansion_add(_sum_1, _det5p, _sum_3);
434 | }
435 |
436 | expansion_add(_sum_3, _sum_2, _final);
437 | }
438 |
439 | # undef REAL_TYPE
440 | # undef INDX_TYPE
441 |
442 |
443 | }
444 |
445 | # endif//__MP_UTILS__
446 |
447 |
448 |
449 |
--------------------------------------------------------------------------------
/geompred.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | ------------------------------------------------------------
4 | * robust geometric predicates, a'la shewchuk
5 | ------------------------------------------------------------
6 | *
7 | * This program may be freely redistributed under the
8 | * condition that the copyright notices (including this
9 | * entire header) are not removed, and no compensation
10 | * is received through use of the software. Private,
11 | * research, and institutional use is free. You may
12 | * distribute modified versions of this code UNDER THE
13 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
14 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
15 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
16 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
17 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
18 | * of this code as part of a commercial system is
19 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
20 | * AUTHOR. (If you are not directly supplying this
21 | * code to a customer, and you are instead telling them
22 | * how they can obtain it for free, then you are not
23 | * required to make any arrangement with me.)
24 | *
25 | * Disclaimer: Neither I nor: Columbia University, The
26 | * Massachusetts Institute of Technology, The
27 | * University of Sydney, nor The National Aeronautics
28 | * and Space Administration warrant this code in any
29 | * way whatsoever. This code is provided "as-is" to be
30 | * used at your own risk.
31 | *
32 | ------------------------------------------------------------
33 | *
34 | * Last updated: 01 March, 2020
35 | *
36 | * Copyright 2020--
37 | * Darren Engwirda
38 | * de2363@columbia.edu
39 | * https://github.com/dengwirda/
40 | *
41 | ------------------------------------------------------------
42 | */
43 |
44 | # pragma once
45 |
46 | # ifndef __PREDICATES__
47 | # define __PREDICATES__
48 |
49 | # include "basebase.hpp"
50 | # include "mpfloats.hpp"
51 |
52 | # include
53 |
54 | # include "predicate/predicate_k.hpp"
55 |
56 | # endif//__PREDICATES__
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/mpfloats.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | ------------------------------------------------------------
4 | * robust multi-precision floating-point expansions...
5 | ------------------------------------------------------------
6 | *
7 | * This program may be freely redistributed under the
8 | * condition that the copyright notices (including this
9 | * entire header) are not removed, and no compensation
10 | * is received through use of the software. Private,
11 | * research, and institutional use is free. You may
12 | * distribute modified versions of this code UNDER THE
13 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
14 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
15 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
16 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
17 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
18 | * of this code as part of a commercial system is
19 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
20 | * AUTHOR. (If you are not directly supplying this
21 | * code to a customer, and you are instead telling them
22 | * how they can obtain it for free, then you are not
23 | * required to make any arrangement with me.)
24 | *
25 | * Disclaimer: Neither I nor: Columbia University, The
26 | * Massachusetts Institute of Technology, The
27 | * University of Sydney, nor The National Aeronautics
28 | * and Space Administration warrant this code in any
29 | * way whatsoever. This code is provided "as-is" to be
30 | * used at your own risk.
31 | *
32 | ------------------------------------------------------------
33 | *
34 | * Last updated: 11 April, 2020
35 | *
36 | * Copyright 2020--
37 | * Darren Engwirda
38 | * de2363@columbia.edu
39 | * https://github.com/dengwirda/
40 | *
41 | ------------------------------------------------------------
42 | */
43 |
44 | # pragma once
45 |
46 | # ifndef __MP_FLOATS__
47 | # define __MP_FLOATS__
48 |
49 | # include "basebase.hpp"
50 |
51 | namespace mp_float
52 | {
53 | typedef double real_type;
54 | typedef int indx_type;
55 | }
56 |
57 | # include
58 | # include
59 | # include
60 |
61 | // pragma STDC FENV_ACCESS ON
62 |
63 | # include "expansion/dd_float.hpp"
64 | # include "expansion/ia_float.hpp"
65 | # include "expansion/mp_float.hpp"
66 |
67 | # include "expansion/mp_utils.hpp"
68 |
69 | # endif//__MP_FLOATS__
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/predicate/bisect_k.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | --------------------------------------------------------
4 | * PREDICATE-k: robust geometric predicates in E^k.
5 | --------------------------------------------------------
6 | *
7 | * This program may be freely redistributed under the
8 | * condition that the copyright notices (including this
9 | * entire header) are not removed, and no compensation
10 | * is received through use of the software. Private,
11 | * research, and institutional use is free. You may
12 | * distribute modified versions of this code UNDER THE
13 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
14 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
15 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
16 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
17 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
18 | * of this code as part of a commercial system is
19 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
20 | * AUTHOR. (If you are not directly supplying this
21 | * code to a customer, and you are instead telling them
22 | * how they can obtain it for free, then you are not
23 | * required to make any arrangement with me.)
24 | *
25 | * Disclaimer: Neither I nor: Columbia University, The
26 | * Massachusetts Institute of Technology, The
27 | * University of Sydney, nor The National Aeronautics
28 | * and Space Administration warrant this code in any
29 | * way whatsoever. This code is provided "as-is" to be
30 | * used at your own risk.
31 | *
32 | --------------------------------------------------------
33 | *
34 | * Last updated: 14 April, 2020
35 | *
36 | * Copyright 2020--
37 | * Darren Engwirda
38 | * de2363@columbia.edu
39 | * https://github.com/dengwirda/
40 | *
41 | --------------------------------------------------------
42 | */
43 |
44 | // from predicate_k.hpp...
45 |
46 |
47 | /*
48 | --------------------------------------------------------
49 | *
50 | * Compute an exact orientation wrt. bisector using
51 | * multi-precision expansions, a'la shewchuk
52 | *
53 | * |c-a|**2 - wa = |c-b|**2 - wb
54 | *
55 | * This is the unweighted "bisect" predicate in E^2.
56 | *
57 | --------------------------------------------------------
58 | */
59 |
60 | __normal_call REAL_TYPE bisect2d_e (
61 | __const_ptr(REAL_TYPE) _pa ,
62 | __const_ptr(REAL_TYPE) _pb ,
63 | __const_ptr(REAL_TYPE) _pc ,
64 | bool_type &_OK
65 | )
66 | {
67 | /*--------------- bisect2d predicate, "exact" version */
68 | mp::expansion< 2 > _ab_xx_, _ab_yy_,
69 | _ac_xx_, _ac_yy_,
70 | _bc_xx_, _bc_yy_;
71 | mp::expansion< 4 > _tt_xx_, _tt_yy_;
72 | mp::expansion< 32> _absum_;
73 |
74 | _OK = true;
75 |
76 | /*----------------------------------- compute: d(p,q) */
77 | _ab_xx_.from_sub(_pa[0], _pb[0]);
78 | _ab_yy_.from_sub(_pa[1], _pb[1]);
79 |
80 | _ac_xx_.from_sub(_pa[0], _pc[0]);
81 | _ac_yy_.from_sub(_pa[1], _pc[1]);
82 |
83 | _bc_xx_.from_sub(_pb[0], _pc[0]);
84 | _bc_yy_.from_sub(_pb[1], _pc[1]);
85 |
86 | mp::expansion_add(_ac_xx_, _bc_xx_,
87 | _tt_xx_) ;
88 | mp::expansion_add(_ac_yy_, _bc_yy_,
89 | _tt_yy_) ;
90 |
91 | mp::expansion_dot(_ab_xx_, _tt_xx_,
92 | _ab_yy_, _tt_yy_,
93 | _absum_) ;
94 |
95 | /*----------------------------------- return signed d */
96 | return mp::expansion_est(_absum_) ;
97 | }
98 |
99 | __normal_call REAL_TYPE bisect2d_i (
100 | __const_ptr(REAL_TYPE) _pa ,
101 | __const_ptr(REAL_TYPE) _pb ,
102 | __const_ptr(REAL_TYPE) _pc ,
103 | bool_type &_OK
104 | )
105 | {
106 | /*--------------- bisect2d predicate, "bound" version */
107 | ia_flt _acx, _acy,
108 | _bcx, _bcy,
109 | _abx, _aby, _sgn;
110 |
111 | ia_rnd _rnd; // up rounding!
112 |
113 | _abx.from_sub(_pa[0], _pb[0]) ; // coord. diff.
114 | _aby.from_sub(_pa[1], _pb[1]) ;
115 |
116 | _acx.from_sub(_pa[0], _pc[0]) ;
117 | _acy.from_sub(_pa[1], _pc[1]) ;
118 |
119 | _bcx.from_sub(_pb[0], _pc[0]) ;
120 | _bcy.from_sub(_pb[1], _pc[1]) ;
121 |
122 | _sgn = (_abx * (_acx + _bcx))
123 | + (_aby * (_acy + _bcy)) ;
124 |
125 | _OK =
126 | _sgn.lo() >= (REAL_TYPE)0.
127 | || _sgn.up() <= (REAL_TYPE)0. ;
128 |
129 | return ( _sgn.mid () ) ;
130 | }
131 |
132 | __normal_call REAL_TYPE bisect2d_f (
133 | __const_ptr(REAL_TYPE) _pa ,
134 | __const_ptr(REAL_TYPE) _pb ,
135 | __const_ptr(REAL_TYPE) _pc ,
136 | bool_type &_OK
137 | )
138 | {
139 | /*--------------- bisect2d predicate, "float" version */
140 | REAL_TYPE static const _ER =
141 | + 5. * std::pow(mp::_epsilon, 1) ;
142 |
143 | REAL_TYPE _acx, _acy;
144 | REAL_TYPE _bcx, _bcy;
145 | REAL_TYPE _acsqr, _bcsqr ;
146 |
147 | REAL_TYPE _sgn, _FT ;
148 |
149 | REAL_TYPE _ACSQR, _BCSQR ;
150 |
151 | _acx = _pa [0] - _pc [0] ; // coord. diff.
152 | _acy = _pa [1] - _pc [1] ;
153 |
154 | _bcx = _pb [0] - _pc [0] ;
155 | _bcy = _pb [1] - _pc [1] ;
156 |
157 | _acsqr = _acx * _acx +
158 | _acy * _acy ;
159 | _bcsqr = _bcx * _bcx +
160 | _bcy * _bcy ;
161 |
162 | _ACSQR = std::abs(_acsqr);
163 | _BCSQR = std::abs(_bcsqr);
164 |
165 | _FT = _ACSQR + _BCSQR ; // roundoff tol
166 | _FT *= _ER ;
167 |
168 | _sgn = _acsqr - _bcsqr ; // d_ab - d_bc
169 |
170 | _OK = _sgn > +_FT || _sgn < -_FT ;
171 |
172 | return _sgn ;
173 | }
174 |
175 | /*
176 | --------------------------------------------------------
177 | *
178 | * Compute an exact orientation wrt. bisector using
179 | * multi-precision expansions, a'la shewchuk
180 | *
181 | * |c-a|**2 - wa = |c-b|**2 - wb
182 | *
183 | * This is the weighted "bisect" predicate in E^2.
184 | *
185 | --------------------------------------------------------
186 | */
187 |
188 | __normal_call REAL_TYPE bisect2w_e (
189 | __const_ptr(REAL_TYPE) _pa ,
190 | __const_ptr(REAL_TYPE) _pb ,
191 | __const_ptr(REAL_TYPE) _pc ,
192 | bool_type &_OK
193 | )
194 | {
195 | /*--------------- bisect2w predicate, "exact" version */
196 | mp::expansion< 2 > _ab_xx_, _ab_yy_,
197 | _ab_ww_,
198 | _ac_xx_, _ac_yy_,
199 | _bc_xx_, _bc_yy_;
200 | mp::expansion< 4 > _tt_xx_, _tt_yy_;
201 | mp::expansion< 32> _ttsum_;
202 | mp::expansion< 34> _absum_;
203 |
204 | _OK = true;
205 |
206 | /*----------------------------------- compute: d(p,q) */
207 | _ab_xx_.from_sub(_pa[0], _pb[0]);
208 | _ab_yy_.from_sub(_pa[1], _pb[1]);
209 | _ab_ww_.from_sub(_pa[2], _pb[2]);
210 |
211 | _ac_xx_.from_sub(_pa[0], _pc[0]);
212 | _ac_yy_.from_sub(_pa[1], _pc[1]);
213 |
214 | _bc_xx_.from_sub(_pb[0], _pc[0]);
215 | _bc_yy_.from_sub(_pb[1], _pc[1]);
216 |
217 | mp::expansion_add(_ac_xx_, _bc_xx_,
218 | _tt_xx_) ;
219 | mp::expansion_add(_ac_yy_, _bc_yy_,
220 | _tt_yy_) ;
221 |
222 | mp::expansion_dot(_ab_xx_, _tt_xx_,
223 | _ab_yy_, _tt_yy_,
224 | _ttsum_) ;
225 |
226 | mp::expansion_sub(_ttsum_, _ab_ww_,
227 | _absum_) ;
228 |
229 | /*----------------------------------- return signed d */
230 | return mp::expansion_est(_absum_) ;
231 | }
232 |
233 | __normal_call REAL_TYPE bisect2w_i (
234 | __const_ptr(REAL_TYPE) _pa ,
235 | __const_ptr(REAL_TYPE) _pb ,
236 | __const_ptr(REAL_TYPE) _pc ,
237 | bool_type &_OK
238 | )
239 | {
240 | /*--------------- bisect2w predicate, "bound" version */
241 | ia_flt _acx, _acy, _abw,
242 | _bcx, _bcy,
243 | _abx, _aby, _sgn;
244 |
245 | ia_rnd _rnd; // up rounding!
246 |
247 | _abx.from_sub(_pa[0], _pb[0]) ; // coord. diff.
248 | _aby.from_sub(_pa[1], _pb[1]) ;
249 | _abw.from_sub(_pa[2], _pb[2]) ;
250 |
251 | _acx.from_sub(_pa[0], _pc[0]) ;
252 | _acy.from_sub(_pa[1], _pc[1]) ;
253 |
254 | _bcx.from_sub(_pb[0], _pc[0]) ;
255 | _bcy.from_sub(_pb[1], _pc[1]) ;
256 |
257 | _sgn = (_abx * (_acx + _bcx))
258 | + (_aby * (_acy + _bcy)) ;
259 |
260 | _sgn-= _abw ;
261 |
262 | _OK =
263 | _sgn.lo() >= (REAL_TYPE)0.
264 | || _sgn.up() <= (REAL_TYPE)0. ;
265 |
266 | return ( _sgn.mid () ) ;
267 | }
268 |
269 | __normal_call REAL_TYPE bisect2w_f (
270 | __const_ptr(REAL_TYPE) _pa ,
271 | __const_ptr(REAL_TYPE) _pb ,
272 | __const_ptr(REAL_TYPE) _pc ,
273 | bool_type &_OK
274 | )
275 | {
276 | /*--------------- bisect2w predicate, "float" version */
277 | REAL_TYPE static const _ER =
278 | + 6. * std::pow(mp::_epsilon, 1) ;
279 |
280 | REAL_TYPE _acx, _acy;
281 | REAL_TYPE _bcx, _bcy;
282 | REAL_TYPE _acsqr, _bcsqr ;
283 | REAL_TYPE _a_sum, _b_sum ;
284 |
285 | REAL_TYPE _A_SUM, _B_SUM ;
286 |
287 | REAL_TYPE _sgn, _FT;
288 |
289 | _acx = _pa [0] - _pc [0] ; // coord. diff.
290 | _acy = _pa [1] - _pc [1] ;
291 |
292 | _bcx = _pb [0] - _pc [0] ;
293 | _bcy = _pb [1] - _pc [1] ;
294 |
295 | _acsqr = _acx * _acx +
296 | _acy * _acy ;
297 | _bcsqr = _bcx * _bcx +
298 | _bcy * _bcy ;
299 |
300 | _a_sum = _acsqr - _pa[2] ;
301 | _b_sum = _bcsqr - _pb[2] ;
302 |
303 | _A_SUM = std::abs(_acsqr)
304 | + std::abs(_pa[2]);
305 | _B_SUM = std::abs(_bcsqr)
306 | + std::abs(_pb[2]);
307 |
308 | _FT = _A_SUM + _B_SUM ; // roundoff tol
309 | _FT *= _ER ;
310 |
311 | _sgn = _a_sum - _b_sum ; // d_ab - d_bc
312 |
313 | _OK = _sgn > +_FT || _sgn < -_FT ;
314 |
315 | return _sgn ;
316 | }
317 |
318 | /*
319 | --------------------------------------------------------
320 | *
321 | * Compute an exact orientation wrt. bisector using
322 | * multi-precision expansions, a'la shewchuk
323 | *
324 | * |c-a|**2 - wa = |c-b|**2 - wb
325 | *
326 | * This is the unweighted "bisect" predicate in E^3.
327 | *
328 | --------------------------------------------------------
329 | */
330 |
331 | __normal_call REAL_TYPE bisect3d_e (
332 | __const_ptr(REAL_TYPE) _pa ,
333 | __const_ptr(REAL_TYPE) _pb ,
334 | __const_ptr(REAL_TYPE) _pc ,
335 | bool_type &_OK
336 | )
337 | {
338 | /*--------------- bisect3d predicate, "exact" version */
339 | mp::expansion< 2 > _ab_xx_, _ab_yy_,
340 | _ab_zz_,
341 | _ac_xx_, _ac_yy_,
342 | _ac_zz_,
343 | _bc_xx_, _bc_yy_,
344 | _bc_zz_;
345 | mp::expansion< 4 > _tt_xx_, _tt_yy_,
346 | _tt_zz_;
347 | mp::expansion< 48> _absum_;
348 |
349 | _OK = true;
350 |
351 | /*----------------------------------- compute: d(p,q) */
352 | _ab_xx_.from_sub(_pa[0], _pb[0]);
353 | _ab_yy_.from_sub(_pa[1], _pb[1]);
354 | _ab_zz_.from_sub(_pa[2], _pb[2]);
355 |
356 | _ac_xx_.from_sub(_pa[0], _pc[0]);
357 | _ac_yy_.from_sub(_pa[1], _pc[1]);
358 | _ac_zz_.from_sub(_pa[2], _pc[2]);
359 |
360 | _bc_xx_.from_sub(_pb[0], _pc[0]);
361 | _bc_yy_.from_sub(_pb[1], _pc[1]);
362 | _bc_zz_.from_sub(_pb[2], _pc[2]);
363 |
364 | mp::expansion_add(_ac_xx_, _bc_xx_,
365 | _tt_xx_) ;
366 | mp::expansion_add(_ac_yy_, _bc_yy_,
367 | _tt_yy_) ;
368 | mp::expansion_add(_ac_zz_, _bc_zz_,
369 | _tt_zz_) ;
370 |
371 | mp::expansion_dot(_ab_xx_, _tt_xx_,
372 | _ab_yy_, _tt_yy_,
373 | _ab_zz_, _tt_zz_,
374 | _absum_) ;
375 |
376 | /*----------------------------------- return signed d */
377 | return mp::expansion_est(_absum_) ;
378 | }
379 |
380 | __normal_call REAL_TYPE bisect3d_i (
381 | __const_ptr(REAL_TYPE) _pa ,
382 | __const_ptr(REAL_TYPE) _pb ,
383 | __const_ptr(REAL_TYPE) _pc ,
384 | bool_type &_OK
385 | )
386 | {
387 | /*--------------- bisect3d predicate, "bound" version */
388 | ia_flt _acx, _acy, _acz ,
389 | _bcx, _bcy, _bcz ,
390 | _abx, _aby, _abz ;
391 | ia_flt _sgn;
392 |
393 | ia_rnd _rnd; // up rounding!
394 |
395 | _abx.from_sub(_pa[0], _pb[0]) ; // coord. diff.
396 | _aby.from_sub(_pa[1], _pb[1]) ;
397 | _abz.from_sub(_pa[2], _pb[2]) ;
398 |
399 | _acx.from_sub(_pa[0], _pc[0]) ;
400 | _acy.from_sub(_pa[1], _pc[1]) ;
401 | _acz.from_sub(_pa[2], _pc[2]) ;
402 |
403 | _bcx.from_sub(_pb[0], _pc[0]) ;
404 | _bcy.from_sub(_pb[1], _pc[1]) ;
405 | _bcz.from_sub(_pb[2], _pc[2]) ;
406 |
407 | _sgn = (_abx * (_acx + _bcx))
408 | + (_aby * (_acy + _bcy))
409 | + (_abz * (_acz + _bcz)) ;
410 |
411 | _OK =
412 | _sgn.lo() >= (REAL_TYPE)0.
413 | || _sgn.up() <= (REAL_TYPE)0. ;
414 |
415 | return ( _sgn.mid () ) ;
416 | }
417 |
418 | __normal_call REAL_TYPE bisect3d_f (
419 | __const_ptr(REAL_TYPE) _pa ,
420 | __const_ptr(REAL_TYPE) _pb ,
421 | __const_ptr(REAL_TYPE) _pc ,
422 | bool_type &_OK
423 | )
424 | {
425 | /*--------------- bisect3d predicate, "float" version */
426 | REAL_TYPE static const _ER =
427 | + 6. * std::pow(mp::_epsilon, 1) ;
428 |
429 | REAL_TYPE _acx, _acy, _acz ;
430 | REAL_TYPE _bcx, _bcy, _bcz ;
431 | REAL_TYPE _acsqr, _bcsqr ;
432 |
433 | REAL_TYPE _sgn, _FT ;
434 |
435 | REAL_TYPE _ACSQR, _BCSQR ;
436 |
437 | _acx = _pa [0] - _pc [0] ; // coord. diff.
438 | _acy = _pa [1] - _pc [1] ;
439 | _acz = _pa [2] - _pc [2] ;
440 |
441 | _bcx = _pb [0] - _pc [0] ;
442 | _bcy = _pb [1] - _pc [1] ;
443 | _bcz = _pb [2] - _pc [2] ;
444 |
445 | _acsqr = _acx * _acx +
446 | _acy * _acy +
447 | _acz * _acz ;
448 | _bcsqr = _bcx * _bcx +
449 | _bcy * _bcy +
450 | _bcz * _bcz ;
451 |
452 | _ACSQR = std::abs(_acsqr);
453 | _BCSQR = std::abs(_bcsqr);
454 |
455 | _FT = _ACSQR + _BCSQR ; // roundoff tol
456 | _FT *= _ER ;
457 |
458 | _sgn = _acsqr - _bcsqr ; // d_ab - d_bc
459 |
460 | _OK = _sgn > +_FT || _sgn < -_FT ;
461 |
462 | return _sgn ;
463 | }
464 |
465 | /*
466 | --------------------------------------------------------
467 | *
468 | * Compute an exact orientation wrt. bisector using
469 | * multi-precision expansions, a'la shewchuk
470 | *
471 | * |c-a|**2 - wa = |c-b|**2 - wb
472 | *
473 | * This is the weighted "bisect" predicate in E^3.
474 | *
475 | --------------------------------------------------------
476 | */
477 |
478 | __normal_call REAL_TYPE bisect3w_e (
479 | __const_ptr(REAL_TYPE) _pa ,
480 | __const_ptr(REAL_TYPE) _pb ,
481 | __const_ptr(REAL_TYPE) _pc ,
482 | bool_type &_OK
483 | )
484 | {
485 | /*--------------- bisect3w predicate, "exact" version */
486 | mp::expansion< 2 > _ab_xx_, _ab_yy_,
487 | _ab_zz_, _ab_ww_,
488 | _ac_xx_, _ac_yy_,
489 | _ac_zz_,
490 | _bc_xx_, _bc_yy_,
491 | _bc_zz_;
492 | mp::expansion< 4 > _tt_xx_, _tt_yy_,
493 | _tt_zz_;
494 | mp::expansion< 48> _ttsum_;
495 | mp::expansion< 50> _absum_;
496 |
497 | _OK = true;
498 |
499 | /*----------------------------------- compute: d(p,q) */
500 | _ab_xx_.from_sub(_pa[0], _pb[0]);
501 | _ab_yy_.from_sub(_pa[1], _pb[1]);
502 | _ab_zz_.from_sub(_pa[2], _pb[2]);
503 | _ab_ww_.from_sub(_pa[3], _pb[3]);
504 |
505 | _ac_xx_.from_sub(_pa[0], _pc[0]);
506 | _ac_yy_.from_sub(_pa[1], _pc[1]);
507 | _ac_zz_.from_sub(_pa[2], _pc[2]);
508 |
509 | _bc_xx_.from_sub(_pb[0], _pc[0]);
510 | _bc_yy_.from_sub(_pb[1], _pc[1]);
511 | _bc_zz_.from_sub(_pb[2], _pc[2]);
512 |
513 | mp::expansion_add(_ac_xx_, _bc_xx_,
514 | _tt_xx_) ;
515 | mp::expansion_add(_ac_yy_, _bc_yy_,
516 | _tt_yy_) ;
517 | mp::expansion_add(_ac_zz_, _bc_zz_,
518 | _tt_zz_) ;
519 |
520 | mp::expansion_dot(_ab_xx_, _tt_xx_,
521 | _ab_yy_, _tt_yy_,
522 | _ab_zz_, _tt_zz_,
523 | _ttsum_) ;
524 |
525 | mp::expansion_sub(_ttsum_, _ab_ww_,
526 | _absum_) ;
527 |
528 | /*----------------------------------- return signed d */
529 | return mp::expansion_est(_absum_) ;
530 | }
531 |
532 | __normal_call REAL_TYPE bisect3w_i (
533 | __const_ptr(REAL_TYPE) _pa ,
534 | __const_ptr(REAL_TYPE) _pb ,
535 | __const_ptr(REAL_TYPE) _pc ,
536 | bool_type &_OK
537 | )
538 | {
539 | /*--------------- bisect3w predicate, "bound" version */
540 | ia_flt _acx, _acy, _acz ,
541 | _abw,
542 | _bcx, _bcy, _bcz ,
543 | _abx, _aby, _abz ;
544 | ia_flt _sgn;
545 |
546 | ia_rnd _rnd; // up rounding!
547 |
548 | _abx.from_sub(_pa[0], _pb[0]) ; // coord. diff.
549 | _aby.from_sub(_pa[1], _pb[1]) ;
550 | _abz.from_sub(_pa[2], _pb[2]) ;
551 | _abw.from_sub(_pa[3], _pb[3]) ;
552 |
553 | _acx.from_sub(_pa[0], _pc[0]) ;
554 | _acy.from_sub(_pa[1], _pc[1]) ;
555 | _acz.from_sub(_pa[2], _pc[2]) ;
556 |
557 | _bcx.from_sub(_pb[0], _pc[0]) ;
558 | _bcy.from_sub(_pb[1], _pc[1]) ;
559 | _bcz.from_sub(_pb[2], _pc[2]) ;
560 |
561 | _sgn = (_abx * (_acx + _bcx))
562 | + (_aby * (_acy + _bcy))
563 | + (_abz * (_acz + _bcz)) ;
564 |
565 | _sgn-= _abw ;
566 |
567 | _OK =
568 | _sgn.lo() >= (REAL_TYPE)0.
569 | || _sgn.up() <= (REAL_TYPE)0. ;
570 |
571 | return ( _sgn.mid () ) ;
572 | }
573 |
574 | __normal_call REAL_TYPE bisect3w_f (
575 | __const_ptr(REAL_TYPE) _pa ,
576 | __const_ptr(REAL_TYPE) _pb ,
577 | __const_ptr(REAL_TYPE) _pc ,
578 | bool_type &_OK
579 | )
580 | {
581 | /*--------------- bisect3w predicate, "float" version */
582 | REAL_TYPE static const _ER =
583 | + 7. * std::pow(mp::_epsilon, 1) ;
584 |
585 | REAL_TYPE _acx, _acy, _acz ;
586 | REAL_TYPE _bcx, _bcy, _bcz ;
587 | REAL_TYPE _acsqr, _bcsqr ;
588 | REAL_TYPE _a_sum, _b_sum ;
589 |
590 | REAL_TYPE _A_SUM, _B_SUM ;
591 |
592 | REAL_TYPE _sgn, _FT;
593 |
594 | _acx = _pa [0] - _pc [0] ; // coord. diff.
595 | _acy = _pa [1] - _pc [1] ;
596 | _acz = _pa [2] - _pc [2] ;
597 |
598 | _bcx = _pb [0] - _pc [0] ;
599 | _bcy = _pb [1] - _pc [1] ;
600 | _bcz = _pb [2] - _pc [2] ;
601 |
602 | _acsqr = _acx * _acx +
603 | _acy * _acy +
604 | _acz * _acz ;
605 | _bcsqr = _bcx * _bcx +
606 | _bcy * _bcy +
607 | _bcz * _bcz ;
608 |
609 | _a_sum = _acsqr - _pa[3] ;
610 | _b_sum = _bcsqr - _pb[3] ;
611 |
612 | _A_SUM = std::abs(_acsqr)
613 | + std::abs(_pa[3]);
614 | _B_SUM = std::abs(_bcsqr)
615 | + std::abs(_pb[3]);
616 |
617 | _FT = _A_SUM + _B_SUM ; // roundoff tol
618 | _FT *= _ER ;
619 |
620 | _sgn = _a_sum - _b_sum ; // d_ab - d_bc
621 |
622 | _OK = _sgn > +_FT || _sgn < -_FT ;
623 |
624 | return _sgn ;
625 | }
626 |
627 |
628 |
629 |
--------------------------------------------------------------------------------
/predicate/inball_k.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | --------------------------------------------------------
4 | * PREDICATE-k: robust geometric predicates in E^k.
5 | --------------------------------------------------------
6 | *
7 | * This program may be freely redistributed under the
8 | * condition that the copyright notices (including this
9 | * entire header) are not removed, and no compensation
10 | * is received through use of the software. Private,
11 | * research, and institutional use is free. You may
12 | * distribute modified versions of this code UNDER THE
13 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
14 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
15 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
16 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
17 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
18 | * of this code as part of a commercial system is
19 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
20 | * AUTHOR. (If you are not directly supplying this
21 | * code to a customer, and you are instead telling them
22 | * how they can obtain it for free, then you are not
23 | * required to make any arrangement with me.)
24 | *
25 | * Disclaimer: Neither I nor: Columbia University, The
26 | * Massachusetts Institute of Technology, The
27 | * University of Sydney, nor The National Aeronautics
28 | * and Space Administration warrant this code in any
29 | * way whatsoever. This code is provided "as-is" to be
30 | * used at your own risk.
31 | *
32 | --------------------------------------------------------
33 | *
34 | * Last updated: 14 April, 2020
35 | *
36 | * Copyright 2020--
37 | * Darren Engwirda
38 | * de2363@columbia.edu
39 | * https://github.com/dengwirda/
40 | *
41 | --------------------------------------------------------
42 | */
43 |
44 | // from predicate_k.hpp...
45 |
46 |
47 | /*
48 | --------------------------------------------------------
49 | *
50 | * Compute an exact determinant using multi-precision
51 | * expansions, a'la shewchuk
52 | *
53 | * | ax ay dot(a, a) +1. |
54 | * | bx by dot(b, b) +1. |
55 | * | cx cy dot(c, c) +1. |
56 | * | dx dy dot(d, d) +1. |
57 | *
58 | * This is the unweighted "in-ball" predicate in E^2.
59 | *
60 | --------------------------------------------------------
61 | */
62 |
63 | __normal_call REAL_TYPE inball2d_e (
64 | __const_ptr(REAL_TYPE) _pa ,
65 | __const_ptr(REAL_TYPE) _pb ,
66 | __const_ptr(REAL_TYPE) _pc ,
67 | __const_ptr(REAL_TYPE) _pd ,
68 | bool_type &_OK
69 | )
70 | {
71 | /*--------------- inball2d predicate, "exact" version */
72 | mp::expansion< 4 > _a_lift, _b_lift,
73 | _c_lift, _d_lift;
74 | mp::expansion< 4 > _d2_ab_, _d2_ac_,
75 | _d2_ad_,
76 | _d2_bc_, _d2_bd_,
77 | _d2_cd_;
78 | mp::expansion< 12> _d3_abc, _d3_abd,
79 | _d3_acd, _d3_bcd;
80 | mp::expansion<384> _d4full;
81 |
82 | _OK = true;
83 |
84 | /*-------------------------------------- lifted terms */
85 | mp::expansion_add(
86 | mp::expansion_from_sqr(_pa[ 0]),
87 | mp::expansion_from_sqr(_pa[ 1]),
88 | _a_lift ) ;
89 |
90 | mp::expansion_add(
91 | mp::expansion_from_sqr(_pb[ 0]),
92 | mp::expansion_from_sqr(_pb[ 1]),
93 | _b_lift ) ;
94 |
95 | mp::expansion_add(
96 | mp::expansion_from_sqr(_pc[ 0]),
97 | mp::expansion_from_sqr(_pc[ 1]),
98 | _c_lift ) ;
99 |
100 | mp::expansion_add(
101 | mp::expansion_from_sqr(_pd[ 0]),
102 | mp::expansion_from_sqr(_pd[ 1]),
103 | _d_lift ) ;
104 |
105 | /*-------------------------------------- 2 x 2 minors */
106 | compute_det_2x2(_pa[ 0], _pa[ 1],
107 | _pb[ 0], _pb[ 1],
108 | _d2_ab_ ) ;
109 |
110 | compute_det_2x2(_pa[ 0], _pa[ 1],
111 | _pc[ 0], _pc[ 1],
112 | _d2_ac_ ) ;
113 |
114 | compute_det_2x2(_pa[ 0], _pa[ 1],
115 | _pd[ 0], _pd[ 1],
116 | _d2_ad_ ) ;
117 |
118 | compute_det_2x2(_pb[ 0], _pb[ 1],
119 | _pc[ 0], _pc[ 1],
120 | _d2_bc_ ) ;
121 |
122 | compute_det_2x2(_pb[ 0], _pb[ 1],
123 | _pd[ 0], _pd[ 1],
124 | _d2_bd_ ) ;
125 |
126 | compute_det_2x2(_pc[ 0], _pc[ 1],
127 | _pd[ 0], _pd[ 1],
128 | _d2_cd_ ) ;
129 |
130 | /*-------------------------------------- 3 x 3 minors */
131 | unitary_det_3x3(_d2_cd_, _d2_bd_,
132 | _d2_bc_,
133 | _d3_bcd, +3) ;
134 |
135 | unitary_det_3x3(_d2_cd_, _d2_ad_,
136 | _d2_ac_,
137 | _d3_acd, +3) ;
138 |
139 | unitary_det_3x3(_d2_bd_, _d2_ad_,
140 | _d2_ab_,
141 | _d3_abd, +3) ;
142 |
143 | unitary_det_3x3(_d2_bc_, _d2_ac_,
144 | _d2_ab_,
145 | _d3_abc, +3) ;
146 |
147 | /*-------------------------------------- 4 x 4 result */
148 | compute_det_4x4(_d3_bcd, _a_lift,
149 | _d3_acd, _b_lift,
150 | _d3_abd, _c_lift,
151 | _d3_abc, _d_lift,
152 | _d4full, +3) ;
153 |
154 | /*-------------------------------------- leading det. */
155 | return mp::expansion_est(_d4full) ;
156 | }
157 |
158 | __normal_call REAL_TYPE inball2d_i (
159 | __const_ptr(REAL_TYPE) _pa ,
160 | __const_ptr(REAL_TYPE) _pb ,
161 | __const_ptr(REAL_TYPE) _pc ,
162 | __const_ptr(REAL_TYPE) _pd ,
163 | bool_type &_OK
164 | )
165 | {
166 | /*--------------- inball2d predicate, "bound" version */
167 | ia_flt _adx, _ady, _adw ,
168 | _bdx, _bdy, _bdw ,
169 | _cdx, _cdy, _cdw ;
170 | ia_flt _ali, _bli, _cli ;
171 | ia_flt _bdxcdy, _cdxbdy ,
172 | _cdxady, _adxcdy ,
173 | _adxbdy, _bdxady ;
174 |
175 | ia_flt _d33;
176 |
177 | ia_rnd _rnd; // up rounding!
178 |
179 | _adx.from_sub(_pa[0], _pd[0]) ; // coord. diff.
180 | _ady.from_sub(_pa[1], _pd[1]) ;
181 | _adw.from_sub(_pa[2], _pd[2]) ;
182 |
183 | _bdx.from_sub(_pb[0], _pd[0]) ;
184 | _bdy.from_sub(_pb[1], _pd[1]) ;
185 | _bdw.from_sub(_pb[2], _pd[2]) ;
186 |
187 | _cdx.from_sub(_pc[0], _pd[0]) ;
188 | _cdy.from_sub(_pc[1], _pd[1]) ;
189 | _cdw.from_sub(_pc[2], _pd[2]) ;
190 |
191 | _ali = sqr (_adx) + sqr (_ady) ; // lifted terms
192 |
193 | _bli = sqr (_bdx) + sqr (_bdy) ;
194 |
195 | _cli = sqr (_cdx) + sqr (_cdy) ;
196 |
197 | _bdxcdy = _bdx * _cdy ; // 2 x 2 minors
198 | _cdxbdy = _cdx * _bdy ;
199 | _cdxady = _cdx * _ady ;
200 | _adxcdy = _adx * _cdy ;
201 | _adxbdy = _adx * _bdy ;
202 | _bdxady = _bdx * _ady ;
203 |
204 | _d33 = // 3 x 3 result
205 | _ali * (_bdxcdy - _cdxbdy)
206 | + _bli * (_cdxady - _adxcdy)
207 | + _cli * (_adxbdy - _bdxady) ;
208 |
209 | _OK =
210 | _d33.lo() >= (REAL_TYPE)0.
211 | ||_d33.up() <= (REAL_TYPE)0. ;
212 |
213 | return ( _d33.mid() ) ;
214 | }
215 |
216 | __normal_call REAL_TYPE inball2d_f (
217 | __const_ptr(REAL_TYPE) _pa ,
218 | __const_ptr(REAL_TYPE) _pb ,
219 | __const_ptr(REAL_TYPE) _pc ,
220 | __const_ptr(REAL_TYPE) _pd ,
221 | bool_type &_OK
222 | )
223 | {
224 | /*--------------- inball2d predicate, "float" version */
225 | REAL_TYPE static const _ER =
226 | + 11. * std::pow(mp::_epsilon, 1) ;
227 |
228 | REAL_TYPE _adx, _ady, _ali ,
229 | _bdx, _bdy, _bli ,
230 | _cdx, _cdy, _cli ;
231 | REAL_TYPE _bdxcdy, _cdxbdy ,
232 | _cdxady, _adxcdy ,
233 | _adxbdy, _bdxady ;
234 |
235 | REAL_TYPE _BDXCDY, _CDXBDY ,
236 | _CDXADY, _ADXCDY ,
237 | _ADXBDY, _BDXADY ;
238 |
239 | REAL_TYPE _d33, _FT ;
240 |
241 | _adx = _pa [0] - _pd [0] ; // coord. diff.
242 | _ady = _pa [1] - _pd [1] ;
243 |
244 | _bdx = _pb [0] - _pd [0] ;
245 | _bdy = _pb [1] - _pd [1] ;
246 |
247 | _cdx = _pc [0] - _pd [0] ;
248 | _cdy = _pc [1] - _pd [1] ;
249 |
250 | _ali = _adx * _adx + _ady * _ady; // lifted terms
251 |
252 | _bli = _bdx * _bdx + _bdy * _bdy;
253 |
254 | _cli = _cdx * _cdx + _cdy * _cdy;
255 |
256 | _bdxcdy = _bdx * _cdy ; // 2 x 2 minors
257 | _cdxbdy = _cdx * _bdy ;
258 | _cdxady = _cdx * _ady ;
259 | _adxcdy = _adx * _cdy ;
260 | _adxbdy = _adx * _bdy ;
261 | _bdxady = _bdx * _ady ;
262 |
263 | _BDXCDY = std::abs (_bdxcdy) ;
264 | _CDXBDY = std::abs (_cdxbdy) ;
265 | _CDXADY = std::abs (_cdxady) ;
266 | _ADXCDY = std::abs (_adxcdy) ;
267 | _ADXBDY = std::abs (_adxbdy) ;
268 | _BDXADY = std::abs (_bdxady) ;
269 |
270 | _FT = // roundoff tol
271 | _ali * (_BDXCDY + _CDXBDY)
272 | + _bli * (_CDXADY + _ADXCDY)
273 | + _cli * (_ADXBDY + _BDXADY) ;
274 |
275 | _FT *= _ER ;
276 |
277 | _d33 = // 3 x 3 result
278 | _ali * (_bdxcdy - _cdxbdy)
279 | + _bli * (_cdxady - _adxcdy)
280 | + _cli * (_adxbdy - _bdxady) ;
281 |
282 | _OK =
283 | _d33 > +_FT || _d33 < -_FT ;
284 |
285 | return ( _d33 ) ;
286 | }
287 |
288 | /*
289 | --------------------------------------------------------
290 | *
291 | * Compute an exact determinant using multi-precision
292 | * expansions, a'la shewchuk
293 | *
294 | * | ax ay dot(a, a) - aw +1. |
295 | * | bx by dot(b, b) - bw +1. |
296 | * | cx cy dot(c, c) - cw +1. |
297 | * | dx dy dot(d, d) - dw +1. |
298 | *
299 | * This is the weighted "in-ball" predicate in E^2.
300 | *
301 | --------------------------------------------------------
302 | */
303 |
304 | __normal_call REAL_TYPE inball2w_e (
305 | __const_ptr(REAL_TYPE) _pa ,
306 | __const_ptr(REAL_TYPE) _pb ,
307 | __const_ptr(REAL_TYPE) _pc ,
308 | __const_ptr(REAL_TYPE) _pd ,
309 | bool_type &_OK
310 | )
311 | {
312 | /*--------------- inball2w predicate, "exact" version */
313 | mp::expansion< 5 > _a_lift, _b_lift,
314 | _c_lift, _d_lift;
315 | mp::expansion< 4 > _t_lift;
316 | mp::expansion< 4 > _d2_ab_, _d2_ac_,
317 | _d2_ad_,
318 | _d2_bc_, _d2_bd_,
319 | _d2_cd_;
320 | mp::expansion< 12> _d3_abc, _d3_abd,
321 | _d3_acd, _d3_bcd;
322 | mp::expansion<480> _d4full;
323 |
324 | _OK = true;
325 |
326 | /*-------------------------------------- lifted terms */
327 | mp::expansion_add(
328 | mp::expansion_from_sqr(_pa[ 0]),
329 | mp::expansion_from_sqr(_pa[ 1]),
330 | _t_lift ) ;
331 | mp::expansion_sub(
332 | _t_lift , _pa[ 2] , _a_lift);
333 |
334 | mp::expansion_add(
335 | mp::expansion_from_sqr(_pb[ 0]),
336 | mp::expansion_from_sqr(_pb[ 1]),
337 | _t_lift ) ;
338 | mp::expansion_sub(
339 | _t_lift , _pb[ 2] , _b_lift);
340 |
341 | mp::expansion_add(
342 | mp::expansion_from_sqr(_pc[ 0]),
343 | mp::expansion_from_sqr(_pc[ 1]),
344 | _t_lift ) ;
345 | mp::expansion_sub(
346 | _t_lift , _pc[ 2] , _c_lift);
347 |
348 | mp::expansion_add(
349 | mp::expansion_from_sqr(_pd[ 0]),
350 | mp::expansion_from_sqr(_pd[ 1]),
351 | _t_lift ) ;
352 | mp::expansion_sub(
353 | _t_lift , _pd[ 2] , _d_lift);
354 |
355 | /*-------------------------------------- 2 x 2 minors */
356 | compute_det_2x2(_pa[ 0], _pa[ 1],
357 | _pb[ 0], _pb[ 1],
358 | _d2_ab_ ) ;
359 |
360 | compute_det_2x2(_pa[ 0], _pa[ 1],
361 | _pc[ 0], _pc[ 1],
362 | _d2_ac_ ) ;
363 |
364 | compute_det_2x2(_pa[ 0], _pa[ 1],
365 | _pd[ 0], _pd[ 1],
366 | _d2_ad_ ) ;
367 |
368 | compute_det_2x2(_pb[ 0], _pb[ 1],
369 | _pc[ 0], _pc[ 1],
370 | _d2_bc_ ) ;
371 |
372 | compute_det_2x2(_pb[ 0], _pb[ 1],
373 | _pd[ 0], _pd[ 1],
374 | _d2_bd_ ) ;
375 |
376 | compute_det_2x2(_pc[ 0], _pc[ 1],
377 | _pd[ 0], _pd[ 1],
378 | _d2_cd_ ) ;
379 |
380 | /*-------------------------------------- 3 x 3 minors */
381 | unitary_det_3x3(_d2_cd_, _d2_bd_,
382 | _d2_bc_,
383 | _d3_bcd, +3) ;
384 |
385 | unitary_det_3x3(_d2_cd_, _d2_ad_,
386 | _d2_ac_,
387 | _d3_acd, +3) ;
388 |
389 | unitary_det_3x3(_d2_bd_, _d2_ad_,
390 | _d2_ab_,
391 | _d3_abd, +3) ;
392 |
393 | unitary_det_3x3(_d2_bc_, _d2_ac_,
394 | _d2_ab_,
395 | _d3_abc, +3) ;
396 |
397 | /*-------------------------------------- 4 x 4 result */
398 | compute_det_4x4(_d3_bcd, _a_lift,
399 | _d3_acd, _b_lift,
400 | _d3_abd, _c_lift,
401 | _d3_abc, _d_lift,
402 | _d4full, +3) ;
403 |
404 | /*-------------------------------------- leading det. */
405 | return mp::expansion_est(_d4full) ;
406 | }
407 |
408 | __normal_call REAL_TYPE inball2w_i (
409 | __const_ptr(REAL_TYPE) _pa ,
410 | __const_ptr(REAL_TYPE) _pb ,
411 | __const_ptr(REAL_TYPE) _pc ,
412 | __const_ptr(REAL_TYPE) _pd ,
413 | bool_type &_OK
414 | )
415 | {
416 | /*--------------- inball2w predicate, "bound" version */
417 | ia_flt _adx, _ady, _adw ,
418 | _bdx, _bdy, _bdw ,
419 | _cdx, _cdy, _cdw ;
420 | ia_flt _ali, _bli, _cli ;
421 | ia_flt _bdxcdy, _cdxbdy ,
422 | _cdxady, _adxcdy ,
423 | _adxbdy, _bdxady ;
424 |
425 | ia_flt _d33;
426 |
427 | ia_rnd _rnd; // up rounding!
428 |
429 | _adx.from_sub(_pa[0], _pd[0]) ; // coord. diff.
430 | _ady.from_sub(_pa[1], _pd[1]) ;
431 | _adw.from_sub(_pa[2], _pd[2]) ;
432 |
433 | _bdx.from_sub(_pb[0], _pd[0]) ;
434 | _bdy.from_sub(_pb[1], _pd[1]) ;
435 | _bdw.from_sub(_pb[2], _pd[2]) ;
436 |
437 | _cdx.from_sub(_pc[0], _pd[0]) ;
438 | _cdy.from_sub(_pc[1], _pd[1]) ;
439 | _cdw.from_sub(_pc[2], _pd[2]) ;
440 |
441 | _ali = sqr (_adx) + sqr (_ady) // lifted terms
442 | - _adw ;
443 |
444 | _bli = sqr (_bdx) + sqr (_bdy)
445 | - _bdw ;
446 |
447 | _cli = sqr (_cdx) + sqr (_cdy)
448 | - _cdw ;
449 |
450 | _bdxcdy = _bdx * _cdy ; // 2 x 2 minors
451 | _cdxbdy = _cdx * _bdy ;
452 | _cdxady = _cdx * _ady ;
453 | _adxcdy = _adx * _cdy ;
454 | _adxbdy = _adx * _bdy ;
455 | _bdxady = _bdx * _ady ;
456 |
457 | _d33 = // 3 x 3 result
458 | _ali * (_bdxcdy - _cdxbdy)
459 | + _bli * (_cdxady - _adxcdy)
460 | + _cli * (_adxbdy - _bdxady) ;
461 |
462 | _OK =
463 | _d33.lo() >= (REAL_TYPE)0.
464 | ||_d33.up() <= (REAL_TYPE)0. ;
465 |
466 | return ( _d33.mid() ) ;
467 | }
468 |
469 | __normal_call REAL_TYPE inball2w_f (
470 | __const_ptr(REAL_TYPE) _pa ,
471 | __const_ptr(REAL_TYPE) _pb ,
472 | __const_ptr(REAL_TYPE) _pc ,
473 | __const_ptr(REAL_TYPE) _pd ,
474 | bool_type &_OK
475 | )
476 | {
477 | /*--------------- inball2w predicate, "float" version */
478 | REAL_TYPE static const _ER =
479 | + 12. * std::pow(mp::_epsilon, 1) ;
480 |
481 | REAL_TYPE _adx, _ady, _adw ,
482 | _bdx, _bdy, _bdw ,
483 | _cdx, _cdy, _cdw ;
484 | REAL_TYPE _ali, _bli, _cli ;
485 | REAL_TYPE _bdxcdy, _cdxbdy ,
486 | _cdxady, _adxcdy ,
487 | _adxbdy, _bdxady ;
488 |
489 | REAL_TYPE _ALI, _BLI, _CLI ;
490 | REAL_TYPE _BDXCDY, _CDXBDY ,
491 | _CDXADY, _ADXCDY ,
492 | _ADXBDY, _BDXADY ;
493 |
494 | REAL_TYPE _d33, _FT ;
495 |
496 | _adx = _pa [0] - _pd [0] ; // coord. diff.
497 | _ady = _pa [1] - _pd [1] ;
498 | _adw = _pa [2] - _pd [2] ;
499 |
500 | _bdx = _pb [0] - _pd [0] ;
501 | _bdy = _pb [1] - _pd [1] ;
502 | _bdw = _pb [2] - _pd [2] ;
503 |
504 | _cdx = _pc [0] - _pd [0] ;
505 | _cdy = _pc [1] - _pd [1] ;
506 | _cdw = _pc [2] - _pd [2] ;
507 |
508 | _ali = _adx * _adx + _ady * _ady // lifted terms
509 | - _adw ;
510 |
511 | _ALI = std::abs (_ali) ;
512 |
513 | _bli = _bdx * _bdx + _bdy * _bdy
514 | - _bdw ;
515 |
516 | _BLI = std::abs (_bli) ;
517 |
518 | _cli = _cdx * _cdx + _cdy * _cdy
519 | - _cdw ;
520 |
521 | _CLI = std::abs (_cli) ;
522 |
523 | _bdxcdy = _bdx * _cdy ; // 2 x 2 minors
524 | _cdxbdy = _cdx * _bdy ;
525 | _cdxady = _cdx * _ady ;
526 | _adxcdy = _adx * _cdy ;
527 | _adxbdy = _adx * _bdy ;
528 | _bdxady = _bdx * _ady ;
529 |
530 | _BDXCDY = std::abs (_bdxcdy) ;
531 | _CDXBDY = std::abs (_cdxbdy) ;
532 | _CDXADY = std::abs (_cdxady) ;
533 | _ADXCDY = std::abs (_adxcdy) ;
534 | _ADXBDY = std::abs (_adxbdy) ;
535 | _BDXADY = std::abs (_bdxady) ;
536 |
537 | _FT = // roundoff tol
538 | _ALI * (_BDXCDY + _CDXBDY)
539 | + _BLI * (_CDXADY + _ADXCDY)
540 | + _CLI * (_ADXBDY + _BDXADY) ;
541 |
542 | _FT *= _ER ;
543 |
544 | _d33 = // 3 x 3 result
545 | _ali * (_bdxcdy - _cdxbdy)
546 | + _bli * (_cdxady - _adxcdy)
547 | + _cli * (_adxbdy - _bdxady) ;
548 |
549 | _OK =
550 | _d33 > +_FT || _d33 < -_FT ;
551 |
552 | return ( _d33 ) ;
553 | }
554 |
555 | /*
556 | --------------------------------------------------------
557 | *
558 | * Compute an exact determinant using multi-precision
559 | * expansions, a'la shewchuk
560 | *
561 | * | ax ay az dot(a, a) +1. |
562 | * | bx by bz dot(b, b) +1. |
563 | * | cx cy cz dot(c, c) +1. |
564 | * | dx dy dz dot(d, d) +1. |
565 | * | ex ey ez dot(e, e) +1. |
566 | *
567 | * This is the unweighted "in-ball" predicate in E^3.
568 | *
569 | --------------------------------------------------------
570 | */
571 |
572 | __normal_call REAL_TYPE inball3d_e (
573 | __const_ptr(REAL_TYPE) _pa ,
574 | __const_ptr(REAL_TYPE) _pb ,
575 | __const_ptr(REAL_TYPE) _pc ,
576 | __const_ptr(REAL_TYPE) _pd ,
577 | __const_ptr(REAL_TYPE) _pe ,
578 | bool_type &_OK
579 | )
580 | {
581 | /*--------------- inball3d predicate, "exact" version */
582 | mp::expansion< 6 > _a_lift, _b_lift,
583 | _c_lift, _d_lift,
584 | _e_lift;
585 | mp::expansion< 4 > _d2_ab_, _d2_ac_,
586 | _d2_ad_, _d2_ae_,
587 | _d2_bc_, _d2_bd_,
588 | _d2_be_,
589 | _d2_cd_, _d2_ce_,
590 | _d2_de_;
591 | mp::expansion< 24> _d3_abc, _d3_abd,
592 | _d3_abe,
593 | _d3_acd, _d3_ace,
594 | _d3_ade,
595 | _d3_bcd, _d3_bce,
596 | _d3_bde, _d3_cde;
597 | mp::expansion< 96> _d4abcd, _d4abce,
598 | _d4abde, _d4acde,
599 | _d4bcde;
600 | mp::expansion<5760>_d5full;
601 |
602 | _OK = true;
603 |
604 | mp::expansion< 1 > _pa_zz_(_pa[ 2]);
605 | mp::expansion< 1 > _pb_zz_(_pb[ 2]);
606 | mp::expansion< 1 > _pc_zz_(_pc[ 2]);
607 | mp::expansion< 1 > _pd_zz_(_pd[ 2]);
608 | mp::expansion< 1 > _pe_zz_(_pe[ 2]);
609 |
610 | /*-------------------------------------- lifted terms */
611 | mp::expansion_add(
612 | mp::expansion_from_sqr(_pa[ 0]),
613 | mp::expansion_from_sqr(_pa[ 1]),
614 | mp::expansion_from_sqr(_pa[ 2]),
615 | _a_lift ) ;
616 |
617 | mp::expansion_add(
618 | mp::expansion_from_sqr(_pb[ 0]),
619 | mp::expansion_from_sqr(_pb[ 1]),
620 | mp::expansion_from_sqr(_pb[ 2]),
621 | _b_lift ) ;
622 |
623 | mp::expansion_add(
624 | mp::expansion_from_sqr(_pc[ 0]),
625 | mp::expansion_from_sqr(_pc[ 1]),
626 | mp::expansion_from_sqr(_pc[ 2]),
627 | _c_lift ) ;
628 |
629 | mp::expansion_add(
630 | mp::expansion_from_sqr(_pd[ 0]),
631 | mp::expansion_from_sqr(_pd[ 1]),
632 | mp::expansion_from_sqr(_pd[ 2]),
633 | _d_lift ) ;
634 |
635 | mp::expansion_add(
636 | mp::expansion_from_sqr(_pe[ 0]),
637 | mp::expansion_from_sqr(_pe[ 1]),
638 | mp::expansion_from_sqr(_pe[ 2]),
639 | _e_lift ) ;
640 |
641 | /*-------------------------------------- 2 x 2 minors */
642 | compute_det_2x2(_pa[ 0], _pa[ 1],
643 | _pb[ 0], _pb[ 1],
644 | _d2_ab_ ) ;
645 |
646 | compute_det_2x2(_pa[ 0], _pa[ 1],
647 | _pc[ 0], _pc[ 1],
648 | _d2_ac_ ) ;
649 |
650 | compute_det_2x2(_pa[ 0], _pa[ 1],
651 | _pd[ 0], _pd[ 1],
652 | _d2_ad_ ) ;
653 |
654 | compute_det_2x2(_pa[ 0], _pa[ 1],
655 | _pe[ 0], _pe[ 1],
656 | _d2_ae_ ) ;
657 |
658 | compute_det_2x2(_pb[ 0], _pb[ 1],
659 | _pc[ 0], _pc[ 1],
660 | _d2_bc_ ) ;
661 |
662 | compute_det_2x2(_pb[ 0], _pb[ 1],
663 | _pd[ 0], _pd[ 1],
664 | _d2_bd_ ) ;
665 |
666 | compute_det_2x2(_pb[ 0], _pb[ 1],
667 | _pe[ 0], _pe[ 1],
668 | _d2_be_ ) ;
669 |
670 | compute_det_2x2(_pc[ 0], _pc[ 1],
671 | _pd[ 0], _pd[ 1],
672 | _d2_cd_ ) ;
673 |
674 | compute_det_2x2(_pc[ 0], _pc[ 1],
675 | _pe[ 0], _pe[ 1],
676 | _d2_ce_ ) ;
677 |
678 | compute_det_2x2(_pd[ 0], _pd[ 1],
679 | _pe[ 0], _pe[ 1],
680 | _d2_de_ ) ;
681 |
682 | /*-------------------------------------- 3 x 3 minors */
683 | compute_det_3x3(_d2_bc_, _pa_zz_,
684 | _d2_ac_, _pb_zz_,
685 | _d2_ab_, _pc_zz_,
686 | _d3_abc, +3) ;
687 |
688 | compute_det_3x3(_d2_bd_, _pa_zz_,
689 | _d2_ad_, _pb_zz_,
690 | _d2_ab_, _pd_zz_,
691 | _d3_abd, +3) ;
692 |
693 | compute_det_3x3(_d2_be_, _pa_zz_,
694 | _d2_ae_, _pb_zz_,
695 | _d2_ab_, _pe_zz_,
696 | _d3_abe, +3) ;
697 |
698 | compute_det_3x3(_d2_cd_, _pa_zz_,
699 | _d2_ad_, _pc_zz_,
700 | _d2_ac_, _pd_zz_,
701 | _d3_acd, +3) ;
702 |
703 | compute_det_3x3(_d2_ce_, _pa_zz_,
704 | _d2_ae_, _pc_zz_,
705 | _d2_ac_, _pe_zz_,
706 | _d3_ace, +3) ;
707 |
708 | compute_det_3x3(_d2_de_, _pa_zz_,
709 | _d2_ae_, _pd_zz_,
710 | _d2_ad_, _pe_zz_,
711 | _d3_ade, +3) ;
712 |
713 | compute_det_3x3(_d2_cd_, _pb_zz_,
714 | _d2_bd_, _pc_zz_,
715 | _d2_bc_, _pd_zz_,
716 | _d3_bcd, +3) ;
717 |
718 | compute_det_3x3(_d2_ce_, _pb_zz_,
719 | _d2_be_, _pc_zz_,
720 | _d2_bc_, _pe_zz_,
721 | _d3_bce, +3) ;
722 |
723 | compute_det_3x3(_d2_de_, _pb_zz_,
724 | _d2_be_, _pd_zz_,
725 | _d2_bd_, _pe_zz_,
726 | _d3_bde, +3) ;
727 |
728 | compute_det_3x3(_d2_de_, _pc_zz_,
729 | _d2_ce_, _pd_zz_,
730 | _d2_cd_, _pe_zz_,
731 | _d3_cde, +3) ;
732 |
733 | /*-------------------------------------- 4 x 4 minors */
734 | unitary_det_4x4(_d3_cde, _d3_bde,
735 | _d3_bce, _d3_bcd,
736 | _d4bcde, +4) ;
737 |
738 | unitary_det_4x4(_d3_cde, _d3_ade,
739 | _d3_ace, _d3_acd,
740 | _d4acde, +4) ;
741 |
742 | unitary_det_4x4(_d3_bde, _d3_ade,
743 | _d3_abe, _d3_abd,
744 | _d4abde, +4) ;
745 |
746 | unitary_det_4x4(_d3_bce, _d3_ace,
747 | _d3_abe, _d3_abc,
748 | _d4abce, +4) ;
749 |
750 | unitary_det_4x4(_d3_bcd, _d3_acd,
751 | _d3_abd, _d3_abc,
752 | _d4abcd, +4) ;
753 |
754 | /*-------------------------------------- 5 x 5 result */
755 | compute_det_5x5(_d4bcde, _a_lift,
756 | _d4acde, _b_lift,
757 | _d4abde, _c_lift,
758 | _d4abce, _d_lift,
759 | _d4abcd, _e_lift,
760 | _d5full, +4) ;
761 |
762 | /*-------------------------------------- leading det. */
763 | return mp::expansion_est(_d5full) ;
764 | }
765 |
766 | __normal_call REAL_TYPE inball3d_i (
767 | __const_ptr(REAL_TYPE) _pa ,
768 | __const_ptr(REAL_TYPE) _pb ,
769 | __const_ptr(REAL_TYPE) _pc ,
770 | __const_ptr(REAL_TYPE) _pd ,
771 | __const_ptr(REAL_TYPE) _pe ,
772 | bool_type &_OK
773 | )
774 | {
775 | /*--------------- inball3d predicate, "bound" version */
776 | ia_flt _aex, _aey, _aez ,
777 | _ali,
778 | _bex, _bey, _bez ,
779 | _bli,
780 | _cex, _cey, _cez ,
781 | _cli,
782 | _dex, _dey, _dez ,
783 | _dli;
784 | ia_flt _aexbey, _bexaey ,
785 | _aexcey, _cexaey ,
786 | _bexcey, _cexbey ,
787 | _cexdey, _dexcey ,
788 | _dexaey, _aexdey ,
789 | _bexdey, _dexbey ;
790 | ia_flt _ab_, _bc_, _cd_, _da_,
791 | _ac_, _bd_;
792 | ia_flt _abc, _bcd, _cda, _dab;
793 | ia_flt _d44;
794 |
795 | ia_rnd _rnd; // up rounding!
796 |
797 | _aex.from_sub(_pa[0], _pe[0]) ; // coord. diff.
798 | _aey.from_sub(_pa[1], _pe[1]) ;
799 | _aez.from_sub(_pa[2], _pe[2]) ;
800 |
801 | _bex.from_sub(_pb[0], _pe[0]) ;
802 | _bey.from_sub(_pb[1], _pe[1]) ;
803 | _bez.from_sub(_pb[2], _pe[2]) ;
804 |
805 | _cex.from_sub(_pc[0], _pe[0]) ;
806 | _cey.from_sub(_pc[1], _pe[1]) ;
807 | _cez.from_sub(_pc[2], _pe[2]) ;
808 |
809 | _dex.from_sub(_pd[0], _pe[0]) ;
810 | _dey.from_sub(_pd[1], _pe[1]) ;
811 | _dez.from_sub(_pd[2], _pe[2]) ;
812 |
813 | _ali = sqr (_aex) + sqr (_aey) // lifted terms
814 | + sqr (_aez) ;
815 |
816 | _bli = sqr (_bex) + sqr (_bey)
817 | + sqr (_bez) ;
818 |
819 | _cli = sqr (_cex) + sqr (_cey)
820 | + sqr (_cez) ;
821 |
822 | _dli = sqr (_dex) + sqr (_dey)
823 | + sqr (_dez) ;
824 |
825 | _aexbey = _aex * _bey ; // 2 x 2 minors
826 | _bexaey = _bex * _aey ;
827 | _ab_ = _aexbey - _bexaey ;
828 |
829 | _bexcey = _bex * _cey;
830 | _cexbey = _cex * _bey;
831 | _bc_ = _bexcey - _cexbey ;
832 |
833 | _cexdey = _cex * _dey;
834 | _dexcey = _dex * _cey;
835 | _cd_ = _cexdey - _dexcey ;
836 |
837 | _dexaey = _dex * _aey;
838 | _aexdey = _aex * _dey;
839 | _da_ = _dexaey - _aexdey ;
840 |
841 | _aexcey = _aex * _cey;
842 | _cexaey = _cex * _aey;
843 | _ac_ = _aexcey - _cexaey ;
844 |
845 | _bexdey = _bex * _dey;
846 | _dexbey = _dex * _bey;
847 | _bd_ = _bexdey - _dexbey ;
848 |
849 | _abc = // 3 x 3 minors
850 | _aez * _bc_ - _bez * _ac_
851 | + _cez * _ab_ ;
852 |
853 | _bcd =
854 | _bez * _cd_ - _cez * _bd_
855 | + _dez * _bc_ ;
856 |
857 | _cda =
858 | _cez * _da_ + _dez * _ac_
859 | + _aez * _cd_ ;
860 |
861 | _dab =
862 | _dez * _ab_ + _aez * _bd_
863 | + _bez * _da_ ;
864 |
865 | _d44 = // 4 x 4 result
866 | _dli * _abc - _cli * _dab
867 | + _bli * _cda - _ali * _bcd ;
868 |
869 | _OK =
870 | _d44.lo() >= (REAL_TYPE)0.
871 | ||_d44.up() <= (REAL_TYPE)0.;
872 |
873 | return ( _d44.mid() ) ;
874 | }
875 |
876 | __normal_call REAL_TYPE inball3d_f (
877 | __const_ptr(REAL_TYPE) _pa ,
878 | __const_ptr(REAL_TYPE) _pb ,
879 | __const_ptr(REAL_TYPE) _pc ,
880 | __const_ptr(REAL_TYPE) _pd ,
881 | __const_ptr(REAL_TYPE) _pe ,
882 | bool_type &_OK
883 | )
884 | {
885 | /*--------------- inball3d predicate, "float" version */
886 | REAL_TYPE static const _ER =
887 | + 17. * std::pow(mp::_epsilon, 1) ;
888 |
889 | REAL_TYPE _aex, _aey, _aez ,
890 | _ali,
891 | _bex, _bey, _bez ,
892 | _bli,
893 | _cex, _cey, _cez ,
894 | _cli,
895 | _dex, _dey, _dez ,
896 | _dli;
897 | REAL_TYPE _aexbey, _bexaey ,
898 | _aexcey, _cexaey ,
899 | _bexcey, _cexbey ,
900 | _cexdey, _dexcey ,
901 | _dexaey, _aexdey ,
902 | _bexdey, _dexbey ;
903 | REAL_TYPE _ab_, _bc_, _cd_, _da_,
904 | _ac_, _bd_;
905 | REAL_TYPE _abc, _bcd, _cda, _dab;
906 |
907 | REAL_TYPE _AEZ, _BEZ, _CEZ, _DEZ;
908 | REAL_TYPE _AEXBEY, _BEXAEY ,
909 | _AEXCEY, _CEXAEY ,
910 | _BEXCEY, _CEXBEY ,
911 | _CEXDEY, _DEXCEY ,
912 | _DEXAEY, _AEXDEY ,
913 | _BEXDEY, _DEXBEY ;
914 | REAL_TYPE _AB_, _BC_, _CD_, _DA_,
915 | _AC_, _BD_;
916 | REAL_TYPE _ABC, _BCD, _CDA, _DAB;
917 |
918 | REAL_TYPE _d44, _FT ;
919 |
920 | _aex = _pa [0] - _pe [0] ; // coord. diff.
921 | _aey = _pa [1] - _pe [1] ;
922 | _aez = _pa [2] - _pe [2] ;
923 |
924 | _AEZ = std::abs (_aez) ;
925 |
926 | _bex = _pb [0] - _pe [0] ;
927 | _bey = _pb [1] - _pe [1] ;
928 | _bez = _pb [2] - _pe [2] ;
929 |
930 | _BEZ = std::abs (_bez) ;
931 |
932 | _cex = _pc [0] - _pe [0] ;
933 | _cey = _pc [1] - _pe [1] ;
934 | _cez = _pc [2] - _pe [2] ;
935 |
936 | _CEZ = std::abs (_cez) ;
937 |
938 | _dex = _pd [0] - _pe [0] ;
939 | _dey = _pd [1] - _pe [1] ;
940 | _dez = _pd [2] - _pe [2] ;
941 |
942 | _DEZ = std::abs (_dez) ;
943 |
944 | _ali = _aex * _aex + _aey * _aey // lifted terms
945 | + _aez * _aez ;
946 |
947 | _bli = _bex * _bex + _bey * _bey
948 | + _bez * _bez ;
949 |
950 | _cli = _cex * _cex + _cey * _cey
951 | + _cez * _cez ;
952 |
953 | _dli = _dex * _dex + _dey * _dey
954 | + _dez * _dez ;
955 |
956 | _aexbey = _aex * _bey ; // 2 x 2 minors
957 | _bexaey = _bex * _aey ;
958 | _ab_ = _aexbey - _bexaey ;
959 |
960 | _AEXBEY = std::abs (_aexbey) ;
961 | _BEXAEY = std::abs (_bexaey) ;
962 | _AB_ = _AEXBEY + _BEXAEY ;
963 |
964 | _bexcey = _bex * _cey;
965 | _cexbey = _cex * _bey;
966 | _bc_ = _bexcey - _cexbey ;
967 |
968 | _BEXCEY = std::abs (_bexcey) ;
969 | _CEXBEY = std::abs (_cexbey) ;
970 | _BC_ = _BEXCEY + _CEXBEY ;
971 |
972 | _cexdey = _cex * _dey;
973 | _dexcey = _dex * _cey;
974 | _cd_ = _cexdey - _dexcey ;
975 |
976 | _CEXDEY = std::abs (_cexdey) ;
977 | _DEXCEY = std::abs (_dexcey) ;
978 | _CD_ = _CEXDEY + _DEXCEY ;
979 |
980 | _dexaey = _dex * _aey;
981 | _aexdey = _aex * _dey;
982 | _da_ = _dexaey - _aexdey ;
983 |
984 | _DEXAEY = std::abs (_dexaey) ;
985 | _AEXDEY = std::abs (_aexdey) ;
986 | _DA_ = _DEXAEY + _AEXDEY ;
987 |
988 | _aexcey = _aex * _cey;
989 | _cexaey = _cex * _aey;
990 | _ac_ = _aexcey - _cexaey ;
991 |
992 | _AEXCEY = std::abs (_aexcey) ;
993 | _CEXAEY = std::abs (_cexaey) ;
994 | _AC_ = _AEXCEY + _CEXAEY ;
995 |
996 | _bexdey = _bex * _dey;
997 | _dexbey = _dex * _bey;
998 | _bd_ = _bexdey - _dexbey ;
999 |
1000 | _BEXDEY = std::abs (_bexdey) ;
1001 | _DEXBEY = std::abs (_dexbey) ;
1002 | _BD_ = _BEXDEY + _DEXBEY ;
1003 |
1004 | _abc = // 3 x 3 minors
1005 | _aez * _bc_ - _bez * _ac_
1006 | + _cez * _ab_ ;
1007 | _ABC =
1008 | _AEZ * _BC_ + _BEZ * _AC_
1009 | + _CEZ * _AB_ ;
1010 |
1011 | _bcd =
1012 | _bez * _cd_ - _cez * _bd_
1013 | + _dez * _bc_ ;
1014 | _BCD =
1015 | _BEZ * _CD_ + _CEZ * _BD_
1016 | + _DEZ * _BC_ ;
1017 |
1018 | _cda =
1019 | _cez * _da_ + _dez * _ac_
1020 | + _aez * _cd_ ;
1021 | _CDA =
1022 | _CEZ * _DA_ + _DEZ * _AC_
1023 | + _AEZ * _CD_ ;
1024 |
1025 | _dab =
1026 | _dez * _ab_ + _aez * _bd_
1027 | + _bez * _da_ ;
1028 | _DAB =
1029 | _DEZ * _AB_ + _AEZ * _BD_
1030 | + _BEZ * _DA_ ;
1031 |
1032 | _FT = // roundoff tol
1033 | _dli * _ABC + _cli * _DAB
1034 | + _bli * _CDA + _ali * _BCD ;
1035 |
1036 | _FT *= _ER ;
1037 |
1038 | _d44 = // 4 x 4 result
1039 | _dli * _abc - _cli * _dab
1040 | + _bli * _cda - _ali * _bcd ;
1041 |
1042 | _OK =
1043 | _d44 > _FT || _d44 < -_FT ;
1044 |
1045 | return ( _d44 ) ;
1046 | }
1047 |
1048 | /*
1049 | --------------------------------------------------------
1050 | *
1051 | * Compute an exact determinant using multi-precision
1052 | * expansions, a'la shewchuk
1053 | *
1054 | * | ax ay az dot(a, a) - aw +1. |
1055 | * | bx by bz dot(b, b) - bw +1. |
1056 | * | cx cy cz dot(c, c) - cw +1. |
1057 | * | dx dy dz dot(d, d) - dw +1. |
1058 | * | ex ey ez dot(e, e) - ew +1. |
1059 | *
1060 | * This is the weighted "in-ball" predicate in E^3.
1061 | *
1062 | --------------------------------------------------------
1063 | */
1064 |
1065 | __normal_call REAL_TYPE inball3w_e (
1066 | __const_ptr(REAL_TYPE) _pa ,
1067 | __const_ptr(REAL_TYPE) _pb ,
1068 | __const_ptr(REAL_TYPE) _pc ,
1069 | __const_ptr(REAL_TYPE) _pd ,
1070 | __const_ptr(REAL_TYPE) _pe ,
1071 | bool_type &_OK
1072 | )
1073 | {
1074 | /*--------------- inball3w predicate, "exact" version */
1075 | mp::expansion< 7 > _a_lift, _b_lift,
1076 | _c_lift, _d_lift,
1077 | _e_lift;
1078 | mp::expansion< 6 > _t_lift;
1079 | mp::expansion< 4 > _d2_ab_, _d2_ac_,
1080 | _d2_ad_, _d2_ae_,
1081 | _d2_bc_, _d2_bd_,
1082 | _d2_be_,
1083 | _d2_cd_, _d2_ce_,
1084 | _d2_de_;
1085 | mp::expansion< 24> _d3_abc, _d3_abd,
1086 | _d3_abe,
1087 | _d3_acd, _d3_ace,
1088 | _d3_ade,
1089 | _d3_bcd, _d3_bce,
1090 | _d3_bde, _d3_cde;
1091 | mp::expansion< 96> _d4abcd, _d4abce,
1092 | _d4abde, _d4acde,
1093 | _d4bcde;
1094 | mp::expansion<6720>_d5full;
1095 |
1096 | _OK = true;
1097 |
1098 | mp::expansion< 1 > _pa_zz_(_pa[ 2]);
1099 | mp::expansion< 1 > _pb_zz_(_pb[ 2]);
1100 | mp::expansion< 1 > _pc_zz_(_pc[ 2]);
1101 | mp::expansion< 1 > _pd_zz_(_pd[ 2]);
1102 | mp::expansion< 1 > _pe_zz_(_pe[ 2]);
1103 |
1104 | /*-------------------------------------- lifted terms */
1105 | mp::expansion_add(
1106 | mp::expansion_from_sqr(_pa[ 0]),
1107 | mp::expansion_from_sqr(_pa[ 1]),
1108 | mp::expansion_from_sqr(_pa[ 2]),
1109 | _t_lift ) ;
1110 | mp::expansion_sub(
1111 | _t_lift , _pa[ 3] , _a_lift);
1112 |
1113 | mp::expansion_add(
1114 | mp::expansion_from_sqr(_pb[ 0]),
1115 | mp::expansion_from_sqr(_pb[ 1]),
1116 | mp::expansion_from_sqr(_pb[ 2]),
1117 | _t_lift ) ;
1118 | mp::expansion_sub(
1119 | _t_lift , _pb[ 3] , _b_lift);
1120 |
1121 | mp::expansion_add(
1122 | mp::expansion_from_sqr(_pc[ 0]),
1123 | mp::expansion_from_sqr(_pc[ 1]),
1124 | mp::expansion_from_sqr(_pc[ 2]),
1125 | _t_lift ) ;
1126 | mp::expansion_sub(
1127 | _t_lift , _pc[ 3] , _c_lift);
1128 |
1129 | mp::expansion_add(
1130 | mp::expansion_from_sqr(_pd[ 0]),
1131 | mp::expansion_from_sqr(_pd[ 1]),
1132 | mp::expansion_from_sqr(_pd[ 2]),
1133 | _t_lift ) ;
1134 | mp::expansion_sub(
1135 | _t_lift , _pd[ 3] , _d_lift);
1136 |
1137 | mp::expansion_add(
1138 | mp::expansion_from_sqr(_pe[ 0]),
1139 | mp::expansion_from_sqr(_pe[ 1]),
1140 | mp::expansion_from_sqr(_pe[ 2]),
1141 | _t_lift ) ;
1142 | mp::expansion_sub(
1143 | _t_lift , _pe[ 3] , _e_lift);
1144 |
1145 | /*-------------------------------------- 2 x 2 minors */
1146 | compute_det_2x2(_pa[ 0], _pa[ 1],
1147 | _pb[ 0], _pb[ 1],
1148 | _d2_ab_ ) ;
1149 |
1150 | compute_det_2x2(_pa[ 0], _pa[ 1],
1151 | _pc[ 0], _pc[ 1],
1152 | _d2_ac_ ) ;
1153 |
1154 | compute_det_2x2(_pa[ 0], _pa[ 1],
1155 | _pd[ 0], _pd[ 1],
1156 | _d2_ad_ ) ;
1157 |
1158 | compute_det_2x2(_pa[ 0], _pa[ 1],
1159 | _pe[ 0], _pe[ 1],
1160 | _d2_ae_ ) ;
1161 |
1162 | compute_det_2x2(_pb[ 0], _pb[ 1],
1163 | _pc[ 0], _pc[ 1],
1164 | _d2_bc_ ) ;
1165 |
1166 | compute_det_2x2(_pb[ 0], _pb[ 1],
1167 | _pd[ 0], _pd[ 1],
1168 | _d2_bd_ ) ;
1169 |
1170 | compute_det_2x2(_pb[ 0], _pb[ 1],
1171 | _pe[ 0], _pe[ 1],
1172 | _d2_be_ ) ;
1173 |
1174 | compute_det_2x2(_pc[ 0], _pc[ 1],
1175 | _pd[ 0], _pd[ 1],
1176 | _d2_cd_ ) ;
1177 |
1178 | compute_det_2x2(_pc[ 0], _pc[ 1],
1179 | _pe[ 0], _pe[ 1],
1180 | _d2_ce_ ) ;
1181 |
1182 | compute_det_2x2(_pd[ 0], _pd[ 1],
1183 | _pe[ 0], _pe[ 1],
1184 | _d2_de_ ) ;
1185 |
1186 | /*-------------------------------------- 3 x 3 minors */
1187 | compute_det_3x3(_d2_bc_, _pa_zz_,
1188 | _d2_ac_, _pb_zz_,
1189 | _d2_ab_, _pc_zz_,
1190 | _d3_abc, +3) ;
1191 |
1192 | compute_det_3x3(_d2_bd_, _pa_zz_,
1193 | _d2_ad_, _pb_zz_,
1194 | _d2_ab_, _pd_zz_,
1195 | _d3_abd, +3) ;
1196 |
1197 | compute_det_3x3(_d2_be_, _pa_zz_,
1198 | _d2_ae_, _pb_zz_,
1199 | _d2_ab_, _pe_zz_,
1200 | _d3_abe, +3) ;
1201 |
1202 | compute_det_3x3(_d2_cd_, _pa_zz_,
1203 | _d2_ad_, _pc_zz_,
1204 | _d2_ac_, _pd_zz_,
1205 | _d3_acd, +3) ;
1206 |
1207 | compute_det_3x3(_d2_ce_, _pa_zz_,
1208 | _d2_ae_, _pc_zz_,
1209 | _d2_ac_, _pe_zz_,
1210 | _d3_ace, +3) ;
1211 |
1212 | compute_det_3x3(_d2_de_, _pa_zz_,
1213 | _d2_ae_, _pd_zz_,
1214 | _d2_ad_, _pe_zz_,
1215 | _d3_ade, +3) ;
1216 |
1217 | compute_det_3x3(_d2_cd_, _pb_zz_,
1218 | _d2_bd_, _pc_zz_,
1219 | _d2_bc_, _pd_zz_,
1220 | _d3_bcd, +3) ;
1221 |
1222 | compute_det_3x3(_d2_ce_, _pb_zz_,
1223 | _d2_be_, _pc_zz_,
1224 | _d2_bc_, _pe_zz_,
1225 | _d3_bce, +3) ;
1226 |
1227 | compute_det_3x3(_d2_de_, _pb_zz_,
1228 | _d2_be_, _pd_zz_,
1229 | _d2_bd_, _pe_zz_,
1230 | _d3_bde, +3) ;
1231 |
1232 | compute_det_3x3(_d2_de_, _pc_zz_,
1233 | _d2_ce_, _pd_zz_,
1234 | _d2_cd_, _pe_zz_,
1235 | _d3_cde, +3) ;
1236 |
1237 | /*-------------------------------------- 4 x 4 minors */
1238 | unitary_det_4x4(_d3_cde, _d3_bde,
1239 | _d3_bce, _d3_bcd,
1240 | _d4bcde, +4) ;
1241 |
1242 | unitary_det_4x4(_d3_cde, _d3_ade,
1243 | _d3_ace, _d3_acd,
1244 | _d4acde, +4) ;
1245 |
1246 | unitary_det_4x4(_d3_bde, _d3_ade,
1247 | _d3_abe, _d3_abd,
1248 | _d4abde, +4) ;
1249 |
1250 | unitary_det_4x4(_d3_bce, _d3_ace,
1251 | _d3_abe, _d3_abc,
1252 | _d4abce, +4) ;
1253 |
1254 | unitary_det_4x4(_d3_bcd, _d3_acd,
1255 | _d3_abd, _d3_abc,
1256 | _d4abcd, +4) ;
1257 |
1258 | /*-------------------------------------- 5 x 5 result */
1259 | compute_det_5x5(_d4bcde, _a_lift,
1260 | _d4acde, _b_lift,
1261 | _d4abde, _c_lift,
1262 | _d4abce, _d_lift,
1263 | _d4abcd, _e_lift,
1264 | _d5full, +4) ;
1265 |
1266 | /*-------------------------------------- leading det. */
1267 | return mp::expansion_est(_d5full) ;
1268 | }
1269 |
1270 | __normal_call REAL_TYPE inball3w_i (
1271 | __const_ptr(REAL_TYPE) _pa ,
1272 | __const_ptr(REAL_TYPE) _pb ,
1273 | __const_ptr(REAL_TYPE) _pc ,
1274 | __const_ptr(REAL_TYPE) _pd ,
1275 | __const_ptr(REAL_TYPE) _pe ,
1276 | bool_type &_OK
1277 | )
1278 | {
1279 | /*--------------- inball3w predicate, "bound" version */
1280 | ia_flt _aex, _aey, _aez ,
1281 | _aew, _ali,
1282 | _bex, _bey, _bez ,
1283 | _bew, _bli,
1284 | _cex, _cey, _cez ,
1285 | _cew, _cli,
1286 | _dex, _dey, _dez ,
1287 | _dew, _dli;
1288 | ia_flt _aexbey, _bexaey ,
1289 | _aexcey, _cexaey ,
1290 | _bexcey, _cexbey ,
1291 | _cexdey, _dexcey ,
1292 | _dexaey, _aexdey ,
1293 | _bexdey, _dexbey ;
1294 | ia_flt _ab_, _bc_, _cd_, _da_,
1295 | _ac_, _bd_;
1296 | ia_flt _abc, _bcd, _cda, _dab;
1297 | ia_flt _d44;
1298 |
1299 | ia_rnd _rnd; // up rounding!
1300 |
1301 | _aex.from_sub(_pa[0], _pe[0]) ; // coord. diff.
1302 | _aey.from_sub(_pa[1], _pe[1]) ;
1303 | _aez.from_sub(_pa[2], _pe[2]) ;
1304 | _aew.from_sub(_pa[3], _pe[3]) ;
1305 |
1306 | _bex.from_sub(_pb[0], _pe[0]) ;
1307 | _bey.from_sub(_pb[1], _pe[1]) ;
1308 | _bez.from_sub(_pb[2], _pe[2]) ;
1309 | _bew.from_sub(_pb[3], _pe[3]) ;
1310 |
1311 | _cex.from_sub(_pc[0], _pe[0]) ;
1312 | _cey.from_sub(_pc[1], _pe[1]) ;
1313 | _cez.from_sub(_pc[2], _pe[2]) ;
1314 | _cew.from_sub(_pc[3], _pe[3]) ;
1315 |
1316 | _dex.from_sub(_pd[0], _pe[0]) ;
1317 | _dey.from_sub(_pd[1], _pe[1]) ;
1318 | _dez.from_sub(_pd[2], _pe[2]) ;
1319 | _dew.from_sub(_pd[3], _pe[3]) ;
1320 |
1321 | _ali = sqr(_aex) + sqr(_aey) // lifted terms
1322 | + sqr(_aez) - _aew ;
1323 |
1324 | _bli = sqr(_bex) + sqr(_bey)
1325 | + sqr(_bez) - _bew ;
1326 |
1327 | _cli = sqr(_cex) + sqr(_cey)
1328 | + sqr(_cez) - _cew ;
1329 |
1330 | _dli = sqr(_dex) + sqr(_dey)
1331 | + sqr(_dez) - _dew ;
1332 |
1333 | _aexbey = _aex * _bey ; // 2 x 2 minors
1334 | _bexaey = _bex * _aey ;
1335 | _ab_ = _aexbey - _bexaey ;
1336 |
1337 | _bexcey = _bex * _cey;
1338 | _cexbey = _cex * _bey;
1339 | _bc_ = _bexcey - _cexbey ;
1340 |
1341 | _cexdey = _cex * _dey;
1342 | _dexcey = _dex * _cey;
1343 | _cd_ = _cexdey - _dexcey ;
1344 |
1345 | _dexaey = _dex * _aey;
1346 | _aexdey = _aex * _dey;
1347 | _da_ = _dexaey - _aexdey ;
1348 |
1349 | _aexcey = _aex * _cey;
1350 | _cexaey = _cex * _aey;
1351 | _ac_ = _aexcey - _cexaey ;
1352 |
1353 | _bexdey = _bex * _dey;
1354 | _dexbey = _dex * _bey;
1355 | _bd_ = _bexdey - _dexbey ;
1356 |
1357 | _abc = // 3 x 3 minors
1358 | _aez * _bc_ - _bez * _ac_
1359 | + _cez * _ab_ ;
1360 |
1361 | _bcd =
1362 | _bez * _cd_ - _cez * _bd_
1363 | + _dez * _bc_ ;
1364 |
1365 | _cda =
1366 | _cez * _da_ + _dez * _ac_
1367 | + _aez * _cd_ ;
1368 |
1369 | _dab =
1370 | _dez * _ab_ + _aez * _bd_
1371 | + _bez * _da_ ;
1372 |
1373 | _d44 = // 4 x 4 result
1374 | _dli * _abc - _cli * _dab
1375 | + _bli * _cda - _ali * _bcd ;
1376 |
1377 | _OK =
1378 | _d44.lo() >= (REAL_TYPE)0.
1379 | ||_d44.up() <= (REAL_TYPE)0.;
1380 |
1381 | return ( _d44.mid() ) ;
1382 | }
1383 |
1384 | __normal_call REAL_TYPE inball3w_f (
1385 | __const_ptr(REAL_TYPE) _pa ,
1386 | __const_ptr(REAL_TYPE) _pb ,
1387 | __const_ptr(REAL_TYPE) _pc ,
1388 | __const_ptr(REAL_TYPE) _pd ,
1389 | __const_ptr(REAL_TYPE) _pe ,
1390 | bool_type &_OK
1391 | )
1392 | {
1393 | /*--------------- inball3w predicate, "float" version */
1394 | REAL_TYPE static const _ER =
1395 | + 18. * std::pow(mp::_epsilon, 1) ;
1396 |
1397 | REAL_TYPE _aex, _aey, _aez ,
1398 | _aew, _ali,
1399 | _bex, _bey, _bez ,
1400 | _bew, _bli,
1401 | _cex, _cey, _cez ,
1402 | _cew, _cli,
1403 | _dex, _dey, _dez ,
1404 | _dew, _dli;
1405 | REAL_TYPE _aexbey, _bexaey ,
1406 | _aexcey, _cexaey ,
1407 | _bexcey, _cexbey ,
1408 | _cexdey, _dexcey ,
1409 | _dexaey, _aexdey ,
1410 | _bexdey, _dexbey ;
1411 | REAL_TYPE _ab_, _bc_, _cd_, _da_,
1412 | _ac_, _bd_;
1413 | REAL_TYPE _abc, _bcd, _cda, _dab;
1414 |
1415 | REAL_TYPE _AEZ, _BEZ, _CEZ, _DEZ;
1416 | REAL_TYPE _ALI, _BLI, _CLI, _DLI;
1417 | REAL_TYPE _AEXBEY, _BEXAEY ,
1418 | _CEXAEY, _AEXCEY ,
1419 | _BEXCEY, _CEXBEY ,
1420 | _CEXDEY, _DEXCEY ,
1421 | _DEXAEY, _AEXDEY ,
1422 | _BEXDEY, _DEXBEY ;
1423 | REAL_TYPE _AB_, _BC_, _CD_, _DA_,
1424 | _AC_, _BD_;
1425 | REAL_TYPE _ABC, _BCD, _CDA, _DAB;
1426 |
1427 | REAL_TYPE _d44, _FT ;
1428 |
1429 | _aex = _pa [0] - _pe [0] ; // coord. diff.
1430 | _aey = _pa [1] - _pe [1] ;
1431 | _aez = _pa [2] - _pe [2] ;
1432 | _aew = _pa [3] - _pe [3] ;
1433 |
1434 | _AEZ = std::abs (_aez) ;
1435 |
1436 | _bex = _pb [0] - _pe [0] ;
1437 | _bey = _pb [1] - _pe [1] ;
1438 | _bez = _pb [2] - _pe [2] ;
1439 | _bew = _pb [3] - _pe [3] ;
1440 |
1441 | _BEZ = std::abs (_bez) ;
1442 |
1443 | _cex = _pc [0] - _pe [0] ;
1444 | _cey = _pc [1] - _pe [1] ;
1445 | _cez = _pc [2] - _pe [2] ;
1446 | _cew = _pc [3] - _pe [3] ;
1447 |
1448 | _CEZ = std::abs (_cez) ;
1449 |
1450 | _dex = _pd [0] - _pe [0] ;
1451 | _dey = _pd [1] - _pe [1] ;
1452 | _dez = _pd [2] - _pe [2] ;
1453 | _dew = _pd [3] - _pe [3] ;
1454 |
1455 | _DEZ = std::abs (_dez) ;
1456 |
1457 | _ali = _aex * _aex + _aey * _aey // lifted terms
1458 | + _aez * _aez - _aew ;
1459 |
1460 | _ALI = std::abs (_ali) ;
1461 |
1462 | _bli = _bex * _bex + _bey * _bey
1463 | + _bez * _bez - _bew ;
1464 |
1465 | _BLI = std::abs (_bli) ;
1466 |
1467 | _cli = _cex * _cex + _cey * _cey
1468 | + _cez * _cez - _cew ;
1469 |
1470 | _CLI = std::abs (_cli) ;
1471 |
1472 | _dli = _dex * _dex + _dey * _dey
1473 | + _dez * _dez - _dew ;
1474 |
1475 | _DLI = std::abs (_dli) ;
1476 |
1477 | _aexbey = _aex * _bey ; // 2 x 2 minors
1478 | _bexaey = _bex * _aey ;
1479 | _ab_ = _aexbey - _bexaey ;
1480 |
1481 | _AEXBEY = std::abs (_aexbey) ;
1482 | _BEXAEY = std::abs (_bexaey) ;
1483 | _AB_ = _AEXBEY + _BEXAEY ;
1484 |
1485 | _bexcey = _bex * _cey;
1486 | _cexbey = _cex * _bey;
1487 | _bc_ = _bexcey - _cexbey ;
1488 |
1489 | _BEXCEY = std::abs (_bexcey) ;
1490 | _CEXBEY = std::abs (_cexbey) ;
1491 | _BC_ = _BEXCEY + _CEXBEY ;
1492 |
1493 | _cexdey = _cex * _dey;
1494 | _dexcey = _dex * _cey;
1495 | _cd_ = _cexdey - _dexcey ;
1496 |
1497 | _CEXDEY = std::abs (_cexdey) ;
1498 | _DEXCEY = std::abs (_dexcey) ;
1499 | _CD_ = _CEXDEY + _DEXCEY ;
1500 |
1501 | _dexaey = _dex * _aey;
1502 | _aexdey = _aex * _dey;
1503 | _da_ = _dexaey - _aexdey ;
1504 |
1505 | _DEXAEY = std::abs (_dexaey) ;
1506 | _AEXDEY = std::abs (_aexdey) ;
1507 | _DA_ = _DEXAEY + _AEXDEY ;
1508 |
1509 | _aexcey = _aex * _cey;
1510 | _cexaey = _cex * _aey;
1511 | _ac_ = _aexcey - _cexaey ;
1512 |
1513 | _AEXCEY = std::abs (_aexcey) ;
1514 | _CEXAEY = std::abs (_cexaey) ;
1515 | _AC_ = _AEXCEY + _CEXAEY ;
1516 |
1517 | _bexdey = _bex * _dey;
1518 | _dexbey = _dex * _bey;
1519 | _bd_ = _bexdey - _dexbey ;
1520 |
1521 | _BEXDEY = std::abs (_bexdey) ;
1522 | _DEXBEY = std::abs (_dexbey) ;
1523 | _BD_ = _BEXDEY + _DEXBEY ;
1524 |
1525 | _abc = // 3 x 3 minors
1526 | _aez * _bc_ - _bez * _ac_
1527 | + _cez * _ab_ ;
1528 | _ABC =
1529 | _AEZ * _BC_ + _BEZ * _AC_
1530 | + _CEZ * _AB_ ;
1531 |
1532 | _bcd =
1533 | _bez * _cd_ - _cez * _bd_
1534 | + _dez * _bc_ ;
1535 | _BCD =
1536 | _BEZ * _CD_ + _CEZ * _BD_
1537 | + _DEZ * _BC_ ;
1538 |
1539 | _cda =
1540 | _cez * _da_ + _dez * _ac_
1541 | + _aez * _cd_ ;
1542 | _CDA =
1543 | _CEZ * _DA_ + _DEZ * _AC_
1544 | + _AEZ * _CD_ ;
1545 |
1546 | _dab =
1547 | _dez * _ab_ + _aez * _bd_
1548 | + _bez * _da_ ;
1549 | _DAB =
1550 | _DEZ * _AB_ + _AEZ * _BD_
1551 | + _BEZ * _DA_ ;
1552 |
1553 | _FT = // roundoff tol
1554 | _DLI * _ABC + _CLI * _DAB
1555 | + _BLI * _CDA + _ALI * _BCD ;
1556 |
1557 | _FT *= _ER ;
1558 |
1559 | _d44 = // 4 x 4 result
1560 | _dli * _abc - _cli * _dab
1561 | + _bli * _cda - _ali * _bcd ;
1562 |
1563 | _OK =
1564 | _d44 > _FT || _d44 < -_FT ;
1565 |
1566 | return ( _d44 ) ;
1567 | }
1568 |
1569 |
1570 |
1571 |
--------------------------------------------------------------------------------
/predicate/orient_k.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | --------------------------------------------------------
4 | * PREDICATE-k: robust geometric predicates in E^k.
5 | --------------------------------------------------------
6 | *
7 | * This program may be freely redistributed under the
8 | * condition that the copyright notices (including this
9 | * entire header) are not removed, and no compensation
10 | * is received through use of the software. Private,
11 | * research, and institutional use is free. You may
12 | * distribute modified versions of this code UNDER THE
13 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
14 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
15 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
16 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
17 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
18 | * of this code as part of a commercial system is
19 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
20 | * AUTHOR. (If you are not directly supplying this
21 | * code to a customer, and you are instead telling them
22 | * how they can obtain it for free, then you are not
23 | * required to make any arrangement with me.)
24 | *
25 | * Disclaimer: Neither I nor: Columbia University, The
26 | * Massachusetts Institute of Technology, The
27 | * University of Sydney, nor The National Aeronautics
28 | * and Space Administration warrant this code in any
29 | * way whatsoever. This code is provided "as-is" to be
30 | * used at your own risk.
31 | *
32 | --------------------------------------------------------
33 | *
34 | * Last updated: 14 April, 2020
35 | *
36 | * Copyright 2020--
37 | * Darren Engwirda
38 | * de2363@columbia.edu
39 | * https://github.com/dengwirda/
40 | *
41 | --------------------------------------------------------
42 | */
43 |
44 | // from predicate_k.hpp...
45 |
46 |
47 | /*
48 | --------------------------------------------------------
49 | *
50 | * Compute an exact determinant using multi-precision
51 | * expansions, a'la shewchuk
52 | *
53 | * | ax ay +1. |
54 | * | bx by +1. |
55 | * | cx cy +1. |
56 | *
57 | * This is the planar "orientation" predicate in E^2.
58 | *
59 | --------------------------------------------------------
60 | */
61 |
62 | __normal_call REAL_TYPE orient2d_e (
63 | __const_ptr(REAL_TYPE) _pa ,
64 | __const_ptr(REAL_TYPE) _pb ,
65 | __const_ptr(REAL_TYPE) _pc ,
66 | bool_type &_OK
67 | )
68 | {
69 | /*--------------- orient2d predicate, "exact" version */
70 | mp::expansion< 4 > _d2_ab_, _d2_ac_,
71 | _d2_bc_;
72 | mp::expansion< 12> _d3full;
73 |
74 | _OK = true;
75 |
76 | /*-------------------------------------- 2 x 2 minors */
77 | compute_det_2x2(_pa[ 0], _pa[ 1],
78 | _pb[ 0], _pb[ 1],
79 | _d2_ab_ ) ;
80 |
81 | compute_det_2x2(_pa[ 0], _pa[ 1],
82 | _pc[ 0], _pc[ 1],
83 | _d2_ac_ ) ;
84 |
85 | compute_det_2x2(_pb[ 0], _pb[ 1],
86 | _pc[ 0], _pc[ 1],
87 | _d2_bc_ ) ;
88 |
89 | /*-------------------------------------- 3 x 3 result */
90 | unitary_det_3x3(_d2_bc_, _d2_ac_,
91 | _d2_ab_,
92 | _d3full, +3) ;
93 |
94 | /*-------------------------------------- leading det. */
95 | return mp::expansion_est(_d3full) ;
96 | }
97 |
98 | __normal_call REAL_TYPE orient2d_i (
99 | __const_ptr(REAL_TYPE) _pa ,
100 | __const_ptr(REAL_TYPE) _pb ,
101 | __const_ptr(REAL_TYPE) _pc ,
102 | bool_type &_OK
103 | )
104 | {
105 | /*--------------- orient2d predicate, "bound" version */
106 | ia_flt _acx, _acy ;
107 | ia_flt _bcx, _bcy ;
108 | ia_flt _acxbcy, _acybcx ;
109 |
110 | ia_flt _sgn;
111 |
112 | ia_rnd _rnd; // up rounding!
113 |
114 | _acx.from_sub(_pa[0], _pc[0]) ; // coord. diff.
115 | _acy.from_sub(_pa[1], _pc[1]) ;
116 |
117 | _bcx.from_sub(_pb[0], _pc[0]) ;
118 | _bcy.from_sub(_pb[1], _pc[1]) ;
119 |
120 | _acxbcy = _acx * _bcy ;
121 | _acybcx = _acy * _bcx ;
122 |
123 | _sgn = _acxbcy - _acybcx ; // 2 x 2 result
124 |
125 | _OK =
126 | _sgn.lo() >= (REAL_TYPE)0.
127 | || _sgn.up() <= (REAL_TYPE)0. ;
128 |
129 | return ( _sgn.mid() ) ;
130 | }
131 |
132 | __normal_call REAL_TYPE orient2d_f (
133 | __const_ptr(REAL_TYPE) _pa ,
134 | __const_ptr(REAL_TYPE) _pb ,
135 | __const_ptr(REAL_TYPE) _pc ,
136 | bool_type &_OK
137 | )
138 | {
139 | /*--------------- orient2d predicate, "float" version */
140 | REAL_TYPE static const _ER =
141 | + 4. * std::pow(mp::_epsilon, 1) ;
142 |
143 | REAL_TYPE _acx, _acy ;
144 | REAL_TYPE _bcx, _bcy ;
145 | REAL_TYPE _acxbcy, _acybcx ;
146 |
147 | REAL_TYPE _ACXBCY, _ACYBCX ;
148 |
149 | REAL_TYPE _sgn, _FT;
150 |
151 | _acx = _pa [0] - _pc [0] ; // coord. diff.
152 | _acy = _pa [1] - _pc [1] ;
153 |
154 | _bcx = _pb [0] - _pc [0] ;
155 | _bcy = _pb [1] - _pc [1] ;
156 |
157 | _acxbcy = _acx * _bcy ;
158 | _acybcx = _acy * _bcx ;
159 |
160 | _ACXBCY = std::abs(_acxbcy);
161 | _ACYBCX = std::abs(_acybcx);
162 |
163 | _FT = _ACXBCY + _ACYBCX ; // roundoff tol
164 | _FT *= _ER ;
165 |
166 | _sgn = _acxbcy - _acybcx ; // 2 x 2 result
167 |
168 | _OK =
169 | _sgn > +_FT || _sgn < -_FT ;
170 |
171 | return ( _sgn ) ;
172 | }
173 |
174 | /*
175 | --------------------------------------------------------
176 | *
177 | * Compute an exact determinant using multi-precision
178 | * expansions, a'la shewchuk
179 | *
180 | * | ax ay az +1. |
181 | * | bx by bz +1. |
182 | * | cx cy cz +1. |
183 | * | dx dy dz +1. |
184 | *
185 | * This is the planar "orientation" predicate in E^3.
186 | *
187 | --------------------------------------------------------
188 | */
189 |
190 | __normal_call REAL_TYPE orient3d_e (
191 | __const_ptr(REAL_TYPE) _pa ,
192 | __const_ptr(REAL_TYPE) _pb ,
193 | __const_ptr(REAL_TYPE) _pc ,
194 | __const_ptr(REAL_TYPE) _pd ,
195 | bool_type &_OK
196 | )
197 | {
198 | /*--------------- orient3d predicate, "exact" version */
199 | mp::expansion< 4 > _d2_ab_, _d2_ac_,
200 | _d2_ad_,
201 | _d2_bc_, _d2_bd_,
202 | _d2_cd_;
203 | mp::expansion< 12> _d3_abc, _d3_abd,
204 | _d3_acd, _d3_bcd;
205 | mp::expansion< 96> _d4full;
206 |
207 | _OK = true;
208 |
209 | mp::expansion< 1 > _pa_zz_(_pa[ 2]);
210 | mp::expansion< 1 > _pb_zz_(_pb[ 2]);
211 | mp::expansion< 1 > _pc_zz_(_pc[ 2]);
212 | mp::expansion< 1 > _pd_zz_(_pd[ 2]);
213 |
214 | /*-------------------------------------- 2 x 2 minors */
215 | compute_det_2x2(_pa[ 0], _pa[ 1],
216 | _pb[ 0], _pb[ 1],
217 | _d2_ab_ ) ;
218 |
219 | compute_det_2x2(_pa[ 0], _pa[ 1],
220 | _pc[ 0], _pc[ 1],
221 | _d2_ac_ ) ;
222 |
223 | compute_det_2x2(_pa[ 0], _pa[ 1],
224 | _pd[ 0], _pd[ 1],
225 | _d2_ad_ ) ;
226 |
227 | compute_det_2x2(_pb[ 0], _pb[ 1],
228 | _pc[ 0], _pc[ 1],
229 | _d2_bc_ ) ;
230 |
231 | compute_det_2x2(_pb[ 0], _pb[ 1],
232 | _pd[ 0], _pd[ 1],
233 | _d2_bd_ ) ;
234 |
235 | compute_det_2x2(_pc[ 0], _pc[ 1],
236 | _pd[ 0], _pd[ 1],
237 | _d2_cd_ ) ;
238 |
239 | /*-------------------------------------- 3 x 3 minors */
240 | unitary_det_3x3(_d2_cd_, _d2_bd_,
241 | _d2_bc_,
242 | _d3_bcd, +3) ;
243 |
244 | unitary_det_3x3(_d2_cd_, _d2_ad_,
245 | _d2_ac_,
246 | _d3_acd, +3) ;
247 |
248 | unitary_det_3x3(_d2_bd_, _d2_ad_,
249 | _d2_ab_,
250 | _d3_abd, +3) ;
251 |
252 | unitary_det_3x3(_d2_bc_, _d2_ac_,
253 | _d2_ab_,
254 | _d3_abc, +3) ;
255 |
256 | /*-------------------------------------- 4 x 4 result */
257 | compute_det_4x4(_d3_bcd, _pa_zz_,
258 | _d3_acd, _pb_zz_,
259 | _d3_abd, _pc_zz_,
260 | _d3_abc, _pd_zz_,
261 | _d4full, +3) ;
262 |
263 | /*-------------------------------------- leading det. */
264 | return mp::expansion_est(_d4full) ;
265 | }
266 |
267 | __normal_call REAL_TYPE orient3d_i (
268 | __const_ptr(REAL_TYPE) _pa ,
269 | __const_ptr(REAL_TYPE) _pb ,
270 | __const_ptr(REAL_TYPE) _pc ,
271 | __const_ptr(REAL_TYPE) _pd ,
272 | bool_type &_OK
273 | )
274 | {
275 | /*--------------- orient3d predicate, "bound" version */
276 | ia_flt _adx, _ady, _adz ,
277 | _bdx, _bdy, _bdz ,
278 | _cdx, _cdy, _cdz ;
279 | ia_flt _bdxcdy, _cdxbdy ,
280 | _cdxady, _adxcdy ,
281 | _adxbdy, _bdxady ;
282 |
283 | ia_flt _sgn;
284 |
285 | ia_rnd _rnd; // up rounding!
286 |
287 | _adx.from_sub(_pa[0], _pd[0]) ; // coord. diff.
288 | _ady.from_sub(_pa[1], _pd[1]) ;
289 | _adz.from_sub(_pa[2], _pd[2]) ;
290 |
291 | _bdx.from_sub(_pb[0], _pd[0]) ;
292 | _bdy.from_sub(_pb[1], _pd[1]) ;
293 | _bdz.from_sub(_pb[2], _pd[2]) ;
294 |
295 | _cdx.from_sub(_pc[0], _pd[0]) ;
296 | _cdy.from_sub(_pc[1], _pd[1]) ;
297 | _cdz.from_sub(_pc[2], _pd[2]) ;
298 |
299 | _bdxcdy = _bdx * _cdy ; // 2 x 2 minors
300 | _cdxbdy = _cdx * _bdy ;
301 | _cdxady = _cdx * _ady ;
302 | _adxcdy = _adx * _cdy ;
303 | _adxbdy = _adx * _bdy ;
304 | _bdxady = _bdx * _ady ;
305 |
306 | _sgn = // 3 x 3 result
307 | _adz * (_bdxcdy - _cdxbdy)
308 | + _bdz * (_cdxady - _adxcdy)
309 | + _cdz * (_adxbdy - _bdxady);
310 |
311 | _OK =
312 | _sgn.lo() >= (REAL_TYPE)0.
313 | ||_sgn.up() <= (REAL_TYPE)0.;
314 |
315 | return ( _sgn.mid() ) ;
316 | }
317 |
318 | __normal_call REAL_TYPE orient3d_f (
319 | __const_ptr(REAL_TYPE) _pa ,
320 | __const_ptr(REAL_TYPE) _pb ,
321 | __const_ptr(REAL_TYPE) _pc ,
322 | __const_ptr(REAL_TYPE) _pd ,
323 | bool_type &_OK
324 | )
325 | {
326 | /*--------------- orient3d predicate, "float" version */
327 | REAL_TYPE static const _ER =
328 | + 8. * std::pow(mp::_epsilon, 1) ;
329 |
330 | REAL_TYPE _adx, _ady, _adz ,
331 | _bdx, _bdy, _bdz ,
332 | _cdx, _cdy, _cdz ;
333 | REAL_TYPE _bdxcdy, _cdxbdy ,
334 | _cdxady, _adxcdy ,
335 | _adxbdy, _bdxady ;
336 |
337 | REAL_TYPE _ADZ, _BDZ, _CDZ ;
338 | REAL_TYPE _BDXCDY, _CDXBDY ,
339 | _CDXADY, _ADXCDY ,
340 | _ADXBDY, _BDXADY ;
341 |
342 | REAL_TYPE _sgn, _FT;
343 |
344 | _adx = _pa [0] - _pd [0] ; // coord. diff.
345 | _ady = _pa [1] - _pd [1] ;
346 | _adz = _pa [2] - _pd [2] ;
347 |
348 | _ADZ = std::abs (_adz) ;
349 |
350 | _bdx = _pb [0] - _pd [0] ;
351 | _bdy = _pb [1] - _pd [1] ;
352 | _bdz = _pb [2] - _pd [2] ;
353 |
354 | _BDZ = std::abs (_bdz) ;
355 |
356 | _cdx = _pc [0] - _pd [0] ;
357 | _cdy = _pc [1] - _pd [1] ;
358 | _cdz = _pc [2] - _pd [2] ;
359 |
360 | _CDZ = std::abs (_cdz) ;
361 |
362 | _bdxcdy = _bdx * _cdy ; // 2 x 2 minors
363 | _cdxbdy = _cdx * _bdy ;
364 | _cdxady = _cdx * _ady ;
365 | _adxcdy = _adx * _cdy ;
366 | _adxbdy = _adx * _bdy ;
367 | _bdxady = _bdx * _ady ;
368 |
369 | _BDXCDY = std::abs (_bdxcdy) ;
370 | _CDXBDY = std::abs (_cdxbdy) ;
371 | _CDXADY = std::abs (_cdxady) ;
372 | _ADXCDY = std::abs (_adxcdy) ;
373 | _ADXBDY = std::abs (_adxbdy) ;
374 | _BDXADY = std::abs (_bdxady) ;
375 |
376 | _FT = // roundoff tol
377 | _ADZ * (_BDXCDY + _CDXBDY)
378 | + _BDZ * (_CDXADY + _ADXCDY)
379 | + _CDZ * (_ADXBDY + _BDXADY) ;
380 |
381 | _FT *= _ER ;
382 |
383 | _sgn = // 3 x 3 result
384 | _adz * (_bdxcdy - _cdxbdy)
385 | + _bdz * (_cdxady - _adxcdy)
386 | + _cdz * (_adxbdy - _bdxady) ;
387 |
388 | _OK =
389 | _sgn > +_FT || _sgn < -_FT ;
390 |
391 | return ( _sgn ) ;
392 | }
393 |
394 |
395 |
396 |
--------------------------------------------------------------------------------
/predicate/predicate_k.hpp:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | --------------------------------------------------------
4 | * PREDICATE-k: robust geometric predicates in E^k.
5 | --------------------------------------------------------
6 | *
7 | * Compute "robust" geometric predicates using filtered
8 | * floating-point + multi-precision expansions.
9 | *
10 | * The sign-correctness of each predicate is guaranteed
11 | * --- using exact arithmetic where necessary to
12 | * eliminate floating-point round-off. See Shewchuk for
13 | * additional detail
14 | *
15 | * J. R. Shewchuk (1997), Adaptive Precision Floating-
16 | * Point Arithmetic & Fast Robust Geometric Predicates
17 | * Discrete & Computational Geometry, 18, pp. 305-363.
18 | *
19 | * A translational version of BFS semi-static filtering
20 | * is employed, adapted from, e.g.
21 | *
22 | * C. Burnikel, S. Funke, and M. Seel (2001), Exact
23 | * geometric computation using cascading.
24 | * IJCGA (Special issue) 11 (3), pp. 245–266.
25 | *
26 | * O. Devillers and S. Pion (2002), Efficient Exact
27 | * Geometric Predicates for Delaunay Triangulations.
28 | * RR-4351, INRIA. inria-00072237
29 | *
30 | --------------------------------------------------------
31 | *
32 | * This program may be freely redistributed under the
33 | * condition that the copyright notices (including this
34 | * entire header) are not removed, and no compensation
35 | * is received through use of the software. Private,
36 | * research, and institutional use is free. You may
37 | * distribute modified versions of this code UNDER THE
38 | * CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE
39 | * TO IT IN THE SAME FILE REMAIN UNDER COPYRIGHT OF THE
40 | * ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE
41 | * MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR
42 | * NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution
43 | * of this code as part of a commercial system is
44 | * permissible ONLY BY DIRECT ARRANGEMENT WITH THE
45 | * AUTHOR. (If you are not directly supplying this
46 | * code to a customer, and you are instead telling them
47 | * how they can obtain it for free, then you are not
48 | * required to make any arrangement with me.)
49 | *
50 | * Disclaimer: Neither I nor: Columbia University, The
51 | * Massachusetts Institute of Technology, The
52 | * University of Sydney, nor The National Aeronautics
53 | * and Space Administration warrant this code in any
54 | * way whatsoever. This code is provided "as-is" to be
55 | * used at your own risk.
56 | *
57 | --------------------------------------------------------
58 | *
59 | * Last updated: 15 April, 2020
60 | *
61 | * Copyright 2020--
62 | * Darren Engwirda
63 | * de2363@columbia.edu
64 | * https://github.com/dengwirda/
65 | *
66 | --------------------------------------------------------
67 | */
68 |
69 | # pragma once
70 |
71 | # ifndef __PREDICATE_K__
72 | # define __PREDICATE_K__
73 |
74 | # define USE_KERNEL_FLTPOINT
75 | // define USE_KERNEL_INTERVAL
76 |
77 | namespace geompred {
78 |
79 | # define REAL_TYPE mp_float::real_type
80 | # define INDX_TYPE mp_float::indx_type
81 |
82 | namespace mp=mp_float;
83 |
84 | enum _kernel {
85 | ORIENT2D_f, ORIENT2D_i, ORIENT2D_e ,
86 | ORIENT3D_f, ORIENT3D_i, ORIENT3D_e ,
87 | BISECT2D_f, BISECT2D_i, BISECT2D_e ,
88 | BISECT2W_f, BISECT2W_i, BISECT2W_e ,
89 | BISECT3D_f, BISECT3D_i, BISECT3D_e ,
90 | BISECT3W_f, BISECT3W_i, BISECT3W_e ,
91 | INBALL2D_f, INBALL2D_i, INBALL2D_e ,
92 | INBALL2W_f, INBALL2W_i, INBALL2W_e ,
93 | INBALL3D_f, INBALL3D_i, INBALL3D_e ,
94 | INBALL3W_f, INBALL3W_i, INBALL3W_e ,
95 | LASTKERNEL } ;
96 |
97 | size_t _nn_calls[LASTKERNEL] = {0} ;
98 |
99 | # include "orient_k.hpp"
100 | # include "bisect_k.hpp"
101 | // include "linear_k.hpp"
102 | # include "inball_k.hpp"
103 |
104 | __inline_call REAL_TYPE orient2d (
105 | __const_ptr(REAL_TYPE) _pa ,
106 | __const_ptr(REAL_TYPE) _pb ,
107 | __const_ptr(REAL_TYPE) _pc
108 | )
109 | {
110 | /*------------ orient2d predicate, "filtered" version */
111 | REAL_TYPE _rr;
112 | bool_type _OK;
113 |
114 | # ifdef USE_KERNEL_FLTPOINT
115 | _nn_calls[ORIENT2D_f] += +1;
116 |
117 | _rr = orient2d_f( // "float" kernel
118 | _pa, _pb, _pc, _OK
119 | ) ;
120 |
121 | if (_OK && std::isnormal(_rr))
122 | return _rr ;
123 | # endif
124 |
125 | # ifdef USE_KERNEL_INTERVAL
126 | _nn_calls[ORIENT2D_i] += +1;
127 |
128 | _rr = orient2d_i( // "bound" kernel
129 | _pa, _pb, _pc, _OK
130 | ) ;
131 |
132 | if (_OK) return _rr ;
133 | # endif
134 |
135 | _nn_calls[ORIENT2D_e] += +1;
136 |
137 | _rr = orient2d_e( // "exact" kernel
138 | _pa, _pb, _pc, _OK
139 | ) ;
140 |
141 | if (_OK) return _rr ;
142 |
143 | return (REAL_TYPE) +0.0E+00;
144 | }
145 |
146 | __inline_call REAL_TYPE orient3d (
147 | __const_ptr(REAL_TYPE) _pa ,
148 | __const_ptr(REAL_TYPE) _pb ,
149 | __const_ptr(REAL_TYPE) _pc ,
150 | __const_ptr(REAL_TYPE) _pd
151 | )
152 | {
153 | /*------------ orient3d predicate, "filtered" version */
154 | REAL_TYPE _rr;
155 | bool_type _OK;
156 |
157 | # ifdef USE_KERNEL_FLTPOINT
158 | _nn_calls[ORIENT3D_f] += +1;
159 |
160 | _rr = orient3d_f( // "float" kernel
161 | _pa, _pb, _pc, _pd, _OK
162 | ) ;
163 |
164 | if (_OK && std::isnormal(_rr))
165 | return _rr ;
166 | # endif
167 |
168 | # ifdef USE_KERNEL_INTERVAL
169 | _nn_calls[ORIENT3D_i] += +1;
170 |
171 | _rr = orient3d_i( // "bound" kernel
172 | _pa, _pb, _pc, _pd, _OK
173 | ) ;
174 |
175 | if (_OK) return _rr ;
176 | # endif
177 |
178 | _nn_calls[ORIENT3D_e] += +1;
179 |
180 | _rr = orient3d_e( // "exact" kernel
181 | _pa, _pb, _pc, _pd, _OK
182 | ) ;
183 |
184 | if (_OK) return _rr ;
185 |
186 | return (REAL_TYPE) +0.0E+00;
187 | }
188 |
189 | __inline_call REAL_TYPE bisect2d (
190 | __const_ptr(REAL_TYPE) _pa ,
191 | __const_ptr(REAL_TYPE) _pb ,
192 | __const_ptr(REAL_TYPE) _pc
193 | )
194 | {
195 | /*------------ bisect2d predicate, "filtered" version */
196 | REAL_TYPE _rr;
197 | bool_type _OK;
198 |
199 | # ifdef USE_KERNEL_FLTPOINT
200 | _nn_calls[BISECT2D_f] += +1;
201 |
202 | _rr = bisect2d_f( // "float" kernel
203 | _pa, _pb, _pc, _OK
204 | ) ;
205 |
206 | if (_OK && std::isnormal(_rr))
207 | return _rr ;
208 | # endif
209 |
210 | # ifdef USE_KERNEL_INTERVAL
211 | _nn_calls[BISECT2D_i] += +1;
212 |
213 | _rr = bisect2d_i( // "bound" kernel
214 | _pa, _pb, _pc, _OK
215 | ) ;
216 |
217 | if (_OK) return _rr ;
218 | # endif
219 |
220 | _nn_calls[BISECT2D_e] += +1;
221 |
222 | _rr = bisect2d_e( // "exact" kernel
223 | _pa, _pb, _pc, _OK
224 | ) ;
225 |
226 | if (_OK) return _rr ;
227 |
228 | return (REAL_TYPE) +0.0E+00;
229 | }
230 |
231 | __inline_call REAL_TYPE bisect2w (
232 | __const_ptr(REAL_TYPE) _pa ,
233 | __const_ptr(REAL_TYPE) _pb ,
234 | __const_ptr(REAL_TYPE) _pc
235 | )
236 | {
237 | /*------------ bisect2w predicate, "filtered" version */
238 | if (_pa [ 2] == _pb [ 2] )
239 | { // equal weights, do bisect2d
240 | return bisect2d(_pa, _pb, _pc) ;
241 | }
242 | else
243 | {
244 | REAL_TYPE _rr; // given weights, full kernel
245 | bool_type _OK;
246 |
247 | # ifdef USE_KERNEL_FLTPOINT
248 | _nn_calls[BISECT2W_f] += +1;
249 |
250 | _rr = bisect2w_f( // "float" kernel
251 | _pa, _pb, _pc, _OK
252 | ) ;
253 |
254 | if (_OK && std::isnormal(_rr))
255 | return _rr ;
256 | # endif
257 |
258 | # ifdef USE_KERNEL_INTERVAL
259 | _nn_calls[BISECT2W_i] += +1;
260 |
261 | _rr = bisect2w_i( // "bound" kernel
262 | _pa, _pb, _pc, _OK
263 | ) ;
264 |
265 | if (_OK) return _rr ;
266 | # endif
267 |
268 | _nn_calls[BISECT2W_e] += +1;
269 |
270 | _rr = bisect2w_e( // "exact" kernel
271 | _pa, _pb, _pc, _OK
272 | ) ;
273 |
274 | if (_OK) return _rr ;
275 |
276 | return (REAL_TYPE) +0.0E+00;
277 | }
278 | }
279 |
280 | __inline_call REAL_TYPE bisect3d (
281 | __const_ptr(REAL_TYPE) _pa ,
282 | __const_ptr(REAL_TYPE) _pb ,
283 | __const_ptr(REAL_TYPE) _pc
284 | )
285 | {
286 | /*------------ bisect3d predicate, "filtered" version */
287 | REAL_TYPE _rr;
288 | bool_type _OK;
289 |
290 | # ifdef USE_KERNEL_FLTPOINT
291 | _nn_calls[BISECT3D_f] += +1;
292 |
293 | _rr = bisect3d_f( // "float" kernel
294 | _pa, _pb, _pc, _OK
295 | ) ;
296 |
297 | if (_OK && std::isnormal(_rr))
298 | return _rr ;
299 | # endif
300 |
301 | # ifdef USE_KERNEL_INTERVAL
302 | _nn_calls[BISECT3D_i] += +1;
303 |
304 | _rr = bisect3d_i( // "bound" kernel
305 | _pa, _pb, _pc, _OK
306 | ) ;
307 |
308 | if (_OK) return _rr ;
309 | # endif
310 |
311 | _nn_calls[BISECT3D_e] += +1;
312 |
313 | _rr = bisect3d_e( // "exact" kernel
314 | _pa, _pb, _pc, _OK
315 | ) ;
316 |
317 | if (_OK) return _rr ;
318 |
319 | return (REAL_TYPE) +0.0E+00;
320 | }
321 |
322 | __inline_call REAL_TYPE bisect3w (
323 | __const_ptr(REAL_TYPE) _pa ,
324 | __const_ptr(REAL_TYPE) _pb ,
325 | __const_ptr(REAL_TYPE) _pc
326 | )
327 | {
328 | /*------------ bisect3w predicate, "filtered" version */
329 | if (_pa [ 3] == _pb [ 3] )
330 | { // equal weights, do bisect3d
331 | return bisect3d(_pa, _pb, _pc) ;
332 | }
333 | else
334 | {
335 | REAL_TYPE _rr; // given weights, full kernel
336 | bool_type _OK;
337 |
338 | # ifdef USE_KERNEL_FLTPOINT
339 | _nn_calls[BISECT3W_f] += +1;
340 |
341 | _rr = bisect3w_f( // "float" kernel
342 | _pa, _pb, _pc, _OK
343 | ) ;
344 |
345 | if (_OK && std::isnormal(_rr))
346 | return _rr ;
347 | # endif
348 |
349 | # ifdef USE_KERNEL_INTERVAL
350 | _nn_calls[BISECT3W_i] += +1;
351 |
352 | _rr = bisect3w_i( // "bound" kernel
353 | _pa, _pb, _pc, _OK
354 | ) ;
355 |
356 | if (_OK) return _rr ;
357 | # endif
358 |
359 | _nn_calls[BISECT3W_e] += +1;
360 |
361 | _rr = bisect3w_e( // "exact" kernel
362 | _pa, _pb, _pc, _OK
363 | ) ;
364 |
365 | if (_OK) return _rr ;
366 |
367 | return (REAL_TYPE) +0.0E+00;
368 | }
369 | }
370 |
371 | __inline_call REAL_TYPE inball2d (
372 | __const_ptr(REAL_TYPE) _pa ,
373 | __const_ptr(REAL_TYPE) _pb ,
374 | __const_ptr(REAL_TYPE) _pc ,
375 | __const_ptr(REAL_TYPE) _pd
376 | )
377 | {
378 | /*------------ inball2d predicate, "filtered" version */
379 | REAL_TYPE _rr;
380 | bool_type _OK;
381 |
382 | # ifdef USE_KERNEL_FLTPOINT
383 | _nn_calls[INBALL2D_f] += +1;
384 |
385 | _rr = inball2d_f( // "float" kernel
386 | _pa, _pb, _pc, _pd, _OK
387 | ) ;
388 |
389 | if (_OK && std::isnormal(_rr))
390 | return _rr ;
391 | # endif
392 |
393 | # ifdef USE_KERNEL_INTERVAL
394 | _nn_calls[INBALL2D_i] += +1;
395 |
396 | _rr = inball2d_i( // "bound" kernel
397 | _pa, _pb, _pc, _pd, _OK
398 | ) ;
399 |
400 | if (_OK) return _rr ;
401 | # endif
402 |
403 | _nn_calls[INBALL2D_e] += +1;
404 |
405 | _rr = inball2d_e( // "exact" kernel
406 | _pa, _pb, _pc, _pd, _OK
407 | ) ;
408 |
409 | if (_OK) return _rr ;
410 |
411 | return (REAL_TYPE) +0.0E+00;
412 | }
413 |
414 | __inline_call REAL_TYPE inball2w (
415 | __const_ptr(REAL_TYPE) _pa ,
416 | __const_ptr(REAL_TYPE) _pb ,
417 | __const_ptr(REAL_TYPE) _pc ,
418 | __const_ptr(REAL_TYPE) _pd
419 | )
420 | {
421 | /*------------ inball2w predicate, "filtered" version */
422 | if (_pa [ 2] == _pb [ 2] &&
423 | _pb [ 2] == _pc [ 2] &&
424 | _pc [ 2] == _pd [ 2] )
425 | {
426 | return inball2d ( // equal weights, do inball2d
427 | _pa, _pb, _pc, _pd
428 | ) ;
429 | }
430 | else
431 | {
432 | REAL_TYPE _rr; // given weights, full kernel
433 | bool_type _OK;
434 |
435 | # ifdef USE_KERNEL_FLTPOINT
436 | _nn_calls[INBALL2W_f] += +1;
437 |
438 | _rr = inball2w_f( // "float" kernel
439 | _pa, _pb, _pc, _pd, _OK
440 | ) ;
441 |
442 | if (_OK && std::isnormal(_rr))
443 | return _rr ;
444 | # endif
445 |
446 | # ifdef USE_KERNEL_INTERVAL
447 | _nn_calls[INBALL2W_i] += +1;
448 |
449 | _rr = inball2w_i( // "bound" kernel
450 | _pa, _pb, _pc, _pd, _OK
451 | ) ;
452 |
453 | if (_OK) return _rr ;
454 | # endif
455 |
456 | _nn_calls[INBALL2W_e] += +1;
457 |
458 | _rr = inball2w_e( // "exact" kernel
459 | _pa, _pb, _pc, _pd, _OK
460 | ) ;
461 |
462 | if (_OK) return _rr ;
463 |
464 | return (REAL_TYPE) +0.0E+00;
465 | }
466 | }
467 |
468 | __inline_call REAL_TYPE inball3d (
469 | __const_ptr(REAL_TYPE) _pa ,
470 | __const_ptr(REAL_TYPE) _pb ,
471 | __const_ptr(REAL_TYPE) _pc ,
472 | __const_ptr(REAL_TYPE) _pd ,
473 | __const_ptr(REAL_TYPE) _pe
474 | )
475 | {
476 | /*------------ inball3d predicate, "filtered" version */
477 | REAL_TYPE _rr;
478 | bool_type _OK;
479 |
480 | # ifdef USE_KERNEL_FLTPOINT
481 | _nn_calls[INBALL3D_f] += +1;
482 |
483 | _rr = inball3d_f( // "float" kernel
484 | _pa, _pb, _pc, _pd, _pe, _OK
485 | ) ;
486 |
487 | if (_OK && std::isnormal(_rr))
488 | return _rr ;
489 | # endif
490 |
491 | # ifdef USE_KERNEL_INTERVAL
492 | _nn_calls[INBALL3D_i] += +1;
493 |
494 | _rr = inball3d_i( // "bound" kernel
495 | _pa, _pb, _pc, _pd, _pe, _OK
496 | ) ;
497 |
498 | if (_OK) return _rr ;
499 | # endif
500 |
501 | _nn_calls[INBALL3D_e] += +1;
502 |
503 | _rr = inball3d_e( // "exact" kernel
504 | _pa, _pb, _pc, _pd, _pe, _OK
505 | ) ;
506 |
507 | if (_OK) return _rr ;
508 |
509 | return (REAL_TYPE) +0.0E+00;
510 | }
511 |
512 | __inline_call REAL_TYPE inball3w (
513 | __const_ptr(REAL_TYPE) _pa ,
514 | __const_ptr(REAL_TYPE) _pb ,
515 | __const_ptr(REAL_TYPE) _pc ,
516 | __const_ptr(REAL_TYPE) _pd ,
517 | __const_ptr(REAL_TYPE) _pe
518 | )
519 | {
520 | /*------------ inball3w predicate, "filtered" version */
521 | if (_pa [ 3] == _pb [ 3] &&
522 | _pb [ 3] == _pc [ 3] &&
523 | _pc [ 3] == _pd [ 3] &&
524 | _pd [ 3] == _pe [ 3] )
525 | {
526 | return inball3d ( // equal weights, do inball3d
527 | _pa, _pb, _pc, _pd, _pe
528 | ) ;
529 | }
530 | else
531 | {
532 | REAL_TYPE _rr; // given weights, full kernel
533 | bool_type _OK;
534 |
535 | # ifdef USE_KERNEL_FLTPOINT
536 | _nn_calls[INBALL3W_f] += +1;
537 |
538 | _rr = inball3w_f( // "float" kernal
539 | _pa, _pb, _pc, _pd, _pe, _OK
540 | ) ;
541 |
542 | if (_OK && std::isnormal(_rr))
543 | return _rr ;
544 | # endif
545 |
546 | # ifdef USE_KERNEL_INTERVAL
547 | _nn_calls[INBALL3D_i] += +1;
548 |
549 | _rr = inball3w_i( // "bound" kernel
550 | _pa, _pb, _pc, _pd, _pe, _OK
551 | ) ;
552 |
553 | if (_OK) return _rr ;
554 | # endif
555 |
556 | _nn_calls[INBALL3W_e] += +1;
557 |
558 | _rr = inball3w_e( // "exact" kernel
559 | _pa, _pb, _pc, _pd, _pe, _OK
560 | ) ;
561 |
562 | if (_OK) return _rr ;
563 |
564 | return (REAL_TYPE) +0.0E+00;
565 | }
566 | }
567 |
568 | # undef REAL_TYPE
569 | # undef INDX_TYPE
570 |
571 | # undef USE_KERNEL_FLTPOINT
572 | # undef USE_KERNEL_INTERVAL
573 |
574 | }
575 |
576 | # endif//__PREDICATE_K__
577 |
578 |
579 |
580 |
--------------------------------------------------------------------------------