Geogram  Version 1.9.1
A programming library of geometric algorithms
rationalg.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2000-2023 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_BASIC_RATIONALG
41 #define GEOGRAM_BASIC_RATIONALG
42 
43 #include <geogram/basic/common.h>
44 
50 namespace GEO {
51 
59  template <class T> class rationalg {
60  public:
61  typedef T value_type;
62 
63  rationalg() = default;
64 
69  explicit rationalg(double x) : num_(x), denom_(1.0) {
70  }
71 
76  explicit rationalg(const T& x) : num_(x), denom_(1.0) {
77  }
78 
84  explicit rationalg(T&& x) : num_(x), denom_(1.0) {
85  }
86 
92  explicit rationalg(double num, double denom)
93  : num_(num), denom_(denom) {
94  }
95 
101  explicit rationalg(const T& num, const T& denom)
102  : num_(num), denom_(denom) {
103  }
104 
111  explicit rationalg(
112  T&& num, T&& denom
113  ) : num_(num), denom_(denom) {
114  }
115 
120  rationalg(const rationalg<T>& rhs) = default;
121 
126  rationalg(rationalg<T>&& rhs) = default;
127 
133  rationalg<T>& operator= (const rationalg<T>& rhs) = default;
134 
141 
146  const T& num() const {
147  return num_;
148  }
149 
154  const T& denom() const {
155  return denom_;
156  }
157 
162  T& num() {
163  return num_;
164  }
165 
170  T& denom() {
171  return denom_;
172  }
173 
178  void optimize() {
181  }
182 
183  /********************************************************************/
184 
191  if(has_same_denom(rhs)) {
192  num_ += rhs.num_;
193  } else {
194  num_ = num_ * rhs.denom_ + rhs.num_ * denom_;
195  denom_ *= rhs.denom_;
196  }
197  return *this;
198  }
199 
206  if(has_same_denom(rhs)) {
207  num_ -= rhs.num_;
208  } else {
209  num_ = num_ * rhs.denom_ - rhs.num_ * denom_;
210  denom_ *= rhs.denom_;
211  }
212  return *this;
213  }
214 
221  num_ *= rhs.num_;
222  denom_ *= rhs.denom_;
223  return *this;
224  }
225 
232  num_ *= rhs.denom_;
233  denom_ *= rhs.num_;
234  return *this;
235  }
236 
242  rationalg<T>& operator+= (double rhs) {
243  num_ += denom_ * T(rhs);
244  return *this;
245  }
246 
252  rationalg<T>& operator-= (double rhs) {
253  num_ -= denom_ * T(rhs);
254  return *this;
255  }
256 
265  rationalg<T>& operator*= (double rhs) {
266  num_ *= T(rhs);
267  return *this;
268  }
269 
278  rationalg<T>& operator/= (double rhs) {
279  denom_ *= T(rhs);
280  return *this;
281  }
282 
283  /********************************************************************/
284 
291  if(has_same_denom(rhs)) {
292  return rationalg(
293  num_ + rhs.num_,
294  denom_
295  );
296  }
297  return rationalg(
298  num_ * rhs.denom_ + rhs.num_ * denom_,
299  denom_ * rhs.denom_
300  );
301  }
302 
310  if(has_same_denom(rhs)) {
311  return rationalg(
312  num_ - rhs.num_,
313  denom_
314  );
315  }
316  return rationalg(
317  num_ * rhs.denom_ - rhs.num_ * denom_,
318  denom_ * rhs.denom_
319  );
320  }
321 
329  return rationalg(
330  num_ * rhs.num_,
331  denom_ * rhs.denom_
332  );
333  }
334 
342  return rationalg(
343  num_ * rhs.denom_,
344  denom_ * rhs.num_
345  );
346  }
347 
348 
354  rationalg<T> operator+ (double rhs) const {
355  return rationalg(
356  num_ + T(rhs) * denom_,
357  denom_
358  );
359  }
360 
366  rationalg<T> operator- (double rhs) const {
367  return rationalg(
368  num_ - T(rhs) * denom_,
369  denom_
370  );
371  }
372 
378  rationalg<T> operator* (double rhs) const {
379  return rationalg(
380  num_ * T(rhs),
381  denom_
382  );
383  }
384 
390  rationalg<T> operator/ (double rhs) const {
391  return rationalg(
392  num_,
393  denom_* T(rhs)
394  );
395  }
396 
397  /********************************************************************/
398 
404  return rationalg(
405  -num_,
406  denom_
407  );
408  }
409 
410  /********************************************************************/
411 
416  Sign sign() const {
417  geo_debug_assert(denom_.sign() != ZERO);
418  return Sign(num_.sign() * denom_.sign());
419  }
420 
421  /********************************************************************/
422 
427  Sign compare(const rationalg<T>& rhs) const {
428  if(sign() != rhs.sign()){
429  return Sign(sign()-rhs.sign());
430  }
431  if(has_same_denom(rhs)) {
432  return Sign(num_.compare(rhs.num_) * denom_.sign());
433  }
434  return Sign(
435  (num_ * rhs.denom_).compare(rhs.num_ * denom_) *
436  denom_.sign() * rhs.denom_.sign()
437  );
438  }
439 
444  Sign compare(double rhs) const {
445  return Sign(
446  num_.compare(T(rhs)*denom_) * denom_.sign()
447  );
448  }
449 
457  bool operator> (const rationalg<T>& rhs) const {
458  return (int(compare(rhs))>0);
459  }
460 
468  bool operator>= (const rationalg<T>& rhs) const {
469  return (int(compare(rhs))>=0);
470  }
471 
479  bool operator< (const rationalg<T>& rhs) const {
480  return (int(compare(rhs))<0);
481  }
482 
490  bool operator<= (const rationalg<T>& rhs) const {
491  return (int(compare(rhs))<=0);
492  }
493 
501  bool operator> (double rhs) const {
502  return (int(compare(rhs))>0);
503  }
504 
512  bool operator>= (double rhs) const {
513  return (int(compare(rhs))>=0);
514  }
515 
523  bool operator< (double rhs) const {
524  return (int(compare(rhs))<0);
525  }
526 
534  bool operator<= (double rhs) const {
535  return (int(compare(rhs))<=0);
536  }
537 
538  /********************************************************************/
539 
545  double estimate() const {
546  return num_.estimate() / denom_.estimate();
547  }
548 
549  protected:
554  void copy(const rationalg<T>& rhs) {
555  num_ = rhs.num_;
556  denom_ = rhs.denom_;
557  }
558 
569  bool has_same_denom(const rationalg<T>& rhs) const {
570  return denom_ == rhs.denom_;
571  }
572 
573  private:
574  T num_;
575  T denom_;
576  };
577 
578  /**************************************************************************/
579 
587  template <class T>
588  inline rationalg<T> operator+ (double a, const rationalg<T>& b) {
589  return b + a;
590  }
591 
599  template <class T>
600  inline rationalg<T> operator- (double a, const rationalg<T>& b) {
601  rationalg<T> result = b - a;
602  result.num().negate();
603  return result;
604  }
605 
613  template <class T>
614  inline rationalg<T> operator* (double a, const rationalg<T>& b) {
615  return b * a;
616  }
617 
625  template <class T>
626  inline rationalg<T> operator/ (double a, const rationalg<T>& b) {
627  return rationalg<T>(
628  T(a)*b.denom(),
629  b.num()
630  );
631  }
632 
641  template <class T>
642  inline bool operator== (const rationalg<T>& a, const rationalg<T>& b) {
643  return (a.compare(b) == ZERO);
644  }
645 
654  template <class T>
655  inline bool operator== (const rationalg<T>& a, double b) {
656  return (a.compare(b) == ZERO);
657  }
658 
667  template <class T>
668  inline bool operator== (double a, const rationalg<T>& b) {
669  return (b.compare(a) == ZERO);
670  }
671 
680  template <class T>
681  inline bool operator!= (const rationalg<T>& a, const rationalg<T>& b) {
682  return (a.compare(b) != ZERO);
683  }
684 
693  template <class T>
694  inline bool operator!= (const rationalg<T>& a, double b) {
695  return (a.compare(b) != ZERO);
696  }
697 
706  template <class T>
707  inline bool operator!= (double a, const rationalg<T>& b) {
708  return (b.compare(a) != ZERO);
709  }
710 
711  /**************************************************************************/
712 
718  template <class T> inline Sign geo_sgn(const rationalg<T>& x) {
719  return x.sign();
720  }
721 
729  template <class T> inline Sign geo_cmp(
730  const rationalg<T>& a, const rationalg<T>& b
731  ) {
732  return a.compare(b);
733  }
734 
735  namespace Numeric {
736 
737  template <class T> inline void optimize_number_representation(
738  rationalg<T>& x
739  ) {
740  x.optimize();
741  }
742 
743  }
744 
745  /**************************************************************************/
746 
747 }
748 
749 #endif
#define geo_debug_assert(x)
Verifies that a condition is met.
Definition: assert.h:196
rationalg (generic rational) is used to compute the sign of rational fractions exactly.
Definition: rationalg.h:59
rationalg< T > operator/(const rationalg< T > &rhs) const
Computes the ratio between two rationalgs.
Definition: rationalg.h:341
rationalg(const T &x)
Constructs a new rationalg from an T.
Definition: rationalg.h:76
Sign sign() const
Gets the sign of a rationalg.
Definition: rationalg.h:416
rationalg(const T &num, const T &denom)
Constructs a new rationalg from two T.
Definition: rationalg.h:101
rationalg< T > & operator/=(const rationalg< T > &rhs)
Divides this rationalg by a rationalg.
Definition: rationalg.h:231
bool operator<=(const rationalg< T > &rhs) const
Compares this rationalg with another one.
Definition: rationalg.h:490
bool operator>=(const rationalg< T > &rhs) const
Compares this rationalg with another one.
Definition: rationalg.h:468
const T & num() const
gets the numerator.
Definition: rationalg.h:146
T & denom()
gets the denominator.
Definition: rationalg.h:170
rationalg(T &&x)
Constructs a new rationalg from an T with move semantics.
Definition: rationalg.h:84
rationalg< T > & operator-=(const rationalg< T > &rhs)
Subtracts a rationalg to this rationalg.
Definition: rationalg.h:205
rationalg< T > & operator+=(const rationalg< T > &rhs)
Adds a rationalg to this rationalg.
Definition: rationalg.h:190
rationalg< T > & operator*=(const rationalg< T > &rhs)
Multiplies this rationalg by a rationalg.
Definition: rationalg.h:220
Sign compare(double rhs) const
Compares a rationalg with a double.
Definition: rationalg.h:444
void copy(const rationalg< T > &rhs)
Copies a rational into this one.
Definition: rationalg.h:554
rationalg(double x)
Constructs a new rationalg from a double.
Definition: rationalg.h:69
rationalg(T &&num, T &&denom)
Constructs a new rationalg from two T with move semantics.
Definition: rationalg.h:111
bool has_same_denom(const rationalg< T > &rhs) const
Tests whether a rationalg has trivially the same denominator this rationalg.
Definition: rationalg.h:569
rationalg< T > operator-() const
Computes the opposite of this rationalg.
Definition: rationalg.h:403
Sign compare(const rationalg< T > &rhs) const
Compares two rationalg.
Definition: rationalg.h:427
rationalg< T > operator+(const rationalg< T > &rhs) const
Computes the sum of two rationalgs.
Definition: rationalg.h:290
rationalg< T > operator*(const rationalg< T > &rhs) const
Computes the product between two rationalgs.
Definition: rationalg.h:328
T & num()
gets the numerator.
Definition: rationalg.h:162
double estimate() const
Computes an approximation of the stored value in this rational.
Definition: rationalg.h:545
rationalg(rationalg< T > &&rhs)=default
Move-constructor.
rationalg(double num, double denom)
Constructs a new rationalg from two doubles.
Definition: rationalg.h:92
const T & denom() const
gets the denominator.
Definition: rationalg.h:154
rationalg< T > & operator=(const rationalg< T > &rhs)=default
Assignment operator.
bool operator>(const rationalg< T > &rhs) const
Compares this rationalg with another one.
Definition: rationalg.h:457
rationalg(const rationalg< T > &rhs)=default
Copy-constructor.
void optimize()
Optimizes the internal representation without changing the represented value.
Definition: rationalg.h:178
bool operator<(const rationalg< T > &rhs) const
Compares this rationalg with another one.
Definition: rationalg.h:479
Common include file, providing basic definitions. Should be included before anything else by all head...
bool operator!=(const aligned_allocator< T1, A1 > &, const aligned_allocator< T2, A2 > &)
Tests whether two aligned_allocators are different.
Definition: memory.h:617
bool operator==(const aligned_allocator< T1, A1 > &, const aligned_allocator< T2, A2 > &)
Tests whether two aligned_allocators are equal.
Definition: memory.h:606
void optimize_number_representation(T &x)
place holder for optimizing internal number representation
Definition: numeric.h:267
Global Vorpaline namespace.
Definition: basic.h:55
Quaternion operator-(const Quaternion &a, const Quaternion &b)
Computes the difference between two Quaternion.
Definition: quaternion.h:252
Sign geo_sgn(const T &x)
Gets the sign of a value.
Definition: numeric.h:90
Sign
Integer constants that represent the sign of a value.
Definition: numeric.h:68
@ ZERO
Definition: numeric.h:72
Sign geo_cmp(const T &a, const T &b)
Compares two values.
Definition: numeric.h:106
Quaternion operator+(const Quaternion &a, const Quaternion &b)
Computes the sum of two Quaternion.
Definition: quaternion.h:239