vnl_polynomial.h
Go to the documentation of this file.
1 // This is core/vnl/vnl_polynomial.h
2 #ifndef vnl_polynomial_h_
3 #define vnl_polynomial_h_
4 //:
5 // \file
6 // \brief Evaluation of univariate polynomials
7 // Templated class (on the data type of the coefficients),
8 // further very similar to the vnl_real_polynomial class,
9 // except that it uses std::vector instead of vnl_vector as data container,
10 // that the zero polynomial is represented by an empty vector,
11 // and that the coefficients go in the other direction.
12 //
13 // Important note on the implementation choice (reversed coefficient vector
14 // as opposed to the class vnl_real_npolynomial):
15 // The choice made here is definitely the more natural one, since it makes
16 // polynomials of different degrees much more naturally comparable, and hence
17 // simplifies the implementation of e.g. operator+(). Indeed: even if the
18 // degrees are different, the coefficients [i] of two polynomials are the ones
19 // to be considered together since they both refer to $X^i$. Also, normalizing
20 // the internal representation (in case the highest order coefficient is zero)
21 // now just needs to pop_back() instead of shifting the coefficients vector.
22 // In summary, the choice made here is both more natural and more performant.
23 //
24 // \author Peter Vanroose, ABIS Leuven.
25 // \date August 2011
26 //
27 // \verbatim
28 // Modifications
29 // 20 Aug 2011 - Peter Vanroose - internal repr change: coeff vector reversed
30 // \endverbatim
31 
32 #include <vector>
33 #include <iosfwd>
34 #ifdef _MSC_VER
35 # include <vcl_msvc_warnings.h>
36 #endif
37 #include <cassert>
38 #include "vnl/vnl_export.h"
39 
40 //: Evaluation of polynomials.
41 // vnl_polynomial<T> represents a univariate polynomial with
42 // coefficients of datatype T, stored as a vector of values.
43 // This allows evaluation of the polynomial $p(X)$ at given values of $X$,
44 // and of its derivative $p'(X)$ or primitive function $\int p$.
45 //
46 // The class also provides the common polynomial arithmetic, i.e.,
47 // + - *, and even long division (through operators / and %).
48 //
49 // The coefficients (coeffs_) are stored as a vector, starting with
50 // the constant term. Hence coeffs_[n] is the coefficient of $X^n$,
51 
52 template <class T>
53 class VNL_EXPORT vnl_polynomial
54 {
55  public:
56  //: Initialize the polynomial from its coefficients, lowest order first.
57  // The polynomial is $ a[d] X^d + a[d-1] X^{d-1} + \cdots + a[0] = 0 $.
58  // Note that this constructor expects the constant term coefficient first,
59  // as opposed to the C array constructor!
60  // An assertion makes sure that the input vector is in normalised form, i.e.,
61  // that it is either empty or that the highest order coefficient is nonzero.
62  vnl_polynomial(std::vector<T> const& a): coeffs_(a) { assert(a.begin()==a.end() || a.back() != T(0)); }
63 
64  //: Initialize polynomial from C array, highest order first.
65  // The parameter \p len is the number of coefficients passed in,
66  // which equals the degree plus one.
67  // Note that this constructor expects the highest order coefficients first,
68  // as opposed to the std::vector constructor!
69  vnl_polynomial(T const* a, unsigned len) { assert(len==0 || *a != T(0)); while (len--) coeffs_.push_back(a[len]); }
70 
71  //: Initialize polynomial from single value, thus creating a monomial.
72  // This is effectively an implicit cast from type T to class vnl_polynomial,
73  // useful when adding or multiplying a polynomial with a number.
74  vnl_polynomial(T const& a): coeffs_(1u, a) { if (a==T(0)) coeffs_.clear(); }
75 
76  //: Initialize polynomial of a given degree.
77  // The default constructor initializes to the zero polynomial (which has degree -1).
78  // but even with an explicit argument, the polynomial is the zero polynomial
79  // (with non-compact storage) so it should always be used in conjunction with
80  // operator[] for setting individual coefficients, at least coefficient [d].
81  vnl_polynomial(int d=-1): coeffs_(d+1) { assert (d>=-1); }
82 
83  //: comparison operator
84  bool operator==(vnl_polynomial<T> const& p) const { return p.coefficients() == coeffs_; }
85 
86  //: Returns negative of this polynomial
88 
89  //: Returns polynomial which is sum of this with polynomial f
91 
92  //: Returns polynomial which is difference of this with polynomial f
93  vnl_polynomial<T> operator-(vnl_polynomial<T> const& f) const { return operator+(-f); }
94 
95  //: Returns polynomial which is product of this with polynomial f
97 
98  //: Returns polynomial which is the result of the long division by polynomial f
99  // Beware that this operation might not make sense for integral types T
100  // if the highest order coefficient of f is not 1 or -1!
102 
103  //: Returns polynomial which is the remainder after a long division by polynomial f
104  // Beware that this operation might not make sense for integral types T
105  // if the highest order coefficient of f is not 1 or -1!
107 
108  vnl_polynomial<T>& operator+=(vnl_polynomial<T> const& f) { return *this = operator+(f); }
109  vnl_polynomial<T>& operator-=(vnl_polynomial<T> const& f) { return *this = operator-(f); }
110  vnl_polynomial<T>& operator*=(vnl_polynomial<T> const& f) { return *this = operator*(f); }
111  vnl_polynomial<T>& operator/=(vnl_polynomial<T> const& f) { return *this = operator/(f); }
112  vnl_polynomial<T>& operator%=(vnl_polynomial<T> const& f) { return *this = operator%(f); }
113 
114  //: Evaluate polynomial at value \p x
115  T evaluate(T const& x) const;
116 
117  //: Return derivative of this polynomial
118  vnl_polynomial<T> derivative() const;
119 
120  //: Evaluate derivative at value \p x
121  T devaluate(T const& x) const { return derivative().evaluate(x); }
122 
123  //: Return primitive function (inverse derivative) of this polynomial
124  // Since a primitive function is not unique, the one with constant term 0 is returned.
125  // Beware that this operation might not make sense for integral types T!
126  vnl_polynomial<T> primitive() const;
127 
128  //: Evaluate integral at \p x (assuming constant of integration is zero)
129  // Beware that this operation might not make sense for integral types T!
130  T evaluate_integral(T const& x) const { return primitive().evaluate(x); }
131 
132  //: Evaluate integral between \p x1 and \p x2
133  // Beware that this operation might not make sense for integral types T!
134  T evaluate_integral(T const& x1, T const& x2) const { return evaluate_integral(x2)-evaluate_integral(x1); }
135 
136  // Data Access---------------------------------------------------------------
137 
138  //: Return the degree (highest power of X) of the polynomial.
139  // If the polynomial is zero, the degree is effectively -1.
140  // Note that this method assumes a compactified representation, i.e., one
141  // where the highest order coefficient is non-zero. Otherwise, the value
142  // returned by degree() will be larger than the degree.
143  int degree() const { return int(coeffs_.size()) - 1; }
144 
145  //: Access to the polynomial coefficient of $X^i$
146  T& operator [] (unsigned int i) { assert(int(i)<=degree()); return coeffs_[i]; }
147  //: Access to the polynomial coefficient of $X^i$
148  T operator [] (unsigned int i) const { assert(int(i)<=degree()); return coeffs_[i]; }
149 
150  //: Return the vector of coefficients
151  const std::vector<T>& coefficients() const { return coeffs_; }
152  //: Return the vector of coefficients
153  std::vector<T>& coefficients() { return coeffs_; }
154 
155  void set_coefficients(std::vector<T> const& coeffs) {coeffs_ = coeffs;}
156 
157  //: Print this polynomial to stream
158  void print(std::ostream& os) const;
159 
160  protected:
161  //: The coefficients of the polynomial.
162  // coeffs_.front() is the const term.
163  // coeffs_[n] is the coefficient of the $X^n$ term
164  std::vector<T> coeffs_;
165 };
166 
167 template <class T>
168 std::ostream& operator<<(std::ostream& os, vnl_polynomial<T> const& p) { p.print(os); return os; }
169 
170 #define VNL_POLYNOMIAL_INSTANTIATE(T) extern "please #include vnl/vnl_polynomial.hxx instead"
171 
172 #endif // vnl_polynomial_h_
T evaluate_integral(T const &x1, T const &x2) const
Evaluate integral between x1 and x2.
T evaluate_integral(T const &x) const
Evaluate integral at x (assuming constant of integration is zero).
vnl_polynomial(int d=-1)
Initialize polynomial of a given degree.
vnl_polynomial(T const *a, unsigned len)
Initialize polynomial from C array, highest order first.
vnl_polynomial< T > & operator-=(vnl_polynomial< T > const &f)
vnl_vector< T > operator *(vnl_matrix_inverse< T > const &i, vnl_vector< T > const &B)
vnl_polynomial< T > & operator+=(vnl_polynomial< T > const &f)
std::vector< T > & coefficients()
Return the vector of coefficients.
void set_coefficients(std::vector< T > const &coeffs)
std::ostream & operator<<(std::ostream &s, vnl_decnum const &r)
decimal output.
Definition: vnl_decnum.h:393
void print(std::ostream &os) const
Print this polynomial to stream.
T devaluate(T const &x) const
Evaluate derivative at value x.
const std::vector< T > & coefficients() const
Return the vector of coefficients.
vnl_polynomial< T > & operator%=(vnl_polynomial< T > const &f)
vnl_polynomial< T > & operator/=(vnl_polynomial< T > const &f)
std::vector< T > coeffs_
The coefficients of the polynomial.
vnl_bignum operator-(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the difference of two bignum numbers.
Definition: vnl_bignum.h:290
vnl_polynomial(std::vector< T > const &a)
Initialize the polynomial from its coefficients, lowest order first.
bool operator==(vnl_polynomial< T > const &p) const
comparison operator.
vnl_bignum operator+(vnl_bignum const &r1, long r2)
Returns the sum of two bignum numbers.
Definition: vnl_bignum.h:279
vnl_polynomial< T > operator-(vnl_polynomial< T > const &f) const
Returns polynomial which is difference of this with polynomial f.
vnl_bignum operator/(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the division of two bignum numbers.
Definition: vnl_bignum.h:349
vnl_polynomial(T const &a)
Initialize polynomial from single value, thus creating a monomial.
int degree() const
Return the degree (highest power of X) of the polynomial.
vnl_bignum operator%(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the remainder of r1 divided by r2.
Definition: vnl_bignum.h:396
Evaluation of polynomials.