MLIR  19.0.0git
Polynomial.h
Go to the documentation of this file.
1 //===- Polynomial.h - A data class for polynomials --------------*- 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 #ifndef MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
10 #define MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
11 
12 #include "mlir/Support/LLVM.h"
14 #include "llvm/ADT/APFloat.h"
15 #include "llvm/ADT/APInt.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/Hashing.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/Twine.h"
20 #include "llvm/Support/raw_ostream.h"
21 
22 namespace mlir {
23 
24 class MLIRContext;
25 
26 namespace polynomial {
27 
28 /// This restricts statically defined polynomials to have at most 64-bit
29 /// coefficients. This may be relaxed in the future, but it seems unlikely one
30 /// would want to specify 128-bit polynomials statically in the source code.
31 constexpr unsigned apintBitWidth = 64;
32 
33 template <class Derived, typename CoefficientType>
34 class MonomialBase {
35 public:
36  MonomialBase(const CoefficientType &coeff, const APInt &expo)
37  : coefficient(coeff), exponent(expo) {}
38  virtual ~MonomialBase() = default;
39 
40  const CoefficientType &getCoefficient() const { return coefficient; }
41  CoefficientType &getMutableCoefficient() { return coefficient; }
42  const APInt &getExponent() const { return exponent; }
43  void setCoefficient(const CoefficientType &coeff) { coefficient = coeff; }
44  void setExponent(const APInt &exp) { exponent = exp; }
45 
46  bool operator==(const MonomialBase &other) const {
47  return other.coefficient == coefficient && other.exponent == exponent;
48  }
49  bool operator!=(const MonomialBase &other) const {
50  return other.coefficient != coefficient || other.exponent != exponent;
51  }
52 
53  /// Monomials are ordered by exponent.
54  bool operator<(const MonomialBase &other) const {
55  return (exponent.ult(other.exponent));
56  }
57 
58  Derived add(const Derived &other) {
59  assert(exponent == other.exponent);
60  CoefficientType newCoeff = coefficient + other.coefficient;
61  Derived result;
62  result.setCoefficient(newCoeff);
63  result.setExponent(exponent);
64  return result;
65  }
66 
67  virtual bool isMonic() const = 0;
68  virtual void
69  coefficientToString(llvm::SmallString<16> &coeffString) const = 0;
70 
71  template <class D, typename T>
72  friend ::llvm::hash_code hash_value(const MonomialBase<D, T> &arg);
73 
74 protected:
75  CoefficientType coefficient;
76  APInt exponent;
77 };
78 
79 /// A class representing a monomial of a single-variable polynomial with integer
80 /// coefficients.
81 class IntMonomial : public MonomialBase<IntMonomial, APInt> {
82 public:
83  IntMonomial(int64_t coeff, uint64_t expo)
84  : MonomialBase(APInt(apintBitWidth, coeff), APInt(apintBitWidth, expo)) {}
85 
87  : MonomialBase(APInt(apintBitWidth, 0), APInt(apintBitWidth, 0)) {}
88 
89  ~IntMonomial() override = default;
90 
91  bool isMonic() const override { return coefficient == 1; }
92 
93  void coefficientToString(llvm::SmallString<16> &coeffString) const override {
94  coefficient.toStringSigned(coeffString);
95  }
96 };
97 
98 /// A class representing a monomial of a single-variable polynomial with integer
99 /// coefficients.
100 class FloatMonomial : public MonomialBase<FloatMonomial, APFloat> {
101 public:
102  FloatMonomial(double coeff, uint64_t expo)
103  : MonomialBase(APFloat(coeff), APInt(apintBitWidth, expo)) {}
104 
105  FloatMonomial() : MonomialBase(APFloat((double)0), APInt(apintBitWidth, 0)) {}
106 
107  ~FloatMonomial() override = default;
108 
109  bool isMonic() const override { return coefficient == APFloat(1.0); }
110 
111  void coefficientToString(llvm::SmallString<16> &coeffString) const override {
112  coefficient.toString(coeffString);
113  }
114 };
115 
116 template <class Derived, typename Monomial>
118 public:
119  PolynomialBase() = delete;
120 
121  explicit PolynomialBase(ArrayRef<Monomial> terms) : terms(terms) {};
122 
123  explicit operator bool() const { return !terms.empty(); }
124  bool operator==(const PolynomialBase &other) const {
125  return other.terms == terms;
126  }
127  bool operator!=(const PolynomialBase &other) const {
128  return !(other.terms == terms);
129  }
130 
131  void print(raw_ostream &os, ::llvm::StringRef separator,
132  ::llvm::StringRef exponentiation) const {
133  bool first = true;
134  for (const Monomial &term : getTerms()) {
135  if (first) {
136  first = false;
137  } else {
138  os << separator;
139  }
140  std::string coeffToPrint;
141  if (term.isMonic() && term.getExponent().uge(1)) {
142  coeffToPrint = "";
143  } else {
144  llvm::SmallString<16> coeffString;
145  term.coefficientToString(coeffString);
146  coeffToPrint = coeffString.str();
147  }
148 
149  if (term.getExponent() == 0) {
150  os << coeffToPrint;
151  } else if (term.getExponent() == 1) {
152  os << coeffToPrint << "x";
153  } else {
154  llvm::SmallString<16> expString;
155  term.getExponent().toStringSigned(expString);
156  os << coeffToPrint << "x" << exponentiation << expString;
157  }
158  }
159  }
160 
161  Derived add(const Derived &other) {
162  SmallVector<Monomial> newTerms;
163  auto it1 = terms.begin();
164  auto it2 = other.terms.begin();
165  while (it1 != terms.end() || it2 != other.terms.end()) {
166  if (it1 == terms.end()) {
167  newTerms.emplace_back(*it2);
168  it2++;
169  continue;
170  }
171 
172  if (it2 == other.terms.end()) {
173  newTerms.emplace_back(*it1);
174  it1++;
175  continue;
176  }
177 
178  while (it1->getExponent().ult(it2->getExponent())) {
179  newTerms.emplace_back(*it1);
180  it1++;
181  if (it1 == terms.end())
182  break;
183  }
184 
185  while (it2->getExponent().ult(it1->getExponent())) {
186  newTerms.emplace_back(*it2);
187  it2++;
188  if (it2 == terms.end())
189  break;
190  }
191 
192  newTerms.emplace_back(it1->add(*it2));
193  it1++;
194  it2++;
195  }
196  return Derived(newTerms);
197  }
198 
199  // Prints polynomial to 'os'.
200  void print(raw_ostream &os) const { print(os, " + ", "**"); }
201 
202  void dump() const;
203 
204  // Prints polynomial so that it can be used as a valid identifier
205  std::string toIdentifier() const {
206  std::string result;
207  llvm::raw_string_ostream os(result);
208  print(os, "_", "");
209  return os.str();
210  }
211 
212  unsigned getDegree() const {
213  return terms.back().getExponent().getZExtValue();
214  }
215 
216  ArrayRef<Monomial> getTerms() const { return terms; }
217 
218  template <class D, typename T>
219  friend ::llvm::hash_code hash_value(const PolynomialBase<D, T> &arg);
220 
221 private:
222  // The monomial terms for this polynomial.
223  SmallVector<Monomial> terms;
224 };
225 
226 /// A single-variable polynomial with integer coefficients.
227 ///
228 /// Eg: x^1024 + x + 1
229 class IntPolynomial : public PolynomialBase<IntPolynomial, IntMonomial> {
230 public:
232 
233  // Returns a Polynomial from a list of monomials.
234  // Fails if two monomials have the same exponent.
237 
238  /// Returns a polynomial with coefficients given by `coeffs`. The value
239  /// coeffs[i] is converted to a monomial with exponent i.
241 };
242 
243 /// A single-variable polynomial with double coefficients.
244 ///
245 /// Eg: 1.0 x^1024 + 3.5 x + 1e-05
246 class FloatPolynomial : public PolynomialBase<FloatPolynomial, FloatMonomial> {
247 public:
249  : PolynomialBase(terms) {}
250 
251  // Returns a Polynomial from a list of monomials.
252  // Fails if two monomials have the same exponent.
255 
256  /// Returns a polynomial with coefficients given by `coeffs`. The value
257  /// coeffs[i] is converted to a monomial with exponent i.
259 };
260 
261 // Make Polynomials hashable.
262 template <class D, typename T>
263 inline ::llvm::hash_code hash_value(const PolynomialBase<D, T> &arg) {
264  return ::llvm::hash_combine_range(arg.terms.begin(), arg.terms.end());
265 }
266 
267 template <class D, typename T>
268 inline ::llvm::hash_code hash_value(const MonomialBase<D, T> &arg) {
269  return llvm::hash_combine(::llvm::hash_value(arg.coefficient),
270  ::llvm::hash_value(arg.exponent));
271 }
272 
273 template <class D, typename T>
274 inline raw_ostream &operator<<(raw_ostream &os,
275  const PolynomialBase<D, T> &polynomial) {
276  polynomial.print(os);
277  return os;
278 }
279 
280 } // namespace polynomial
281 } // namespace mlir
282 
283 #endif // MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
This class provides support for representing a failure result, or a valid value of type T.
Definition: LogicalResult.h:78
A class representing a monomial of a single-variable polynomial with integer coefficients.
Definition: Polynomial.h:100
bool isMonic() const override
Definition: Polynomial.h:109
~FloatMonomial() override=default
FloatMonomial(double coeff, uint64_t expo)
Definition: Polynomial.h:102
void coefficientToString(llvm::SmallString< 16 > &coeffString) const override
Definition: Polynomial.h:111
A single-variable polynomial with double coefficients.
Definition: Polynomial.h:246
FloatPolynomial(ArrayRef< FloatMonomial > terms)
Definition: Polynomial.h:248
static FailureOr< FloatPolynomial > fromMonomials(ArrayRef< FloatMonomial > monomials)
Definition: Polynomial.cpp:41
static FloatPolynomial fromCoefficients(ArrayRef< double > coeffs)
Returns a polynomial with coefficients given by coeffs.
Definition: Polynomial.cpp:64
A class representing a monomial of a single-variable polynomial with integer coefficients.
Definition: Polynomial.h:81
void coefficientToString(llvm::SmallString< 16 > &coeffString) const override
Definition: Polynomial.h:93
IntMonomial(int64_t coeff, uint64_t expo)
Definition: Polynomial.h:83
bool isMonic() const override
Definition: Polynomial.h:91
~IntMonomial() override=default
A single-variable polynomial with integer coefficients.
Definition: Polynomial.h:229
static IntPolynomial fromCoefficients(ArrayRef< int64_t > coeffs)
Returns a polynomial with coefficients given by coeffs.
Definition: Polynomial.cpp:60
IntPolynomial(ArrayRef< IntMonomial > terms)
Definition: Polynomial.h:231
static FailureOr< IntPolynomial > fromMonomials(ArrayRef< IntMonomial > monomials)
Definition: Polynomial.cpp:36
bool operator<(const MonomialBase &other) const
Monomials are ordered by exponent.
Definition: Polynomial.h:54
bool operator!=(const MonomialBase &other) const
Definition: Polynomial.h:49
void setExponent(const APInt &exp)
Definition: Polynomial.h:44
virtual void coefficientToString(llvm::SmallString< 16 > &coeffString) const =0
MonomialBase(const CoefficientType &coeff, const APInt &expo)
Definition: Polynomial.h:36
const CoefficientType & getCoefficient() const
Definition: Polynomial.h:40
CoefficientType & getMutableCoefficient()
Definition: Polynomial.h:41
Derived add(const Derived &other)
Definition: Polynomial.h:58
void setCoefficient(const CoefficientType &coeff)
Definition: Polynomial.h:43
virtual bool isMonic() const =0
bool operator==(const MonomialBase &other) const
Definition: Polynomial.h:46
CoefficientType coefficient
Definition: Polynomial.h:75
const APInt & getExponent() const
Definition: Polynomial.h:42
friend ::llvm::hash_code hash_value(const MonomialBase< D, T > &arg)
Definition: Polynomial.h:268
virtual ~MonomialBase()=default
void print(raw_ostream &os) const
Definition: Polynomial.h:200
Derived add(const Derived &other)
Definition: Polynomial.h:161
std::string toIdentifier() const
Definition: Polynomial.h:205
friend ::llvm::hash_code hash_value(const PolynomialBase< D, T > &arg)
Definition: Polynomial.h:263
ArrayRef< Monomial > getTerms() const
Definition: Polynomial.h:216
bool operator==(const PolynomialBase &other) const
Definition: Polynomial.h:124
void print(raw_ostream &os, ::llvm::StringRef separator, ::llvm::StringRef exponentiation) const
Definition: Polynomial.h:131
PolynomialBase(ArrayRef< Monomial > terms)
Definition: Polynomial.h:121
bool operator!=(const PolynomialBase &other) const
Definition: Polynomial.h:127
inline ::llvm::hash_code hash_value(const MonomialBase< D, T > &arg)
Definition: Polynomial.h:268
raw_ostream & operator<<(raw_ostream &os, const PolynomialBase< D, T > &polynomial)
Definition: Polynomial.h:274
inline ::llvm::hash_code hash_value(const PolynomialBase< D, T > &arg)
Definition: Polynomial.h:263
constexpr unsigned apintBitWidth
This restricts statically defined polynomials to have at most 64-bit coefficients.
Definition: Polynomial.h:31
Include the generated interface declarations.