g4tools  5.4.0
Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes | List of all members
tools::spline::cubic Class Reference
Inheritance diagram for tools::spline::cubic:
Inheritance graph
[legend]
Collaboration diagram for tools::spline::cubic:
Collaboration graph
[legend]

Public Member Functions

 cubic (std::ostream &a_out, size_t a_n, double a_x[], double a_y[], double a_valbeg=0, double a_valend=0)
 
 cubic (const cubic &a_from)
 
cubicoperator= (const cubic &a_from)
 
double eval (double x) const
 
- Public Member Functions inherited from tools::spline::base_spline
 base_spline (std::ostream &a_out, double delta, double xmin, double xmax, size_t np, bool step)
 
virtual ~base_spline ()
 

Protected Member Functions

 cubic (std::ostream &a_out)
 
size_t find_x (double x) const
 
void build_coeff ()
 
- Protected Member Functions inherited from tools::spline::base_spline
 base_spline (std::ostream &a_out)
 
 base_spline (const base_spline &a_from)
 
base_splineoperator= (const base_spline &a_from)
 

Static Protected Member Functions

template<typename T >
static int TMath_Nint (T x)
 
static int TMath_FloorNint (double x)
 

Protected Attributes

std::vector< cubic_polyfPoly
 
double fValBeg
 
double fValEnd
 
int fBegCond
 
int fEndCond
 
- Protected Attributes inherited from tools::spline::base_spline
std::ostream & m_out
 
double fDelta
 
double fXmin
 
double fXmax
 
size_t fNp
 
bool fKstep
 

Detailed Description

Definition at line 145 of file spline.

Constructor & Destructor Documentation

◆ cubic() [1/3]

tools::spline::cubic::cubic ( std::ostream &  a_out)
inlineprotected

Definition at line 147 of file spline.

147 : base_spline(a_out) , fPoly(0), fValBeg(0), fValEnd(0), fBegCond(-1), fEndCond(-1) {}

◆ cubic() [2/3]

tools::spline::cubic::cubic ( std::ostream &  a_out,
size_t  a_n,
double  a_x[],
double  a_y[],
double  a_valbeg = 0,
double  a_valend = 0 
)
inline

Definition at line 149 of file spline.

150  :base_spline(a_out,-1,0,0,a_n,false)
151  ,fValBeg(a_valbeg), fValEnd(a_valend), fBegCond(0), fEndCond(0)
152  {
153  if(!a_n) {
154  m_out << "tools::spline::cubic : a_np is null." << std::endl;
155  return;
156  }
157  fXmin = a_x[0];
158  fXmax = a_x[a_n-1];
159  fPoly.resize(a_n);
160  for (size_t i=0; i<a_n; ++i) {
161  fPoly[i].X() = a_x[i];
162  fPoly[i].Y() = a_y[i];
163  }
164  build_coeff(); // Build the spline coefficients
165  }

◆ cubic() [3/3]

tools::spline::cubic::cubic ( const cubic a_from)
inline

Definition at line 167 of file spline.

168  :base_spline(a_from)
169  ,fPoly(a_from.fPoly),fValBeg(a_from.fValBeg),fValEnd(a_from.fValEnd),fBegCond(a_from.fBegCond),fEndCond(a_from.fEndCond)
170  {}

Member Function Documentation

◆ build_coeff()

void tools::spline::cubic::build_coeff ( )
inlineprotected

subroutine cubspl ( tau, c, n, ibcbeg, ibcend ) from * a practical guide to splines * by c. de boor ************************ input *************************** n = number of data points. assumed to be .ge. 2. (tau(i), c(1,i), i=1,...,n) = abscissae and ordinates of the data points. tau is assumed to be strictly increasing. ibcbeg, ibcend = boundary condition indicators, and c(2,1), c(2,n) = boundary condition information. specifically, ibcbeg = 0 means no boundary condition at tau(1) is given. in this case, the not-a-knot condition is used, i.e. the jump in the third derivative across tau(2) is forced to zero, thus the first and the second cubic polynomial pieces are made to coincide.) ibcbeg = 1 means that the slope at tau(1) is made to equal c(2,1), supplied by input. ibcbeg = 2 means that the second derivative at tau(1) is made to equal c(2,1), supplied by input. ibcend = 0, 1, or 2 has analogous meaning concerning the boundary condition at tau(n), with the additional infor- mation taken from c(2,n). *********************** output ************************** c(j,i), j=1,...,4; i=1,...,l (= n-1) = the polynomial coefficients of the cubic interpolating spline with interior knots (or joints) tau(2), ..., tau(n-1). precisely, in the interval (tau(i), tau(i+1)), the spline f is given by f(x) = c(1,i)+h*(c(2,i)+h*(c(3,i)+h*c(4,i)/3.)/2.) where h = x - tau(i). the function program ppvalu may be used to evaluate f or its derivatives from tau,c, l = n-1, and k=4.

