ARTS  2.3.1285(git:92a29ea9-dirty)
rational.h
Go to the documentation of this file.
1 /* Copyright (C) 2012
2 Richard Larsson <ric.larsson@gmail.com>
3 
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any
7 later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 USA. */
18 
27 #ifndef rational_h
28 #define rational_h
29 
30 #include <cassert>
31 #include <ostream>
32 #include "array.h"
33 #include "bifstream.h"
34 #include "bofstream.h"
35 #include "math_funcs.h"
36 #include "matpack.h"
37 
38 
45 constexpr Index gcd(Index a, Index b) {
46  if (b == 0)
47  return a;
48  else
49  return gcd(b, a%b);
50 }
51 
52 
54 class Rational {
55  public:
61  explicit constexpr Rational(const Index nom = 0, const Index denom = 1)
62  : mnom(denom ? nom : 0), mdenom(denom) {
63  const auto div = gcd(nom, denom);
64  if (div) {
65  mnom /= div;
66  mdenom /= div;
67  }
68  }
69 
82  explicit Rational(const String& s);
83 
85  constexpr Index Nom() const { return mnom; }
86 
88  constexpr Index Denom() const { return mdenom; }
89 
91  Index& Nom() { return mnom; }
92 
94  Index& Denom() { return mdenom; }
95 
97  void Nom(Index x) { mnom = x; }
98 
100  void Denom(Index x) { mdenom = x; }
101 
103  void simplify_in_place();
104 
110  constexpr bool isUndefined() const { return (mdenom == 0); }
111 
117  constexpr bool isDefined() const { return mdenom not_eq 0; }
118 
125  constexpr bool isIndex(int n=1) const {
126  return isDefined() and not bool((n*mnom) % mdenom);
127  }
128 
136  constexpr Index toIndex(int n=1) const {
137  return isIndex(n) ? (n*mnom) / mdenom
138  : throw std::logic_error(
139  "Rational is not representative of an integer");
140  }
141 
146  constexpr Numeric toNumeric() const {
147  return Numeric(mnom) / Numeric(mdenom);
148  }
149 
157  constexpr int toInt(int n=1) const { return int(toIndex(n)); }
158 
165  mnom = mnom * a.Denom() + a.Nom() * mdenom;
166  mdenom *= a.Denom();
167  return *this;
168  }
169 
175  Rational& operator+=(const Index& a) {
176  mnom += mdenom * a;
177  return *this;
178  }
179 
186  mnom = mnom * a.Denom() - a.Nom() * mdenom;
187  mdenom *= a.Denom();
188  return *this;
189  }
190 
196  Rational& operator-=(const Index& a) {
197  mnom -= mdenom * a;
198  return *this;
199  }
200 
207  mnom *= a.Denom();
208  mdenom *= a.Nom();
209  return *this;
210  }
211 
217  Rational& operator/=(const Index& a) {
218  mdenom *= a;
219  return *this;
220  }
221 
228  mnom *= a.Nom();
229  mdenom *= a.Denom();
230  return *this;
231  }
232 
238  Rational& operator*=(const Index& a) {
239  mnom *= a;
240  return *this;
241  }
242 
244  constexpr Rational operator++(int) const {
245  return isDefined()
246  ? Rational(mnom + mdenom, mdenom)
247  : throw std::logic_error("Undefined Rational in operator++");
248  }
249 
251  constexpr Rational operator--(int) const {
252  return isDefined()
253  ? Rational(mnom - mdenom, mdenom)
254  : throw std::logic_error("Undefined Rational in operator--");
255  }
256 
259  mnom += mdenom;
260  return *this;
261  }
262 
265  mnom -= mdenom;
266  return *this;
267  }
268 
270  explicit constexpr operator bool() const {
271  return isDefined() and bool(mnom);
272  }
273 
275  explicit constexpr operator Numeric() const { return toNumeric(); }
276 
278  explicit constexpr operator Index() const { return toIndex(); }
279 
281  explicit constexpr operator int() const { return toInt(); }
282 
285  bif >> mnom >> mdenom;
286  return bif;
287  }
288 
290  bofstream& write(bofstream& bof) const {
291  bof << mnom << mdenom;
292  return bof;
293  }
294 
296  constexpr Rational& fixSign() {
297  if (mdenom < 0) {
298  mnom = -mnom;
299  mdenom = -mdenom;
300  }
301  return *this;
302  }
303 
304  private:
305  // Rational is supposed to be used rationally ( mnom / mdenom )
308 }; // Rational;
309 
315 constexpr Rational reduce_by_gcd(const Rational a) {
316  const Index div = gcd(a.Nom(), a.Denom());
317  if (div)
318  return Rational(a.Nom() / div, a.Denom() / div);
319  else
320  return a;
321 }
322 
330 constexpr Rational numeric2rational(Numeric x, size_t maxdec=4) {
331  Index nom=0, denom=1;
332 
333  // Keep track of sign independently
334  const bool signchange = x < 0;
335  x = x < 0 ? -x : x;
336 
337  // Add numbers by keeping the floor
338  size_t i=0;
339  do {
340  const Index xi=Index(x);
341  nom += xi;
342  x = 10 * (x - Numeric(xi));
343  nom *= 10;
344  denom *= 10;
345  i++;
346  } while (i<=maxdec);
347 
348  // Fix possible rounding error
349  if (x >= 5)
350  nom += 10;
351 
352  // Change sign or not
353  if (signchange)
354  return Rational(-nom, denom);
355  else
356  return Rational(nom, denom);
357 }
358 
359 
360 // An undefined rational to be used everywhere for a undefined rationals
361 #define RATIONAL_UNDEFINED Rational(0, 0)
362 
368 constexpr Rational operator-(const Rational a) {
369  return Rational(-a.Nom(), a.Denom());
370 }
371 
377 constexpr Rational operator+(const Rational a) { return a; }
378 
385 constexpr Rational operator+(const Rational a, const Rational b) {
386  return (a.Denom() == b.Denom())
387  ? Rational(a.Nom() + b.Nom(), a.Denom())
388  : Rational(a.Nom() * b.Denom() + b.Nom() * a.Denom(),
389  a.Denom() * b.Denom());
390 }
391 
398 constexpr Rational operator+(const Rational a, Index b) {
399  return Rational(a.Nom() + b * a.Denom(), a.Denom());
400 }
401 
408 constexpr Rational operator+(Index b, const Rational a) { return operator+(a, b); }
409 
416 constexpr Rational operator-(const Rational a, const Rational b) {
417  return (a.Denom() == b.Denom())
418  ? Rational(a.Nom() - b.Nom(), a.Denom())
419  : Rational(a.Nom() * b.Denom() - b.Nom() * a.Denom(),
420  a.Denom() * b.Denom());
421 }
422 
429 constexpr Rational operator-(const Rational a, Index b) {
430  return Rational(a.Nom() - b * a.Denom(), a.Denom());
431 }
432 
439 constexpr Rational operator-(Index b, const Rational a) {
440  return Rational(-a.Nom() + b * a.Denom(), a.Denom());
441 }
442 
449 constexpr Rational operator/(const Rational a, const Rational b) {
450  return Rational(a.Nom() * b.Denom(), a.Denom() * b.Nom());
451 }
452 
459 constexpr Rational operator/(const Rational a, Index b) {
460  return Rational(a.Nom(), a.Denom() * b);
461 }
462 
469 constexpr Rational operator/(Index b, const Rational a) {
470  return Rational(a.Denom() * b, a.Nom());
471 }
472 
479 constexpr Rational operator*(const Rational a, const Rational b) {
480  return Rational(a.Nom() * b.Nom(), a.Denom() * b.Denom());
481 }
482 
489 constexpr Rational operator*(const Rational a, Index b) {
490  return Rational(a.Nom() * b, a.Denom());
491 }
492 
499 constexpr Rational operator*(Index b, const Rational a) { return operator*(a, b); }
500 
507 constexpr Rational operator%(const Rational a, const Rational b) {
508  return (a.Denom() == b.Denom())
509  ? Rational(a.Nom() % b.Nom(), a.Denom())
510  : Rational((a.Nom() * b.Denom()) % (a.Denom() * b.Nom()),
511  a.Denom() * b.Denom());
512 }
513 
520 constexpr Rational operator%(const Rational a, Index b) {
521  return Rational(a.Nom() % (a.Denom() * b), a.Denom());
522 }
523 
530 constexpr Rational operator%(Index b, const Rational a) {
531  return Rational((b * a.Denom()) % a.Nom(), a.Denom());
532 }
533 
541 constexpr bool operator==(const Rational a, const Rational b) {
542  return a.isDefined() and b.isDefined() and
543  a.Nom() * b.Denom() == a.Denom() * b.Nom();
544 }
545 
553 constexpr bool operator!=(Rational a, Rational b) {
554  return not operator==(a, b);
555 }
556 
564 constexpr bool operator<(Rational a, Rational b) {
565  return a.isDefined() and b.isDefined() and
566  a.Nom() * b.Denom() < a.Denom() * b.Nom();
567 }
568 
576 constexpr bool operator>(Rational a, Rational b) { return operator<(b, a); }
577 
585 constexpr bool operator<=(Rational a, Rational b) {
586  return not operator>(a, b);
587 }
588 
596 constexpr bool operator>=(const Rational a, const Rational b) {
597  return not operator<(a, b);
598 }
599 
606 constexpr bool operator!(const Rational a) { return a.Nom() and a.isDefined(); }
607 
613 inline Numeric fac(const Rational r) { return (::fac(r.toIndex())); }
614 
620 inline Numeric sqrt(const Rational r) { return std::sqrt(r.toNumeric()); }
621 
628 inline Numeric pow(const Rational base, Numeric exp) {
629  return std::pow(base.toNumeric(), exp);
630 }
631 
638 inline Numeric pow(Numeric base, const Rational exp) {
639  return std::pow(base, exp.toNumeric());
640 }
641 
648 inline Numeric pow(const Rational base, const Rational exp) {
649  return pow(base, exp.toNumeric());
650 }
651 
653 std::ostream& operator<<(std::ostream& os, const Rational& a);
654 
656 std::istream& operator>>(std::istream& is, Rational& a);
657 
664 constexpr bool operator<(const Index a, const Rational b) {
665  return Rational(a, 1) < b;
666 }
667 
674 constexpr bool operator<(const Rational a, const Index b) {
675  return a < Rational(b, 1);
676 }
677 
684 constexpr bool operator>(const Index a, const Rational b) {
685  return Rational(a, 1) > b;
686 }
687 
694 constexpr bool operator>(const Rational a, const Index b) {
695  return a > Rational(b, 1);
696 }
697 
704 constexpr bool operator==(const Rational a, const Index b) {
705  return a == Rational(b, 1);
706 }
707 
714 constexpr bool operator!=(const Rational a, const Index b) {
715  return not(a == b);
716 }
717 
723 constexpr Rational abs(const Rational a) {
724  return a < 0 ? -a : a;
725 }
726 
733 constexpr Rational max(const Rational a, const Rational b) {
734  return a < b ? b : a;
735 } // Let other operators find out if this is allowed instead
736 
738 
744 constexpr Rational operator ""_2(unsigned long long int n) {
745  return Rational(n, 2);
746 };
747 
753 constexpr Rational operator ""_rat(unsigned long long int n) {
754  return Rational(n, 1);
755 };
756 
762 constexpr bool even(const Rational r) {
763  if (r % 2)
764  return false;
765  else
766  return true;
767 }
768 
769 #endif // rational_h
770 
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
constexpr bool operator<=(Rational a, Rational b)
Less than or equal to.
Definition: rational.h:585
constexpr bool operator==(const Rational a, const Rational b)
Equality.
Definition: rational.h:541
Rational & operator/=(const Index &a)
Divide by this.
Definition: rational.h:217
constexpr bool operator>=(const Rational a, const Rational b)
More than or equal to.
Definition: rational.h:596
constexpr bool operator<(Rational a, Rational b)
Less than.
Definition: rational.h:564
std::ostream & operator<<(std::ostream &os, const Rational &a)
Output operator.
Definition: rational.cc:33
constexpr Rational operator%(const Rational a, const Rational b)
Remainder.
Definition: rational.h:507
constexpr bool operator>(Rational a, Rational b)
More than.
Definition: rational.h:576
Rational & operator+=(const Index &a)
Add to this.
Definition: rational.h:175
void Denom(Index x)
Denominator.
Definition: rational.h:100
Rational & operator*=(const Rational &a)
Multiply by this.
Definition: rational.h:227
constexpr Rational abs(const Rational a)
Absolute.
Definition: rational.h:723
Index & Denom()
Denominator.
Definition: rational.h:94
constexpr Index Nom() const
Nominator.
Definition: rational.h:85
constexpr Rational operator--(int) const
Remove one if possible.
Definition: rational.h:251
constexpr Rational(const Index nom=0, const Index denom=1)
Initialization call.
Definition: rational.h:61
Index mnom
Definition: rational.h:306
bifstream & read(bifstream &bif)
Binary read for Rational.
Definition: rational.h:284
constexpr Index gcd(Index a, Index b)
Returns the greatest common denominator of two numbers.
Definition: rational.h:45
constexpr Rational max(const Rational a, const Rational b)
Maximum.
Definition: rational.h:733
Rational & operator/=(const Rational &a)
Divide by this.
Definition: rational.h:206
Rational & operator++()
Add one if possible.
Definition: rational.h:258
Rational & operator+=(const Rational &a)
Add to this.
Definition: rational.h:164
bofstream & write(bofstream &bof) const
Binary write for Rational.
Definition: rational.h:290
constexpr Rational reduce_by_gcd(const Rational a)
Returns the rational reduced by the greates.
Definition: rational.h:315
Index mdenom
Definition: rational.h:307
constexpr Rational & fixSign()
Makes the sign of mdenom positive.
Definition: rational.h:296
Rational & operator--()
Remove one if possible.
Definition: rational.h:264
This file contains the definition of Array.
Index & Nom()
Nominator.
Definition: rational.h:91
constexpr bool operator!=(Rational a, Rational b)
Inequality.
Definition: rational.h:553
Array< Rational > ArrayOfRational
Definition: rational.h:737
constexpr Rational operator*(const Rational a, const Rational b)
Multiplication.
Definition: rational.h:479
constexpr bool isDefined() const
Is the object defined.
Definition: rational.h:117
Binary output file stream class.
Definition: bifstream.h:42
Implements rational numbers to work with other ARTS types.
Definition: rational.h:54
This file contains the class declaration of bifstream.
This file contains the class declaration of bofstream.
constexpr Index toIndex(int n=1) const
Converts the value to index by n-scaled division.
Definition: rational.h:136
constexpr Index Denom() const
Denominator.
Definition: rational.h:88
Rational & operator-=(const Rational &a)
Remove from this.
Definition: rational.h:185
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
constexpr Rational operator+(const Rational a)
Positive.
Definition: rational.h:377
std::istream & operator>>(std::istream &is, Rational &a)
Input operator.
Definition: rational.cc:44
constexpr Numeric toNumeric() const
Converts this to a Numeric.
Definition: rational.h:146
Numeric pow(const Rational base, Numeric exp)
Power of.
Definition: rational.h:628
This can be used to make arrays out of anything.
Definition: array.h:40
Rational & operator-=(const Index &a)
Remove from this.
Definition: rational.h:196
Numeric fac(const Rational r)
Factorial.
Definition: rational.h:613
constexpr Rational numeric2rational(Numeric x, size_t maxdec=4)
Rational from Numeric.
Definition: rational.h:330
constexpr bool isUndefined() const
Is the object not defined.
Definition: rational.h:110
Binary output file stream class.
Definition: bofstream.h:42
constexpr bool operator!(const Rational a)
Not.
Definition: rational.h:606
Rational & operator*=(const Index &a)
Multiply by this.
Definition: rational.h:238
constexpr Rational operator/(const Rational a, const Rational b)
Division.
Definition: rational.h:449
constexpr bool even(const Rational r)
Returns true if even integer.
Definition: rational.h:762
void Nom(Index x)
Nominator.
Definition: rational.h:97
constexpr int toInt(int n=1) const
Converts the value to int by n-scaled division in Index form.
Definition: rational.h:157
constexpr Rational operator-(const Rational a)
Negative.
Definition: rational.h:368
constexpr bool isIndex(int n=1) const
Is the object a n-scaled Index.
Definition: rational.h:125
void simplify_in_place()
Simplify by reducing the values locally.
Definition: rational.cc:104
constexpr Rational operator++(int) const
Add one if possible.
Definition: rational.h:244
Numeric sqrt(const Rational r)
Square root.
Definition: rational.h:620