Skip to content

Commit 014912a

Browse files
[MLIR][Presburger] Fix reduce bug in Fraction class and add tests (#68298)
Modified `Fraction.reduce()` to work with negative fractions as well. Added tests to verify the implementation of arithmetic and relational operators on Fractions.
1 parent 98b114d commit 014912a

File tree

3 files changed

+61
-7
lines changed

3 files changed

+61
-7
lines changed

mlir/include/mlir/Analysis/Presburger/Fraction.h

+9-7
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,17 @@ struct Fraction {
3030
Fraction() = default;
3131

3232
/// Construct a Fraction from a numerator and denominator.
33-
Fraction(const MPInt &oNum, const MPInt &oDen = MPInt(1)) : num(oNum), den(oDen) {
33+
Fraction(const MPInt &oNum, const MPInt &oDen = MPInt(1))
34+
: num(oNum), den(oDen) {
3435
if (den < 0) {
3536
num = -num;
3637
den = -den;
3738
}
3839
}
3940
/// Overloads for passing literals.
4041
Fraction(const MPInt &num, int64_t den = 1) : Fraction(num, MPInt(den)) {}
41-
Fraction(int64_t num, const MPInt &den = MPInt(1)) : Fraction(MPInt(num), den) {}
42+
Fraction(int64_t num, const MPInt &den = MPInt(1))
43+
: Fraction(MPInt(num), den) {}
4244
Fraction(int64_t num, int64_t den) : Fraction(MPInt(num), MPInt(den)) {}
4345

4446
// Return the value of the fraction as an integer. This should only be called
@@ -102,7 +104,7 @@ inline bool operator>=(const Fraction &x, const Fraction &y) {
102104
inline Fraction reduce(const Fraction &f) {
103105
if (f == Fraction(0))
104106
return Fraction(0, 1);
105-
MPInt g = gcd(f.num, f.den);
107+
MPInt g = gcd(abs(f.num), abs(f.den));
106108
return Fraction(f.num / g, f.den / g);
107109
}
108110

@@ -122,22 +124,22 @@ inline Fraction operator-(const Fraction &x, const Fraction &y) {
122124
return reduce(Fraction(x.num * y.den - x.den * y.num, x.den * y.den));
123125
}
124126

125-
inline Fraction& operator+=(Fraction &x, const Fraction &y) {
127+
inline Fraction &operator+=(Fraction &x, const Fraction &y) {
126128
x = x + y;
127129
return x;
128130
}
129131

130-
inline Fraction& operator-=(Fraction &x, const Fraction &y) {
132+
inline Fraction &operator-=(Fraction &x, const Fraction &y) {
131133
x = x - y;
132134
return x;
133135
}
134136

135-
inline Fraction& operator/=(Fraction &x, const Fraction &y) {
137+
inline Fraction &operator/=(Fraction &x, const Fraction &y) {
136138
x = x / y;
137139
return x;
138140
}
139141

140-
inline Fraction& operator*=(Fraction &x, const Fraction &y) {
142+
inline Fraction &operator*=(Fraction &x, const Fraction &y) {
141143
x = x * y;
142144
return x;
143145
}

mlir/unittests/Analysis/Presburger/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
add_mlir_unittest(MLIRPresburgerTests
2+
FractionTest.cpp
23
IntegerPolyhedronTest.cpp
34
IntegerRelationTest.cpp
45
LinearTransformTest.cpp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include "mlir/Analysis/Presburger/Fraction.h"
2+
#include "./Utils.h"
3+
#include <gmock/gmock.h>
4+
#include <gtest/gtest.h>
5+
6+
using namespace mlir;
7+
using namespace presburger;
8+
9+
TEST(FractionTest, getAsInteger) {
10+
Fraction f(3, 1);
11+
EXPECT_EQ(f.getAsInteger(), MPInt(3));
12+
}
13+
14+
TEST(FractionTest, nearIntegers) {
15+
Fraction f(52, 14);
16+
17+
EXPECT_EQ(floor(f), 3);
18+
EXPECT_EQ(ceil(f), 4);
19+
}
20+
21+
TEST(FractionTest, reduce) {
22+
Fraction f(20, 35), g(-56, 63);
23+
EXPECT_EQ(f, Fraction(4, 7));
24+
EXPECT_EQ(g, Fraction(-8, 9));
25+
}
26+
27+
TEST(FractionTest, arithmetic) {
28+
Fraction f(3, 4), g(-2, 3);
29+
30+
EXPECT_EQ(f / g, Fraction(-9, 8));
31+
EXPECT_EQ(f * g, Fraction(-1, 2));
32+
EXPECT_EQ(f + g, Fraction(1, 12));
33+
EXPECT_EQ(f - g, Fraction(17, 12));
34+
35+
f /= g;
36+
EXPECT_EQ(f, Fraction(-9, 8));
37+
f *= g;
38+
EXPECT_EQ(f, Fraction(3, 4));
39+
f += g;
40+
EXPECT_EQ(f, Fraction(Fraction(1, 12)));
41+
f -= g;
42+
EXPECT_EQ(f, Fraction(3, 4));
43+
}
44+
45+
TEST(FractionTest, relational) {
46+
Fraction f(2, 5), g(3, 7);
47+
EXPECT_TRUE(f < g);
48+
EXPECT_FALSE(g < f);
49+
50+
EXPECT_EQ(f, Fraction(4, 10));
51+
}

0 commit comments

Comments
 (0)