1 /*
2 This file is part of LilyPond, the GNU music typesetter.
3
4 Copyright (C) 1997--2021 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef RATIONAL_HH
21 #define RATIONAL_HH
22
23 #include "compare.hh"
24 #include "flower-proto.hh"
25 #include "std-string.hh"
26 #include <limits.h>
27
28 /**
29 Rational numbers. Included is support for + and - infinity.
30 */
31 class Rational
32 {
33 /**
34 Sign of rational.
35 -2, .. 2
36
37 -2,2 is - and + infinity.
38 -1,1 is negative and positive.
39 0 if *this is zero.
40 */
41 int sign_;
42 U64 num_, den_;
43
44 private:
45 // n.b. can be used to intialize abnormally
Rational(int sign,U64 num,U64 den)46 constexpr Rational (int sign, U64 num, U64 den)
47 : sign_ (sign), num_ (num), den_ (den)
48 {
49 }
50
51 void normalize ();
52
53 public:
numerator() const54 I64 numerator () const { return sign_ * static_cast<I64> (num_); }
denominator() const55 I64 denominator () const { return static_cast<I64> (den_); }
num() const56 I64 num () const { return numerator (); }
den() const57 I64 den () const { return denominator (); }
58
59 // n.b. not valid for infinities
60 I64 trunc_int () const;
61 Rational trunc_rat () const;
62 Rational div_rat (Rational) const;
63 Rational mod_rat (Rational) const;
64 Rational abs () const;
65 void negate ();
66
operator bool() const67 explicit operator bool () const { return sign_ != 0; }
68 explicit operator double () const;
69
operator -() const70 constexpr Rational operator - () const { return { -sign_, num_, den_ }; }
71
72 // default to zero
Rational()73 constexpr Rational () : sign_ (0), num_ (1), den_ (1) {}
74
75 // positive infinity
infinity()76 static constexpr Rational infinity () { return { 2, 1, 1 }; }
77
78 // not-a-number
nan()79 static constexpr Rational nan () { return { 1, 0, 0 }; }
80
81 // Allow implicit conversion from integer. All of these must be defined or
82 // deleted to avoid ambiguity. "long long" is specified by the C++ standard
83 // to be at least 64 bits wide, which is what we are storing.
Rational(int n)84 Rational (int n) : Rational (static_cast<long long> (n)) {}
Rational(long n)85 Rational (long n) : Rational (static_cast<long long> (n)) {}
86 Rational (long long n);
Rational(unsigned n)87 Rational (unsigned n) : Rational (static_cast<unsigned long long> (n)) {}
Rational(unsigned long n)88 Rational (unsigned long n) : Rational (static_cast<unsigned long long> (n)) {}
89 Rational (unsigned long long);
90
91 // n.b. {0, 0} is treated as zero rather than NaN
92 explicit Rational (I64, I64);
93
94 explicit Rational (double);
95 Rational (Rational const &r) = default;
96 Rational &operator = (Rational const &r) = default;
97
98 Rational &operator *= (Rational);
99 Rational &operator /= (Rational);
100 Rational &operator += (Rational);
101 Rational &operator -= (Rational);
102 Rational &operator %= (Rational);
103 static int compare (Rational const &, Rational const &);
104 int sign () const;
105 std::string to_string () const;
106
107 // false for positive infinity, negative infinity, or not-a-number
isfinite(Rational const & r)108 friend bool isfinite (Rational const &r) { return r.den_ && !isinf (r); }
109
110 // true for positive or negative infinity
isinf(Rational const & r)111 friend bool isinf (Rational const &r) { return r.sign_ / 2; }
112
113 // true for not-a-number
isnan(Rational const & r)114 friend bool isnan (Rational const &r) { return !r.den_; }
115 };
116
117 #include "arithmetic-operator.hh"
118
119 IMPLEMENT_ARITHMETIC_OPERATOR (Rational, / );
120 IMPLEMENT_ARITHMETIC_OPERATOR (Rational, +);
121 IMPLEMENT_ARITHMETIC_OPERATOR (Rational, *);
122 IMPLEMENT_ARITHMETIC_OPERATOR (Rational, -);
123 IMPLEMENT_ARITHMETIC_OPERATOR (Rational, % );
124
125 INSTANTIATE_COMPARE (Rational const &, Rational::compare);
126
127 int compare (Rational const &, Rational const &);
128 int sign (Rational r);
129
130 inline std::string
to_string(Rational const & r)131 to_string (Rational const &r)
132 {
133 return r.to_string ();
134 }
135
136 #endif // RATIONAL_HH
137