[Mlir-commits] [mlir] [MLIR][Presburger] Helper functions to compute the constant term of a generating function (PR #77819)

Arjun P llvmlistbot at llvm.org
Sat Jan 13 04:54:35 PST 2024


================
@@ -144,3 +145,107 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
                             std::vector({numerator}),
                             std::vector({denominator}));
 }
+
+/// 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 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 d = 0, ... n-1, we construct a vector
+/// 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,
+/// which we ignore.
+/// At step d > 0 , we need a number v
+/// s.t. <x_i[:d], vs++[v]> != 0 for all i.
+/// => <x_i[:d-1], vs> + x_i[d]*v != 0
+/// => v != - <x_i[:d-1], vs> / x_i[d]
+/// 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 d'th step.
+Point mlir::presburger::detail::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 = 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; i++)
+        dotProduct = dotProduct + vector[i] * newPoint[i];
+      lowerDimDotProducts.push_back(dotProduct);
+    }
+
+    // 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] == 0)
+        continue;
+      disallowedValue = -lowerDimDotProducts[i] / vectors[i][d];
+      if (maxDisallowedValue < disallowedValue)
+        maxDisallowedValue = disallowedValue;
+    }
+
+    newValue = Fraction(ceil(maxDisallowedValue + Fraction(1, 1)), 1);
+    newPoint.append(1, newValue);
----------------
Superty wrote:

not sure what .append(1, ...) is, but you can just use .push_back()

https://github.com/llvm/llvm-project/pull/77819


More information about the Mlir-commits mailing list