33 #define SP_REAL_PASTE(prefix,suffix) prefix##suffix
34 #define SP_PASTE(prefix,suffix) SP_REAL_PASTE(prefix,suffix)
41 #undef SP_REAL_STRINGIZE
43 #define SP_REAL_STRINGIZE(s) #s
44 #define SP_STRINGIZE(s) SP_REAL_STRINGIZE(s)
51 #define SPLINE_FN(name) SP_PASTE(name, SP_OBJ)
53 static int SPLINE_FN(expand_)(SP_OBJ *sp,
int nmax);
66 SP_OBJ *SPLINE_FN(new_)(
int npts)
72 sp = (SP_OBJ *) malloc(
sizeof(SP_OBJ));
74 lprintf(stderr, SP_STRINGIZE(SPLINE_FN(new_))
": Insufficient memory.\n");
93 if(npts > 0 && SPLINE_FN(expand_)(sp, npts))
94 return SPLINE_FN(del_)(sp);
107 SP_OBJ *SPLINE_FN(del_)(SP_OBJ *sp)
115 sp->x = sp->y = sp->y2 = sp->wrk = NULL;
131 static int SPLINE_FN(expand_)(SP_OBJ *sp,
int nmax)
136 if(nmax > sp->nmax) {
140 size_t needed = 4 * nmax *
sizeof(SP_TYPE);
145 SP_TYPE *memory = (SP_TYPE* )(sp->memory ? realloc(sp->memory, needed) : malloc(needed));
147 lprintf(stderr, SP_STRINGIZE(SPLINE_FN(expand_))
": Insufficient memory.\n");
155 sp->wrk = (sp->y2 = (sp->y = (sp->x = memory) + nmax) + nmax) + nmax;
192 int SPLINE_FN(create_)(SP_OBJ *sp, SP_TYPE *x, SP_TYPE *y,
int npts)
204 if(SPLINE_FN(expand_)(sp, npts))
209 memcpy(sp->x, x, npts *
sizeof(SP_TYPE));
210 memcpy(sp->y, y, npts *
sizeof(SP_TYPE));
241 betaij = &sp->wrk[1];
245 for(j=1; j<npts-1; j++,x++,y++,y2++,betaij++) {
251 *betaij = (1.0f-lambda)/betajj;
255 xspan = x[1] - x[-1];
256 lambda = (x[0] - x[-1])/xspan;
260 betajj = 2.0f - lambda * *betaij;
264 yval = 6.0f * ((y[0]-y[1])/(x[0]-x[1]) - (y[-1]-y[0])/(x[-1]-x[0]))/xspan;
269 *y2 = (yval - lambda * y2[-1])/betajj;
284 for(j=npts-2; j>0; j--,y2--,betaij--)
285 y2[-1] -= *betaij * *y2;
311 int SPLINE_FN(eval_)(SP_OBJ *sp, SP_TYPE xpos,
int sequential,
316 SP_TYPE *y2 = sp->y2;
323 if(xpos < x[0] || xpos > x[npts-1]) {
324 lprintf(stderr, SP_STRINGIZE(SPLINE_FN(eval_))
": X value (%g) not in range %g -> %g.\n",
325 xpos, x[0], x[npts-1]);
332 if(xpos > x[sp->below]) {
333 for(above=sp->below; xpos > x[above]; above++);
336 for(below=sp->below; xpos < x[below]; below--);
346 while(above-below > 1) {
347 mid = (above + below)/2;
363 SP_TYPE h = x[above] - x[below];
364 SP_TYPE a = (x[above] - xpos)/h;
365 SP_TYPE b = (xpos - x[below])/h;
366 *yval = a*y[below] + b*y[above] + h * h *
367 (a*(a*a-1.0)*y2[below] + b*(b*b-1.0)*y2[above]) / 6.0f;