Rings for MAT 685
Mathematical ring implementation to demonstrate templates and inheritance
polynomial.hpp
1 #ifndef __POLYNOMIAL_H_
2 #define __POLYNOMIAL_H_
3 
4 #include <initializer_list>
5 using std::initializer_list;
6 #include <vector>
7 using std::vector;
8 
9 #include <iostream>
10 using std::ostream;
11 
12 #include "rings.hpp"
13 
14 namespace Rings {
15 
16 typedef int32_t DEGREE_TYPE;
17 
23 template<typename R>
24 class Polynomial : virtual public Commutative_Ring_Element {
25 
26 protected:
27 
28  DEGREE_TYPE deg;
29  vector<R> coeffs;
37 
39  void clear_coeffs();
41  void set_degree(DEGREE_TYPE);
46  void verify_degree();
51  void common_division(const Polynomial<R> &) const;
52 
53 public:
54 
55  // constructors
56 
58  Polynomial();
60  Polynomial(const Polynomial<R> &);
62  Polynomial(const initializer_list<R> &);
64  Polynomial(const vector<R> &);
65 
66  // required methods
67 
69  DEGREE_TYPE degree() const;
71  const R & coeff(DEGREE_TYPE) const;
73  const R & operator () (const R &) const;
74 
76  void set_coeff(DEGREE_TYPE, const R &);
77 
79  const Polynomial<R> & operator = (const Ring_Element &);
80 
81  virtual bool operator == (const Ring_Element &) const override;
82  virtual bool operator != (const Ring_Element &) const override;
87  bool operator == (const R &) const;
88 
90  const Polynomial<R> & operator / (const Polynomial<R> &) const;
92  const Polynomial<R> & operator % (const Polynomial<R> &) const;
93 
94  // overriding Commutative_Ring_Element pure virtual
95 
96  virtual bool is_one() const override;
97  virtual bool is_zero() const override;
98  virtual bool has_inverse() const override;
99  virtual bool is_cancellable() const override;
100 
101  virtual Polynomial<R> & operator + (const Ring_Element &) const override;
102  virtual Polynomial<R> & operator - (const Ring_Element &) const override;
103  virtual Polynomial<R> & operator * (const Ring_Element &) const override;
104 
105 };
106 
107 template<typename R>
109  deg = 0;
110  coeffs.resize(1, 0);
111 }
112 
113 template<typename R>
115  : deg(other.deg), coeffs(deg + 1)
116 {
117  for (unsigned i = 0; i <= deg; ++i)
118  coeffs[i] = other.coeffs[i];
119 }
120 
121 template<typename R>
122 Polynomial<R>::Polynomial(const initializer_list<R> & list)
123  : deg(list.size() - 1), coeffs(deg + 1)
124 {
125  DEGREE_TYPE i = 0;
126  for (auto c : list) {
127  coeffs[i] = c;
128  ++i;
129  }
130  verify_degree();
131 }
132 
133 template<typename R>
134 Polynomial<R>::Polynomial(const vector<R> & list)
135  : deg(list.size()), coeffs(deg + 1)
136 {
137  DEGREE_TYPE i = 0;
138  for (auto c : list) {
139  coeffs[i] = c;
140  ++i;
141  }
142  verify_degree();
143 }
144 
145 template<typename R>
147  unsigned i;
148  for (i = deg; i > 0 and coeffs[i].is_zero(); --i) { /* do nothing */ }
149  deg = i;
150 }
151 
152 template<typename R>
153 void Polynomial<R>::set_degree(DEGREE_TYPE d) {
154  if (deg < d)
155  coeffs.resize(d + 1);
156  deg = d;
157 }
158 
159 template<typename R>
161  R zero;
162  for (DEGREE_TYPE i = 0; i <= deg; ++i)
163  coeffs[i] = zero;
164 }
165 
166 template<typename R>
167 DEGREE_TYPE Polynomial<R>::degree() const { return deg; }
168 
169 template<typename R>
170 const R & Polynomial<R>::coeff(DEGREE_TYPE d) const { return coeffs[d]; }
171 
172 template<typename R>
173 const R & Polynomial<R>::operator() (const R & a) const {
174  static R result;
175  for (DEGREE_TYPE i = 0; i <= deg; ++i) {
176  if (not coeffs[i].is_zero()) {
177  R term(a);
178  for (DEGREE_TYPE j = 0; j <= deg; ++j)
179  term = term * a;
180  term = term * coeffs[i];
181  result = result + term;
182  }
183  }
184  return result;
185 }
186 
187 template<typename R>
188 void Polynomial<R>::set_coeff(DEGREE_TYPE d, const R & value) {
189  coeffs[d] = value;
190 }
191 
192 template<typename R>
194  if (*this != o) {
195  const Polynomial<R> & other = dynamic_cast<const Polynomial<R> &>(o);
196  coeffs.resize(other.degree() + 1);
197  deg = other.degree();
198  for (DEGREE_TYPE i = 0; i < deg; ++i)
199  coeffs[i] = other.coeffs[i];
200  }
201  return *this;
202 }
203 
204 template<typename R>
206  auto & other = dynamic_cast<const Polynomial<R> &>(o);
207  bool result = deg == other.deg;
208  for (DEGREE_TYPE i = 0; result and i < deg; ++i)
209  result = coeffs[i] == other.coeffs[i];
210  return result;
211 }
212 
213 template<typename R>
215  auto & other = dynamic_cast<const Polynomial<R> &>(o);
216  bool result = deg == other.deg;
217  for (DEGREE_TYPE i = 0; result and i < deg; ++i)
218  result = coeffs[i] == other.coeffs[i];
219  return result;
220 }
221 
222 template<typename R>
223 bool Polynomial<R>::operator == (const R & value) const {
224  return deg == 0 and coeffs[0] == value;
225 }
226 
227 template<typename R>
228 bool Polynomial<R>::is_one() const {
229  return degree() == 0 and coeffs[0].is_one();
230 }
231 
232 template<typename R>
234  return degree() == 0 and coeffs[0].is_zero();
235 }
236 
237 template<typename R>
239  return degree() == 0 and coeffs[0].is_cancellable();
240 }
241 
242 template<typename R>
244  bool result = false;
245  for (DEGREE_TYPE i = 0; i < deg and not result; ++i)
246  result = not coeffs[i].is_zero() and coeffs[i].is_cancellable();
247  return result;
248 }
249 
250 template<typename R>
252  const
253 {
254  static Polynomial<R> result;
255  const Polynomial<R> & other = dynamic_cast<const Polynomial<R> &>(o);
256  DEGREE_TYPE d = degree();
257  if (d < other.degree()) d = other.degree();
258  result.set_degree(d);
259  result.clear_coeffs();
260  DEGREE_TYPE i;
261  for (i = 0; i <= degree() and i <= other.degree(); ++i)
262  result.coeffs[i] = coeffs[i] + other.coeffs[i];
263  for ( /* */ ; i <= degree(); ++i)
264  result.coeffs[i] = coeffs[i];
265  for ( /* */ ; i <= other.degree(); ++i)
266  result.coeffs[i] = other.coeffs[i];
267  result.verify_degree();
268  return result;
269 }
270 
271 template<typename R>
273  const
274 {
275  static Polynomial<R> result;
276  const Polynomial<R> & other = dynamic_cast<const Polynomial<R> &>(o);
277  DEGREE_TYPE d = degree();
278  if (d < other.degree()) d = other.degree();
279  result.set_degree(d);
280  result.clear_coeffs();
281  DEGREE_TYPE i;
282  for (i = 0; i <= degree() and i <= other.degree(); ++i)
283  result.coeffs[i] = coeffs[i] - other.coeffs[i];
284  for ( /* */ ; i <= degree(); ++i)
285  result.coeffs[i] = coeffs[i];
286  for ( /* */ ; i <= other.degree(); ++i)
287  result.coeffs[i] = result.coeffs[i] - other.coeffs[i];
288  result.verify_degree();
289  return result;
290 }
291 
292 template<typename R>
294  const
295 {
296  static Polynomial<R> result;
297  const Polynomial<R> & other = dynamic_cast<const Polynomial<R> &>(o);
298  DEGREE_TYPE d = degree() + other.degree();
299  result.set_degree(d);
300  result.clear_coeffs();
301  for (DEGREE_TYPE i = 0; i <= degree(); ++i)
302  for (DEGREE_TYPE j = 0; j <= other.degree(); ++j)
303  result.coeffs[i + j] = result.coeffs[i + j] + coeffs[i] * other.coeffs[j];
304  result.verify_degree();
305  return result;
306 }
307 
308 template<typename R>
310  last_divisor = other;
311  if (deg < other.deg) last_quotient.set_degree(0);
312  else last_quotient.set_degree(deg - other.deg);
313  last_quotient.clear_coeffs();
314  last_remainder = *this;
315  while (last_remainder.deg >= other.deg) {
316  DEGREE_TYPE d = last_remainder.deg - other.deg;
317  last_quotient.coeffs[d] = last_remainder.coeffs[last_remainder.deg];
318  for (unsigned i = 0; i <= other.deg; ++i)
319  last_remainder.coeffs[i + d] = last_remainder.coeffs[i + d]
320  - other.coeffs[i]*last_remainder.coeffs[last_remainder.deg];
321  last_remainder.verify_degree();
322  }
323 }
324 
325 template<typename R>
327  const
328 {
329  static Polynomial<R> result;
330  if (other == last_divisor)
331  result = last_quotient;
332  else {
333  common_division(other);
334  result = last_quotient;
335  }
336  return result;
337 }
338 
339 template<typename R>
341  const
342 {
343  static Polynomial<R> result;
344  if (other == last_divisor)
345  result = last_remainder;
346  else {
347  common_division(other);
348  result = last_remainder;
349  }
350  return result;
351 }
352 
357 template<typename R>
358 ostream & operator << (ostream & os, const Polynomial<R> & p) {
359  bool first = true;
360  for (DEGREE_TYPE d = p.degree(); d > 0; --d) {
361  if (not p.coeff(d).is_zero()) {
362  if (first) first = false;
363  else {
364  os << " + ";
365  }
366  if (not p.coeff(d).is_one()) os << p.coeff(d) << " ";
367  os << "x";
368  if (d > 1)
369  os << "^" << d;
370  }
371  }
372  if (p.degree() == 0 or not p.coeff(0).is_zero()) {
373  if (not first) os << " + ";
374  os << p.coeff(0);
375  }
376  return os;
377 }
378 
379 template <typename R>
381 template <typename R>
383 template <typename R>
385 
386 }
387 
388 #endif
vector< R > coeffs
polynomial’s coefficients
Definition: polynomial.hpp:29
const R & coeff(DEGREE_TYPE) const
returns the coefficient at the specified degree
Definition: polynomial.hpp:170
elements of this type should have commutative multiplication
Definition: rings.hpp:39
void set_coeff(DEGREE_TYPE, const R &)
sets the value of the coefficient at the given degree
Definition: polynomial.hpp:188
virtual bool is_cancellable() const override
should be True iff element can cancel across an equation; e.g., .
Definition: polynomial.hpp:243
void verify_degree()
verifies that the leading coefficient is zero; if not, decreases degree until either it is or the deg...
Definition: polynomial.hpp:146
Polynomial()
generates a zero polynomial
Definition: polynomial.hpp:108
static Polynomial< R > last_divisor
storage for previously used divisor
Definition: polynomial.hpp:32
const R & operator()(const R &) const
computes the value of the polynomial at the given point
Definition: polynomial.hpp:173
void set_degree(DEGREE_TYPE)
sets the degree to the specified value and resizes if necessary
Definition: polynomial.hpp:153
Definition: integer.hpp:6
virtual Polynomial< R > & operator*(const Ring_Element &) const override
multiplicationL other element should be of same type, use a cast
Definition: polynomial.hpp:293
virtual bool is_zero() const override
should be True iff element is additive identity
Definition: polynomial.hpp:233
virtual bool operator==(const Ring_Element &) const override
comparison: other element has same value
Definition: polynomial.hpp:205
static Polynomial< R > last_remainder
storage for previously computed remainder
Definition: polynomial.hpp:36
void clear_coeffs()
sets all coefficients to zero
Definition: polynomial.hpp:160
virtual bool operator!=(const Ring_Element &) const override
comparison: other element has different value
Definition: polynomial.hpp:214
DEGREE_TYPE degree() const
indicates the polynomial&#39;s degree
Definition: polynomial.hpp:167
virtual bool has_inverse() const override
should be True iff element has a multiplicative inverse
Definition: polynomial.hpp:238
const Polynomial< R > & operator=(const Ring_Element &)
assignment operator may be needed
Definition: polynomial.hpp:193
a class for elements with the capabilities of ring arithmetic
Definition: rings.hpp:9
static Polynomial< R > last_quotient
storage for previously computed quotient
Definition: polynomial.hpp:34
const Polynomial< R > & operator/(const Polynomial< R > &) const
quotient from dividing this by the given divisor
Definition: polynomial.hpp:326
virtual Polynomial< R > & operator+(const Ring_Element &) const override
addition: other element should be of same type, use a cast
Definition: polynomial.hpp:251
virtual bool is_one() const override
should be True iff element is multiplicative identity
Definition: polynomial.hpp:228
virtual Polynomial< R > & operator-(const Ring_Element &) const override
subtraction: other element should be of same type, use a cast
Definition: polynomial.hpp:272
const Polynomial< R > & operator%(const Polynomial< R > &) const
remainder from dividing this by the given divisor
Definition: polynomial.hpp:340
void common_division(const Polynomial< R > &) const
utility function that obtains both divisor and remainder from division
Definition: polynomial.hpp:309
a dense univariate polynomial, templated according to the coefficient’s type
Definition: polynomial.hpp:24
DEGREE_TYPE deg
polynomial’s degree
Definition: polynomial.hpp:28