MLIR  19.0.0git
Fraction.h
Go to the documentation of this file.
1 //===- Fraction.h - MLIR Fraction Class -------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This is a simple class to represent fractions. It supports arithmetic,
10 // comparison, floor, and ceiling operations.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_ANALYSIS_PRESBURGER_FRACTION_H
15 #define MLIR_ANALYSIS_PRESBURGER_FRACTION_H
16 
19 
20 namespace mlir {
21 namespace presburger {
22 
23 /// A class to represent fractions. The sign of the fraction is represented
24 /// in the sign of the numerator; the denominator is always positive.
25 ///
26 /// Note that overflows may occur if the numerator or denominator are not
27 /// representable by 64-bit integers.
28 struct Fraction {
29  /// Default constructor initializes the represented rational number to zero.
30  Fraction() = default;
31 
32  /// Construct a Fraction from a numerator and denominator.
33  Fraction(const MPInt &oNum, const MPInt &oDen = MPInt(1))
34  : num(oNum), den(oDen) {
35  if (den < 0) {
36  num = -num;
37  den = -den;
38  }
39  }
40  /// Overloads for passing literals.
41  Fraction(const MPInt &num, int64_t den) : Fraction(num, MPInt(den)) {}
42  Fraction(int64_t num, const MPInt &den = MPInt(1))
43  : Fraction(MPInt(num), den) {}
44  Fraction(int64_t num, int64_t den) : Fraction(MPInt(num), MPInt(den)) {}
45 
46  // Return the value of the fraction as an integer. This should only be called
47  // when the fraction's value is really an integer.
48  MPInt getAsInteger() const {
49  assert(num % den == 0 && "Get as integer called on non-integral fraction!");
50  return num / den;
51  }
52 
53  llvm::raw_ostream &print(llvm::raw_ostream &os) const {
54  return os << "(" << num << "/" << den << ")";
55  }
56 
57  /// The numerator and denominator, respectively. The denominator is always
58  /// positive.
59  MPInt num{0}, den{1};
60 };
61 
62 /// Three-way comparison between two fractions.
63 /// Returns +1, 0, and -1 if the first fraction is greater than, equal to, or
64 /// less than the second fraction, respectively.
65 inline int compare(const Fraction &x, const Fraction &y) {
66  MPInt diff = x.num * y.den - y.num * x.den;
67  if (diff > 0)
68  return +1;
69  if (diff < 0)
70  return -1;
71  return 0;
72 }
73 
74 inline MPInt floor(const Fraction &f) { return floorDiv(f.num, f.den); }
75 
76 inline MPInt ceil(const Fraction &f) { return ceilDiv(f.num, f.den); }
77 
78 inline Fraction operator-(const Fraction &x) { return Fraction(-x.num, x.den); }
79 
80 inline bool operator<(const Fraction &x, const Fraction &y) {
81  return compare(x, y) < 0;
82 }
83 
84 inline bool operator<=(const Fraction &x, const Fraction &y) {
85  return compare(x, y) <= 0;
86 }
87 
88 inline bool operator==(const Fraction &x, const Fraction &y) {
89  return compare(x, y) == 0;
90 }
91 
92 inline bool operator!=(const Fraction &x, const Fraction &y) {
93  return compare(x, y) != 0;
94 }
95 
96 inline bool operator>(const Fraction &x, const Fraction &y) {
97  return compare(x, y) > 0;
98 }
99 
100 inline bool operator>=(const Fraction &x, const Fraction &y) {
101  return compare(x, y) >= 0;
102 }
103 
104 inline Fraction abs(const Fraction &f) {
105  assert(f.den > 0 && "denominator of fraction must be positive!");
106  return Fraction(abs(f.num), f.den);
107 }
108 
109 inline Fraction reduce(const Fraction &f) {
110  if (f == Fraction(0))
111  return Fraction(0, 1);
112  MPInt g = gcd(abs(f.num), abs(f.den));
113  return Fraction(f.num / g, f.den / g);
114 }
115 
116 inline Fraction operator*(const Fraction &x, const Fraction &y) {
117  return reduce(Fraction(x.num * y.num, x.den * y.den));
118 }
119 
120 inline Fraction operator/(const Fraction &x, const Fraction &y) {
121  return reduce(Fraction(x.num * y.den, x.den * y.num));
122 }
123 
124 inline Fraction operator+(const Fraction &x, const Fraction &y) {
125  return reduce(Fraction(x.num * y.den + x.den * y.num, x.den * y.den));
126 }
127 
128 inline Fraction operator-(const Fraction &x, const Fraction &y) {
129  return reduce(Fraction(x.num * y.den - x.den * y.num, x.den * y.den));
130 }
131 
132 // Find the integer nearest to a given fraction.
133 inline MPInt round(const Fraction &f) {
134  MPInt rem = f.num % f.den;
135  return (f.num / f.den) + (rem > f.den / 2);
136 }
137 
138 inline Fraction &operator+=(Fraction &x, const Fraction &y) {
139  x = x + y;
140  return x;
141 }
142 
143 inline Fraction &operator-=(Fraction &x, const Fraction &y) {
144  x = x - y;
145  return x;
146 }
147 
148 inline Fraction &operator/=(Fraction &x, const Fraction &y) {
149  x = x / y;
150  return x;
151 }
152 
153 inline Fraction &operator*=(Fraction &x, const Fraction &y) {
154  x = x * y;
155  return x;
156 }
157 
158 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Fraction &x) {
159  x.print(os);
160  return os;
161 }
162 
163 } // namespace presburger
164 } // namespace mlir
165 
166 #endif // MLIR_ANALYSIS_PRESBURGER_FRACTION_H
This class provides support for multi-precision arithmetic.
Definition: MPInt.h:87
LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt gcd(const MPInt &a, const MPInt &b)
Definition: MPInt.h:399
llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const Fraction &x)
Definition: Fraction.h:158
MPInt round(const Fraction &f)
Definition: Fraction.h:133
Fraction & operator-=(Fraction &x, const Fraction &y)
Definition: Fraction.h:143
Fraction operator+(const Fraction &x, const Fraction &y)
Definition: Fraction.h:124
LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt ceilDiv(const MPInt &lhs, const MPInt &rhs)
Definition: MPInt.h:374
bool operator==(const Fraction &x, const Fraction &y)
Definition: Fraction.h:88
bool operator>(const Fraction &x, const Fraction &y)
Definition: Fraction.h:96
bool operator<(const Fraction &x, const Fraction &y)
Definition: Fraction.h:80
int compare(const Fraction &x, const Fraction &y)
Three-way comparison between two fractions.
Definition: Fraction.h:65
bool operator>=(const Fraction &x, const Fraction &y)
Definition: Fraction.h:100
Fraction reduce(const Fraction &f)
Definition: Fraction.h:109
Fraction operator-(const Fraction &x)
Definition: Fraction.h:78
bool operator<=(const Fraction &x, const Fraction &y)
Definition: Fraction.h:84
Fraction & operator*=(Fraction &x, const Fraction &y)
Definition: Fraction.h:153
Fraction abs(const Fraction &f)
Definition: Fraction.h:104
MPInt ceil(const Fraction &f)
Definition: Fraction.h:76
Fraction & operator/=(Fraction &x, const Fraction &y)
Definition: Fraction.h:148
bool operator!=(const Fraction &x, const Fraction &y)
Definition: Fraction.h:92
Fraction & operator+=(Fraction &x, const Fraction &y)
Definition: Fraction.h:138
Fraction operator*(const Fraction &x, const Fraction &y)
Definition: Fraction.h:116
MPInt floor(const Fraction &f)
Definition: Fraction.h:74
Fraction operator/(const Fraction &x, const Fraction &y)
Definition: Fraction.h:120
LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt floorDiv(const MPInt &lhs, const MPInt &rhs)
Definition: MPInt.h:382
Include the generated interface declarations.
A class to represent fractions.
Definition: Fraction.h:28
Fraction()=default
Default constructor initializes the represented rational number to zero.
MPInt getAsInteger() const
Definition: Fraction.h:48
Fraction(const MPInt &num, int64_t den)
Overloads for passing literals.
Definition: Fraction.h:41
Fraction(int64_t num, const MPInt &den=MPInt(1))
Definition: Fraction.h:42
Fraction(int64_t num, int64_t den)
Definition: Fraction.h:44
MPInt num
The numerator and denominator, respectively.
Definition: Fraction.h:59
llvm::raw_ostream & print(llvm::raw_ostream &os) const
Definition: Fraction.h:53
Fraction(const MPInt &oNum, const MPInt &oDen=MPInt(1))
Construct a Fraction from a numerator and denominator.
Definition: Fraction.h:33