MuseScore  3.4
Music composition and notation
fraction.h
Go to the documentation of this file.
1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2019 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12 
13 // everything contained in .h file for performance reasons
14 
15 #ifndef __FRACTION_H__
16 #define __FRACTION_H__
17 
18 #include "config.h"
19 #include "mscore.h"
20 
21 namespace Ms {
22 
23 //---------------------------------------------------------
24 // gcd
25 // greatest common divisor. always returns a positive val
26 // however, since int / uint = uint by C++ rules,
27 // return int to avoid accidental implicit unsigned cast
28 //---------------------------------------------------------
29 
30 static int_least64_t gcd(int_least64_t a, int_least64_t b)
31  {
32  int bp;
33  if (b > a) { bp = b; b = a; a = bp; } // Saves one % if true
34  while (b != 0) {
35  bp = b; b = a % b; a = bp;
36  }
37 
38  return (a >= 0 ? a : -a);
39  }
40 
41 
42 //---------------------------------------------------------
43 // Fraction
44 //---------------------------------------------------------
45 
46 class Fraction {
47 
48  // ensure 64 bit to avoid overflows in comparisons
49  int_least64_t _numerator { 0 };
50  int_least64_t _denominator { 1 };
51 
52  public:
53 
54 #if 0
55  // implicit conversion from int to Fraction: this is convenient but may hide some potential bugs
56  constexpr Fraction(int z=0, int n=1) : _numerator(z), _denominator(n) {}
57 #else
58  // no implicit conversion from int to Fraction:
59  constexpr Fraction() {}
60  constexpr Fraction(int z, int n) : _numerator { n < 0 ? -z : z }, _denominator { n < 0 ? -n : n } { }
61 #endif
62  int numerator() const { return _numerator; }
63  int denominator() const { return _denominator; }
64  int_least64_t& rnumerator() { return _numerator; }
65  int_least64_t& rdenominator() { return _denominator; }
66 
67  void setNumerator(int v) { _numerator = v; }
68  void setDenominator(int v) {
69  if (v < 0) { _numerator = -_numerator; _denominator = -v; }
70  else _denominator = v;
71  }
72  void set(int z, int n) {
73  if (n < 0) { _numerator = -z; _denominator = -n; }
74  else { _numerator = z; _denominator = n; }
75  }
76 
77  bool isZero() const { return _numerator == 0; }
78  bool isNotZero() const { return _numerator != 0; }
79 
80  bool isValid() const { return _denominator != 0; }
81 
82  // check if two fractions are identical (numerator & denominator)
83  // == operator checks for equal value:
84  bool identical(const Fraction& v) const {
85  return (_numerator == v._numerator) &&
87  }
88 
89  Fraction absValue() const {
90  return Fraction(qAbs(_numerator), _denominator); }
91 
92 
93  // --- reduction --- //
94 
95  void reduce()
96  {
97  const int g = gcd(_numerator, _denominator);
98  _numerator /= g; _denominator /= g;
99  }
100 
101  Fraction reduced() const
102  {
103  const int g = gcd(_numerator, _denominator);
104  return Fraction(_numerator / g, _denominator / g);
105  }
106 
107  // --- comparison --- //
108 
109  bool operator<(const Fraction& val) const
110  {
111  return _numerator * val._denominator < val._numerator * _denominator;
112  }
113 
114  bool operator<=(const Fraction& val) const
115  {
116  return _numerator * val._denominator <= val._numerator * _denominator;
117  }
118 
119  bool operator>=(const Fraction& val) const
120  {
121  return _numerator * val._denominator >= val._numerator * _denominator;
122  }
123 
124  bool operator>(const Fraction& val) const
125  {
126  return _numerator * val._denominator > val._numerator * _denominator;
127  }
128 
129  bool operator==(const Fraction& val) const
130  {
131  return _numerator * val._denominator == val._numerator * _denominator;
132  }
133 
134  bool operator!=(const Fraction& val) const
135  {
136  return _numerator * val._denominator != val._numerator * _denominator;
137  }
138 
139  // --- arithmetic --- //
140 
141  Fraction& operator+=(const Fraction& val)
142  {
143  if (_denominator == val._denominator)
144  _numerator += val._numerator; // Common enough use case to be handled separately for efficiency
145  else {
146  const int g = gcd(_denominator, val._denominator);
147  const int m1 = val._denominator / g; // This saves one division over straight lcm
148  _numerator = _numerator * m1 + val._numerator * (_denominator / g);
149  _denominator = m1 * _denominator;
150  }
151  return *this;
152  }
153 
154  Fraction& operator-=(const Fraction& val)
155  {
156  if (_denominator == val._denominator)
157  _numerator -= val._numerator; // Common enough use case to be handled separately for efficiency
158  else {
159  const int g = gcd(_denominator, val._denominator);
160  const int m1 = val._denominator / g; // This saves one division over straight lcm
161  _numerator = _numerator * m1 - val._numerator * (_denominator / g);
162  _denominator = m1 * _denominator;
163  }
164  return *this;
165  }
166 
167  Fraction& operator*=(const Fraction& val)
168  {
169  _numerator *= val._numerator;
170  _denominator *= val._denominator;
171  if (val._denominator != 1) reduce(); // We should be free to fully reduce here
172  return *this;
173  }
174 
175  Fraction& operator*=(int val)
176  {
177  _numerator *= val;
178  return *this;
179  }
180 
181  Fraction& operator/=(const Fraction& val)
182  {
183  const int sign = (val._numerator >= 0 ? 1 : -1);
184  _numerator *= (sign*val._denominator);
185  _denominator *= (sign*val._numerator);
186  if (val._numerator != sign) reduce();
187  return *this;
188  }
189 
190  #if 0
191  Fraction& operator/=(int val)
192  {
193  _denominator *= val;
194  return *this;
195  }
196  #endif
197 
198  Fraction operator+(const Fraction& v) const { return Fraction(*this) += v; }
199  Fraction operator-(const Fraction& v) const { return Fraction(*this) -= v; }
200  Fraction operator-() const { return Fraction(-_numerator, _denominator); }
201  Fraction operator*(const Fraction& v) const { return Fraction(*this) *= v; }
202  Fraction operator/(const Fraction& v) const { return Fraction(*this) /= v; }
203  // Fraction operator/(int v) const { return Fraction(*this) /= v; }
204 
205 
206  //---------------------------------------------------------
207  // fromTicks
208  //---------------------------------------------------------
209 
210  static Fraction fromTicks(int ticks)
211  {
212  if (ticks == -1)
213  return Fraction(-1,1); // HACK
214  return Fraction(ticks, MScore::division * 4).reduced();
215  }
216 
217  //---------------------------------------------------------
218  // eps
220  //---------------------------------------------------------
221 
222  static Fraction eps() { return Fraction(1, MScore::division * 4); }
223 
224  //---------------------------------------------------------
225  // ticks
226  //---------------------------------------------------------
227 
228  int ticks() const
229  {
230  if (_numerator == -1 && _denominator == 1) // HACK
231  return -1;
232 
233  // MScore::division - ticks per quarter note
234  // MScore::division * 4 - ticks per whole note
235  // result: rounded (MScore::division * 4 * _numerator * 1.0 / _denominator) value
236  const int sgn = (_numerator < 0) ? -1 : 1;
237  const auto result = sgn * (static_cast<int_least64_t>(sgn * _numerator) * MScore::division * 4 + (_denominator/2)) / _denominator;
238  return static_cast<int>(result);
239  }
240 
241 
242 
243  QString print() const { return QString("%1/%2").arg(_numerator).arg(_denominator); }
244  QString toString() const { return print(); }
245  static Fraction fromString(const QString& str) {
246  const int i = str.indexOf('/');
247  return (i == -1) ? Fraction(str.toInt(), 1) : Fraction(str.leftRef(i).toInt(), str.midRef(i+1).toInt());
248  }
249  operator QVariant() const { return QVariant::fromValue(*this); }
250  };
251 
252  inline Fraction operator*(const Fraction& f, int v) { return Fraction(f) *= v; }
253  inline Fraction operator*(int v, const Fraction& f) { return Fraction(f) *= v; }
254 
255 } // namespace Ms
256 
257 Q_DECLARE_METATYPE(Ms::Fraction);
258 
259 #endif
int numerator() const
Definition: fraction.h:62
Fraction reduced() const
Definition: fraction.h:101
Fraction operator/(const Fraction &v) const
Definition: fraction.h:202
int denominator() const
Definition: fraction.h:63
QString print() const
Definition: fraction.h:243
static Fraction fromTicks(int ticks)
Definition: fraction.h:210
Fraction & operator/=(const Fraction &val)
Definition: fraction.h:181
QString toString() const
Definition: fraction.h:244
bool operator<(const Fraction &val) const
Definition: fraction.h:109
bool isZero() const
Definition: fraction.h:77
Fraction & operator*=(const Fraction &val)
Definition: fraction.h:167
constexpr Fraction()
Definition: fraction.h:59
bool operator>(const Fraction &val) const
Definition: fraction.h:124
static Fraction fromString(const QString &str)
Definition: fraction.h:245
bool identical(const Fraction &v) const
Definition: fraction.h:84
int_least64_t _denominator
Definition: fraction.h:50
void setNumerator(int v)
Definition: fraction.h:67
void reduce()
Definition: fraction.h:95
bool operator<=(const Fraction &val) const
Definition: fraction.h:114
bool operator>=(const Fraction &val) const
Definition: fraction.h:119
constexpr Fraction(int z, int n)
Definition: fraction.h:60
bool operator!=(const Fraction &val) const
Definition: fraction.h:134
bool isNotZero() const
Definition: fraction.h:78
Definition: aeolus.cpp:26
Fraction operator-() const
Definition: fraction.h:200
Fraction operator*(const Fraction &v) const
Definition: fraction.h:201
Fraction operator-(const Fraction &v) const
Definition: fraction.h:199
Fraction & operator+=(const Fraction &val)
Definition: fraction.h:141
int_least64_t & rdenominator()
Definition: fraction.h:65
void setDenominator(int v)
Definition: fraction.h:68
int_least64_t & rnumerator()
Definition: fraction.h:64
Fraction & operator*=(int val)
Definition: fraction.h:175
static int division
Definition: mscore.h:357
int ticks() const
Definition: fraction.h:228
bool isValid() const
Definition: fraction.h:80
Definition: fraction.h:46
bool operator==(const Fraction &val) const
Definition: fraction.h:129
Fraction & operator-=(const Fraction &val)
Definition: fraction.h:154
Fraction absValue() const
Definition: fraction.h:89
int_least64_t _numerator
Definition: fraction.h:49
Fraction operator+(const Fraction &v) const
Definition: fraction.h:198
static Fraction eps()
A very small fraction, corresponds to 1 MIDI tick.
Definition: fraction.h:222