Geogram Version 1.10.1
A programming library of geometric algorithms
Loading...
Searching...
No Matches
expansion_nt.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_EXPANSION_NT
41#define GEOGRAM_NUMERICS_EXPANSION_NT
42
47
56namespace GEO {
57
58 class expansion_nt;
59
70 class GEOGRAM_API expansion_nt {
71 public:
72
77 enum Operation {
78 SUM, DIFF, PRODUCT
79 };
80
84 expansion_nt() : rep_(nullptr) {
85 }
86
91 explicit expansion_nt(double x) {
92 rep_ = expansion::new_expansion_on_heap(1);
93 rep()[0] = x;
94 rep().set_length(1);
95 }
96
103 explicit expansion_nt(const expansion& rhs) {
104 rep_ = expansion::new_expansion_on_heap(rhs.length());
105 rep().assign(rhs);
106 }
107
121 explicit expansion_nt(
122 Operation op, const expansion& x, const expansion& y
123 ) {
124 switch(op) {
125 case SUM:
126 rep_ = expansion::new_expansion_on_heap(
127 expansion::sum_capacity(x,y)
128 );
129 rep_->assign_sum(x,y);
130 break;
131 case DIFF:
132 rep_ = expansion::new_expansion_on_heap(
133 expansion::diff_capacity(x,y)
134 );
135 rep_->assign_diff(x,y);
136 break;
137 case PRODUCT:
138 rep_ = expansion::new_expansion_on_heap(
139 expansion::product_capacity(x,y)
140 );
141 rep_->assign_product(x,y);
142 break;
143 }
144 }
145
159 explicit expansion_nt(
160 Operation op,
161 const expansion& x, const expansion& y, const expansion& z
162 ) {
163 switch(op) {
164 case SUM:
165 rep_ = expansion::new_expansion_on_heap(
166 expansion::sum_capacity(x,y,z)
167 );
168 rep_->assign_sum(x,y,z);
169 break;
170 case DIFF:
172 break;
173 case PRODUCT:
174 rep_ = expansion::new_expansion_on_heap(
175 expansion::product_capacity(x,y,z)
176 );
177 rep_->assign_product(x,y,z);
178 break;
179 }
180 }
181
195 explicit expansion_nt(
196 Operation op,
197 const expansion& x, const expansion& y,
198 const expansion& z, const expansion& t
199 ) {
200 switch(op) {
201 case SUM:
202 rep_ = expansion::new_expansion_on_heap(
203 expansion::sum_capacity(x,y,z,t)
204 );
205 rep_->assign_sum(x,y,z,t);
206 break;
207 case DIFF:
209 break;
210 case PRODUCT:
211 // HERE: TODO CHECK SIZE
212 const expansion& p1 = expansion_product(x,y);
213 const expansion& p2 = expansion_product(z,t);
214 rep_ = expansion::new_expansion_on_heap(
215 expansion::product_capacity(p1,p2)
216 );
217 rep_->assign_sum(p1,p2);
218 break;
219 }
220 }
221
235 explicit expansion_nt(Operation op, double x, double y) {
236 switch(op) {
237 case SUM:
238 rep_ = expansion::new_expansion_on_heap(
239 expansion::sum_capacity(x,y)
240 );
241 rep_->assign_sum(x,y);
242 break;
243 case DIFF:
244 rep_ = expansion::new_expansion_on_heap(
245 expansion::diff_capacity(x,y)
246 );
247 rep_->assign_diff(x,y);
248 break;
249 case PRODUCT:
250 rep_ = expansion::new_expansion_on_heap(
251 expansion::product_capacity(x,y)
252 );
253 rep_->assign_product(x,y);
254 break;
255 }
256 }
257
263 copy(rhs);
264 }
265
272 rep_ = nullptr;
273 std::swap(rep_, rhs.rep_);
274 }
275
281 expansion_nt& operator= (const expansion_nt& rhs) {
282 if(&rhs != this) {
283 cleanup();
284 copy(rhs);
285 }
286 return *this;
287 }
288
294 expansion_nt& operator= (expansion_nt&& rhs) {
295 if(&rhs != this) {
296 cleanup();
297 std::swap(rep_, rhs.rep_);
298 }
299 return *this;
300 }
301
308 cleanup();
309 }
310
316 void optimize() {
317 rep().optimize();
318 }
319
323 void negate() {
324 rep().negate();
325 }
326
327 /********************************************************************/
328
334 expansion_nt& operator+= (const expansion_nt& rhs);
335
341 expansion_nt& operator-= (const expansion_nt& rhs);
342
348 expansion_nt& operator*= (const expansion_nt& rhs);
349
355 expansion_nt& operator+= (double rhs);
356
362 expansion_nt& operator-= (double rhs);
363
372 expansion_nt& operator*= (double rhs);
373
374 /********************************************************************/
375
381 expansion_nt operator+ (const expansion_nt& rhs) const;
382
389 expansion_nt operator- (const expansion_nt& rhs) const;
390
397 expansion_nt operator* (const expansion_nt& rhs) const;
398
404 expansion_nt operator+ (double rhs) const;
405
411 expansion_nt operator- (double rhs) const;
412
418 expansion_nt operator* (double rhs) const;
419
420 /********************************************************************/
421
426 expansion_nt operator- () const;
427
428 /********************************************************************/
429
434 Sign compare(const expansion_nt& rhs) const {
435 return rep().compare(rhs.rep());
436 }
437
442 Sign compare(double rhs) const {
443 return rep().compare(rhs);
444 }
445
453 bool operator> (const expansion_nt& rhs) const {
454 return (int(compare(rhs))>0);
455 }
456
464 bool operator>= (const expansion_nt& rhs) const {
465 return (int(compare(rhs))>=0);
466 }
467
475 bool operator< (const expansion_nt& rhs) const {
476 return (int(compare(rhs))<0);
477 }
478
486 bool operator<= (const expansion_nt& rhs) const {
487 return (int(compare(rhs))<=0);
488 }
489
497 bool operator> (double rhs) const {
498 return (int(compare(rhs))>0);
499 }
500
508 bool operator>= (double rhs) const {
509 return (int(compare(rhs))>=0);
510 }
511
519 bool operator< (double rhs) const {
520 return (int(compare(rhs))<0);
521 }
522
530 bool operator<= (double rhs) const {
531 return (int(compare(rhs))<=0);
532 }
533
534 /********************************************************************/
535
541 double estimate() const {
542 return rep().estimate();
543 }
544
549 Sign sign() const {
550 return rep().sign();
551 }
552
560 index_t length() const {
561 return rep().length();
562 }
563
572 double component(index_t i) const {
573 geo_debug_assert(i < length());
574 return rep()[i];
575 }
576
586 rep_(rep) {
587 }
588
598 return *rep_;
599 }
600
609 const expansion& rep() const {
610 return *rep_;
611 }
612
618 std::string to_string() const {
619 return (rep_ == nullptr) ?
620 std::string("null") :
621 rep_->to_string() ;
622 }
623
630 bool is_one() const {
631 return rep().equals(1.0);
632 }
633
640 bool is_zero() const {
641 return sign() == ZERO;
642 }
643
644 protected:
645
652 void copy(const expansion_nt& rhs) {
653 if(rhs.rep_ == nullptr) {
654 rep_ = nullptr;
655 } else {
656 rep_ = expansion::new_expansion_on_heap(rhs.rep().capacity());
657 rep_->set_length(rhs.rep().length());
658 for(index_t i=0; i<rep_->length(); ++i) {
659 (*rep_)[i] = rhs.rep()[i];
660 }
661 }
662 }
663
667 void cleanup() {
668 if(rep_ != nullptr) {
669 expansion::delete_expansion_on_heap(rep_);
670 rep_ = nullptr;
671 }
672 }
673
674 private:
675 expansion* rep_;
676 friend expansion_nt operator- (double a, const expansion_nt& b);
677
678 friend expansion_nt expansion_nt_sq_dist(
679 const double* a, const double* b, coord_index_t dim
680 );
681
682 friend expansion_nt expansion_nt_dot_at(
683 const double* a, const double* b, const double* c,
684 coord_index_t dim
685 );
686 // friend class rational_nt;
687 };
688
696 inline expansion_nt operator+ (double a, const expansion_nt& b) {
697 return b + a;
698 }
699
707 inline expansion_nt operator- (double a, const expansion_nt& b) {
708 expansion_nt result = b - a;
709 result.rep().negate();
710 return result;
711 }
712
720 inline expansion_nt operator* (double a, const expansion_nt& b) {
721 return b * a;
722 }
723
732 inline bool operator== (const expansion_nt& a, const expansion_nt& b) {
733 return a.rep().equals(b.rep());
734 }
735
744 inline bool operator== (const expansion_nt& a, double b) {
745 return a.rep().equals(b);
746 }
747
756 inline bool operator== (double a, const expansion_nt& b) {
757 return b.rep().equals(a);
758 }
759
768 inline bool operator!= (const expansion_nt& a, const expansion_nt& b) {
769 return !a.rep().equals(b.rep());
770 }
771
780 inline bool operator!= (const expansion_nt& a, double b) {
781 return !a.rep().equals(b);
782 }
783
792 inline bool operator!= (double a, const expansion_nt& b) {
793 return !b.rep().equals(a);
794 }
795
807 const double* a, const double* b, coord_index_t dim
808 ) {
811 );
812 result->assign_sq_dist(a, b, dim);
813 return expansion_nt(result);
814 }
815
828 const double* a, const double* b, const double* c, coord_index_t dim
829 ) {
832 );
833 result->assign_dot_at(a, b, c, dim);
834 return expansion_nt(result);
835 }
836
837 /************************************************************************/
838
844 template <> inline Sign geo_sgn(const expansion_nt& x) {
845 return x.sign();
846 }
847
855 template <> inline Sign geo_cmp(
856 const expansion_nt& x, const expansion_nt& y
857 ) {
858 return x.compare(y);
859 }
860
861 /************************************************************************/
862
870 inline bool expansion_nt_is_zero(const expansion_nt& x) {
871 return (x.sign() == GEO::ZERO);
872 }
873
881 inline bool expansion_nt_is_one(const expansion_nt& x) {
882 return x.rep().equals(1.0);
883 }
884
885
895 const expansion_nt& x, const expansion_nt& y
896 ) {
897 const expansion& diff = expansion_diff(x.rep(), y.rep());
898 return diff.sign();
899 }
900
908 expansion_nt result(
911 ))
912 );
913 result.rep().assign_square(x.rep());
914 return result;
915 }
916
917
925 const expansion_nt& a00,const expansion_nt& a01,
926 const expansion_nt& a10,const expansion_nt& a11
927 );
928
936 const expansion_nt& a00,const expansion_nt& a01,const expansion_nt& a02,
937 const expansion_nt& a10,const expansion_nt& a11,const expansion_nt& a12,
938 const expansion_nt& a20,const expansion_nt& a21,const expansion_nt& a22
939 );
940
948 const expansion_nt& a00,const expansion_nt& a01,
949 const expansion_nt& a02,const expansion_nt& a03,
950 const expansion_nt& a10,const expansion_nt& a11,
951 const expansion_nt& a12,const expansion_nt& a13,
952 const expansion_nt& a20,const expansion_nt& a21,
953 const expansion_nt& a22,const expansion_nt& a23,
954 const expansion_nt& a30,const expansion_nt& a31,
955 const expansion_nt& a32,const expansion_nt& a33
956 );
957
958// Make things a bit faster if target OS has large stack size
959#ifdef GEO_HAS_BIG_STACK
960
966 template <> inline expansion_nt det2x2(
967 const expansion_nt& a11, const expansion_nt& a12,
968 const expansion_nt& a21, const expansion_nt& a22
969 ) {
971 a11,a12,
972 a21,a22
973 );
974 }
975
981 template <> inline expansion_nt det3x3(
982 const expansion_nt& a11, const expansion_nt& a12,
983 const expansion_nt& a13,
984 const expansion_nt& a21, const expansion_nt& a22,
985 const expansion_nt& a23,
986 const expansion_nt& a31, const expansion_nt& a32,
987 const expansion_nt& a33
988 ) {
990 a11,a12,a13,
991 a21,a22,a23,
992 a31,a32,a33
993 );
994 }
995
1001 template <> inline expansion_nt det4x4(
1002 const expansion_nt& a11, const expansion_nt& a12,
1003 const expansion_nt& a13, const expansion_nt& a14,
1004 const expansion_nt& a21, const expansion_nt& a22,
1005 const expansion_nt& a23, const expansion_nt& a24,
1006 const expansion_nt& a31, const expansion_nt& a32,
1007 const expansion_nt& a33, const expansion_nt& a34,
1008 const expansion_nt& a41, const expansion_nt& a42,
1009 const expansion_nt& a43, const expansion_nt& a44
1010 ) {
1012 a11,a12,a13,a14,
1013 a21,a22,a23,a24,
1014 a31,a32,a33,a34,
1015 a41,a42,a43,a44
1016 );
1017 }
1018
1019#endif
1020
1021 /************************************************************************/
1022}
1023
1030inline std::ostream& operator<< (
1031 std::ostream& os, const GEO::expansion_nt& a
1032) {
1033 return os << a.estimate();
1034}
1035
1043inline std::istream& operator>> ( std::istream& is, GEO::expansion_nt& a) {
1044 double d;
1045 is >> d;
1046 if (is) {
1047 a = GEO::expansion_nt(d);
1048 }
1049 return is;
1050}
1051
1052/*****************************************************************************/
1053
1054namespace GEO {
1055
1056 /**************************************************************************/
1057
1058 namespace Numeric {
1059
1060 template<> inline void optimize_number_representation(expansion_nt& x) {
1061 x.optimize();
1062 }
1063
1071 template<> Sign GEOGRAM_API ratio_compare(
1072 const expansion_nt& a_num, const expansion_nt& a_denom,
1073 const expansion_nt& b_num, const expansion_nt& b_denom
1074 );
1075 }
1076
1077 /**************************************************************************/
1078
1080
1081 /**************************************************************************/
1082
1084 template <> struct is_scalar<expansion_nt> {
1085 typedef expansion_nt type;
1086 static constexpr bool value = true;
1087 };
1088
1089 /**************************************************************************/
1090}
1091
1092#endif
#define geo_assert_not_reached
Sets a non reachable point in the program.
Definition assert.h:177
#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.
bool is_zero() const
Tests whether an expansion_nt is equal to zero.
const expansion & rep() const
Gets the internal expansion that represents this expansion_nt.
double estimate() const
Computes an approximation of the stored value in this expansion.
void copy(const expansion_nt &rhs)
Copies an expansion into this one.
Sign sign() const
Gets the sign of this expansion_nt.
expansion & rep()
Gets the internal expansion that represents this expansion_nt.
expansion_nt expansion_nt_sq_dist(const double *a, const double *b, coord_index_t dim)
Computes an expansion that represents the square distance between two points.
double component(index_t i) const
Gets the i-th component of this expansion.
~expansion_nt()
Expansion_nt destructor.
std::string to_string() const
Gets a string representation of this expansion.
expansion_nt expansion_nt_dot_at(const double *a, const double *b, const double *c, coord_index_t dim)
Computes an expansion that represents the dot product of two vectors determined by three points.
expansion_nt(expansion_nt &&rhs)
Move-constructor.
expansion_nt(Operation op, const expansion &x, const expansion &y, const expansion &z)
Constructs a new expansion_nt from three expansions.
expansion_nt()
Constructs an uninitialized expansion_nt.
expansion_nt(const expansion &rhs)
Constructs a new expansion_nt from an expansion.
void cleanup()
Cleanups the memory associated with this expansion_nt.
index_t length() const
Gets the length of this expansion.
void optimize()
Optimizes the internal representation without changing the represented value.
expansion_nt(Operation op, const expansion &x, const expansion &y)
Constructs a new expansion_nt from two expansions.
bool is_one() const
Tests whether an expansion_nt is equal to one.
Sign compare(const expansion_nt &rhs) const
Compares two expansion_nt.
expansion_nt(expansion *rep)
Constructs a new expansion_nt from an expansion.
expansion_nt(Operation op, double x, double y)
Constructs a new expansion_nt from two doubles.
expansion_nt(Operation op, const expansion &x, const expansion &y, const expansion &z, const expansion &t)
Constructs a new expansion_nt from four expansions.
Operation
This type is used by the constructor that takes two expansions.
expansion_nt(const expansion_nt &rhs)
Copy-constructor.
Sign compare(double rhs) const
Compares an expansion_nt with a double.
void negate()
Flips the sign of an expansion.
expansion_nt(double x)
Constructs a new expansion_nt from a double.
Represents numbers in arbitrary precision with a low-level API.
index_t length() const
Gets the length of this expansion.
bool equals(const expansion &rhs) const
Compares two expansions.
index_t capacity() const
Gets the capacity of 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 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 square_capacity(double a)
Computes the required capacity of an expansion to store the exact square of a double.
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.
static expansion * new_expansion_on_heap(index_t capa)
Allocates an expansion on the heap.
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)...
Sign sign() const
Gets the sign of the expansion.
rationalg (generic rational) is used to compute the sign of rational fractions exactly.
Definition rationalg.h:60
std::ostream & operator<<(std::ostream &os, const GEO::expansion_nt &a)
Displays the approximated value of an expansion_nt to a stream.
std::istream & operator>>(std::istream &is, GEO::expansion_nt &a)
Reads a double precision number from a stream and converts it to an approximation.
Common include file, providing basic definitions. Should be included before anything else by all head...
Generic matrix type.
Implementation of multi-precision arithmetics.
Sign ratio_compare(const T &a_num, const T &a_denom, const T &b_num, const T &b_denom)
Compares two rational numbers given as separate numerators and denominators.
Definition numeric.h:289
void optimize_number_representation(T &x)
place holder for optimizing internal number representation
Definition numeric.h:278
Global Vorpaline namespace.
Definition basic.h:55
bool expansion_nt_is_zero(const expansion_nt &x)
Tests whether an expansion_nt is zero.
Quaternion operator-(const Quaternion &a, const Quaternion &b)
Computes the difference between two Quaternion.
Definition quaternion.h:252
expansion_nt expansion_nt_determinant(const expansion_nt &a00, const expansion_nt &a01, const expansion_nt &a10, const expansion_nt &a11)
Computes a 2x2 determinant.
T det3x3(const T &a11, const T &a12, const T &a13, const T &a21, const T &a22, const T &a23, const T &a31, const T &a32, const T &a33)
Computes a three-by-three determinant.
Definition determinant.h:69
T det4x4(const T &a11, const T &a12, const T &a13, const T &a14, const T &a21, const T &a22, const T &a23, const T &a24, const T &a31, const T &a32, const T &a33, const T &a34, const T &a41, const T &a42, const T &a43, const T &a44)
Computes a four-by-four determinant.
Definition determinant.h:85
Sign geo_sgn(const T &x)
Gets the sign of a value.
Definition numeric.h:110
expansion_nt expansion_nt_square(const expansion_nt &x)
Computes the square of an expansion_nt.
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:340
Sign expansion_nt_compare(const expansion_nt &x, const expansion_nt &y)
Compares two expansion_nt.
Sign
Integer constants that represent the sign of a value.
Definition numeric.h:72
@ ZERO
Definition numeric.h:76
T det2x2(const T &a11, const T &a12, const T &a21, const T &a22)
Computes a two-by-two determinant.
Definition determinant.h:58
Sign geo_cmp(const T &a, const T &b)
Compares two values.
Definition numeric.h:92
bool expansion_nt_is_one(const expansion_nt &x)
Tests whether an expansion_nt is equal to one.
Quaternion operator+(const Quaternion &a, const Quaternion &b)
Computes the sum of two Quaternion.
Definition quaternion.h:239
geo_coord_index_t coord_index_t
The type for storing coordinate indices, and iterating on the coordinates of a point.
Definition numeric.h:374
Generic implementation of rational type.
type traits for scalars
Definition numeric.h:400