@@ -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,30 @@ 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
+ newTerms.emplace_back (it1->add (*it2));
179
+ it1++;
180
+ it2++;
181
+ }
182
+ return Derived (newTerms);
183
+ }
184
+
152
185
// Prints polynomial to 'os'.
153
186
void print (raw_ostream &os) const { print (os, " + " , " **" ); }
154
187
@@ -168,8 +201,8 @@ class PolynomialBase {
168
201
169
202
ArrayRef<Monomial> getTerms () const { return terms; }
170
203
171
- template <typename T>
172
- friend ::llvm::hash_code hash_value (const PolynomialBase<T> &arg);
204
+ template <class D , typename T>
205
+ friend ::llvm::hash_code hash_value (const PolynomialBase<D, T> &arg);
173
206
174
207
private:
175
208
// The monomial terms for this polynomial.
@@ -179,7 +212,7 @@ class PolynomialBase {
179
212
// / A single-variable polynomial with integer coefficients.
180
213
// /
181
214
// / Eg: x^1024 + x + 1
182
- class IntPolynomial : public PolynomialBase <IntMonomial> {
215
+ class IntPolynomial : public PolynomialBase <IntPolynomial, IntMonomial> {
183
216
public:
184
217
explicit IntPolynomial (ArrayRef<IntMonomial> terms) : PolynomialBase(terms) {}
185
218
@@ -196,7 +229,7 @@ class IntPolynomial : public PolynomialBase<IntMonomial> {
196
229
// / A single-variable polynomial with double coefficients.
197
230
// /
198
231
// / Eg: 1.0 x^1024 + 3.5 x + 1e-05
199
- class FloatPolynomial : public PolynomialBase <FloatMonomial> {
232
+ class FloatPolynomial : public PolynomialBase <FloatPolynomial, FloatMonomial> {
200
233
public:
201
234
explicit FloatPolynomial (ArrayRef<FloatMonomial> terms)
202
235
: PolynomialBase(terms) {}
@@ -212,20 +245,20 @@ class FloatPolynomial : public PolynomialBase<FloatMonomial> {
212
245
};
213
246
214
247
// Make Polynomials hashable.
215
- template <typename T>
216
- inline ::llvm::hash_code hash_value (const PolynomialBase<T> &arg) {
248
+ template <class D , typename T>
249
+ inline ::llvm::hash_code hash_value (const PolynomialBase<D, T> &arg) {
217
250
return ::llvm::hash_combine_range (arg.terms .begin (), arg.terms .end ());
218
251
}
219
252
220
- template <typename T>
221
- inline ::llvm::hash_code hash_value (const MonomialBase<T> &arg) {
253
+ template <class D , typename T>
254
+ inline ::llvm::hash_code hash_value (const MonomialBase<D, T> &arg) {
222
255
return llvm::hash_combine (::llvm::hash_value (arg.coefficient ),
223
256
::llvm::hash_value (arg.exponent));
224
257
}
225
258
226
- template <typename T>
259
+ template <class D , typename T>
227
260
inline raw_ostream &operator <<(raw_ostream &os,
228
- const PolynomialBase<T> &polynomial) {
261
+ const PolynomialBase<D, T> &polynomial) {
229
262
polynomial.print (os);
230
263
return os;
231
264
}
0 commit comments