Mercurial > hg > x
comparison splines.cpp @ 1:6422640a802f
first upload
author | Wen X <xue.wen@elec.qmul.ac.uk> |
---|---|
date | Tue, 05 Oct 2010 10:45:57 +0100 |
parents | |
children | 5f3c32dc6e17 |
comparison
equal
deleted
inserted
replaced
0:9b9f21935f24 | 1:6422640a802f |
---|---|
1 //--------------------------------------------------------------------------- | |
2 | |
3 | |
4 #include "splines.h" | |
5 | |
6 //--------------------------------------------------------------------------- | |
7 /* | |
8 function tridiagonal: solves linear system A[N][N]x[N]=d[N] where A is tridiagonal | |
9 | |
10 In: tridiagonal matrix A[N][N] gives as three vectors - lower subdiagonal | |
11 a[1:N-1], main diagonal b[0:N-1], upper subdiagonal c[0:N-2] | |
12 vector d[N] | |
13 Out: vector d[N] now containing x[N] | |
14 | |
15 No return value. | |
16 */ | |
17 void tridiagonal(int N, double* a, double* b, double* c, double* d) | |
18 { | |
19 for (int k=1; k<N; k++) | |
20 { | |
21 double m=a[k]/b[k-1]; | |
22 b[k]=b[k]-m*c[k-1]; | |
23 d[k]=d[k]-m*d[k-1]; | |
24 } | |
25 d[N-1]=d[N-1]/b[N-1]; | |
26 for (int k=N-2; k>=0; k--) | |
27 d[k]=(d[k]-c[k]*d[k+1])/b[k]; | |
28 }//tridiagonal | |
29 | |
30 /* | |
31 function CubicSpline: computing piece-wise trinomial coefficients of a cubic spline | |
32 | |
33 In: x[N+1], y[N+1]: knots | |
34 bordermode: boundary mode of cubic spline | |
35 bordermode=0: natural: y''(x0)=y''(x_N)=0 | |
36 bordermode=1: quadratic runout: y''(x0)=y''(x1), y''(x_N)=y''(x_(N-1)) | |
37 bordermode=2: cubic runout: y''(x0)=2y''(x1)-y''(x2), the same at the end point | |
38 mode: spline format | |
39 mode=0: spline defined on the l'th piece as y(x)=a[l]x^3+b[l]x^2+c[l]x+d[l] | |
40 mode=1: spline defined on the l'th piece as y(x)=a[l]t^3+b[l]t^2+c[l]t+d[l], t=x-x[l] | |
41 Out: a[N],b[N],c[N],d[N]: piecewise trinomial coefficients | |
42 data[]: cubic spline computed for [xstart:xinterval:xend], if specified | |
43 No return value. On start d must be allocated no less than N+1 storage units. | |
44 */ | |
45 void CubicSpline(int N, double* a, double* b, double* c, double* d, double* x, double* y, int bordermode, int mode, double* data, double xinterval, double xstart, double xend) | |
46 { | |
47 double *h=new double[N]; | |
48 for (int i=0; i<N; i++) h[i]=x[i+1]-x[i]; | |
49 | |
50 for (int i=0; i<N-1; i++) | |
51 { | |
52 a[i]=h[i]; | |
53 b[i]=2*(h[i]+h[i+1]); | |
54 c[i]=h[i+1]; | |
55 d[i+1]=6*((y[i+2]-y[i+1])/h[i+1]-(y[i+1]-y[i])/h[i]); | |
56 } | |
57 a[0]=0; c[N-2]=0; | |
58 | |
59 if (bordermode==1) | |
60 { | |
61 b[0]+=h[0]; | |
62 b[N-2]+=h[N-1]; | |
63 } | |
64 else if (bordermode==2) | |
65 { | |
66 b[0]+=2*h[0]; c[0]-=h[0]; | |
67 b[N-2]+=2*h[N-1]; a[N-2]-=h[N-1]; | |
68 } | |
69 | |
70 tridiagonal(N-1, a, b, c, &d[1]); | |
71 | |
72 if (bordermode==0) | |
73 { | |
74 d[0]=0; d[N]=0; | |
75 } | |
76 else if (bordermode==1) | |
77 { | |
78 d[0]=d[1]; d[N]=d[N-1]; | |
79 } | |
80 else if (bordermode==2) | |
81 { | |
82 d[0]=2*d[1]-d[2]; | |
83 d[N]=2*d[N-1]-d[N-2]; | |
84 } | |
85 | |
86 for (int i=0; i<N; i++) | |
87 { | |
88 double zi=d[i], zi1=d[i+1], xi=x[i], xi1=x[i+1], hi=h[i]; | |
89 double co1=y[i+1]/hi-hi*zi1/6, co2=y[i]/hi-hi*zi/6; | |
90 if (mode==0) | |
91 { | |
92 a[i]=(zi1-zi)/6/hi; | |
93 b[i]=(-xi*zi1+xi1*zi)/2/hi; | |
94 c[i]=(zi1*xi*xi-zi*xi1*xi1)/2/hi+co1-co2; | |
95 d[i]=(-zi1*xi*xi*xi+zi*xi1*xi1*xi1)/6/hi-co1*xi+co2*xi1; | |
96 } | |
97 else if (mode==1) | |
98 { | |
99 a[i]=(zi1-zi)/6/hi; | |
100 b[i]=zi/2; | |
101 c[i]=-zi*hi/2+co1-co2; | |
102 d[i]=zi*hi*hi/6+co2*hi; | |
103 } | |
104 zi=zi1; | |
105 } | |
106 delete[] h; | |
107 if (data) | |
108 { | |
109 if (xend<xstart) xend=x[N], xstart=x[0]; | |
110 int Count=(xend-xstart)/xinterval+1; | |
111 for (int i=0, n=0; i<Count; i++) | |
112 { | |
113 double xx=xstart+i*xinterval; | |
114 while (n<N-1 && xx>x[n+1]) n++; | |
115 if (mode==1) xx=xx-x[n]; | |
116 data[i]=d[n]+xx*(c[n]+xx*(b[n]+xx*a[n])); | |
117 } | |
118 } | |
119 }//CubicSpline | |
120 | |
121 /* | |
122 function CubicSpline: computing piece-wise trinomial coefficients of a cubic spline with uniformly placed knots | |
123 | |
124 In: y[N+1]: spline values at knots (0, h, 2h, ..., Nh) | |
125 bordermode: boundary mode of cubic spline | |
126 bordermode=0: natural: y''(x0)=y''(x_N)=0 | |
127 bordermode=1: quadratic runout: y''(x0)=y''(x1), y''(x_N)=y''(x_(N-1)) | |
128 bordermode=2: cubic runout: y''(x0)=2y''(x1)-y''(x2), the same at the end point | |
129 mode: spline format | |
130 mode=0: spline defined on the l'th piece as y(x)=a[l]x^3+b[l]x^2+c[l]x+d[l] | |
131 mode=1: spline defined on the l'th piece as y(x)=a[l]t^3+b[l]t^2+c[l]t+d[l], t=x-x[l] | |
132 Out: a[N],b[N],c[N],d[N]: piecewise trinomial coefficients | |
133 data[]: cubic spline computed for [xstart:xinterval:xend], if specified | |
134 No return value. On start d must be allocated no less than N+1 storage units. | |
135 */ | |
136 void CubicSpline(int N, double* a, double* b, double* c, double* d, double h, double* y, int bordermode, int mode, double* data, double xinterval, double xstart, double xend) | |
137 { | |
138 for (int i=0; i<N-1; i++) | |
139 { | |
140 a[i]=h; | |
141 b[i]=4*h; | |
142 c[i]=h; | |
143 d[i+1]=6*((y[i+2]-y[i+1])/h-(y[i+1]-y[i])/h); | |
144 } | |
145 a[0]=0; c[N-2]=0; | |
146 | |
147 if (bordermode==1) | |
148 { | |
149 b[0]+=h; | |
150 b[N-2]+=h; | |
151 } | |
152 else if (bordermode==2) | |
153 { | |
154 b[0]+=2*h; c[0]-=h; | |
155 b[N-2]+=2*h; a[N-2]-=h; | |
156 } | |
157 | |
158 tridiagonal(N-1, a, b, c, &d[1]); | |
159 | |
160 if (bordermode==0) | |
161 { | |
162 d[0]=0; d[N]=0; | |
163 } | |
164 else if (bordermode==1) | |
165 { | |
166 d[0]=d[1]; d[N]=d[N-1]; | |
167 } | |
168 else if (bordermode==2) | |
169 { | |
170 d[0]=2*d[1]-d[2]; | |
171 d[N]=2*d[N-1]-d[N-2]; | |
172 } | |
173 | |
174 for (int i=0; i<N; i++) | |
175 { | |
176 double zi=d[i], zi1=d[i+1]; | |
177 if (mode==0) | |
178 { | |
179 double co1=y[i+1]/h-h*zi1/6, co2=y[i]/h-h*zi/6; | |
180 a[i]=(zi1-zi)/6/h; | |
181 b[i]=(-i*zi1+(i+1)*zi)/2; | |
182 c[i]=(zi1*i*i*h-zi*(i+1)*h*(i+1))/2+co1-co2; | |
183 d[i]=(-zi1*i*h*i*h*i+zi*(i+1)*h*(i+1)*h*(i+1))/6-co1*i*h+co2*(i+1)*h; | |
184 } | |
185 else if (mode==1) | |
186 { | |
187 a[i]=(zi1-zi)/6/h; | |
188 b[i]=zi/2; | |
189 c[i]=-(zi*2+zi1)*h/6+(y[i+1]-y[i])/h; | |
190 d[i]=y[i]; | |
191 } | |
192 zi=zi1; | |
193 } | |
194 if (data) | |
195 { | |
196 if (xend<xstart) xend=N*h, xstart=0; | |
197 int Count=(xend-xstart)/xinterval+1; | |
198 for (int i=0, n=0; i<Count; i++) | |
199 { | |
200 double xx=xstart+i*xinterval; | |
201 while (n<N-1 && xx>(n+1)*h) n++; | |
202 if (mode==1) xx=xx-n*h; | |
203 data[i]=d[n]+xx*(c[n]+xx*(b[n]+xx*a[n])); | |
204 } | |
205 } | |
206 }//CubicSpline | |
207 | |
208 /* | |
209 function Smooth_Interpolate: smoothly interpolate/extrapolate P-piece spline from P-1 values. The | |
210 interpolation scheme is chosen according to P: | |
211 P-1=1: constant | |
212 P-1=2: linear function | |
213 P-1=3: quadratic function | |
214 P-1>=4: cubic spline | |
215 | |
216 In: xind[P-1], x[P-1]: knot points | |
217 Out: y[N]: smoothly interpolated signal, y(xind[p])=x[p], p=0, ..., P-2. | |
218 | |
219 No return value. | |
220 */ | |
221 void Smooth_Interpolate(double* y, int N, int P, double* x, double* xind) | |
222 { | |
223 if (P==2) | |
224 { | |
225 for (int n=0; n<N; n++) y[n]=x[0]; | |
226 } | |
227 else if (P==3) | |
228 { | |
229 double alp=(x[1]-x[0])/(xind[1]-xind[0]); | |
230 for (int n=0; n<N; n++) y[n]=x[0]+(n-xind[0])*alp; | |
231 } | |
232 else if (P==4) | |
233 { | |
234 double x0=xind[0], x1=xind[1], x2=xind[2], y0=x[0], y1=x[1], y2=x[2]; | |
235 double ix0_12=y0/((x0-x1)*(x0-x2)), ix1_02=y1/((x1-x0)*(x1-x2)), ix2_01=y2/((x2-x0)*(x2-x1)); | |
236 double a=ix0_12+ix1_02+ix2_01, | |
237 b=-(x1+x2)*ix0_12-(x0+x2)*ix1_02-(x0+x1)*ix2_01, | |
238 c=x1*x2*ix0_12+x0*x2*ix1_02+x0*x1*ix2_01; | |
239 for (int n=0; n<N; n++) y[n]=c+n*(b+n*a); | |
240 } | |
241 else | |
242 { | |
243 double *fa=new double[P*4], *fb=&fa[P], *fc=&fa[P*2], *fd=&fa[P*3]; | |
244 CubicSpline(P-2, fa, fb, fc, fd, xind, x, 0, 1, y, 1, 0, N-1); | |
245 delete[] fa; | |
246 } | |
247 }//Smooth_Interpolate |