91#ifdef CSPLINE_IMPLEMENTATION
93static const double CSPLINE_EPS = 1e-12;
101 size_t capacity = 10*(n + 1) + n;
102 double *mem = (
double*) malloc(capacity *
sizeof(
double));
103 assert((mem != NULL) &&
"ASSERT: cannot allocate enough memory\n");
104 memset(mem, 0, capacity*
sizeof(
double));
111 cs->
x = mem + offset; offset += (n + 1);
112 cs->
y = mem + offset; offset += (n + 1);
113 cs->
a = mem + offset; offset += (n + 1);
114 cs->
h = mem + offset; offset += n;
115 cs->
alpha = mem + offset; offset += (n + 1);
116 cs->
II = mem + offset; offset += (n + 1);
117 cs->
mu = mem + offset; offset += (n + 1);
118 cs->
z = mem + offset; offset += (n + 1);
119 cs->
b = mem + offset; offset += (n + 1);
120 cs->
c = mem + offset; offset += (n + 1);
121 cs->
d = mem + offset; offset += (n + 1);
123 memcpy(cs->
x, x, (n + 1)*
sizeof(
double));
124 memcpy(cs->
y, y, (n + 1)*
sizeof(
double));
125 memcpy(cs->
a, y, (n + 1)*
sizeof(
double));
127 for (
size_t i = 0; i < n; ++i) {
128 cs->
h[i] = cs->
x[i + 1] - cs->
x[i];
130 if (fabs(cs->
h[i]) < CSPLINE_EPS) {
131 printf(
"ERROR: x-values are too close to each other: difference x[%zu] and x[%zu] is less than expected epsilon\n",
137 printf(
"ERROR: x-values have to be strictly increasing. Found x[%zu] = %.5e and x[%zu] = %.5e which must be increasing\n",
138 i, cs->
x[i], i + 1, cs->
x[i + 1]);
143 cs->
alpha[0] = 3.0*(cs->
a[1] - cs->
a[0])/cs->
h[0] - 3.0*fp0;
144 cs->
alpha[n] = 3.0*fpn - 3.0*(cs->
a[n] - cs->
a[n - 1])/cs->
h[n - 1];
146 for (
size_t i = 1; i < n; ++i) {
147 cs->
alpha[i] = 3.0/cs->
h[i]*(cs->
a[i + 1]-cs->
a[i]) - 3.0/cs->
h[i - 1]*(cs->
a[i]-cs->
a[i - 1]);
150 cs->
II[0] = 2.0 * cs->
h[0];
152 cs->
z[0] = cs->
alpha[0] / cs->
II[0];
154 for (
size_t i = 1; i < n; ++i) {
155 cs->
II[i] = 2.0*(cs->
x[i + 1] - cs->
x[i - 1]) - cs->
h[i - 1]*cs->
mu[i - 1];
156 cs->
mu[i] = cs->
h[i] / cs->
II[i];
157 cs->
z[i] = (cs->
alpha[i] - cs->
h[i - 1]*cs->
z[i - 1])/cs->
II[i];
160 cs->
II[n] = cs->
h[n - 1]*(2.0 - cs->
mu[n - 1]);
161 cs->
z[n] = (cs->
alpha[n] - cs->
h[n - 1]*cs->
z[n - 1]) / cs->
II[n];
165 for (
int j = (
int)n - 1; j >= 0; --j) {
166 cs->
c[j] = cs->
z[j] - cs->
mu[j] * cs->
c[j + 1];
167 cs->
b[j] = (cs->
a[j + 1] - cs->
a[j])/cs->
h[j] - cs->
h[j]*(cs->
c[j + 1] + 2.0*cs->
c[j])/3.0;
168 cs->
d[j] = (cs->
c[j + 1] - cs->
c[j]) / 3.0 / cs->
h[j];
176 double xmin = cs->
x[0];
177 double xmax = cs->
x[cs->
N];
178 if ((x < xmin) || (x > xmax)) {
179 printf(
"ERROR: requested x = %.5e is outside interpolation range [%.5e -- %.5e]\n",
185 while ((j <= cs->N - 1) && (x >= cs->
x[j + 1])) j++;
187 *y = cs->
a[j] + cs->
b[j]*(x - cs->
x[j]) + cs->
c[j]*(x - cs->
x[j])*(x - cs->
x[j]) + cs->
d[j]*(x - cs->
x[j])*(x - cs->
x[j])*(x - cs->
x[j]);
CSpline * cspline_init(double *x, double *y, size_t len, double fp0, double fpn)
void cspline_free(CSpline *cs)
bool cspline_eval(CSpline *cs, double x, double *y)
double * h
Definition cspline.h:75
double * mu
Definition cspline.h:78
double * a
Definition cspline.h:74
double * c
Definition cspline.h:81
size_t N
Definition cspline.h:69
double * x
Definition cspline.h:70
double * z
Definition cspline.h:79
double fp0
Definition cspline.h:72
double * II
Definition cspline.h:77
double * d
Definition cspline.h:82
double * alpha
Definition cspline.h:76
double * b
Definition cspline.h:80
double * mem
Definition cspline.h:83
double * y
Definition cspline.h:71
double fpn
Definition cspline.h:73