Definition at line 243 of file spline.

243  {
273 
274  int j, l;
275  double divdf1,divdf3,dtau,g=0;
276  // ***** a tridiagonal linear system for the unknown slopes s(i) of
277  // f at tau(i), i=1,...,n, is generated and then solved by gauss elim-
278  // ination, with s(i) ending up in c(2,i), all i.
279  // c(3,.) and c(4,.) are used initially for temporary storage.
280  l = fNp-1;
281  // compute first differences of x sequence and store in C also,
282  // compute first divided difference of data and store in D.
283  {for (size_t m=1; m<fNp ; ++m) {
284  fPoly[m].C() = fPoly[m].X() - fPoly[m-1].X();
285  fPoly[m].D() = (fPoly[m].Y() - fPoly[m-1].Y())/fPoly[m].C();
286  }}
287  // construct first equation from the boundary condition, of the form
288  // D[0]*s[0] + C[0]*s[1] = B[0]
289  if(fBegCond==0) {
290  if(fNp == 2) {
291  // no condition at left end and n = 2.
292  fPoly[0].D() = 1.;
293  fPoly[0].C() = 1.;
294  fPoly[0].B() = 2.*fPoly[1].D();
295  } else {
296  // not-a-knot condition at left end and n .gt. 2.
297  fPoly[0].D() = fPoly[2].C();
298  fPoly[0].C() = fPoly[1].C() + fPoly[2].C();
299  fPoly[0].B() = ((fPoly[1].C()+2.*fPoly[0].C())*fPoly[1].D()*fPoly[2].C()+
300  fPoly[1].C()*fPoly[1].C()*fPoly[2].D())/fPoly[0].C();
301  }
302  } else if (fBegCond==1) {
303  // slope prescribed at left end.
304  fPoly[0].B() = fValBeg;
305  fPoly[0].D() = 1.;
306  fPoly[0].C() = 0.;
307  } else if (fBegCond==2) {
308  // second derivative prescribed at left end.
309  fPoly[0].D() = 2.;
310  fPoly[0].C() = 1.;
311  fPoly[0].B() = 3.*fPoly[1].D() - fPoly[1].C()/2.*fValBeg;
312  }
313  bool forward_gauss_elimination = true;
314  if(fNp > 2) {
315  // if there are interior knots, generate the corresp. equations and car-
316  // ry out the forward pass of gauss elimination, after which the m-th
317  // equation reads D[m]*s[m] + C[m]*s[m+1] = B[m].
318  {for (int m=1; m<l; ++m) {
319  g = -fPoly[m+1].C()/fPoly[m-1].D();
320  fPoly[m].B() = g*fPoly[m-1].B() + 3.*(fPoly[m].C()*fPoly[m+1].D()+fPoly[m+1].C()*fPoly[m].D());
321  fPoly[m].D() = g*fPoly[m-1].C() + 2.*(fPoly[m].C() + fPoly[m+1].C());
322  }}
323  // construct last equation from the second boundary condition, of the form
324  // (-g*D[n-2])*s[n-2] + D[n-1]*s[n-1] = B[n-1]
325  // if slope is prescribed at right end, one can go directly to back-
326  // substitution, since c array happens to be set up just right for it
327  // at this point.
328  if(fEndCond == 0) {
329  if (fNp > 3 || fBegCond != 0) {
330  // not-a-knot and n .ge. 3, and either n.gt.3 or also not-a-knot at
331  // left end point.
332  g = fPoly[fNp-2].C() + fPoly[fNp-1].C();
333  fPoly[fNp-1].B() = ((fPoly[fNp-1].C()+2.*g)*fPoly[fNp-1].D()*fPoly[fNp-2].C()
334  + fPoly[fNp-1].C()*fPoly[fNp-1].C()*(fPoly[fNp-2].Y()-fPoly[fNp-3].Y())/fPoly[fNp-2].C())/g;
335  g = -g/fPoly[fNp-2].D();
336  fPoly[fNp-1].D() = fPoly[fNp-2].C();
337  } else {
338  // either (n=3 and not-a-knot also at left) or (n=2 and not not-a-
339  // knot at left end point).
340  fPoly[fNp-1].B() = 2.*fPoly[fNp-1].D();
341  fPoly[fNp-1].D() = 1.;
342  g = -1./fPoly[fNp-2].D();
343  }
344  } else if (fEndCond == 1) {
345  fPoly[fNp-1].B() = fValEnd;
346  forward_gauss_elimination = false;
347  } else if (fEndCond == 2) {
348  // second derivative prescribed at right endpoint.
349  fPoly[fNp-1].B() = 3.*fPoly[fNp-1].D() + fPoly[fNp-1].C()/2.*fValEnd;
350  fPoly[fNp-1].D() = 2.;
351  g = -1./fPoly[fNp-2].D();
352  }
353  } else {
354  if(fEndCond == 0) {
355  if (fBegCond > 0) {
356  // either (n=3 and not-a-knot also at left) or (n=2 and not not-a-
357  // knot at left end point).
358  fPoly[fNp-1].B() = 2.*fPoly[fNp-1].D();
359  fPoly[fNp-1].D() = 1.;
360  g = -1./fPoly[fNp-2].D();
361  } else {
362  // not-a-knot at right endpoint and at left endpoint and n = 2.
363  fPoly[fNp-1].B() = fPoly[fNp-1].D();
364  forward_gauss_elimination = false;
365  }
366  } else if(fEndCond == 1) {
367  fPoly[fNp-1].B() = fValEnd;
368  forward_gauss_elimination = false;
369  } else if(fEndCond == 2) {
370  // second derivative prescribed at right endpoint.
371  fPoly[fNp-1].B() = 3.*fPoly[fNp-1].D() + fPoly[fNp-1].C()/2.*fValEnd;
372  fPoly[fNp-1].D() = 2.;
373  g = -1./fPoly[fNp-2].D();
374  }
375  }
376  // complete forward pass of gauss elimination.
377  if(forward_gauss_elimination) {
378  fPoly[fNp-1].D() = g*fPoly[fNp-2].C() + fPoly[fNp-1].D();
379  fPoly[fNp-1].B() = (g*fPoly[fNp-2].B() + fPoly[fNp-1].B())/fPoly[fNp-1].D();
380  }
381  // carry out back substitution
382  j = l-1;
383  do {
384  fPoly[j].B() = (fPoly[j].B() - fPoly[j].C()*fPoly[j+1].B())/fPoly[j].D();
385  --j;
386  } while (j>=0);
387  // ****** generate cubic coefficients in each interval, i.e., the deriv.s
388  // at its left endpoint, from value and slope at its endpoints.
389  for (size_t i=1; i<fNp; ++i) {
390  dtau = fPoly[i].C();
391  divdf1 = (fPoly[i].Y() - fPoly[i-1].Y())/dtau;
392  divdf3 = fPoly[i-1].B() + fPoly[i].B() - 2.*divdf1;
393  fPoly[i-1].C() = (divdf1 - fPoly[i-1].B() - divdf3)/dtau;
394  fPoly[i-1].D() = (divdf3/dtau)/dtau;
395  }
396  }

