Graphite  Version 3
An experimental 3D geometry processing program
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 
43 #include <geogram/basic/common.h>
44 #include <geogram/basic/numeric.h>
45 #include <geogram/basic/memory.h>
46 #include <geogram/basic/assert.h>
47 #include <iostream>
48 #include <sstream>
49 #include <new>
50 #include <math.h>
51 
63 namespace 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 split(double a, double& ahi, double& alo) {
114  double c = expansion_splitter_ * a;
115  double abig = c - a;
116  ahi = c - abig;
117  alo = a - ahi;
118  }
119 
129  inline void two_product(double a, double b, double& x, double& y) {
130 #ifdef FP_FAST_FMA
131  // If the target processor supports the FMA (Fused Multiply Add)
132  // instruction, then the product of two doubles into a length-2
133  // expansion can be implemented as follows. Thanks to Marc Glisse
134  // for the information.
135  // Note: under gcc, automatic generations of fma() for a*b+c needs
136  // to be deactivated, using -ffp-contract=off, else it may break
137  // other functions such as fast_expansion_sum_zeroelim().
138  x = a*b;
139  y = fma(a,b,-x);
140 #else
141  x = a * b;
142  double ahi, alo;
143  split(a, ahi, alo);
144  double bhi, blo;
145  split(b, bhi, blo);
146  double err1 = x - (ahi * bhi);
147  double err2 = err1 - (alo * bhi);
148  double err3 = err2 - (ahi * blo);
149  y = (alo * blo) - err3;
150 #endif
151  }
152 
161  inline void square(double a, double& x, double& y) {
162 #ifdef FP_FAST_FMA
163  // If the target processor supports the FMA (Fused Multiply Add)
164  // instruction, then the product of two doubles into a length-2
165  // expansion can be implemented as follows. Thanks to Marc Glisse
166  // for the information.
167  // Note: under gcc, automatic generations of fma() for a*b+c needs
168  // to be deactivated, using -ffp-contract=off, else it may break
169  // other functions such as fast_expansion_sum_zeroelim().
170  x = a*a;
171  y = fma(a,a,-x);
172 #else
173  x = a * a;
174  double ahi, alo;
175  split(a, ahi, alo);
176  double err1 = x - (ahi * ahi);
177  double err3 = err1 - ((ahi + ahi) * alo);
178  y = (alo * alo) - err3;
179 #endif
180  }
181 
182  /************************************************************************/
183 
197  class GEOGRAM_API expansion {
198  public:
203  index_t length() const {
204  return length_;
205  }
206 
212  index_t capacity() const {
213  return capacity_;
214  }
215 
221  void set_length(index_t new_length) {
222  geo_debug_assert(new_length <= capacity());
223  length_ = new_length;
224  }
225 
231  const double& operator[] (index_t i) const {
232  // Note: we allocate capacity+1 storage
233  // systematically, since basic functions
234  // may access one additional value (without
235  // using it)
236  geo_debug_assert(i <= capacity_);
237  return x_[i];
238  }
239 
245  double& operator[] (index_t i) {
246  // Note: we allocate capacity+1 storage
247  // systematically, since basic functions
248  // may access one additional value (without
249  // using it)
250  geo_debug_assert(i <= capacity_);
251  return x_[i];
252  }
253 
259  double* data() {
260  return x_;
261  }
262 
268  const double* data() const {
269  return x_;
270  }
271 
279  static size_t bytes(index_t capa) {
280  // --> 2*sizeof(double) because x_ is declared of size [2]
281  // to avoid compiler's warning.
282  // --> capa+1 to have an additional 'sentry' at the end
283  // because fast_expansion_sum_zeroelim() may access
284  // an entry past the end (without using it).
285  return
286  sizeof(expansion) - 2 * sizeof(double) +
287  (capa + 1) * sizeof(double);
288  }
289 
299  static size_t bytes_on_stack(index_t capa) {
300 #ifndef GEO_HAS_BIG_STACK
301  // Note: standard predicates need at least 512, hence the min.
302  // index_t(MAX_CAPACITY_ON_STACK) is necessary, else with
303  // MAX_CAPACITY_ON_STACK alone the compiler tries to generate a
304  // reference to NOT_IN_LIST resulting in a link error.
305  // (weird, even with constexpr, I do not understand...)
306  // Probably when the function excepts a *reference*
308  capa <= std::max(index_t(MAX_CAPACITY_ON_STACK),index_t(512))
309  );
310 #endif
311  return bytes(capa);
312  }
313 
324  length_(0),
325  capacity_(capa) {
326  }
327 
335 #ifdef CPPCHECK
336  // cppcheck does not understand that the result
337  // of alloca() is passed to the placement syntax
338  // of operator new.
339  expansion& new_expansion_on_stack(index_t capa);
340 #else
341 #define new_expansion_on_stack(capa) \
342  (new (alloca(expansion::bytes_on_stack(capa)))expansion(capa))
343 #endif
344 
352 
360 
361  // ========================== Initialization from doubles
362 
368  expansion& assign(double a) {
369  set_length(1);
370  x_[0] = a;
371  return *this;
372  }
373 
379  expansion& assign(const expansion& rhs) {
380  geo_debug_assert(capacity() >= rhs.length());
381  set_length(rhs.length());
382  for(index_t i=0; i<rhs.length(); ++i) {
383  x_[i] = rhs.x_[i];
384  }
385  return *this;
386  }
387 
394  assign(rhs);
395  if(sign() == NEGATIVE) {
396  negate();
397  }
398  return *this;
399  }
400 
411  static index_t sum_capacity(double a, double b) {
412  geo_argused(a);
413  geo_argused(b);
414  return 2;
415  }
416 
427  expansion& assign_sum(double a, double b) {
428  set_length(2);
429  two_sum(a, b, x_[1], x_[0]);
430  return *this;
431  }
432 
443  static index_t diff_capacity(double a, double b) {
444  geo_argused(a);
445  geo_argused(b);
446  return 2;
447  }
448 
459  expansion& assign_diff(double a, double b) {
460  set_length(2);
461  two_diff(a, b, x_[1], x_[0]);
462  return *this;
463  }
464 
475  static index_t product_capacity(double a, double b) {
476  geo_argused(a);
477  geo_argused(b);
478  return 2;
479  }
480 
491  expansion& assign_product(double a, double b) {
492  set_length(2);
493  two_product(a, b, x_[1], x_[0]);
494  return *this;
495  }
496 
506  static index_t square_capacity(double a) {
507  geo_argused(a);
508  return 2;
509  }
510 
521  set_length(2);
522  square(a, x_[1], x_[0]);
523  return *this;
524  }
525 
526  // ====== Initialization from expansion and double
527 
538  static index_t sum_capacity(const expansion& a, double b) {
539  geo_argused(b);
540  return a.length() + 1;
541  }
542 
553  expansion& assign_sum(const expansion& a, double b);
554 
565  static index_t diff_capacity(const expansion& a, double b) {
566  geo_argused(b);
567  return a.length() + 1;
568  }
569 
580  expansion& assign_diff(const expansion& a, double b);
581 
592  static index_t product_capacity(const expansion& a, double b) {
593  geo_argused(b);
594  // TODO: implement special case where the double argument
595  // is a power of two.
596  return a.length() * 2;
597  }
598 
609  expansion& assign_product(const expansion& a, double b);
610 
611  // ========================== Initialization from expansions
612 
621  static index_t sum_capacity(const expansion& a, const expansion& b) {
622  return a.length() + b.length();
623  }
624 
635  expansion& assign_sum(const expansion& a, const expansion& b);
636 
647  const expansion& a, const expansion& b, const expansion& c
648  ) {
649  return a.length() + b.length() + c.length();
650  }
651 
664  const expansion& a, const expansion& b, const expansion& c
665  );
666 
678  const expansion& a, const expansion& b,
679  const expansion& c, const expansion& d
680  ) {
681  return a.length() + b.length() + c.length() + d.length();
682  }
683 
697  const expansion& a, const expansion& b,
698  const expansion& c, const expansion& d
699  );
700 
709  static index_t diff_capacity(const expansion& a, const expansion& b) {
710  return a.length() + b.length();
711  }
712 
723  expansion& assign_diff(const expansion& a, const expansion& b);
724 
734  const expansion& a, const expansion& b
735  ) {
736  return a.length() * b.length() * 2;
737  }
738 
750 
761  const expansion& a, const expansion& b, const expansion& c
762  ) {
763  return a.length() * b.length() * c.length() * 4;
764  }
765 
778  const expansion& a, const expansion& b, const expansion& c
779  );
780 
788  static index_t square_capacity(const expansion& a) {
789  if(a.length() == 2) {
790  return 6;
791  } // see two_square()
792  return a.length() * a.length() * 2;
793  }
794 
805 
806  // ====== Determinants =============================
807 
816  const expansion& a11, const expansion& a12,
817  const expansion& a21, const expansion& a22
818  ) {
819  return
820  product_capacity(a11, a22) +
821  product_capacity(a21, a12);
822  }
823 
835  const expansion& a11, const expansion& a12,
836  const expansion& a21, const expansion& a22
837  );
838 
848  const expansion& a11, const expansion& a12, const expansion& a13,
849  const expansion& a21, const expansion& a22, const expansion& a23,
850  const expansion& a31, const expansion& a32, const expansion& a33
851  ) {
852  // Development w.r.t. first row
853  index_t c11_capa = det2x2_capacity(a22, a23, a32, a33);
854  index_t c12_capa = det2x2_capacity(a21, a23, a31, a33);
855  index_t c13_capa = det2x2_capacity(a21, a22, a31, a32);
856  return 2 * (
857  a11.length() * c11_capa +
858  a12.length() * c12_capa +
859  a13.length() * c13_capa
860  );
861  }
862 
876  const expansion& a11, const expansion& a12, const expansion& a13,
877  const expansion& a21, const expansion& a22, const expansion& a23,
878  const expansion& a31, const expansion& a32, const expansion& a33
879  );
880 
891  const expansion& a21, const expansion& a22, const expansion& a23,
892  const expansion& a31, const expansion& a32, const expansion& a33
893  ) {
894  return
895  det2x2_capacity(a22, a23, a32, a33) +
896  det2x2_capacity(a23, a21, a33, a31) +
897  det2x2_capacity(a21, a22, a31, a32);
898  }
899 
912  const expansion& a21, const expansion& a22, const expansion& a23,
913  const expansion& a31, const expansion& a32, const expansion& a33
914  );
915 
916  // ======= Geometry-specific initializations =======
917 
927  return index_t(dim) * 6;
928  }
929 
943  const double* p1, const double* p2, coord_index_t dim
944  );
945 
955  return index_t(dim) * 8;
956  }
957 
971  const double* p1, const double* p2, const double* p0,
972  coord_index_t dim
973  );
974 
975 
984  const expansion& x, const expansion& y, const expansion& z
985  ) {
986  return square_capacity(x) + square_capacity(y) + square_capacity(z);
987  }
988 
998  const expansion& x, const expansion& y, const expansion& z
999  );
1000 
1001  // =============== some general purpose functions =========
1002 
1009  static void initialize();
1010 
1016  for(index_t i = 0; i < length_; ++i) {
1017  x_[i] = -x_[i];
1018  }
1019  return *this;
1020  }
1021 
1029  expansion& scale_fast(double s) {
1030  // TODO: debug assert is_power_of_two(s)
1031  for(index_t i = 0; i < length_; ++i) {
1032  x_[i] *= s;
1033  }
1034  return *this;
1035  }
1036 
1042  double estimate() const {
1043  double result = 0.0;
1044  for(index_t i = 0; i < length(); ++i) {
1045  result += x_[i];
1046  }
1047  return result;
1048  }
1049 
1054  Sign sign() const {
1055  if(length() == 0) {
1056  return ZERO;
1057  }
1058  return geo_sgn(x_[length() - 1]);
1059  }
1060 
1068  bool is_same_as(const expansion& rhs) const;
1069 
1078  bool is_same_as(double rhs) const;
1079 
1080 
1085  Sign compare(const expansion& rhs) const;
1086 
1091  Sign compare(double rhs) const;
1092 
1099  bool equals(const expansion& rhs) const {
1100  return (compare(rhs) == ZERO);
1101  }
1102 
1109  bool equals(double rhs) const {
1110  return (compare(rhs) == ZERO);
1111  }
1112 
1118  std::ostream& show(std::ostream& out) const {
1119  out << "expansion[" << length() << "] = [";
1120  for(index_t i=0; i<length(); ++i) {
1121  out << (*this)[i] << " ";
1122  }
1123  out << "]";
1124  return out;
1125  }
1126 
1131  std::string to_string() const {
1132  std::ostringstream out;
1133  show(out);
1134  return out.str();
1135  }
1136 
1142  void optimize();
1143 
1147  static void show_all_stats();
1148 
1149  protected:
1160  index_t a_length, index_t b_length
1161  ) {
1162  return a_length * b_length * 2;
1163  }
1164 
1175  const double* a, index_t a_length, const expansion& b
1176  );
1177 
1181  expansion(const expansion& rhs) = delete;
1182 
1186  expansion& operator= (const expansion& rhs) = delete;
1187 
1188  private:
1189 
1195 #ifdef GEO_OS_APPLE
1196  static constexpr index_t MAX_CAPACITY_ON_STACK = 256;
1197 #else
1198  static constexpr index_t MAX_CAPACITY_ON_STACK = 1024;
1199 #endif
1200  index_t length_;
1201  index_t capacity_;
1202  double x_[2]; // x_ is in fact of size [capacity_]
1203 
1204  friend class expansion_nt;
1205  };
1206 
1207  // =============== arithmetic operations ===========================
1208 
1221 #define expansion_create(a) \
1222  new_expansion_on_stack(1)->assign(a)
1223 
1224 
1238 #define expansion_abs(e) \
1239  new_expansion_on_stack(e.length())->assign_abs(e)
1240 
1258 #define expansion_sum(a, b) \
1259  new_expansion_on_stack( \
1260  expansion::sum_capacity(a, b) \
1261  )->assign_sum(a, b)
1262 
1280 #define expansion_sum3(a, b, c) \
1281  new_expansion_on_stack( \
1282  expansion::sum_capacity(a, b, c) \
1283  )->assign_sum(a, b, c)
1284 
1305 #define expansion_sum4(a, b, c, d) \
1306  new_expansion_on_stack( \
1307  expansion::sum_capacity(a, b, c, d) \
1308  )->assign_sum(a, b, c, d)
1309 
1327 #define expansion_diff(a, b) \
1328  new_expansion_on_stack( \
1329  expansion::diff_capacity(a, b) \
1330  )->assign_diff(a, b)
1331 
1349 #define expansion_product(a, b) \
1350  new_expansion_on_stack( \
1351  expansion::product_capacity(a, b) \
1352  )->assign_product(a, b)
1353 
1371 #define expansion_product3(a, b, c) \
1372  new_expansion_on_stack( \
1373  expansion::product_capacity(a, b, c) \
1374  )->assign_product(a, b, c)
1375 
1391 #define expansion_square(a) \
1392  new_expansion_on_stack( \
1393  expansion::square_capacity(a) \
1394  )->assign_square(a)
1395 
1396  // =============== determinants =====================================
1397 
1411 #define expansion_det2x2(a11, a12, a21, a22) \
1412  new_expansion_on_stack( \
1413  expansion::det2x2_capacity(a11, a12, a21, a22) \
1414  )->assign_det2x2(a11, a12, a21, a22)
1415 
1432 #define expansion_det3x3(a11, a12, a13, a21, a22, a23, a31, a32, a33) \
1433  new_expansion_on_stack( \
1434  expansion::det3x3_capacity(a11,a12,a13,a21,a22,a23,a31,a32,a33) \
1435  )->assign_det3x3(a11, a12, a13, a21, a22, a23, a31, a32, a33)
1436 
1454 #define expansion_det_111_2x3(a21, a22, a23, a31, a32, a33) \
1455  new_expansion_on_stack( \
1456  expansion::det_111_2x3_capacity(a21, a22, a23, a31, a32, a33) \
1457  )->assign_det_111_2x3(a21, a22, a23, a31, a32, a33)
1458 
1459  // =============== geometric functions ==============================
1460 
1477 #define expansion_sq_dist(a, b, dim) \
1478  new_expansion_on_stack( \
1479  expansion::sq_dist_capacity(dim) \
1480  )->assign_sq_dist(a, b, dim)
1481 
1500 #define expansion_dot_at(a, b, c, dim) \
1501  new_expansion_on_stack( \
1502  expansion::dot_at_capacity(dim) \
1503  )->assign_dot_at(a, b, c, dim)
1504 
1505 
1521 #define expansion_length2(x,y,z) \
1522  new_expansion_on_stack( \
1523  expansion::length2_capacity(x,y,z) \
1524  )->assign_length2(x,y,z)
1525 
1526  /************************************************************************/
1527 
1535  const expansion& a00,const expansion& a01,
1536  const expansion& a10,const expansion& a11
1537  );
1538 
1546  const expansion& a00,const expansion& a01,const expansion& a02,
1547  const expansion& a10,const expansion& a11,const expansion& a12,
1548  const expansion& a20,const expansion& a21,const expansion& a22
1549  );
1550 
1558  const expansion& a00,const expansion& a01,
1559  const expansion& a02,const expansion& a03,
1560  const expansion& a10,const expansion& a11,
1561  const expansion& a12,const expansion& a13,
1562  const expansion& a20,const expansion& a21,
1563  const expansion& a22,const expansion& a23,
1564  const expansion& a30,const expansion& a31,
1565  const expansion& a32,const expansion& a33
1566  );
1567 
1568  /************************************************************************/
1569 
1584  void GEOGRAM_API grow_expansion_zeroelim(
1585  const expansion& e, double b, expansion& h
1586  );
1587 
1603  void GEOGRAM_API scale_expansion_zeroelim(
1604  const expansion& e, double b, expansion& h
1605  );
1606 
1623  const expansion& e, const expansion& f, expansion& h
1624  );
1625 
1626 
1642  const expansion& e, const expansion& f, expansion& h
1643  );
1644 
1645  /************************************************************************/
1646 }
1647 
1648 #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.
Definition: expansion_nt.h:70
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.
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_product(double a, double b, double &x, double &y)
Multiplies two doubles into a length 2 expansion.
static index_t product_capacity(double a, double b)
Computes the required capacity of an expansion to store the exact product of two doubles.
expansion & negate()
Changes the sign of an expansion.
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_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(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_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 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 & assign_sub_product(const double *a, index_t a_length, const expansion &b)
Assigns a sub-product to this 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).
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.
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...
Sign compare(const expansion &rhs) const
Compares two expansions.
expansion & assign_product(double a, double b)
Assigns the product of two doubles to this expansion (should not be used by client code).
index_t capacity() const
Gets the capacity of this expansion.
const double * data() const
Low level access to the array of components.
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.
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 index_t square_capacity(const expansion &a)
Computes the required capacity of an expansion to store the exact square of an expansion.
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...
std::ostream & show(std::ostream &out) const
Displays all the components of this expansion (for debugging purposes).
void set_length(index_t new_length)
Changes the length of an expansion.
expansion & assign_diff(double a, double b)
Assigns the difference of two doubles 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_abs(const expansion &rhs)
Copies the absolute value of an expansion to this expansion.
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 ...
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.
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 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 & 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 expansion * new_expansion_on_heap(index_t capa)
Allocates an expansion on the heap.
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.
double * data()
Low level access to the array of components.
static size_t bytes(index_t capa)
Computes the amount of memory required to store an expansion.
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).
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.
expansion & scale_fast(double s)
Multiplies this expansion by a power of two.
expansion & assign_square(const expansion &a)
Assigns the product of an expansions to this expansion (should not be used by client code).
double estimate() const
Computes an approximation of the stored value in this expansion.
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)....
static index_t square_capacity(double a)
Computes the required capacity of an expansion to store the exact square of a double.
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).
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(double a, double b)
Assigns the sum of two doubles 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...
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).
expansion & assign_square(double a)
Assigns the square of a double to this expansion (should not be used by client code).
expansion & assign(double a)
Assigns a number to this expansion.
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...
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).
std::string to_string() const
Gets a string representation of this expansion.
expansion & assign(const expansion &rhs)
Copies an expansion to this expansion.
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.
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.
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_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:90
geo_index_t index_t
The type for storing and manipulating indices.
Definition: numeric.h:329
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:68
@ ZERO
Definition: numeric.h:72
@ NEGATIVE
Definition: numeric.h:70
geo_coord_index_t coord_index_t
The type for storing coordinate indices, and iterating on the coordinates of a point.
Definition: numeric.h:363
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.