@@ -30,7 +30,7 @@ namespace polynomial {
30
30
// / would want to specify 128-bit polynomials statically in the source code.
31
31
constexpr unsigned apintBitWidth = 64 ;
32
32
33
- template <typename CoefficientType>
33
+ template <class Derived , typename CoefficientType>
34
34
class MonomialBase {
35
35
public:
36
36
MonomialBase (const CoefficientType &coeff, const APInt &expo)
@@ -55,12 +55,21 @@ class MonomialBase {
55
55
return (exponent.ult (other.exponent ));
56
56
}
57
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
+
58
67
virtual bool isMonic () const = 0;
59
68
virtual void
60
69
coefficientToString (llvm::SmallString<16 > &coeffString) const = 0 ;
61
70
62
- template <typename T>
63
- friend ::llvm::hash_code hash_value (const MonomialBase<T> &arg);
71
+ template <class D , typename T>
72
+ friend ::llvm::hash_code hash_value (const MonomialBase<D, T> &arg);
64
73
65
74
protected:
66
75
CoefficientType coefficient;
@@ -69,15 +78,15 @@ class MonomialBase {
69
78
70
79
// / A class representing a monomial of a single-variable polynomial with integer
71
80
// / coefficients.
72
- class IntMonomial : public MonomialBase <APInt> {
81
+ class IntMonomial : public MonomialBase <IntMonomial, APInt> {
73
82
public:
74
83
IntMonomial (int64_t coeff, uint64_t expo)
75
84
: MonomialBase(APInt(apintBitWidth, coeff), APInt(apintBitWidth, expo)) {}
76
85
77
86
IntMonomial ()
78
87
: MonomialBase(APInt(apintBitWidth, 0 ), APInt(apintBitWidth, 0 )) {}
79
88
80
- ~IntMonomial () = default ;
89
+ ~IntMonomial () override = default ;
81
90
82
91
bool isMonic () const override { return coefficient == 1 ; }
83
92
@@ -88,14 +97,14 @@ class IntMonomial : public MonomialBase<APInt> {
88
97
89
98
// / A class representing a monomial of a single-variable polynomial with integer
90
99
// / coefficients.
91
- class FloatMonomial : public MonomialBase <APFloat> {
100
+ class FloatMonomial : public MonomialBase <FloatMonomial, APFloat> {
92
101
public:
93
102
FloatMonomial (double coeff, uint64_t expo)
94
103
: MonomialBase(APFloat(coeff), APInt(apintBitWidth, expo)) {}
95
104
96
105
FloatMonomial () : MonomialBase(APFloat((double )0 ), APInt(apintBitWidth, 0 )) {}
97
106
98
- ~FloatMonomial () = default ;
107
+ ~FloatMonomial () override = default ;
99
108
100
109
bool isMonic () const override { return coefficient == APFloat (1.0 ); }
101
110
@@ -104,7 +113,7 @@ class FloatMonomial : public MonomialBase<APFloat> {
104
113
}
105
114
};
106
115
107
- template <typename Monomial>
116
+ template <class Derived , typename Monomial>
108
117
class PolynomialBase {
109
118
public:
110
119
PolynomialBase () = delete ;
@@ -149,6 +158,44 @@ class PolynomialBase {
149
158
}
150
159
}
151
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
+
152
199
// Prints polynomial to 'os'.
153
200
void print (raw_ostream &os) const { print (os, " + " , " **" ); }
154
201
@@ -168,8 +215,8 @@ class PolynomialBase {
168
215
169
216
ArrayRef<Monomial> getTerms () const { return terms; }
170
217
171
- template <typename T>
172
- friend ::llvm::hash_code hash_value (const PolynomialBase<T> &arg);
218
+ template <class D , typename T>
219
+ friend ::llvm::hash_code hash_value (const PolynomialBase<D, T> &arg);
173
220
174
221
private:
175
222
// The monomial terms for this polynomial.
@@ -179,7 +226,7 @@ class PolynomialBase {
179
226
// / A single-variable polynomial with integer coefficients.
180
227
// /
181
228
// / Eg: x^1024 + x + 1
182
- class IntPolynomial : public PolynomialBase <IntMonomial> {
229
+ class IntPolynomial : public PolynomialBase <IntPolynomial, IntMonomial> {
183
230
public:
184
231
explicit IntPolynomial (ArrayRef<IntMonomial> terms) : PolynomialBase(terms) {}
185
232
@@ -196,7 +243,7 @@ class IntPolynomial : public PolynomialBase<IntMonomial> {
196
243
// / A single-variable polynomial with double coefficients.
197
244
// /
198
245
// / Eg: 1.0 x^1024 + 3.5 x + 1e-05
199
- class FloatPolynomial : public PolynomialBase <FloatMonomial> {
246
+ class FloatPolynomial : public PolynomialBase <FloatPolynomial, FloatMonomial> {
200
247
public:
201
248
explicit FloatPolynomial (ArrayRef<FloatMonomial> terms)
202
249
: PolynomialBase(terms) {}
@@ -212,20 +259,20 @@ class FloatPolynomial : public PolynomialBase<FloatMonomial> {
212
259
};
213
260
214
261
// Make Polynomials hashable.
215
- template <typename T>
216
- inline ::llvm::hash_code hash_value (const PolynomialBase<T> &arg) {
262
+ template <class D , typename T>
263
+ inline ::llvm::hash_code hash_value (const PolynomialBase<D, T> &arg) {
217
264
return ::llvm::hash_combine_range (arg.terms .begin (), arg.terms .end ());
218
265
}
219
266
220
- template <typename T>
221
- inline ::llvm::hash_code hash_value (const MonomialBase<T> &arg) {
267
+ template <class D , typename T>
268
+ inline ::llvm::hash_code hash_value (const MonomialBase<D, T> &arg) {
222
269
return llvm::hash_combine (::llvm::hash_value (arg.coefficient ),
223
270
::llvm::hash_value (arg.exponent));
224
271
}
225
272
226
- template <typename T>
273
+ template <class D , typename T>
227
274
inline raw_ostream &operator <<(raw_ostream &os,
228
- const PolynomialBase<T> &polynomial) {
275
+ const PolynomialBase<D, T> &polynomial) {
229
276
polynomial.print (os);
230
277
return os;
231
278
}
0 commit comments