◆ eval()

double tools::spline::cubic::eval ( double  x) const
inline

Definition at line 182 of file spline.

182  {
183  if(!fNp) return 0;
184  // Eval this spline at x
185  size_t klow = find_x(x);
186  if ( (fNp > 1) && (klow >= (fNp-1))) klow = fNp-2; //see: https://savannah.cern.ch/bugs/?71651
187  return fPoly[klow].eval(x);
188  }

◆ find_x()

size_t tools::spline::cubic::find_x ( double  x) const
inlineprotected

Definition at line 205 of file spline.

205  {
206  int klow=0, khig=fNp-1;
207  //
208  // If out of boundaries, extrapolate
209  // It may be badly wrong
210  if(x<=fXmin) klow=0;
211  else if(x>=fXmax) klow=khig;
212  else {
213  if(fKstep) { // Equidistant knots, use histogramming :
214  klow = TMath_FloorNint((x-fXmin)/fDelta);
215  // Correction for rounding errors
216  if (x < fPoly[klow].X())
217  klow = mx<int>(klow-1,0);
218  else if (klow < khig) {
219  if (x > fPoly[klow+1].X()) ++klow;
220  }
221  } else {
222  int khalf;
223  //
224  // Non equidistant knots, binary search
225  while((khig-klow)>1) {
226  khalf = (klow+khig)/2;
227  if(x>fPoly[khalf].X()) klow=khalf;
228  else khig=khalf;
229  }
230  //
231  // This could be removed, sanity check
232  if( (x<fPoly[klow].X()) || (fPoly[klow+1].X()<x) ) {
233  m_out << "tools::spline::cubic::find_x : Binary search failed"
234  << " x(" << klow << ") = " << fPoly[klow].X() << " < x= " << x
235  << " < x(" << klow+1 << ") = " << fPoly[klow+1].X() << "."
236  << "." << std::endl;
237  }
238  }
239  }
240  return klow;
241  }

