cubic_spline.cxx
Go to the documentation of this file.00001 #include <cxxtls/cubic_spline.h>
00002 #include <vector>
00003
00004 namespace cxxtls
00005 {
00006
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 void
00022 cubic_spline::
00023 compute_coefficients()
00027 {
00028 using std::vector;
00029
00030 dirty_ = false;
00031
00032 size_t n = rep_.size();
00033
00034
00035
00036 vector<double> xn(n+1), fn(n+1), rho(n+1), tau(n+1), s(n+1);
00037
00038 {
00039 const_iterator first = rep_.begin(),
00040 last = rep_.end();
00041
00042 vector<double>::iterator xout = xn.begin() + 1;
00043 vector<double>::iterator yout = fn.begin() + 1;
00044
00045 while(first != last)
00046 {
00047 *xout++ = first->first;
00048 *yout++ = first->second.y_;
00049
00050 ++first;
00051 }
00052
00053 }
00054
00055
00056
00057 size_t nm1 = n-1;
00058
00059 rho[2] = 0;
00060 tau[2] = 0;
00061
00062 int i;
00063
00064 for(i=2; i <= static_cast<int>(nm1); ++i)
00065 {
00066 size_t iim1 = i-1;
00067 size_t ii = i;
00068 size_t iip1 = i+1;
00069
00070 double him1 = xn[ii] - xn[iim1];
00071 double hi = xn[iip1]-xn[ii];
00072 double temp = (him1/hi)*(rho[i]+2)+2;
00073
00074 rho[i+1]=-1.0/temp;
00075
00076 double d = 6.0 *((fn[iip1]-fn[ii])/hi-(fn[ii]-fn[iim1])/him1)/hi;
00077
00078 tau[i+1] = (d-him1*tau[i]/hi)/temp;
00079
00080 }
00081
00082 s[1] = 0;
00083 s[n] = 0;
00084
00085 int nm2 = n-2;
00086
00087 for(i=1; i <= nm2; ++i)
00088 {
00089 size_t ib = n-i;
00090 s[ib] = rho[ib+1] * s[ib+1] +tau[ib+1];
00091 }
00092
00093 {
00094 vector<double>::iterator first = s.begin() + 1,
00095 last = s.end();
00096
00097 rep_t::iterator output = rep_.begin();
00098
00099 while(first != last)
00100 {
00101 output->second.s_ = *first++;
00102 ++output;
00103 }
00104
00105 }
00106
00107
00108 }
00109
00110 double
00111 cubic_spline::
00112 evaluate(double x) const
00113 {
00114 using std::vector;
00115
00116 if(dirty_)
00117 {
00118 cubic_spline* me = const_cast<cubic_spline*>(this);
00119 me->compute_coefficients();
00120 }
00121
00122 size_t n = rep_.size();
00123
00124 if(n == 0)
00125 return 0;
00126
00127 if(rep_.size() == 1)
00128 {
00129 return rep_.begin()->second.y_;
00130 }
00131
00132 if( x < rep_.begin()->first )
00133 {
00134 const_iterator lb = rep_.begin();
00135 const_iterator ub = lb; ++ub;
00136
00137 double m = (ub->second.y_ - lb->second.y_) /
00138 (ub->first - lb->first );
00139
00140 double deltax = lb->first - x;
00141 double deltay = m * deltax;
00142
00143 return lb->second.y_ - deltay;
00144 }
00145
00146 rep_t::const_iterator end = rep_.end(); --end;
00147
00148 if( x >= end->first)
00149 {
00150 const_iterator ub = rep_.end(); --ub;
00151 const_iterator lb = ub; --lb;
00152
00153 double m = (ub->second.y_ - lb->second.y_) /
00154 (ub->first - lb->first );
00155
00156 double deltax = x - ub->first ;
00157 double deltay = m * deltax;
00158
00159 return ub->second.y_ + deltay;
00160 }
00161
00162 const_iterator ilp1 = ceil(x);
00163 const_iterator il = floor(x);
00164
00165 double a = ilp1->first - x;
00166 double b = x - il->first;
00167 double h = ilp1->first - il->first;
00168
00169 return a * il->second.s_ * (a * a / h - h)/6.0 +
00170 b * ilp1->second.s_ * (b * b / h - h)/6.0 +
00171 ( a * il->second.y_ + b * ilp1->second.y_)/h;
00172
00173 }
00174
00175 cubic_spline::const_iterator
00176 cubic_spline::
00177 floor(double x) const
00178
00188
00189 {
00190 const_iterator ub = rep_.upper_bound(x);
00191 const_iterator begin = rep_.begin();
00192
00193 while(ub != begin)
00194 {
00195 --ub;
00196
00197 if(ub->first <= x)
00198 return ub;
00199
00200 }
00201
00202 return rep_.end();
00203
00204 }
00205
00206 }