Geogram Version 1.9.9
A programming library of geometric algorithms
Loading...
Searching...
No Matches
multi_precision.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40#ifndef GEOGRAM_NUMERICS_MULTI_PRECISION
41#define GEOGRAM_NUMERICS_MULTI_PRECISION
42
47#include <iostream>
48#include <sstream>
49#include <new>
50#include <math.h>
51
63namespace GEO {
64
65 extern double expansion_splitter_;
66 extern double expansion_epsilon_;
67
77 inline void two_sum(double a, double b, double& x, double& y) {
78 x = a + b;
79 double bvirt = x - a;
80 double avirt = x - bvirt;
81 double bround = b - bvirt;
82 double around = a - avirt;
83 y = around + bround;
84 }
85
95 inline void two_diff(double a, double b, double& x, double& y) {
96 x = a - b;
97 double bvirt = a - x;
98 double avirt = x + bvirt;
99 double bround = bvirt - b;
100 double around = a - avirt;
101 y = around + bround;
102 }
103
113 inline void fast_two_sum(double a, double b, double& x, double& y) {
114 x = a + b;
115 double bvirt = x - a;
116 y = b - bvirt;
117 }
118
128 inline void fast_two_diff(double a, double b, double& x, double& y) {
129 x = a - b;
130 double bvirt = a - x;
131 y = bvirt - b;
132 }
133
143 inline void split(double a, double& ahi, double& alo) {
144 double c = expansion_splitter_ * a;
145 double abig = c - a;
146 ahi = c - abig;
147 alo = a - ahi;
148 }
149
159 inline void two_product(double a, double b, double& x, double& y) {
160#ifdef FP_FAST_FMA
161 // If the target processor supports the FMA (Fused Multiply Add)
162 // instruction, then the product of two doubles into a length-2
163 // expansion can be implemented as follows. Thanks to Marc Glisse
164 // for the information.
165 // Note: under gcc, automatic generations of fma() for a*b+c needs
166 // to be deactivated, using -ffp-contract=off, else it may break
167 // other functions such as fast_expansion_sum_zeroelim().
168 x = a*b;
169 y = fma(a,b,-x);
170#else
171 x = a * b;
172 double ahi, alo;
173 split(a, ahi, alo);
174 double bhi, blo;
175 split(b, bhi, blo);
176 double err1 = x - (ahi * bhi);
177 double err2 = err1 - (alo * bhi);
178 double err3 = err2 - (ahi * blo);
179 y = (alo * blo) - err3;
180#endif
181 }
182
191 inline void square(double a, double& x, double& y) {
192#ifdef FP_FAST_FMA
193 // If the target processor supports the FMA (Fused Multiply Add)
194 // instruction, then the product of two doubles into a length-2
195 // expansion can be implemented as follows. Thanks to Marc Glisse
196 // for the information.
197 // Note: under gcc, automatic generations of fma() for a*b+c needs
198 // to be deactivated, using -ffp-contract=off, else it may break
199 // other functions such as fast_expansion_sum_zeroelim().
200 x = a*a;
201 y = fma(a,a,-x);
202#else
203 x = a * a;
204 double ahi, alo;
205 split(a, ahi, alo);
206 double err1 = x - (ahi * ahi);
207 double err3 = err1 - ((ahi + ahi) * alo);
208 y = (alo * alo) - err3;
209#endif
210 }
211
212 /************************************************************************/
213
227 class GEOGRAM_API expansion {
228 public:
233 index_t length() const {
234 return length_;
235 }
236
243 return capacity_;
244 }
245
251 void set_length(index_t new_length) {
252 geo_debug_assert(new_length <= capacity());
253 length_ = new_length;
254 }
255
261 const double& operator[] (index_t i) const {
262 // Note: we allocate capacity+1 storage
263 // systematically, since basic functions
264 // may access one additional value (without
265 // using it)
266 geo_debug_assert(i <= capacity_);
267 return x_[i];
268 }
269
275 double& operator[] (index_t i) {
276 // Note: we allocate capacity+1 storage
277 // systematically, since basic functions
278 // may access one additional value (without
279 // using it)
280 geo_debug_assert(i <= capacity_);
281 return x_[i];
282 }
283
289 double* data() {
290 return x_;
291 }
292
298 const double* data() const {
299 return x_;
300 }
301
309 static size_t bytes(index_t capa) {
310 // --> 2*sizeof(double) because x_ is declared of size [2]
311 // to avoid compiler's warning.
312 // --> capa+1 to have an additional 'sentry' at the end
313 // because fast_expansion_sum_zeroelim() may access
314 // an entry past the end (without using it).
315 return
316 sizeof(expansion) - 2 * sizeof(double) +
317 (capa + 1) * sizeof(double);
318 }
319
329 static size_t bytes_on_stack(index_t capa) {
330#ifndef GEO_HAS_BIG_STACK
331 // Note: standard predicates need at least 512, hence the min.
332 // index_t(MAX_CAPACITY_ON_STACK) is necessary, else with
333 // MAX_CAPACITY_ON_STACK alone the compiler tries to generate a
334 // reference to NOT_IN_LIST resulting in a link error.
335 // (weird, even with constexpr, I do not understand...)
336 // Probably when the function excepts a *reference*
338 capa <= std::max(index_t(MAX_CAPACITY_ON_STACK),index_t(512))
339 );
340#endif
341 return bytes(capa);
342 }
343
354 length_(0),
355 capacity_(capa) {
356 }
357
365#ifdef CPPCHECK
366 // cppcheck does not understand that the result
367 // of alloca() is passed to the placement syntax
368 // of operator new.
369 expansion& new_expansion_on_stack(index_t capa);
370#else
371#define new_expansion_on_stack(capa) \
372 (new (alloca(expansion::bytes_on_stack(capa)))expansion(capa))
373#endif
374
382 void* addr = malloc(bytes(capa));
383 return new(addr)expansion(capa);
384 }
385
392 static inline void delete_expansion_on_heap(expansion* e) {
393 free(e);
394 }
395
396 // ========================== Initialization from doubles
397
403 expansion& assign(double a) {
404 set_length(1);
405 x_[0] = a;
406 return *this;
407 }
408
415 geo_debug_assert(capacity() >= rhs.length());
416 set_length(rhs.length());
417 for(index_t i=0; i<rhs.length(); ++i) {
418 x_[i] = rhs.x_[i];
419 }
420 return *this;
421 }
422
429 assign(rhs);
430 if(sign() == NEGATIVE) {
431 negate();
432 }
433 return *this;
434 }
435
446 static index_t sum_capacity(double a, double b) {
447 geo_argused(a);
448 geo_argused(b);
449 return 2;
450 }
451
462 expansion& assign_sum(double a, double b) {
463 set_length(2);
464 two_sum(a, b, x_[1], x_[0]);
465 return *this;
466 }
467
478 static index_t diff_capacity(double a, double b) {
479 geo_argused(a);
480 geo_argused(b);
481 return 2;
482 }
483
494 expansion& assign_diff(double a, double b) {
495 set_length(2);
496 two_diff(a, b, x_[1], x_[0]);
497 return *this;
498 }
499
510 static index_t product_capacity(double a, double b) {
511 geo_argused(a);
512 geo_argused(b);
513 return 2;
514 }
515
526 expansion& assign_product(double a, double b) {
527 set_length(2);
528 two_product(a, b, x_[1], x_[0]);
529 return *this;
530 }
531
541 static index_t square_capacity(double a) {
542 geo_argused(a);
543 return 2;
544 }
545
556 set_length(2);
557 square(a, x_[1], x_[0]);
558 return *this;
559 }
560
561 // ====== Initialization from expansion and double
562
573 static index_t sum_capacity(const expansion& a, double b) {
574 geo_argused(b);
575 return a.length() + 1;
576 }
577
588 expansion& assign_sum(const expansion& a, double b);
589
600 static index_t diff_capacity(const expansion& a, double b) {
601 geo_argused(b);
602 return a.length() + 1;
603 }
604
615 expansion& assign_diff(const expansion& a, double b);
616
627 static index_t product_capacity(const expansion& a, double b) {
628 geo_argused(b);
629 // TODO: implement special case where the double argument
630 // is a power of two.
631 return a.length() * 2;
632 }
633
644 expansion& assign_product(const expansion& a, double b);
645
646 // ========================== Initialization from expansions
647
656 static index_t sum_capacity(const expansion& a, const expansion& b) {
657 return a.length() + b.length();
658 }
659
671
682 const expansion& a, const expansion& b, const expansion& c
683 ) {
684 return a.length() + b.length() + c.length();
685 }
686
699 const expansion& a, const expansion& b, const expansion& c
700 );
701
713 const expansion& a, const expansion& b,
714 const expansion& c, const expansion& d
715 ) {
716 return a.length() + b.length() + c.length() + d.length();
717 }
718
732 const expansion& a, const expansion& b,
733 const expansion& c, const expansion& d
734 );
735
744 static index_t diff_capacity(const expansion& a, const expansion& b) {
745 return a.length() + b.length();
746 }
747
759
769 const expansion& a, const expansion& b
770 ) {
771 return a.length() * b.length() * 2;
772 }
773
785
796 const expansion& a, const expansion& b, const expansion& c
797 ) {
798 return a.length() * b.length() * c.length() * 4;
799 }
800
813 const expansion& a, const expansion& b, const expansion& c
814 );
815
824 if(a.length() == 2) {
825 return 6;
826 } // see two_square()
827 return a.length() * a.length() * 2;
828 }
829
840
841 // ====== Determinants =============================
842
851 const expansion& a11, const expansion& a12,
852 const expansion& a21, const expansion& a22
853 ) {
854 return
855 product_capacity(a11, a22) +
856 product_capacity(a21, a12);
857 }
858
870 const expansion& a11, const expansion& a12,
871 const expansion& a21, const expansion& a22
872 );
873
883 const expansion& a11, const expansion& a12, const expansion& a13,
884 const expansion& a21, const expansion& a22, const expansion& a23,
885 const expansion& a31, const expansion& a32, const expansion& a33
886 ) {
887 // Development w.r.t. first row
888 index_t c11_capa = det2x2_capacity(a22, a23, a32, a33);
889 index_t c12_capa = det2x2_capacity(a21, a23, a31, a33);
890 index_t c13_capa = det2x2_capacity(a21, a22, a31, a32);
891 return 2 * (
892 a11.length() * c11_capa +
893 a12.length() * c12_capa +
894 a13.length() * c13_capa
895 );
896 }
897
911 const expansion& a11, const expansion& a12, const expansion& a13,
912 const expansion& a21, const expansion& a22, const expansion& a23,
913 const expansion& a31, const expansion& a32, const expansion& a33
914 );
915
926 const expansion& a21, const expansion& a22, const expansion& a23,
927 const expansion& a31, const expansion& a32, const expansion& a33
928 ) {
929 return
930 det2x2_capacity(a22, a23, a32, a33) +
931 det2x2_capacity(a23, a21, a33, a31) +
932 det2x2_capacity(a21, a22, a31, a32);
933 }
934
947 const expansion& a21, const expansion& a22, const expansion& a23,
948 const expansion& a31, const expansion& a32, const expansion& a33
949 );
950
951 // ======= Geometry-specific initializations =======
952
962 return index_t(dim) * 6;
963 }
964
978 const double* p1, const double* p2, coord_index_t dim
979 );
980
990 return index_t(dim) * 8;
991 }
992
1006 const double* p1, const double* p2, const double* p0,
1007 coord_index_t dim
1008 );
1009
1010
1019 const expansion& x, const expansion& y, const expansion& z
1020 ) {
1021 return square_capacity(x) + square_capacity(y) + square_capacity(z);
1022 }
1023
1033 const expansion& x, const expansion& y, const expansion& z
1034 );
1035
1036 // =============== some general purpose functions =========
1037
1044 static void initialize();
1045
1051 for(index_t i = 0; i < length_; ++i) {
1052 x_[i] = -x_[i];
1053 }
1054 return *this;
1055 }
1056
1065 // TODO: debug assert is_power_of_two(s)
1066 for(index_t i = 0; i < length_; ++i) {
1067 x_[i] *= s;
1068 }
1069 return *this;
1070 }
1071
1077 double estimate() const {
1078 double result = 0.0;
1079 for(index_t i = 0; i < length(); ++i) {
1080 result += x_[i];
1081 }
1082 return result;
1083 }
1084
1089 Sign sign() const {
1090 if(length() == 0) {
1091 return ZERO;
1092 }
1093 return geo_sgn(x_[length() - 1]);
1094 }
1095
1103 bool is_same_as(const expansion& rhs) const;
1104
1113 bool is_same_as(double rhs) const;
1114
1115
1120 Sign compare(const expansion& rhs) const;
1121
1126 Sign compare(double rhs) const;
1127
1134 bool equals(const expansion& rhs) const {
1135 return (compare(rhs) == ZERO);
1136 }
1137
1144 bool equals(double rhs) const {
1145 return (compare(rhs) == ZERO);
1146 }
1147
1153 std::ostream& show(std::ostream& out) const {
1154 out << "expansion[" << length() << "] = [";
1155 for(index_t i=0; i<length(); ++i) {
1156 out << (*this)[i] << " ";
1157 }
1158 out << "]";
1159 return out;
1160 }
1161
1166 std::string to_string() const {
1167 std::ostringstream out;
1168 show(out);
1169 return out.str();
1170 }
1171
1177 void optimize();
1178
1182 static void show_all_stats();
1183
1184 protected:
1195 index_t a_length, index_t b_length
1196 ) {
1197 return a_length * b_length * 2;
1198 }
1199
1210 const double* a, index_t a_length, const expansion& b
1211 );
1212
1216 expansion(const expansion& rhs) = delete;
1217
1221 expansion& operator= (const expansion& rhs) = delete;
1222
1223 private:
1224
1230#ifdef GEO_OS_APPLE
1231 static constexpr index_t MAX_CAPACITY_ON_STACK = 256;
1232#else
1233 static constexpr index_t MAX_CAPACITY_ON_STACK = 1024;
1234#endif
1235 index_t length_;
1236 index_t capacity_;
1237 double x_[2]; // x_ is in fact of size [capacity_]
1238
1239 friend class expansion_nt;
1240 };
1241
1242 // =============== arithmetic operations ===========================
1243
1256#define expansion_create(a) \
1257 new_expansion_on_stack(1)->assign(a)
1258
1259
1273#define expansion_abs(e) \
1274 new_expansion_on_stack(e.length())->assign_abs(e)
1275
1293#define expansion_sum(a, b) \
1294 new_expansion_on_stack( \
1295 expansion::sum_capacity(a, b) \
1296 )->assign_sum(a, b)
1297
1315#define expansion_sum3(a, b, c) \
1316 new_expansion_on_stack( \
1317 expansion::sum_capacity(a, b, c) \
1318 )->assign_sum(a, b, c)
1319
1340#define expansion_sum4(a, b, c, d) \
1341 new_expansion_on_stack( \
1342 expansion::sum_capacity(a, b, c, d) \
1343 )->assign_sum(a, b, c, d)
1344
1362#define expansion_diff(a, b) \
1363 new_expansion_on_stack( \
1364 expansion::diff_capacity(a, b) \
1365 )->assign_diff(a, b)
1366
1384#define expansion_product(a, b) \
1385 new_expansion_on_stack( \
1386 expansion::product_capacity(a, b) \
1387 )->assign_product(a, b)
1388
1406#define expansion_product3(a, b, c) \
1407 new_expansion_on_stack( \
1408 expansion::product_capacity(a, b, c) \
1409 )->assign_product(a, b, c)
1410
1426#define expansion_square(a) \
1427 new_expansion_on_stack( \
1428 expansion::square_capacity(a) \
1429 )->assign_square(a)
1430
1431 // =============== determinants =====================================
1432
1446#define expansion_det2x2(a11, a12, a21, a22) \
1447 new_expansion_on_stack( \
1448 expansion::det2x2_capacity(a11, a12, a21, a22) \
1449 )->assign_det2x2(a11, a12, a21, a22)
1450
1467#define expansion_det3x3(a11, a12, a13, a21, a22, a23, a31, a32, a33) \
1468 new_expansion_on_stack( \
1469 expansion::det3x3_capacity(a11,a12,a13,a21,a22,a23,a31,a32,a33) \
1470 )->assign_det3x3(a11, a12, a13, a21, a22, a23, a31, a32, a33)
1471
1489#define expansion_det_111_2x3(a21, a22, a23, a31, a32, a33) \
1490 new_expansion_on_stack( \
1491 expansion::det_111_2x3_capacity(a21, a22, a23, a31, a32, a33) \
1492 )->assign_det_111_2x3(a21, a22, a23, a31, a32, a33)
1493
1494 // =============== geometric functions ==============================
1495
1512#define expansion_sq_dist(a, b, dim) \
1513 new_expansion_on_stack( \
1514 expansion::sq_dist_capacity(dim) \
1515 )->assign_sq_dist(a, b, dim)
1516
1535#define expansion_dot_at(a, b, c, dim) \
1536 new_expansion_on_stack( \
1537 expansion::dot_at_capacity(dim) \
1538 )->assign_dot_at(a, b, c, dim)
1539
1540
1556#define expansion_length2(x,y,z) \
1557 new_expansion_on_stack( \
1558 expansion::length2_capacity(x,y,z) \
1559 )->assign_length2(x,y,z)
1560
1561 /************************************************************************/
1562
1570 const expansion& a00,const expansion& a01,
1571 const expansion& a10,const expansion& a11
1572 );
1573
1581 const expansion& a00,const expansion& a01,const expansion& a02,
1582 const expansion& a10,const expansion& a11,const expansion& a12,
1583 const expansion& a20,const expansion& a21,const expansion& a22
1584 );
1585
1593 const expansion& a00,const expansion& a01,
1594 const expansion& a02,const expansion& a03,
1595 const expansion& a10,const expansion& a11,
1596 const expansion& a12,const expansion& a13,
1597 const expansion& a20,const expansion& a21,
1598 const expansion& a22,const expansion& a23,
1599 const expansion& a30,const expansion& a31,
1600 const expansion& a32,const expansion& a33
1601 );
1602
1603 /************************************************************************/
1604
1619 void GEOGRAM_API grow_expansion_zeroelim(
1620 const expansion& e, double b, expansion& h
1621 );
1622
1639 const expansion& e, double b, expansion& h
1640 );
1641
1658 const expansion& e, const expansion& f, expansion& h
1659 );
1660
1661
1677 const expansion& e, const expansion& f, expansion& h
1678 );
1679
1680 /************************************************************************/
1681}
1682
1683#endif
Assertion checking mechanism.
#define geo_debug_assert(x)
Verifies that a condition is met.
Definition assert.h:196
Expansion_nt (expansion Number Type) is used to compute the sign of polynoms exactly.
Represents numbers in arbitrary precision with a low-level API.
static index_t length2_capacity(const expansion &x, const expansion &y, const expansion &z)
Computes the required capacity to store the length of a 3d vector.
static index_t product_capacity(const expansion &a, const expansion &b)
Computes the required capacity of an expansion to store the exact product of two expansions.
void two_product(double a, double b, double &x, double &y)
Multiplies two doubles into a length 2 expansion.
expansion & assign_sum(const expansion &a, const expansion &b, const expansion &c, const expansion &d)
Assigns the sum of four expansions to this expansion (should not be used by client code).
static index_t product_capacity(double a, double b)
Computes the required capacity of an expansion to store the exact product of two doubles.
void two_diff(double a, double b, double &x, double &y)
Subtracts two doubles into a length 2 expansion.
void split(double a, double &ahi, double &alo)
Splits a number into two components, ready for computing a product.
expansion & assign(const expansion &rhs)
Copies an expansion to this expansion.
static index_t sum_capacity(double a, double b)
Computes the required capacity to store the sum of two doubles.
static index_t sum_capacity(const expansion &a, const expansion &b, const expansion &c, const expansion &d)
Computes the required capacity of an expansion to store the exact sum of four expansions.
index_t length() const
Gets the length of this expansion.
expansion & assign_diff(const expansion &a, const expansion &b)
Assigns the difference between two expansions to this expansion (should not be used by client code).
expansion & assign_product(const expansion &a, const expansion &b, const expansion &c)
Assigns the product of three expansions to this expansion (should not be used by client code).
static index_t sub_product_capacity(index_t a_length, index_t b_length)
Computes the required capacity of an expansion to store an exact sub-product.
expansion & scale_fast(double s)
Multiplies this expansion by a power of two.
static void delete_expansion_on_heap(expansion *e)
Deallocates an expansion on the heap.
static index_t sum_capacity(const expansion &a, const expansion &b)
Computes the required capacity of an expansion to store the exact sum of two expansions.
static void initialize()
Initializes the expansion class.
static index_t sum_capacity(const expansion &a, const expansion &b, const expansion &c)
Computes the required capacity of an expansion to store the exact sum of three expansions.
void square(double a, double &x, double &y)
Squares a number into a length 2 expansion.
static index_t diff_capacity(double a, double b)
Computes the required capacity of an expansion to store the exact difference of two doubles.
bool equals(const expansion &rhs) const
Compares two expansions.
Sign compare(const expansion &rhs) const
Compares two expansions.
expansion & assign_det2x2(const expansion &a11, const expansion &a12, const expansion &a21, const expansion &a22)
Assigns a 2x2 determinant to this expansion (should not be used by client code).
expansion & assign_det_111_2x3(const expansion &a21, const expansion &a22, const expansion &a23, const expansion &a31, const expansion &a32, const expansion &a33)
Assigns a 3x3 determinant to this expansion where the first row is 1 1 1(should not be used by client...
expansion & assign_product(const expansion &a, double b)
Assigns the product between an expansion and a double to this expansion (should not be used by client...
index_t capacity() const
Gets the capacity of this expansion.
std::ostream & show(std::ostream &out) const
Displays all the components of this expansion (for debugging purposes).
expansion & assign_abs(const expansion &rhs)
Copies the absolute value of an expansion to this expansion.
expansion & assign_dot_at(const double *p1, const double *p2, const double *p0, coord_index_t dim)
Assigns the dot product of two vectors to this expansion (should not be used by client code).
static index_t sum_capacity(const expansion &a, double b)
Computes the required capacity of an expansion to store the exact sum of an expansion and a double.
double * data()
Low level access to the array of components.
expansion & assign_product(const expansion &a, const expansion &b)
Assigns the product of two expansions to this expansion (should not be used by client code).
static index_t square_capacity(const expansion &a)
Computes the required capacity of an expansion to store the exact square of an expansion.
expansion & assign_sub_product(const double *a, index_t a_length, const expansion &b)
Assigns a sub-product to this expansion.
const double * data() const
Low level access to the array of components.
expansion & assign_diff(double a, double b)
Assigns the difference of two doubles to this expansion (should not be used by client code).
expansion & assign_square(const expansion &a)
Assigns the product of an expansions to this expansion (should not be used by client code).
void set_length(index_t new_length)
Changes the length of an expansion.
expansion & assign_det3x3(const expansion &a11, const expansion &a12, const expansion &a13, const expansion &a21, const expansion &a22, const expansion &a23, const expansion &a31, const expansion &a32, const expansion &a33)
Assigns a 3x3 determinant to this expansion (should not be used by client code).
bool is_same_as(double rhs) const
Compares an expansion and a double bit-by-bit.
expansion & assign(double a)
Assigns a number to this expansion.
expansion & assign_diff(const expansion &a, double b)
Assigns the difference between an expansion and a double to this expansion (should not be used by cli...
expansion & assign_sum(const expansion &a, double b)
Assigns the sum of an expansion and a double to this expansion (should not be used by client code).
static index_t det_111_2x3_capacity(const expansion &a21, const expansion &a22, const expansion &a23, const expansion &a31, const expansion &a32, const expansion &a33)
Computes the required capacity of an expansion to store an exact 3x3 determinant where the first row ...
expansion & assign_sum(double a, double b)
Assigns the sum of two doubles to this expansion (should not be used by client code).
bool equals(double rhs) const
Compares an expansion and a double.
static index_t det2x2_capacity(const expansion &a11, const expansion &a12, const expansion &a21, const expansion &a22)
Computes the required capacity of an expansion to store an exact 2x2 determinant.
expansion(index_t capa)
Client code should not use this constructor.
static index_t diff_capacity(const expansion &a, const expansion &b)
Computes the required capacity of an expansion to store the exact difference of two expansions.
expansion(const expansion &rhs)=delete
Expansions cannot be copied.
static size_t bytes_on_stack(index_t capa)
Computes the amount of memory required to store an expansion on the stack.
static index_t product_capacity(const expansion &a, double b)
Computes the required capacity of an expansion to store the exact product between an expansion and a ...
static index_t sq_dist_capacity(coord_index_t dim)
Computes the required capacity of an expansion to store the exact squared distance between two points...
expansion & negate()
Changes the sign of an expansion.
static index_t product_capacity(const expansion &a, const expansion &b, const expansion &c)
Computes the required capacity of an expansion to store the exact product of three expansions.
static size_t bytes(index_t capa)
Computes the amount of memory required to store an expansion.
static index_t det3x3_capacity(const expansion &a11, const expansion &a12, const expansion &a13, const expansion &a21, const expansion &a22, const expansion &a23, const expansion &a31, const expansion &a32, const expansion &a33)
Computes the required capacity of an expansion to store an exact 3x3 determinant.
double estimate() const
Computes an approximation of the stored value in this expansion.
static index_t square_capacity(double a)
Computes the required capacity of an expansion to store the exact square of a double.
expansion & assign_sum(const expansion &a, const expansion &b)
Assigns the sum of two expansions to this expansion (should not be used by client code).
static void show_all_stats()
Show global statistics.
static index_t dot_at_capacity(coord_index_t dim)
Computes the required capacity of an expansion to store the exact dot product between two vectors.
bool is_same_as(const expansion &rhs) const
Compares two expansions bit-by-bit.
expansion & assign_sum(const expansion &a, const expansion &b, const expansion &c)
Assigns the sum of three expansions to this expansion (should not be used by client code).
static index_t diff_capacity(const expansion &a, double b)
Computes the required capacity of an expansion to store the exact difference between an expansion and...
std::string to_string() const
Gets a string representation of this expansion.
static expansion * new_expansion_on_heap(index_t capa)
Allocates an expansion on the heap.
expansion & assign_length2(const expansion &x, const expansion &y, const expansion &z)
Assigns the length of a vector to this expansion (should not be used by client code)....
expansion & assign_square(double a)
Assigns the square of a double to this expansion (should not be used by client code).
expansion & assign_sq_dist(const double *p1, const double *p2, coord_index_t dim)
Assigns the squared distance between two points to this expansion (should not be used by client code)...
void two_sum(double a, double b, double &x, double &y)
Sums two doubles into a length 2 expansion.
void optimize()
Optimizes the internal representation without changing the represented value.
expansion & assign_product(double a, double b)
Assigns the product of two doubles to this expansion (should not be used by client code).
Sign compare(double rhs) const
Compares two expansions.
Sign sign() const
Gets the sign of the expansion.
Common include file, providing basic definitions. Should be included before anything else by all head...
Types and functions for memory manipulation.
Global Vorpaline namespace.
Definition basic.h:55
void scale_expansion_zeroelim(const expansion &e, double b, expansion &h)
Multiplies an expansion by a scalar, eliminating zero components from the output expansion.
void grow_expansion_zeroelim(const expansion &e, double b, expansion &h)
Adds a scalar to an expansion, eliminating zero components from the output expansion.
void geo_argused(const T &)
Suppresses compiler warnings about unused parameters.
Definition argused.h:60
void fast_two_diff(double a, double b, double &x, double &y)
Computes the difference of two doubles into a length 2 expansion.
void fast_expansion_sum_zeroelim(const expansion &e, const expansion &f, expansion &h)
Sums two expansions, eliminating zero components from the output expansion (sets h = e + f).
Sign geo_sgn(const T &x)
Gets the sign of a value.
Definition numeric.h:107
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:330
void fast_expansion_diff_zeroelim(const expansion &e, const expansion &f, expansion &h)
Computes the difference of two expansions, eliminating zero components from the output expansion.
Sign
Integer constants that represent the sign of a value.
Definition numeric.h:69
@ ZERO
Definition numeric.h:73
@ NEGATIVE
Definition numeric.h:71
void fast_two_sum(double a, double b, double &x, double &y)
Computes the sum of two doubles into a length 2 expansion.
geo_coord_index_t coord_index_t
The type for storing coordinate indices, and iterating on the coordinates of a point.
Definition numeric.h:364
Sign sign_of_expansion_determinant(const expansion &a00, const expansion &a01, const expansion &a10, const expansion &a11)
Computes the sign of a 2x2 determinant.
Types and functions for numbers manipulation.