vnl_polynomial.hxx
Go to the documentation of this file.
1 // This is core/vnl/vnl_polynomial.hxx
2 #ifndef vnl_polynomial_hxx_
3 #define vnl_polynomial_hxx_
4 
5 #include <iostream>
6 #include "vnl_polynomial.h"
7 //:
8 // \file
9 // \brief Evaluation of polynomials - the implementation
10 // Templated class (on the data type of the coefficients),
11 // further very similar to the vnl_real_polynomial class.
12 // \author Peter Vanroose, ABIS Leuven.
13 // \date August 2011
14 
15 #ifdef _MSC_VER
16 # include <vcl_msvc_warnings.h>
17 #endif
18 #include <cassert>
19 
20 //: Evaluate polynomial at value x
21 template <class T>
22 T vnl_polynomial<T>::evaluate(T const& x) const
23 {
24  typename std::vector<T>::const_iterator i = coeffs_.begin();
25  if (i == coeffs_.end()) return T(0);
26  T acc = *i;
27  T xi = x; // will be x^i
28  for (++i; i!=coeffs_.end(); ++i) {
29  acc += *i * xi;
30  xi *= x;
31  }
32  return acc;
33 }
34 
35 //: Returns negative of this polynomial
36 template <class T>
38 {
39  std::vector<T> neg = coeffs_;
40  typename std::vector<T>::iterator i = neg.begin();
41  for (; i!=neg.end(); ++i) *i = - *i;
42  return vnl_polynomial<T>(neg);
43 }
44 
45 //: Returns polynomial which is sum of this with polynomial f
46 template <class T>
48 {
49  // Degree of result is (at most) the maximum of the two input degrees:
50  int d=degree(), d2=f.degree(); // any or both of these might be -1 !
51  std::vector<T> sum = coeffs_;
52  for (int i=0;i<=d&&i<=d2;++i) sum[i]+=f[i];
53  for (int i=d+1;i<=d2;++i) sum.push_back(f[i]);
54  // normalise the result, viz. such that the highest order coefficient is zero:
55  while (sum.end() != sum.begin() && sum.back() == T(0)) sum.pop_back();
56  return vnl_polynomial<T>(sum);
57 }
58 
59 //: Returns polynomial which is product of this with polynomial f
60 template <class T>
62 {
63  int d1=degree(), d2=f.degree(), d = d1+d2;
64  if (d1<0 || d2<0) return vnl_polynomial<T>(); // one of the factors is zero
65  std::vector<T> prod(d+1, T(0));
66  for (int i=0;i<=d1;++i)
67  for (int j=0;j<=d2;++j)
68  prod[i+j] += coeffs_[i]*f[j];
69  return vnl_polynomial<T>(prod);
70 }
71 
72 //: Returns polynomial which is the result of a long division by f
73 // Beware that this operation might not make sense for integral types T
74 // if the highest order coefficient of f is not 1 or -1!
75 template <class T>
77 {
78  int d1=degree(), d2=f.degree(), d=d1-d2; // d will be the degree of the quotient
79  assert (d2 >= 0 && f[d2] != T(0)); // denominator should not be zero
80  if (d<0) return vnl_polynomial<T>(); // nominator is zero, or denominator has higher degree than nominator
81  std::vector<T> quot;
82  for (int i=0;i<=d;++i) {
83  T acc = coeffs_[d1-i];
84  for (int j=0;j<d2&&j<i;++j) acc -= quot[j] * f[d2-j-1];
85  quot.insert(quot.begin(), 1, acc/f[d2]);
86  }
87  return vnl_polynomial<T>(quot);
88 }
89 
90 //: Returns polynomial which is the remainder after long division by f
91 // Beware that this operation might not make sense for integral types T
92 // if the highest order coefficient of f is not 1 or -1!
93 template <class T>
95 {
96  vnl_polynomial<T> quot = operator/(f);
97  if (quot.degree() < 0) return *this;
98  vnl_polynomial<T> prod = f * quot;
99  int n=f.degree(); // size of the result, i.e., one more than degree of the result
100  std::vector<T> diff;
101  for (int i=0; i<n; ++i) diff.push_back(coeffs_[i] - prod[i]);
102  // normalise the result, viz. such that the highest order coefficient is zero:
103  while (diff.end() != diff.begin() && diff.back() == T(0)) diff.pop_back();
104  return vnl_polynomial<T>(diff);
105 }
106 
107 //: Return derivative of this polynomial
108 template <class T>
110 {
111  std::vector<T> cd; // will be one shorter than coeffs_
112  typename std::vector<T>::const_iterator i = coeffs_.begin();
113  T n = T(1);
114  for (++i; i!=coeffs_.end(); ++i,++n)
115  cd.push_back(*i * n);
116  return vnl_polynomial<T>(cd);
117 }
118 
119 //: Return primitive function (inverse derivative) of this polynomial
120 // Since a primitive function is not unique, the one with constant = 0 is returned
121 // Beware that this operation might not make sense for integral types T!
122 template <class T>
124 {
125  std::vector<T> cd; // will be one longer than coeffs_
126  T n = T(0);
127  cd.push_back(n);
128  typename std::vector<T>::const_iterator i = coeffs_.begin();
129  for (++n; i!=coeffs_.end(); ++i,++n)
130  cd.push_back(*i / n);
131  return vnl_polynomial<T>(cd);
132 }
133 
134 template <class T>
135 void vnl_polynomial<T>::print(std::ostream& os) const
136 {
137  bool first_coeff = true;
138 
139  for (int i=degree(); i >= 0; --i) {
140  if (coeffs_[i] == T(0)) continue;
141  os << ' ';
142  if (coeffs_[i] > T(0) && !first_coeff) os << '+';
143  if (i==0) os << coeffs_[i];
144  else if (coeffs_[i] == -T(1)) os << '-';
145  else if (coeffs_[i] != T(1)) os << coeffs_[i] << ' ';
146  if (i == 1) os << 'X';
147  else if (i != 0) os << "X^" << i;
148  first_coeff = false;
149  }
150  if (first_coeff) os << " 0";
151 }
152 
153 #undef VNL_POLYNOMIAL_INSTANTIATE
154 #define VNL_POLYNOMIAL_INSTANTIATE(T) \
155 template class VNL_EXPORT vnl_polynomial<T >; \
156 template VNL_EXPORT std::ostream& operator<<(std::ostream& os, vnl_polynomial<T > const&)
157 
158 #endif // vnl_polynomial_hxx_
vnl_polynomial< T > operator+(vnl_polynomial< T > const &f) const
Returns polynomial which is sum of this with polynomial f.
vnl_polynomial< T > operator/(vnl_polynomial< T > const &f) const
Returns polynomial which is the result of the long division by polynomial f.
vnl_polynomial< T > operator%(vnl_polynomial< T > const &f) const
Returns polynomial which is the remainder after a long division by polynomial f.
void print(std::ostream &os) const
Print this polynomial to stream.
Evaluation of univariate polynomials Templated class (on the data type of the coefficients),...
vnl_polynomial< T > derivative() const
Return derivative of this polynomial.
vnl_polynomial< T > operator-() const
Returns negative of this polynomial.
vnl_polynomial< T > operator *(vnl_polynomial< T > const &f) const
Returns polynomial which is product of this with polynomial f.
vnl_polynomial< T > primitive() const
Return primitive function (inverse derivative) of this polynomial.
T evaluate(T const &x) const
Evaluate polynomial at value x.
vnl_bignum operator/(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the division of two bignum numbers.
Definition: vnl_bignum.h:349
int degree() const
Return the degree (highest power of X) of the polynomial.
Evaluation of polynomials.