◆ operator=()

cubic& tools::spline::cubic::operator= ( const cubic a_from)
inline

Definition at line 171 of file spline.

171  {
172  if(this==&a_from) return *this;
173  base_spline::operator=(a_from);
174  fPoly = a_from.fPoly;
175  fValBeg=a_from.fValBeg;
176  fValEnd=a_from.fValEnd;
177  fBegCond=a_from.fBegCond;
178  fEndCond=a_from.fEndCond;
179  return *this;
180  }

◆ TMath_FloorNint()

static int tools::spline::cubic::TMath_FloorNint ( double  x)
inlinestaticprotected

Definition at line 203 of file spline.

203 { return TMath_Nint(::floor(x)); }

◆ TMath_Nint()

template<typename T >
static int tools::spline::cubic::TMath_Nint ( x)
inlinestaticprotected

Definition at line 191 of file spline.

191  {
192  // Round to nearest integer. Rounds half integers to the nearest even integer.
193  int i;
194  if (x >= 0) {
195  i = int(x + 0.5);
196  if ( i & 1 && x + 0.5 == T(i) ) i--;
197  } else {
198  i = int(x - 0.5);
199  if ( i & 1 && x - 0.5 == T(i) ) i++;
200  }
201  return i;
202  }

Member Data Documentation

◆ fBegCond

int tools::spline::cubic::fBegCond
protected

Definition at line 402 of file spline.

◆ fEndCond

int tools::spline::cubic::fEndCond
protected

Definition at line 403 of file spline.

◆ fPoly

std::vector<cubic_poly> tools::spline::cubic::fPoly
protected

Definition at line 399 of file spline.

◆ fValBeg

double tools::spline::cubic::fValBeg
protected

Definition at line 400 of file spline.

◆ fValEnd

double tools::spline::cubic::fValEnd
protected

Definition at line 401 of file spline.


The documentation for this class was generated from the following file:
tools::spline::cubic::find_x
size_t find_x(double x) const
Definition: spline:205
tools::spline::base_spline::fDelta
double fDelta
Definition: spline:127
tools::spline::cubic::fValEnd
double fValEnd
Definition: spline:401
tools::spline::base_spline::m_out
std::ostream & m_out
Definition: spline:126
tools::spline::cubic::TMath_FloorNint
static int TMath_FloorNint(double x)
Definition: spline:203
tools::spline::base_spline::operator=
base_spline & operator=(const base_spline &a_from)
Definition: spline:116
tools::spline::base_spline::fNp
size_t fNp
Definition: spline:130
tools::spline::cubic::fPoly
std::vector< cubic_poly > fPoly
Definition: spline:399
tools::spline::cubic::TMath_Nint
static int TMath_Nint(T x)
Definition: spline:191
tools::spline::base_spline::base_spline
base_spline(std::ostream &a_out)
Definition: spline:106
tools::spline::base_spline::fKstep
bool fKstep
Definition: spline:131
tools::spline::cubic::fValBeg
double fValBeg
Definition: spline:400
tools::spline::cubic::build_coeff
void build_coeff()
Definition: spline:243
tools::spline::base_spline::fXmin
double fXmin
Definition: spline:128
tools::spline::base_spline::fXmax
double fXmax
Definition: spline:129
tools::spline::cubic::fEndCond
int fEndCond
Definition: spline:403
tools::spline::cubic::fBegCond
int fBegCond
Definition: spline:402