[Mlir-commits] [mlir] [MLIR][Presburger] Helper functions to compute the constant term of a generating function (PR #77819)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sat Jan 13 04:50:58 PST 2024
https://github.com/Abhinav271828 updated https://github.com/llvm/llvm-project/pull/77819
>From e14460853a105da0b19dac35f4725840f217ab27 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Thu, 11 Jan 2024 22:02:02 +0530
Subject: [PATCH 01/13] New constructor
---
mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h | 2 ++
mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp | 6 ++++++
2 files changed, 8 insertions(+)
diff --git a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
index f8ce8524e41b21..e656c7e3fb00c1 100644
--- a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
+++ b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
@@ -39,6 +39,8 @@ class QuasiPolynomial : public PresburgerSpace {
QuasiPolynomial(unsigned numVars, SmallVector<Fraction> coeffs = {},
std::vector<std::vector<SmallVector<Fraction>>> aff = {});
+ QuasiPolynomial(unsigned numVars, Fraction constant);
+
// Find the number of inputs (numDomain) to the polynomial.
// numSymbols is set to zero.
unsigned getNumInputs() const {
diff --git a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
index feed683a203cff..24878dd47a2acf 100644
--- a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
+++ b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
@@ -36,6 +36,12 @@ QuasiPolynomial::QuasiPolynomial(
#endif // NDEBUG
}
+/// Define a quasipolynomial which is a single constant.
+QuasiPolynomial::QuasiPolynomial(unsigned numVars, Fraction constant)
+ : PresburgerSpace(/*numDomain=*/numVars, /*numRange=*/1, /*numSymbols=*/0,
+ /*numLocals=*/0),
+ coefficients({constant}), affine({{}}) {}
+
QuasiPolynomial QuasiPolynomial::operator+(const QuasiPolynomial &x) const {
assert(getNumInputs() == x.getNumInputs() &&
"two quasi-polynomials with different numbers of symbols cannot "
>From f247ebcec062002164177489bbd4e9b7987acce4 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Thu, 11 Jan 2024 22:12:46 +0530
Subject: [PATCH 02/13] Functions
---
.../mlir/Analysis/Presburger/Barvinok.h | 8 ++
mlir/lib/Analysis/Presburger/Barvinok.cpp | 92 +++++++++++++++++++
2 files changed, 100 insertions(+)
diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 213af636e5964d..d67c999083e5c0 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -27,6 +27,7 @@
#include "mlir/Analysis/Presburger/GeneratingFunction.h"
#include "mlir/Analysis/Presburger/IntegerRelation.h"
#include "mlir/Analysis/Presburger/Matrix.h"
+#include "mlir/Analysis/Presburger/QuasiPolynomial.h"
#include <optional>
namespace mlir {
@@ -83,6 +84,13 @@ ConeH getDual(ConeV cone);
GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign,
ConeH cone);
+/// Find the coefficient of a given power of s in a rational function
+/// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials,
+/// and those in Q are Fractions.
+QuasiPolynomial getCoefficientInRationalFunction(unsigned power,
+ std::vector<QuasiPolynomial>,
+ std::vector<Fraction>);
+
} // namespace detail
} // namespace presburger
} // namespace mlir
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 0bdc9015c3d647..d4cd867aa31578 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -144,3 +144,95 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
std::vector({numerator}),
std::vector({denominator}));
}
+
+/// We use a recursive procedure to find a vector not orthogonal
+/// to a given set. Let the inputs be {x_1, ..., x_k}, all vectors of length n.
+///
+/// In the following,
+/// vs[:i] means the elements of vs up to and including the i'th one,
+/// <vs, us> means the dot product of v and u,
+/// vs ++ [v] means the vector vs with the new element v appended to it.
+///
+/// Suppose we have a vector vs which is not orthogonal to
+/// any of {x_1[:n-1], ..., x_k[:n-1]}.
+/// Then we need v s.t. <x_i, vs++[v]> != 0 for all i.
+/// => <x_i[:n-1], vs> + x_i[-1]*v != 0
+/// => v != - <x_i[:n-1], vs> / x_i[-1]
+/// We compute this value for all i, and then
+/// set v to be the maximum element of this set + 1. Thus
+/// v is outside the set as desired, and we append it to vs.
+///
+/// The base case is given in one dimension,
+/// where the vector [1] is not orthogonal to any
+/// of the input vectors (since they are all nonzero).
+Point getNonOrthogonalVector(std::vector<Point> vectors) {
+ unsigned dim = vectors[0].size();
+
+ SmallVector<Fraction> newPoint = {Fraction(1, 1)};
+ std::vector<Fraction> lowerDimDotProducts;
+ Fraction dotProduct;
+ Fraction maxDisallowedValue = Fraction(-1, 0),
+ disallowedValue = Fraction(0, 1);
+ Fraction newValue;
+
+ for (unsigned d = 2; d <= dim; d++) {
+ lowerDimDotProducts.clear();
+
+ // Compute the set of dot products <x_i[:d-1], vs> for each i.
+ for (Point vector : vectors) {
+ dotProduct = Fraction(0, 1);
+ for (unsigned i = 0; i < d - 1; i++)
+ dotProduct = dotProduct + vector[i] * newPoint[i];
+ lowerDimDotProducts.push_back(dotProduct);
+ }
+
+ // Compute - <x_i[:n-1], vs> / x_i[-1] for each i,
+ // and find the biggest such value.
+ for (unsigned i = 0; i < vectors.size(); i++) {
+ if (vectors[i][d - 1] == 0)
+ continue;
+ disallowedValue = - lowerDimDotProducts[i] / vectors[i][d - 1];
+ if (maxDisallowedValue < disallowedValue)
+ maxDisallowedValue = disallowedValue;
+ }
+
+ newValue = Fraction(ceil(maxDisallowedValue + Fraction(1, 1)), 1);
+ newPoint.append(1, newValue);
+ }
+ return newPoint;
+}
+
+/// We use the following recursive formula to find the coefficient of
+/// s^power in the rational function given by P(s)/Q(s).
+///
+/// Let P[i] denote the coefficient of s^i in the polynomial P(s).
+/// (P/Q)[r] =
+/// if (r == 0) then
+/// P[0]/Q[0]
+/// else
+/// (P[r] - {Σ_{i=1}^r (P/Q)[r-i] * Q[i])}/(Q[0])
+/// We therefore recursively call `getCoefficientInRationalFuncion` on
+/// all i \in [0, power).
+///
+/// https://math.ucdavis.edu/~deloera/researchsummary/
+/// barvinokalgorithm-latte1.pdf, p. 1285
+QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
+ unsigned power, std::vector<QuasiPolynomial> num,
+ std::vector<Fraction> den) {
+ if (power == 0)
+ return (num[0] / den[0]);
+
+ unsigned numParam = num[0].getNumInputs();
+
+ QuasiPolynomial t(numParam, Fraction(0, 1));
+
+ // The coefficient of s^power in the numerator.
+ if (power < num.size())
+ t = num[power];
+
+ unsigned limit = power + 1 < den.size() ? power + 1 : den.size();
+ for (unsigned i = 1; i < limit; ++i)
+ t = t - getCoefficientInRationalFunction(power - i, num, den) *
+ QuasiPolynomial(numParam, den[i]);
+ return (t / den[0]).simplify();
+}
\ No newline at end of file
>From 97701e5992c6ddb00e114e48fba1ffdd0edddcb8 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Thu, 11 Jan 2024 22:26:54 +0530
Subject: [PATCH 03/13] Functions
---
mlir/include/mlir/Analysis/Presburger/Barvinok.h | 6 ++++++
mlir/lib/Analysis/Presburger/Barvinok.cpp | 9 +++++----
mlir/unittests/Analysis/Presburger/BarvinokTest.cpp | 2 ++
3 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index d67c999083e5c0..88ec1d33f98140 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -84,6 +84,12 @@ ConeH getDual(ConeV cone);
GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign,
ConeH cone);
+/// Find a vector that is not orthogonal to any of the given vectors,
+/// i.e., has nonzero dot product with those of the given vectors
+/// that are not null.
+/// If any of the vectors is null, it is ignored.
+Point getNonOrthonalVector(std::vector<Point> vectors);
+
/// Find the coefficient of a given power of s in a rational function
/// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials,
/// and those in Q are Fractions.
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index d4cd867aa31578..8cbabd18925c0b 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -165,7 +165,8 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
/// The base case is given in one dimension,
/// where the vector [1] is not orthogonal to any
/// of the input vectors (since they are all nonzero).
-Point getNonOrthogonalVector(std::vector<Point> vectors) {
+Point mlir::presburger::detail::getNonOrthonalVector(
+ std::vector<Point> vectors) {
unsigned dim = vectors[0].size();
SmallVector<Fraction> newPoint = {Fraction(1, 1)};
@@ -179,7 +180,7 @@ Point getNonOrthogonalVector(std::vector<Point> vectors) {
lowerDimDotProducts.clear();
// Compute the set of dot products <x_i[:d-1], vs> for each i.
- for (Point vector : vectors) {
+ for (const Point &vector : vectors) {
dotProduct = Fraction(0, 1);
for (unsigned i = 0; i < d - 1; i++)
dotProduct = dotProduct + vector[i] * newPoint[i];
@@ -188,10 +189,10 @@ Point getNonOrthogonalVector(std::vector<Point> vectors) {
// Compute - <x_i[:n-1], vs> / x_i[-1] for each i,
// and find the biggest such value.
- for (unsigned i = 0; i < vectors.size(); i++) {
+ for (unsigned i = 0, e = vectors.size(); i < e; ++i) {
if (vectors[i][d - 1] == 0)
continue;
- disallowedValue = - lowerDimDotProducts[i] / vectors[i][d - 1];
+ disallowedValue = -lowerDimDotProducts[i] / vectors[i][d - 1];
if (maxDisallowedValue < disallowedValue)
maxDisallowedValue = disallowedValue;
}
diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
index 2936d95c802e9c..3c90868b0d9021 100644
--- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
@@ -82,3 +82,5 @@ TEST(BarvinokTest, unimodularConeGeneratingFunction) {
1, {1}, {makeFracMatrix(2, 3, {{-83, -100, -41}, {-22, -27, -15}})},
{{{8, 47, -17}, {-7, -41, 15}, {1, 5, -2}}}));
}
+
+TEST(BarvinokTest, non)
\ No newline at end of file
>From db3a96dc0b44c534ee63b98db02bca97ae8a129c Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Thu, 11 Jan 2024 22:27:34 +0530
Subject: [PATCH 04/13] Typo
---
mlir/include/mlir/Analysis/Presburger/Barvinok.h | 2 +-
mlir/lib/Analysis/Presburger/Barvinok.cpp | 2 +-
mlir/unittests/Analysis/Presburger/BarvinokTest.cpp | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 88ec1d33f98140..81259e0b9f87b9 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -88,7 +88,7 @@ GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign,
/// i.e., has nonzero dot product with those of the given vectors
/// that are not null.
/// If any of the vectors is null, it is ignored.
-Point getNonOrthonalVector(std::vector<Point> vectors);
+Point getNonOrthogonalVector(std::vector<Point> vectors);
/// Find the coefficient of a given power of s in a rational function
/// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials,
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 8cbabd18925c0b..007437ef5069f1 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -165,7 +165,7 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
/// The base case is given in one dimension,
/// where the vector [1] is not orthogonal to any
/// of the input vectors (since they are all nonzero).
-Point mlir::presburger::detail::getNonOrthonalVector(
+Point mlir::presburger::detail::getNonOrthogonalVector(
std::vector<Point> vectors) {
unsigned dim = vectors[0].size();
diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
index 3c90868b0d9021..ccbd0d9a60191e 100644
--- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
@@ -83,4 +83,4 @@ TEST(BarvinokTest, unimodularConeGeneratingFunction) {
{{{8, 47, -17}, {-7, -41, 15}, {1, 5, -2}}}));
}
-TEST(BarvinokTest, non)
\ No newline at end of file
+TEST(BarvinokTest, getNonOrthonalVector)
\ No newline at end of file
>From 497fb4f49bd0a71033204c1ee4eba3faa85e0302 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Thu, 11 Jan 2024 22:33:09 +0530
Subject: [PATCH 05/13] Test:
---
.../Analysis/Presburger/BarvinokTest.cpp | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
index ccbd0d9a60191e..70eeb4e93e52fe 100644
--- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
@@ -83,4 +83,18 @@ TEST(BarvinokTest, unimodularConeGeneratingFunction) {
{{{8, 47, -17}, {-7, -41, 15}, {1, 5, -2}}}));
}
-TEST(BarvinokTest, getNonOrthonalVector)
\ No newline at end of file
+TEST(BarvinokTest, getNonOrthogonalVector) {
+ std::vector<Point> vectors = {Point({1, 2, 3, 4}), Point({-1, 0, 1, 1}),
+ Point({2, 7, 0, 0}), Point({0, 0, 0, 0})};
+ Point nonOrth = getNonOrthogonalVector(vectors);
+
+ for (unsigned i = 0; i < 3; i++)
+ EXPECT_FALSE(dotProduct(nonOrth, vectors[i]) == 0);
+
+ vectors = {Point({0, 1, 3}), Point({-2, -1, 1}), Point({6, 3, 0}),
+ Point({0, 0, -3}), Point({5, 0, -1})};
+ nonOrth = getNonOrthogonalVector(vectors);
+
+ for (const Point &vector : vectors)
+ EXPECT_FALSE(dotProduct(nonOrth, vector) == 0);
+}
\ No newline at end of file
>From 368b5a5545147562f23b93df7f7a1ccd5c8d368e Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Fri, 12 Jan 2024 00:43:11 +0530
Subject: [PATCH 06/13] DPize
---
mlir/lib/Analysis/Presburger/Barvinok.cpp | 28 ++++++++++++++---------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 007437ef5069f1..7572267c87a8ee 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -220,20 +220,26 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
unsigned power, std::vector<QuasiPolynomial> num,
std::vector<Fraction> den) {
- if (power == 0)
- return (num[0] / den[0]);
unsigned numParam = num[0].getNumInputs();
+ unsigned limit;
- QuasiPolynomial t(numParam, Fraction(0, 1));
+ std::vector<QuasiPolynomial> coefficients(power + 1,
+ QuasiPolynomial(numParam, 0));
- // The coefficient of s^power in the numerator.
- if (power < num.size())
- t = num[power];
+ coefficients[0] = num[0] / den[0];
- unsigned limit = power + 1 < den.size() ? power + 1 : den.size();
- for (unsigned i = 1; i < limit; ++i)
- t = t - getCoefficientInRationalFunction(power - i, num, den) *
- QuasiPolynomial(numParam, den[i]);
- return (t / den[0]).simplify();
+ for (unsigned i = 1; i <= power; i++) {
+ if (i < num.size())
+ coefficients[i] = num[i];
+
+ limit = i + 1 < den.size() ? i + 1 : den.size();
+
+ for (unsigned j = 1; j < limit; j++)
+ coefficients[i] = coefficients[i] -
+ coefficients[i - j] * QuasiPolynomial(numParam, den[j]);
+
+ coefficients[i] = coefficients[i] / den[0];
+ }
+ return (coefficients[power]).simplify();
}
\ No newline at end of file
>From ae433d22eba348ab5e60f1c524cac83af0da6a58 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Fri, 12 Jan 2024 00:43:22 +0530
Subject: [PATCH 07/13] Tests
---
.../Analysis/Presburger/BarvinokTest.cpp | 42 ++++++++++++++++++-
mlir/unittests/Analysis/Presburger/Utils.h | 14 +++++++
2 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
index 70eeb4e93e52fe..072a24262604cb 100644
--- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
@@ -83,6 +83,9 @@ TEST(BarvinokTest, unimodularConeGeneratingFunction) {
{{{8, 47, -17}, {-7, -41, 15}, {1, 5, -2}}}));
}
+// The following vectors are randomly generated.
+// We then check that the output of the function has nonzero
+// dot product with all non-null vectors.
TEST(BarvinokTest, getNonOrthogonalVector) {
std::vector<Point> vectors = {Point({1, 2, 3, 4}), Point({-1, 0, 1, 1}),
Point({2, 7, 0, 0}), Point({0, 0, 0, 0})};
@@ -97,4 +100,41 @@ TEST(BarvinokTest, getNonOrthogonalVector) {
for (const Point &vector : vectors)
EXPECT_FALSE(dotProduct(nonOrth, vector) == 0);
-}
\ No newline at end of file
+}
+
+Fraction getC(QuasiPolynomial q) {
+ Fraction t = 0;
+ for (const Fraction &c : q.getCoefficients())
+ t += c;
+
+ return t;
+}
+
+// The following polynomials are randomly generated and the
+// coefficients are computed by hand.
+// Although the function allows the coefficients of the numerator
+// to be arbitrary quasipolynomials, we stick to constants for simplicity,
+// as the relevant arithmetic operations on quasipolynomials
+// are tested separately.
+TEST(BarvinokTest, getCoefficientInRationalFunction) {
+ std::vector<QuasiPolynomial> numerator = {
+ QuasiPolynomial(0, 2), QuasiPolynomial(0, 3), QuasiPolynomial(0, 5)};
+
+ std::vector<Fraction> denominator = {Fraction(1), Fraction(0), Fraction(4),
+ Fraction(3)};
+
+ QuasiPolynomial coeff =
+ getCoefficientInRationalFunction(1, numerator, denominator);
+
+ EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(coeff, 3);
+
+ numerator = {QuasiPolynomial(0, -1), QuasiPolynomial(0, 4),
+ QuasiPolynomial(0, -2), QuasiPolynomial(0, 5),
+ QuasiPolynomial(0, 6)};
+
+ denominator = {Fraction(8), Fraction(4), Fraction(0), Fraction(-2)};
+
+ coeff = getCoefficientInRationalFunction(3, numerator, denominator);
+
+ EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(coeff, Fraction(55, 64));
+}
diff --git a/mlir/unittests/Analysis/Presburger/Utils.h b/mlir/unittests/Analysis/Presburger/Utils.h
index 6b00898a7e2749..2c05fe7e2057f9 100644
--- a/mlir/unittests/Analysis/Presburger/Utils.h
+++ b/mlir/unittests/Analysis/Presburger/Utils.h
@@ -128,6 +128,20 @@ inline void EXPECT_EQ_REPR_QUASIPOLYNOMIAL(QuasiPolynomial a,
}
}
+// Check the constant term of the quasipolynomial against a constant.
+inline void EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(QuasiPolynomial qp,
+ Fraction f) {
+ SmallVector<Fraction> coeffs = qp.getCoefficients();
+ std::vector<std::vector<SmallVector<Fraction>>> aff = qp.getAffine();
+
+ Fraction t = 0;
+ for (unsigned i = 0, e = coeffs.size(); i < e; ++i) {
+ if (aff[i].size() == 0)
+ t += coeffs[i];
+ }
+ EXPECT_EQ(t, f);
+}
+
/// lhs and rhs represent non-negative integers or positive infinity. The
/// infinity case corresponds to when the Optional is empty.
inline bool infinityOrUInt64LE(std::optional<MPInt> lhs,
>From 738c47609ea1d5825070d7521c8329bf8d0c97b8 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Fri, 12 Jan 2024 19:09:56 +0530
Subject: [PATCH 08/13] Fix doc, small refactors
---
.../mlir/Analysis/Presburger/Barvinok.h | 7 ++---
mlir/lib/Analysis/Presburger/Barvinok.cpp | 26 ++++++++++---------
2 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 81259e0b9f87b9..07cfea6f8610d6 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -91,11 +91,12 @@ GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign,
Point getNonOrthogonalVector(std::vector<Point> vectors);
/// Find the coefficient of a given power of s in a rational function
-/// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials,
+/// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials
+/// over d parameters (distinct from s).
/// and those in Q are Fractions.
QuasiPolynomial getCoefficientInRationalFunction(unsigned power,
- std::vector<QuasiPolynomial>,
- std::vector<Fraction>);
+ ArrayRef<QuasiPolynomial> num,
+ ArrayRef<Fraction> den);
} // namespace detail
} // namespace presburger
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 7572267c87a8ee..1ed0f98c9748dc 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -8,6 +8,7 @@
#include "mlir/Analysis/Presburger/Barvinok.h"
#include "llvm/ADT/Sequence.h"
+#include <algorithm>
using namespace mlir;
using namespace presburger;
@@ -149,17 +150,17 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
/// to a given set. Let the inputs be {x_1, ..., x_k}, all vectors of length n.
///
/// In the following,
-/// vs[:i] means the elements of vs up to and including the i'th one,
-/// <vs, us> means the dot product of v and u,
+/// vs[:i] means the elements of vs up to (not including) the i'th one,
+/// <vs, us> means the dot product of vs and us,
/// vs ++ [v] means the vector vs with the new element v appended to it.
///
/// Suppose we have a vector vs which is not orthogonal to
/// any of {x_1[:n-1], ..., x_k[:n-1]}.
/// Then we need v s.t. <x_i, vs++[v]> != 0 for all i.
-/// => <x_i[:n-1], vs> + x_i[-1]*v != 0
-/// => v != - <x_i[:n-1], vs> / x_i[-1]
+/// => <x_i[:n-1], vs> + x_i[n-1]*v != 0
+/// => v != - <x_i[:n-1], vs> / x_i[n-1]
/// We compute this value for all i, and then
-/// set v to be the maximum element of this set + 1. Thus
+/// set v to be the maximum element of this set plus one. Thus
/// v is outside the set as desired, and we append it to vs.
///
/// The base case is given in one dimension,
@@ -212,30 +213,31 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
/// P[0]/Q[0]
/// else
/// (P[r] - {Σ_{i=1}^r (P/Q)[r-i] * Q[i])}/(Q[0])
-/// We therefore recursively call `getCoefficientInRationalFuncion` on
+/// We therefore recursively call `getCoefficientInRationalFunction` on
/// all i \in [0, power).
///
/// https://math.ucdavis.edu/~deloera/researchsummary/
/// barvinokalgorithm-latte1.pdf, p. 1285
QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
- unsigned power, std::vector<QuasiPolynomial> num,
- std::vector<Fraction> den) {
+ unsigned power, ArrayRef<QuasiPolynomial> num, ArrayRef<Fraction> den) {
unsigned numParam = num[0].getNumInputs();
- unsigned limit;
+ for (const QuasiPolynomial &qp : num)
+ assert(numParam == qp.getNumInputs() &&
+ "the quasipolynomials should all belong to the same space!");
std::vector<QuasiPolynomial> coefficients(power + 1,
QuasiPolynomial(numParam, 0));
coefficients[0] = num[0] / den[0];
- for (unsigned i = 1; i <= power; i++) {
+ for (unsigned i = 1; i <= power; ++i) {
if (i < num.size())
coefficients[i] = num[i];
- limit = i + 1 < den.size() ? i + 1 : den.size();
+ unsigned limit = fmin(i, den.size() - 1);
- for (unsigned j = 1; j < limit; j++)
+ for (unsigned j = 1; j <= limit; ++j)
coefficients[i] = coefficients[i] -
coefficients[i - j] * QuasiPolynomial(numParam, den[j]);
>From ecfb7b998e921788a48d5d6ba37f8d9513c33f88 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Fri, 12 Jan 2024 19:13:06 +0530
Subject: [PATCH 09/13] Add getConstantTerm() to QP
---
.../mlir/Analysis/Presburger/QuasiPolynomial.h | 3 +++
mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp | 10 ++++++++++
.../unittests/Analysis/Presburger/BarvinokTest.cpp | 4 ++--
mlir/unittests/Analysis/Presburger/Utils.h | 14 --------------
4 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
index e656c7e3fb00c1..b56ad57db06664 100644
--- a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
+++ b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
@@ -62,6 +62,9 @@ class QuasiPolynomial : public PresburgerSpace {
// Removes terms which evaluate to zero from the expression.
QuasiPolynomial simplify();
+ // Find the constant term of the expression.
+ Fraction getConstantTerm();
+
private:
SmallVector<Fraction> coefficients;
std::vector<std::vector<SmallVector<Fraction>>> affine;
diff --git a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
index 24878dd47a2acf..49c6944b012515 100644
--- a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
+++ b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
@@ -119,3 +119,13 @@ QuasiPolynomial QuasiPolynomial::simplify() {
}
return QuasiPolynomial(getNumInputs(), newCoeffs, newAffine);
}
+
+// Check the constant term of the quasipolynomial against a constant.
+Fraction QuasiPolynomial::getConstantTerm() {
+ Fraction t = 0;
+ for (unsigned i = 0, e = coefficients.size(); i < e; ++i) {
+ if (affine[i].size() == 0)
+ t += coefficients[i];
+ }
+ return t;
+}
diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
index 072a24262604cb..6852be1157cc73 100644
--- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
@@ -126,7 +126,7 @@ TEST(BarvinokTest, getCoefficientInRationalFunction) {
QuasiPolynomial coeff =
getCoefficientInRationalFunction(1, numerator, denominator);
- EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(coeff, 3);
+ EXPECT_EQ(coeff.getConstantTerm(), 3);
numerator = {QuasiPolynomial(0, -1), QuasiPolynomial(0, 4),
QuasiPolynomial(0, -2), QuasiPolynomial(0, 5),
@@ -136,5 +136,5 @@ TEST(BarvinokTest, getCoefficientInRationalFunction) {
coeff = getCoefficientInRationalFunction(3, numerator, denominator);
- EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(coeff, Fraction(55, 64));
+ EXPECT_EQ(coeff.getConstantTerm(), Fraction(55, 64));
}
diff --git a/mlir/unittests/Analysis/Presburger/Utils.h b/mlir/unittests/Analysis/Presburger/Utils.h
index 2c05fe7e2057f9..6b00898a7e2749 100644
--- a/mlir/unittests/Analysis/Presburger/Utils.h
+++ b/mlir/unittests/Analysis/Presburger/Utils.h
@@ -128,20 +128,6 @@ inline void EXPECT_EQ_REPR_QUASIPOLYNOMIAL(QuasiPolynomial a,
}
}
-// Check the constant term of the quasipolynomial against a constant.
-inline void EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(QuasiPolynomial qp,
- Fraction f) {
- SmallVector<Fraction> coeffs = qp.getCoefficients();
- std::vector<std::vector<SmallVector<Fraction>>> aff = qp.getAffine();
-
- Fraction t = 0;
- for (unsigned i = 0, e = coeffs.size(); i < e; ++i) {
- if (aff[i].size() == 0)
- t += coeffs[i];
- }
- EXPECT_EQ(t, f);
-}
-
/// lhs and rhs represent non-negative integers or positive infinity. The
/// infinity case corresponds to when the Optional is empty.
inline bool infinityOrUInt64LE(std::optional<MPInt> lhs,
>From 0e41f51efe332e93890efb22fbf090b602b61d28 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Fri, 12 Jan 2024 19:18:48 +0530
Subject: [PATCH 10/13] Fix doc
---
mlir/lib/Analysis/Presburger/Barvinok.cpp | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 1ed0f98c9748dc..377b8efeedb167 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -147,21 +147,28 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
}
/// We use a recursive procedure to find a vector not orthogonal
-/// to a given set. Let the inputs be {x_1, ..., x_k}, all vectors of length n.
+/// to a given set, ignoring the null vectors.
+/// Let the inputs be {x_1, ..., x_k}, all vectors of length n.
///
/// In the following,
/// vs[:i] means the elements of vs up to (not including) the i'th one,
/// <vs, us> means the dot product of vs and us,
/// vs ++ [v] means the vector vs with the new element v appended to it.
///
-/// Suppose we have a vector vs which is not orthogonal to
-/// any of {x_1[:n-1], ..., x_k[:n-1]}.
-/// Then we need v s.t. <x_i, vs++[v]> != 0 for all i.
-/// => <x_i[:n-1], vs> + x_i[n-1]*v != 0
-/// => v != - <x_i[:n-1], vs> / x_i[n-1]
-/// We compute this value for all i, and then
+/// We proceed iteratively; for steps i = 2, ... n, we construct a vector
+/// which is not orthogonal to any of {x_1[:i], ..., x_n[:i]}, ignoring
+/// the null vectors.
+/// At step i = 2, we let vs = [1]. Clearly this is not orthogonal to
+/// any vector in the set {x_1[0], ..., x_n[0]}, except the null ones,
+/// which we ignore.
+/// At step i = k + 1, we need a number v
+/// s.t. <x_i[:k+1], vs++[v]> != 0 for all i.
+/// => <x_i[:k], vs> + x_i[k]*v != 0
+/// => v != - <x_i[:k], vs> / x_i[k]
+/// We compute this value for all x_i, and then
/// set v to be the maximum element of this set plus one. Thus
-/// v is outside the set as desired, and we append it to vs.
+/// v is outside the set as desired, and we append it to vs
+/// to obtain the result of the k+1'th step.
///
/// The base case is given in one dimension,
/// where the vector [1] is not orthogonal to any
>From 7d8545dbd0706c77f7d161000f7a328fe0bf9624 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 13 Jan 2024 13:57:54 +0530
Subject: [PATCH 11/13] Fix doc
---
.../mlir/Analysis/Presburger/Barvinok.h | 7 ++--
.../Analysis/Presburger/QuasiPolynomial.h | 1 -
mlir/lib/Analysis/Presburger/Barvinok.cpp | 32 ++++++++-----------
.../Analysis/Presburger/QuasiPolynomial.cpp | 1 -
4 files changed, 18 insertions(+), 23 deletions(-)
diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 07cfea6f8610d6..72cbca71ba5a94 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -91,9 +91,10 @@ GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign,
Point getNonOrthogonalVector(std::vector<Point> vectors);
/// Find the coefficient of a given power of s in a rational function
-/// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials
-/// over d parameters (distinct from s).
-/// and those in Q are Fractions.
+/// given by P(s)/Q(s), where
+/// P is a polynomial, in which the coefficients are QuasiPolynomials
+/// over d parameters (distinct from s), and
+/// and Q is a polynomial with Fraction coefficients.
QuasiPolynomial getCoefficientInRationalFunction(unsigned power,
ArrayRef<QuasiPolynomial> num,
ArrayRef<Fraction> den);
diff --git a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
index b56ad57db06664..d03446f50264fa 100644
--- a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
+++ b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
@@ -62,7 +62,6 @@ class QuasiPolynomial : public PresburgerSpace {
// Removes terms which evaluate to zero from the expression.
QuasiPolynomial simplify();
- // Find the constant term of the expression.
Fraction getConstantTerm();
private:
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 377b8efeedb167..aacfc45e8b9bf1 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -146,33 +146,29 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
std::vector({denominator}));
}
-/// We use a recursive procedure to find a vector not orthogonal
+/// We use an iterative procedure to find a vector not orthogonal
/// to a given set, ignoring the null vectors.
/// Let the inputs be {x_1, ..., x_k}, all vectors of length n.
///
/// In the following,
-/// vs[:i] means the elements of vs up to (not including) the i'th one,
+/// vs[:i] means the elements of vs up to and including the i'th one,
/// <vs, us> means the dot product of vs and us,
/// vs ++ [v] means the vector vs with the new element v appended to it.
///
-/// We proceed iteratively; for steps i = 2, ... n, we construct a vector
+/// We proceed iteratively; for steps d = 0, ... n-1, we construct a vector
/// which is not orthogonal to any of {x_1[:i], ..., x_n[:i]}, ignoring
/// the null vectors.
-/// At step i = 2, we let vs = [1]. Clearly this is not orthogonal to
+/// At step d = 0, we let vs = [1]. Clearly this is not orthogonal to
/// any vector in the set {x_1[0], ..., x_n[0]}, except the null ones,
/// which we ignore.
-/// At step i = k + 1, we need a number v
-/// s.t. <x_i[:k+1], vs++[v]> != 0 for all i.
-/// => <x_i[:k], vs> + x_i[k]*v != 0
-/// => v != - <x_i[:k], vs> / x_i[k]
+/// At step d = t + 1, we need a number v
+/// s.t. <x_i[:t+1], vs++[v]> != 0 for all i.
+/// => <x_i[:t], vs> + x_i[t+1]*v != 0
+/// => v != - <x_i[:t], vs> / x_i[t+1]
/// We compute this value for all x_i, and then
/// set v to be the maximum element of this set plus one. Thus
/// v is outside the set as desired, and we append it to vs
-/// to obtain the result of the k+1'th step.
-///
-/// The base case is given in one dimension,
-/// where the vector [1] is not orthogonal to any
-/// of the input vectors (since they are all nonzero).
+/// to obtain the result of the t+1'th step.
Point mlir::presburger::detail::getNonOrthogonalVector(
std::vector<Point> vectors) {
unsigned dim = vectors[0].size();
@@ -184,23 +180,23 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
disallowedValue = Fraction(0, 1);
Fraction newValue;
- for (unsigned d = 2; d <= dim; d++) {
+ for (unsigned d = 1; d < dim; ++d) {
lowerDimDotProducts.clear();
// Compute the set of dot products <x_i[:d-1], vs> for each i.
for (const Point &vector : vectors) {
dotProduct = Fraction(0, 1);
- for (unsigned i = 0; i < d - 1; i++)
+ for (unsigned i = 0; i < d; i++)
dotProduct = dotProduct + vector[i] * newPoint[i];
lowerDimDotProducts.push_back(dotProduct);
}
- // Compute - <x_i[:n-1], vs> / x_i[-1] for each i,
+ // Compute - <x_i[:d-1], vs> / x_i[d] for each i,
// and find the biggest such value.
for (unsigned i = 0, e = vectors.size(); i < e; ++i) {
- if (vectors[i][d - 1] == 0)
+ if (vectors[i][d] == 0)
continue;
- disallowedValue = -lowerDimDotProducts[i] / vectors[i][d - 1];
+ disallowedValue = -lowerDimDotProducts[i] / vectors[i][d];
if (maxDisallowedValue < disallowedValue)
maxDisallowedValue = disallowedValue;
}
diff --git a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
index 49c6944b012515..f6ee7c8638c197 100644
--- a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
+++ b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
@@ -120,7 +120,6 @@ QuasiPolynomial QuasiPolynomial::simplify() {
return QuasiPolynomial(getNumInputs(), newCoeffs, newAffine);
}
-// Check the constant term of the quasipolynomial against a constant.
Fraction QuasiPolynomial::getConstantTerm() {
Fraction t = 0;
for (unsigned i = 0, e = coefficients.size(); i < e; ++i) {
>From c2b367caddc32b76c1c9e0679589835a1ef6d4b6 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 13 Jan 2024 18:14:39 +0530
Subject: [PATCH 12/13] Minor fixes
---
mlir/lib/Analysis/Presburger/Barvinok.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index aacfc45e8b9bf1..233fe0412fe05b 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -223,6 +223,7 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
/// barvinokalgorithm-latte1.pdf, p. 1285
QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
unsigned power, ArrayRef<QuasiPolynomial> num, ArrayRef<Fraction> den) {
+ assert(den.size() != 0 && "division by empty denominator in rational function!");
unsigned numParam = num[0].getNumInputs();
for (const QuasiPolynomial &qp : num)
@@ -238,7 +239,7 @@ QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
if (i < num.size())
coefficients[i] = num[i];
- unsigned limit = fmin(i, den.size() - 1);
+ unsigned limit = std::min<unsigned long>(i, den.size() - 1);
for (unsigned j = 1; j <= limit; ++j)
coefficients[i] = coefficients[i] -
@@ -246,5 +247,5 @@ QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
coefficients[i] = coefficients[i] / den[0];
}
- return (coefficients[power]).simplify();
+ return coefficients[power].simplify();
}
\ No newline at end of file
>From 47040199c2b5f432e04006b692133b66c8745b42 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 13 Jan 2024 18:20:38 +0530
Subject: [PATCH 13/13] Formatting
---
mlir/lib/Analysis/Presburger/Barvinok.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 233fe0412fe05b..2935d219af5e1d 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -156,7 +156,7 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
/// vs ++ [v] means the vector vs with the new element v appended to it.
///
/// We proceed iteratively; for steps d = 0, ... n-1, we construct a vector
-/// which is not orthogonal to any of {x_1[:i], ..., x_n[:i]}, ignoring
+/// which is not orthogonal to any of {x_1[:d], ..., x_n[:d]}, ignoring
/// the null vectors.
/// At step d = 0, we let vs = [1]. Clearly this is not orthogonal to
/// any vector in the set {x_1[0], ..., x_n[0]}, except the null ones,
@@ -223,7 +223,8 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
/// barvinokalgorithm-latte1.pdf, p. 1285
QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
unsigned power, ArrayRef<QuasiPolynomial> num, ArrayRef<Fraction> den) {
- assert(den.size() != 0 && "division by empty denominator in rational function!");
+ assert(den.size() != 0 &&
+ "division by empty denominator in rational function!");
unsigned numParam = num[0].getNumInputs();
for (const QuasiPolynomial &qp : num)
More information about the Mlir-commits
mailing list