vnl_real_polynomial.cxx
Go to the documentation of this file.
1 // This is core/vnl/vnl_real_polynomial.cxx
2 //:
3 // \file
4 // \brief Evaluation of real polynomials - the implementation
5 // \author Andrew W. Fitzgibbon, Oxford RRG 23 Aug 96
6 //
7 // Modifications
8 // IMS (Manchester) 14/03/2001: Added Manchester IO scheme
9 
10 #include <iostream>
11 #include <complex>
12 #include "vnl_real_polynomial.h"
13 
14 // This is replacing a member template...
15 template <class T>
16 T vnl_real_polynomial_evaluate(double const *a, int n, T const& x)
17 {
18  --n;
19  T acc = a[n];
20  T xn = x;
21  while (n) {
22  acc += a[--n] * xn;
23  xn *= x;
24  } ;
25 
26  return acc;
27 }
28 
29 // The following code confuses doxygen, causing it to link every
30 // mention of double to vnl_real_polynomial::evaluate
31 #ifndef DOXYGEN_SHOULD_SKIP_THIS
32 # ifdef _WIN32
33 # define SELECT(T) <T >
34 # else
35 # define SELECT(T)
36 # endif
37 
38 //: Instantiate templates before use
39 template double vnl_real_polynomial_evaluate SELECT(double )
40  (double const*,int,double const&);
41 template std::complex<double> vnl_real_polynomial_evaluate SELECT(std::complex<double>)
42  (double const*,int,std::complex<double> const&);
43 
44 //: Evaluate polynomial at value x
45 double vnl_real_polynomial::evaluate(double x) const
46 {
47  return vnl_real_polynomial_evaluate SELECT(double)(coeffs_.data_block(), coeffs_.size(), x);
48 }
49 
50 
51 //: Evaluate polynomial at complex value x
52 std::complex<double> vnl_real_polynomial::evaluate(std::complex<double> const& x) const
53 {
54  return vnl_real_polynomial_evaluate SELECT(std::complex<double>)
55  (coeffs_.data_block(), coeffs_.size(), x);
56 }
57 #endif // DOXYGEN_SHOULD_SKIP_THIS
58 
59 //: Evaluate derivative at value x.
60 double vnl_real_polynomial::devaluate(double x) const
61 {
62  return derivative().evaluate(x);
63 }
64 
65 
66 //: Evaluate derivative at complex value x. Not implemented.
67 std::complex<double> vnl_real_polynomial::devaluate(std::complex<double> const& x) const
68 {
69  return derivative().evaluate(x);
70 }
71 
72 //: Evaluate integral at x (assuming constant of integration is zero)
74 {
75  int d = coeffs_.size()-1;
76  const double* f = coeffs_.data_block();
77  double sum = 0.0;
78  int di=1;
79  double xi=x;
80  for (int i=d;i>=0;--i)
81  {
82  sum += f[i]*xi/di;
83  xi*=x;
84  di++;
85  }
86 
87  return sum;
88 }
89 
90 //: Evaluate integral between x1 and x2
91 double vnl_real_polynomial::evaluate_integral(double x1, double x2) const
92 {
93  return evaluate_integral(x2)-evaluate_integral(x1);
94 }
95 
96 //: Returns sum of two polynomials f1(x)+f2(x)
98 {
99  // Degree of result is highest of the two inputs
100  const unsigned int d1=f1.degree();
101  const unsigned int d2=f2.degree();
102  unsigned int d = d1;
103  if (d2>d) d=d2;
104 
105  vnl_real_polynomial sum(d);
106 
107  // Coefficients are stored such that f(i) is coef. on x^(d-i)
108  for (unsigned int i=0; i<=d; ++i)
109  {
110  sum[d-i]=0.0;
111  if (i<=d1) sum[d-i]+=f1[d1-i];
112  if (i<=d2) sum[d-i]+=f2[d2-i];
113  }
114 
115  return sum;
116 }
117 
118 //: Returns sum of two polynomials f1(x)-f2(x)
120 {
121  // Degree of result is highest of the two inputs
122  const unsigned int d1=f1.degree();
123  const unsigned int d2=f2.degree();
124  unsigned int d = d1;
125  if (d2>d) d=d2;
126 
127  vnl_real_polynomial diff(d);
128 
129  // Coefficients are stored such that f(i) is coef. on x^(d-i)
130  for (unsigned int i=0; i<=d; ++i)
131  {
132  diff[d-i]=0.0;
133  if (i<=d1) diff[d-i]+=f1[d1-i];
134  if (i<=d2) diff[d-i]-=f2[d2-i];
135  }
136 
137  return diff;
138 }
139 
140 //: Returns polynomial which is product of two polynomials f1(x)*f2(x)
142 {
143  const unsigned int d1=f1.degree();
144  const unsigned int d2=f2.degree();
145  const unsigned int d = d1+d2;
146 
147  vnl_real_polynomial prod(d);
148  prod.coefficients().fill(0.0);
149 
150  for (unsigned int i=0; i<=d1; ++i)
151  for (unsigned int j=0; j<=d2; ++j)
152  prod[d-(i+j)] += f1[d1-i]*f2[d2-j];
153 
154  return prod;
155 }
156 //: Add rhs to this and return *this
158  *this = (*this) + rhs;
159  return *this;
160 }
161 
162 //: Subtract rhs from this and return *this
164  *this = (*this) - rhs;
165  return *this;
166 }
167 
168 //: multiply rhs with this and return *this
170  *this = (*this) * rhs;
171  return *this;
172 }
173 
174 //: Returns RMS difference between f1 and f2 over range [x1,x2]
175 // $\frac1{\sqrt{|x_2-x_1|}}\,\sqrt{\int_{x_1}^{x_2}\left(f_1(x)-f_2(x)\right)^2\,dx}$
177  double x1, double x2)
178 {
179  double dx = std::fabs(x2-x1);
180  if (dx==0.0) return 0;
181 
182  vnl_real_polynomial df = f2-f1;
183  vnl_real_polynomial df2 = df*df;
184  double area = std::fabs(df2.evaluate_integral(x1,x2));
185  return std::sqrt(area/dx);
186 }
187 
188 //: Return derivative of this polynomial
190 {
191  int d = degree();
192  vnl_vector<double> cd (d);
193  for (int i=d-1,di=1; i>=0; --i,++di)
194  cd[i] = coeffs_[i] * di;
195  return vnl_real_polynomial(cd);
196 }
197 
198 //: Return primitive function (inverse derivative) of this polynomial
199 // Since a primitive function is not unique, the one with constant = 0 is returned
201 {
202  int d = coeffs_.size(); // degree+1
203  vnl_vector<double> cd (d+1);
204  cd[d] = 0.0; // constant term
205  for (int i=d-1,di=1; i>=0; --i,++di)
206  cd[i] = coeffs_[i] / di;
207  return vnl_real_polynomial(cd);
208 }
209 
210 void vnl_real_polynomial::print(std::ostream& os) const
211 {
212  int d = degree();
213  bool first_coeff = true; // to avoid '+' in front of equation
214 
215  for (int i = 0; i <= d; ++i) {
216  if (coeffs_[i] == 0.0) continue;
217  os << ' ';
218  if (coeffs_[i] > 0.0 && !first_coeff) os << '+';
219  if (i==d) os << coeffs_[i]; // the 0-degree coeff should always be output if not zero
220  else if (coeffs_[i] == -1.0) os << '-';
221  else if (coeffs_[i] != 1.0) os << coeffs_[i] << ' ';
222 
223  if (i < d-1) os << "X^" << d-i;
224  else if (i == d-1) os << 'X';
225  first_coeff = false;
226  }
227  if (first_coeff) os << " 0";
228 }
vnl_bignum operator+(vnl_bignum const &r1, long r2)
Returns the sum of two bignum numbers.
Definition: vnl_bignum.h:279
vnl_real_polynomial & operator *=(vnl_real_polynomial const &rhs)
Multiply rhs with this and return *this.
vnl_real_polynomial(vnl_vector< double > const &a)
Initialize polynomial.
vnl_real_polynomial & operator-=(vnl_real_polynomial const &rhs)
Subtract rhs from this and return *this.
T vnl_real_polynomial_evaluate(double const *a, int n, T const &x)
size_t size() const
Return the length, number of elements, dimension of this vector.
Definition: vnl_vector.h:126
T const * data_block() const
Access the contiguous block storing the elements in the vector. O(1).
Definition: vnl_vector.h:230
double evaluate(double x) const
Evaluate polynomial at value x.
const vnl_vector< double > & coefficients() const
Return the vector of coefficients.
Evaluation of real polynomials at real and complex points.
void print(std::ostream &os) const
Print this polynomial to stream.
VNL_EXPORT double vnl_rms_difference(const vnl_real_polynomial &f1, const vnl_real_polynomial &f2, double x1, double x2)
Returns RMS difference between f1 and f2 over range [x1,x2].
vnl_real_polynomial & operator+=(vnl_real_polynomial const &rhs)
Add rhs to this and return *this.
vnl_vector & fill(T const &v)
Set all values to v.
Definition: vnl_vector.hxx:314
vnl_real_polynomial primitive() const
Return primitive function (inverse derivative) of this 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_real_polynomial derivative() const
Return derivative of this polynomial.
vnl_vector< double > coeffs_
The coefficients of the polynomial.
double devaluate(double x) const
Evaluate derivative at value x.
vnl_bignum operator *(vnl_bignum const &r1, vnl_bignum const &r2)
Returns the product of two bignum numbers.
Definition: vnl_bignum.h:302
int degree() const
Return the degree (highest power of x) of the polynomial.
double evaluate_integral(double x) const
Evaluate integral at x (assuming constant of integration is zero).
Evaluation of real polynomials.