170 lines
5.0 KiB
C++
170 lines
5.0 KiB
C++
//===- Fraction.h - MLIR Fraction Class -------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This is a simple class to represent fractions. It supports arithmetic,
|
|
// comparison, floor, and ceiling operations.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef MLIR_ANALYSIS_PRESBURGER_FRACTION_H
|
|
#define MLIR_ANALYSIS_PRESBURGER_FRACTION_H
|
|
|
|
#include "llvm/ADT/DynamicAPInt.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
namespace mlir {
|
|
namespace presburger {
|
|
using llvm::DynamicAPInt;
|
|
|
|
/// A class to represent fractions. The sign of the fraction is represented
|
|
/// in the sign of the numerator; the denominator is always positive.
|
|
///
|
|
/// Note that overflows may occur if the numerator or denominator are not
|
|
/// representable by 64-bit integers.
|
|
struct Fraction {
|
|
/// Default constructor initializes the represented rational number to zero.
|
|
Fraction() = default;
|
|
|
|
/// Construct a Fraction from a numerator and denominator.
|
|
Fraction(const DynamicAPInt &oNum, const DynamicAPInt &oDen = DynamicAPInt(1))
|
|
: num(oNum), den(oDen) {
|
|
if (den < 0) {
|
|
num = -num;
|
|
den = -den;
|
|
}
|
|
}
|
|
/// Overloads for passing literals.
|
|
Fraction(const DynamicAPInt &num, int64_t den)
|
|
: Fraction(num, DynamicAPInt(den)) {}
|
|
Fraction(int64_t num, const DynamicAPInt &den = DynamicAPInt(1))
|
|
: Fraction(DynamicAPInt(num), den) {}
|
|
Fraction(int64_t num, int64_t den)
|
|
: Fraction(DynamicAPInt(num), DynamicAPInt(den)) {}
|
|
|
|
// Return the value of the fraction as an integer. This should only be called
|
|
// when the fraction's value is really an integer.
|
|
DynamicAPInt getAsInteger() const {
|
|
assert(num % den == 0 && "Get as integer called on non-integral fraction!");
|
|
return num / den;
|
|
}
|
|
|
|
llvm::raw_ostream &print(llvm::raw_ostream &os) const {
|
|
return os << "(" << num << "/" << den << ")";
|
|
}
|
|
|
|
/// The numerator and denominator, respectively. The denominator is always
|
|
/// positive.
|
|
DynamicAPInt num{0}, den{1};
|
|
};
|
|
|
|
/// Three-way comparison between two fractions.
|
|
/// Returns +1, 0, and -1 if the first fraction is greater than, equal to, or
|
|
/// less than the second fraction, respectively.
|
|
inline int compare(const Fraction &x, const Fraction &y) {
|
|
DynamicAPInt diff = x.num * y.den - y.num * x.den;
|
|
if (diff > 0)
|
|
return +1;
|
|
if (diff < 0)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
inline DynamicAPInt floor(const Fraction &f) { return floorDiv(f.num, f.den); }
|
|
|
|
inline DynamicAPInt ceil(const Fraction &f) { return ceilDiv(f.num, f.den); }
|
|
|
|
inline Fraction operator-(const Fraction &x) { return Fraction(-x.num, x.den); }
|
|
|
|
inline bool operator<(const Fraction &x, const Fraction &y) {
|
|
return compare(x, y) < 0;
|
|
}
|
|
|
|
inline bool operator<=(const Fraction &x, const Fraction &y) {
|
|
return compare(x, y) <= 0;
|
|
}
|
|
|
|
inline bool operator==(const Fraction &x, const Fraction &y) {
|
|
return compare(x, y) == 0;
|
|
}
|
|
|
|
inline bool operator!=(const Fraction &x, const Fraction &y) {
|
|
return compare(x, y) != 0;
|
|
}
|
|
|
|
inline bool operator>(const Fraction &x, const Fraction &y) {
|
|
return compare(x, y) > 0;
|
|
}
|
|
|
|
inline bool operator>=(const Fraction &x, const Fraction &y) {
|
|
return compare(x, y) >= 0;
|
|
}
|
|
|
|
inline Fraction abs(const Fraction &f) {
|
|
assert(f.den > 0 && "denominator of fraction must be positive!");
|
|
return Fraction(abs(f.num), f.den);
|
|
}
|
|
|
|
inline Fraction reduce(const Fraction &f) {
|
|
if (f == Fraction(0))
|
|
return Fraction(0, 1);
|
|
DynamicAPInt g = gcd(abs(f.num), abs(f.den));
|
|
return Fraction(f.num / g, f.den / g);
|
|
}
|
|
|
|
inline Fraction operator*(const Fraction &x, const Fraction &y) {
|
|
return reduce(Fraction(x.num * y.num, x.den * y.den));
|
|
}
|
|
|
|
inline Fraction operator/(const Fraction &x, const Fraction &y) {
|
|
return reduce(Fraction(x.num * y.den, x.den * y.num));
|
|
}
|
|
|
|
inline Fraction operator+(const Fraction &x, const Fraction &y) {
|
|
return reduce(Fraction(x.num * y.den + x.den * y.num, x.den * y.den));
|
|
}
|
|
|
|
inline Fraction operator-(const Fraction &x, const Fraction &y) {
|
|
return reduce(Fraction(x.num * y.den - x.den * y.num, x.den * y.den));
|
|
}
|
|
|
|
// Find the integer nearest to a given fraction.
|
|
inline DynamicAPInt round(const Fraction &f) {
|
|
DynamicAPInt rem = f.num % f.den;
|
|
return (f.num / f.den) + (rem > f.den / 2);
|
|
}
|
|
|
|
inline Fraction &operator+=(Fraction &x, const Fraction &y) {
|
|
x = x + y;
|
|
return x;
|
|
}
|
|
|
|
inline Fraction &operator-=(Fraction &x, const Fraction &y) {
|
|
x = x - y;
|
|
return x;
|
|
}
|
|
|
|
inline Fraction &operator/=(Fraction &x, const Fraction &y) {
|
|
x = x / y;
|
|
return x;
|
|
}
|
|
|
|
inline Fraction &operator*=(Fraction &x, const Fraction &y) {
|
|
x = x * y;
|
|
return x;
|
|
}
|
|
|
|
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Fraction &x) {
|
|
x.print(os);
|
|
return os;
|
|
}
|
|
|
|
} // namespace presburger
|
|
} // namespace mlir
|
|
|
|
#endif // MLIR_ANALYSIS_PRESBURGER_FRACTION_H
|