main() { int ixin,ixout; float ydin[NXIN][4],xout[NXOUT],yout[NXOUT],x; for (ixout=0,x=fxout; ixout<NXOUT; ixout++,x+=dxout) xout[ixout] = x; csplin(NXIN,xin,yin,ydin); intcub(0,NXIN,xin,ydin,NXOUT,xout,yout); /* fwrite(yout,sizeof(float),NXOUT,stdout); */ pp1d(stdout,"Cubic spline",NXOUT,0,yout); cmonot(NXIN,xin,yin,ydin); intcub(0,NXIN,xin,ydin,NXOUT,xout,yout); /* fwrite(yout,sizeof(float),NXOUT,stdout); */ pp1d(stdout,"Fritsch-Carlson method",NXOUT,0,yout); cakima(NXIN,xin,yin,ydin); intcub(0,NXIN,xin,ydin,NXOUT,xout,yout); /* fwrite(yout,sizeof(float),NXOUT,stdout); */ pp1d(stdout,"Akima's method",NXOUT,0,yout); }
Var* cubic_interp(Var* v0, Var* v1, Var* v2, char* type, float ignore) { float **yd, *out, *xp, *yp, *arena; size_t npts, nout; size_t i, j; float x0, x1, x, h; int done; size_t count = 0; int error = 0; npts = V_DSIZE(v0); nout = V_DSIZE(v2); /* this is the hard way */ yd = calloc(npts, sizeof(float*)); xp = calloc(npts, sizeof(float)); yp = calloc(npts, sizeof(float)); arena = calloc(npts * 4, sizeof(float)); out = calloc(nout, sizeof(float)); for (i = 0; i < npts; i++) { xp[count] = extract_float(v1, i); yp[count] = extract_float(v0, i); yd[count] = arena + 4 * count; /* Handle deleted points and non-increasing data */ if (xp[count] == ignore || yp[count] == ignore) { continue; } if (count && xp[count] <= xp[count - 1]) { parse_error("Error: data is not monotonically increasing x1[%ld] = %f", i, xp[count]); error = 1; break; } count++; } /* this is the case if we're not monotonic increasing */ if (error) { free(arena); free(yd); free(xp); free(yp); return (NULL); } npts = count; cakima(npts, xp, yp, yd); done = i = j = 0; while (!done) { if (i >= nout) break; else if (j >= npts) break; x0 = xp[j]; x1 = xp[j + 1]; x = extract_float(v2, i); if (x == ignore) { out[i] = ignore; i++; } if (x < x0) i++; else if (x > x1) j++; else { h = x - x0; out[i] = yd[j][0] + h * (yd[j][1] + h * (yd[j][2] / 2.0 + h * yd[j][3] / 6.0)); i++; } } free(arena); free(yd); free(xp); free(yp); return (newVal(V_ORG(v2), V_SIZE(v2)[0], V_SIZE(v2)[1], V_SIZE(v2)[2], DV_FLOAT, out)); }