├── 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 | --------------------------------------------------------------------------------