00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "vnl_real_polynomial.h"
00014 #include <vcl_iostream.h>
00015 #include <vcl_complex.h>
00016 #include <vcl_cmath.h>
00017
00018
00019 template <class T>
00020 T vnl_real_polynomial_evaluate(double const *a, int n, T const& x)
00021 {
00022 --n;
00023 T acc = a[n];
00024 T xn = x;
00025 while (n) {
00026 acc += a[--n] * xn;
00027 xn *= x;
00028 } ;
00029
00030 return acc;
00031 }
00032
00033
00034
00035 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00036 # ifdef VCL_WIN32
00037 # define SELECT(T) <T >
00038 # else
00039 # define SELECT(T)
00040 # endif
00041
00042
00043 template double vnl_real_polynomial_evaluate SELECT(double )
00044 (double const*,int,double const&);
00045 template vcl_complex<double> vnl_real_polynomial_evaluate SELECT(vcl_complex<double>)
00046 (double const*,int,vcl_complex<double> const&);
00047
00048
00049 double vnl_real_polynomial::evaluate(double x) const
00050 {
00051 return vnl_real_polynomial_evaluate SELECT(double)(coeffs_.data_block(), coeffs_.size(), x);
00052 }
00053
00054
00055
00056 vcl_complex<double> vnl_real_polynomial::evaluate(vcl_complex<double> const& x) const
00057 {
00058 return vnl_real_polynomial_evaluate SELECT(vcl_complex<double>)
00059 (coeffs_.data_block(), coeffs_.size(), x);
00060 }
00061 #endif // DOXYGEN_SHOULD_SKIP_THIS
00062
00063
00064 double vnl_real_polynomial::devaluate(double x) const
00065 {
00066 return derivative().evaluate(x);
00067 }
00068
00069
00070
00071 vcl_complex<double> vnl_real_polynomial::devaluate(vcl_complex<double> const& x) const
00072 {
00073 return derivative().evaluate(x);
00074 }
00075
00076
00077 double vnl_real_polynomial::evaluate_integral(double x) const
00078 {
00079 int d = coeffs_.size()-1;
00080 const double* f = coeffs_.data_block();
00081 double sum = 0.0;
00082 int di=1;
00083 double xi=x;
00084 for (int i=d;i>=0;--i)
00085 {
00086 sum += f[i]*xi/di;
00087 xi*=x;
00088 di++;
00089 }
00090
00091 return sum;
00092 }
00093
00094
00095 double vnl_real_polynomial::evaluate_integral(double x1, double x2) const
00096 {
00097 return evaluate_integral(x2)-evaluate_integral(x1);
00098 }
00099
00100
00101 vnl_real_polynomial operator+(const vnl_real_polynomial& f1, const vnl_real_polynomial& f2)
00102 {
00103
00104 int d1=f1.degree();
00105 int d2=f2.degree();
00106 int d = d1;
00107 if (d2>d) d=d2;
00108
00109 vnl_real_polynomial sum(d);
00110
00111
00112 for (int i=0;i<=d;++i)
00113 {
00114 sum[d-i]=0.0;
00115 if (i<=d1) sum[d-i]+=f1[d1-i];
00116 if (i<=d2) sum[d-i]+=f2[d2-i];
00117 }
00118
00119 return sum;
00120 }
00121
00122
00123 vnl_real_polynomial operator-(const vnl_real_polynomial& f1, const vnl_real_polynomial& f2)
00124 {
00125
00126 int d1=f1.degree();
00127 int d2=f2.degree();
00128 int d = d1;
00129 if (d2>d) d=d2;
00130
00131 vnl_real_polynomial sum(d);
00132
00133
00134 for (int i=0;i<=d;++i)
00135 {
00136 sum[d-i]=0.0;
00137 if (i<=d1) sum[d-i]+=f1[d1-i];
00138 if (i<=d2) sum[d-i]-=f2[d2-i];
00139 }
00140
00141 return sum;
00142 }
00143
00144
00145 vnl_real_polynomial operator*(const vnl_real_polynomial& f1, const vnl_real_polynomial& f2)
00146 {
00147 int d1=f1.degree();
00148 int d2=f2.degree();
00149 int d = d1+d2;
00150
00151 vnl_real_polynomial sum(d);
00152 sum.coefficients().fill(0.0);
00153
00154 for (int i=0;i<=d1;++i)
00155 for (int j=0;j<=d2;++j)
00156 sum[d-(i+j)] += (f1[d1-i]*f2[d2-j]);
00157
00158 return sum;
00159 }
00160
00161
00162
00163 double vnl_rms_difference(const vnl_real_polynomial& f1, const vnl_real_polynomial& f2,
00164 double x1, double x2)
00165 {
00166 double dx = vcl_fabs(x2-x1);
00167 if (dx==0.0) return 0;
00168
00169 vnl_real_polynomial df = f2-f1;
00170 vnl_real_polynomial df2 = df*df;
00171 double area = vcl_fabs(df2.evaluate_integral(x1,x2));
00172 return vcl_sqrt(area/dx);
00173 }
00174
00175
00176 vnl_real_polynomial vnl_real_polynomial::derivative() const
00177 {
00178 vnl_vector<double> c = coefficients();
00179 int d = degree();
00180 vnl_vector<double> cd (d);
00181 for (int i=0; i<d; ++i)
00182 cd[i] = c[i] * (d-i);
00183 return vnl_real_polynomial(cd);
00184 }
00185
00186
00187
00188 vnl_real_polynomial vnl_real_polynomial::primitive() const
00189 {
00190 vnl_vector<double> c = coefficients();
00191 int d = degree();
00192 vnl_vector<double> cd (d+2);
00193 for (int i=0; i<=d; ++i)
00194 cd[i] = c[i] / (d-i+1);
00195 cd[d+1] = 0.0;
00196 return vnl_real_polynomial(cd);
00197 }
00198
00199 void vnl_real_polynomial::print(vcl_ostream& os) const
00200 {
00201 int d = degree();
00202 int i = 0;
00203 while (i <= d && coeffs_[i] == 0) ++i;
00204 if (i > d) { os << "0 "; return; }
00205 bool b = (coeffs_[i+1] > 0);
00206
00207 for (; i <= d; ++i) {
00208 if (coeffs_[i] == 0) continue;
00209 if (coeffs_[i] > 0 && !b) os << '+';
00210 b = false;
00211 if (coeffs_[i] == -1) os << '-';
00212 else if (coeffs_[i] != 1) os << coeffs_[i];
00213
00214 if (i < d-1) os << " X^" << d-i << ' ';
00215 else if (i == d-1) os << " X ";
00216 }
00217 }