Guest User

Untitled

a guest
Dec 26th, 2017
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.96 KB | None | 0 0
  1. Main Page Data Structures File List Data Fields Globals
  2. spline.c
  3. Go to the documentation of this file.
  4.  
  5. 00001 /*******************************************************************
  6. 00002 RTN SPLINE: Fits cubic smoothing spline to time series
  7. 00003
  8. 00004 Derived from IMSL routines by Edward R Cook, Tree Ring Laboratory,
  9. 00005 Lamont-Doherty Earth Observatory, Palisades, New York, USA
  10. 00006
  11. 00007 Four routines combined into one by
  12. 00008 Richard L Holmes, University of Arizona, Tucson, Arizona, USA
  13. 00009 Modified copyright (C) 10 AUG 1998
  14. 00010
  15. 00011 ********************************************************************/
  16. 00012
  17. 00013 #include <stdio.h>
  18. 00014 #include <stdlib.h>
  19. 00015 #include <math.h>
  20. 00016
  21. 00017 #define PI 3.1415926535897935
  22. 00018
  23. 00019
  24. 00020
  25. 00021 /* DYNAMICALLY ALLOCATE A 2-D ARRAY */
  26. 00022 /* Assumption: nrows*ncols*element_size, rounded up to a multiple */
  27. 00023 /* of sizeof(long double), must fit in a long type. If not, then */
  28. 00024 /* the "i += ..." step could overflow. */
  29. 00025
  30. 00026 void **MATRIX(int nrows, int ncols, int first_row, int first_col,int element_size)
  31. 00027 {
  32. 00028 void **p;
  33. 00029 int alignment;
  34. 00030 long i;
  35. 00031
  36. 00032 if(nrows < 1 || ncols < 1) return(NULL);
  37. 00033 i = nrows*sizeof(void *);
  38. 00034 /* align the addr of the data to be a multiple of sizeof(long double) */
  39. 00035 alignment = i % sizeof(long double);
  40. 00036 if(alignment != 0) alignment = sizeof(long double) - alignment;
  41. 00037 i += nrows*ncols*element_size+alignment;
  42. 00038 if((p = (void **)malloc((size_t)i)) != NULL)
  43. 00039 {
  44. 00040 /* compute the address of matrix[first_row][0] */
  45. 00041 p[0] = (char *)(p+nrows)+alignment-first_col*element_size;
  46. 00042 for(i = 1; i < nrows; i++)
  47. 00043 /* compute the address of matrix[first_row+i][0] */
  48. 00044 p[i] = (char *)(p[i-1])+ncols*element_size;
  49. 00045 /* compute the address of matrix[0][0] */
  50. 00046 p -= first_row;
  51. 00047 }
  52. 00048 return(p);
  53. 00049 }
  54. 00050
  55. 00051
  56. 00052
  57. 00053 /* This function is called from SPLINE when : */
  58. 00054 /* 1. Series is too short to compute spline */
  59. 00055 /* 2. Matrix A is not positive definite */
  60. 00056
  61. 00057 void errorAction(int N, double *Y, float *ZF)
  62. 00058 {
  63. 00059 int k;
  64. 00060 double ZN;
  65. 00061
  66. 00062 ZN = 0.0;
  67. 00063 for(k = 1; k <= N; k++)
  68. 00064 ZN = ZN + Y[k];
  69. 00065
  70. 00066 if (N > 0)
  71. 00067 {
  72. 00068 ZN = ZN/(float)N;
  73. 00069 for(k = 1; k <= N; k++)
  74. 00070 ZF[k-1] = ZN;
  75. 00071 }
  76. 00072
  77. 00073 return;
  78. 00074 }
  79. 00075
  80. 00076
  81. 00077
  82. 00078 /* Function SPLINE: Fits cubic smoothing spline to time series */
  83. 00079 /* Arguments: */
  84. 00080 /* */
  85. 00081 /* N: Number of values in time series */
  86. 00082 /* Z: Time series array to be modeled with spline */
  87. 00083 /* ZF: Computed cubic spline function array fit to time series */
  88. 00084 /* ZSP: Length (rigidity) of spline to be used to model series */
  89. 00085 /* ZPV: Portion of variance at wavelength ZSP contained in spline (0<ZPV<1) */
  90. 00086 /* */
  91. 00087 /* Arguments Z, ZF, ZSP and ZPV are single precision; */
  92. 00088 /* computation is done entirely in double-precision arithmetic */
  93. 00089
  94. 00090 void SPLINE(int N, float *Z, float *ZF, float ZSP, float ZPV)
  95. 00091 {
  96. 00092 int i, j, k, l, m;
  97. 00093 int NC, NC1, NCP1, IMNCP1, I1, I2, JM1, IW, KL, N1, K1;
  98. 00094 double RSP, VPV, PD, RN, D1, D2, SUM;
  99. 00095 double **A, *F, *Y, C1[5], C2[4];
  100. 00096
  101. 00097 C1[0] = 0.0;
  102. 00098 C1[1] = 1.0;
  103. 00099 C1[2] = -4.0;
  104. 00100 C1[3] = 6.0;
  105. 00101 C1[4] = -2.0;
  106. 00102
  107. 00103 C2[0] = 0.0;
  108. 00104 C2[1] = 0.0;
  109. 00105 C2[2] = 0.33333333333333;
  110. 00106 C2[3] = 1.33333333333333;
  111. 00107
  112. 00108 /* Allocate arrays to store intermeediate results */
  113. 00109 A = (double **)MATRIX(N+1, 5, 0, 0, sizeof(double));
  114. 00110 F = (double *)malloc((N+1)*sizeof(double));
  115. 00111 Y = (double *)malloc((N+1)*sizeof(double));
  116. 00112 if (A == NULL || F == NULL || Y == NULL)
  117. 00113 {
  118. 00114 printf("\nSPLINE >> Unable to allocate memory\n");
  119. 00115 return;
  120. 00116 }
  121. 00117
  122. 00118 /* Check whether series is too short to compute spline */
  123. 00119 if (N < 4)
  124. 00120 {
  125. 00121 errorAction(N, Y, ZF);
  126. 00122 return;
  127. 00123 }
  128. 00124
  129. 00125 /* Copy time series into double precision array */
  130. 00126 for(j = 1; j <= N; j++)
  131. 00127 Y[j] = (double)Z[j-1];
  132. 00128
  133. 00129 /* Compute Lagrange multiplier, which defines frequency response of spline */
  134. 00130 RSP = (double)ZSP;
  135. 00131 VPV = (double)ZPV;
  136. 00132 PD = ((1.0/(1.0-VPV)-1.0)*6.0* pow((cos(PI*2.0/RSP)-1.0),2.0))/(cos(PI*2.0/RSP)+2.0);
  137. 00133 for(i = 1; i <= N-2; i++)
  138. 00134 for(j = 1; j <= 3; j++)
  139. 00135 {
  140. 00136 A[i][j] = C1[j] + PD * C2[j];
  141. 00137 A[i][4] = Y[i] + C1[4] * Y[i+1] + Y[i+2];
  142. 00138 }
  143. 00139
  144. 00140 A[1][1] = C2[1];
  145. 00141 A[1][2] = C2[1];
  146. 00142 A[2][1] = C2[1];
  147. 00143 NC = 2;
  148. 00144
  149. 00145 /* Begin LUDAPB */
  150. 00146 RN = 1.0/((double)(N-2) * 16.0);
  151. 00147 D1 = 1.0;
  152. 00148 D2 = 0.0;
  153. 00149 NCP1 = NC + 1;
  154. 00150
  155. 00151 /* Initialize zero elements */
  156. 00152 if (NC != 0)
  157. 00153 {
  158. 00154 for(i = 1; i <= NC; i++)
  159. 00155 for(j = i; j <= NC; j++)
  160. 00156 {
  161. 00157 k = NCP1 - j;
  162. 00158 A[i][k] = 0.0;
  163. 00159 }
  164. 00160 }
  165. 00161
  166. 00162 /* i: row index of element being computed */
  167. 00163 /* j: column index of element being computed */
  168. 00164 /* l: row index of previously computed vector being used to compute inner product */
  169. 00165 /* m: column index */
  170. 00166 for(i = 1; i <= N-2; i++)
  171. 00167 {
  172. 00168 IMNCP1 = i - NCP1;
  173. 00169 I1 = (1 < 1 - IMNCP1? 1 - IMNCP1: 1);
  174. 00170 for(j = I1; j <= NCP1; j++)
  175. 00171 {
  176. 00172 l = IMNCP1 + j;
  177. 00173 I2 = NCP1 - j;
  178. 00174 SUM = A[i][j];
  179. 00175 JM1 = j - 1;
  180. 00176
  181. 00177 if (JM1 > 0)
  182. 00178 {
  183. 00179 for(k = 1; k <= JM1; k++)
  184. 00180 {
  185. 00181 m = I2 + k;
  186. 00182 SUM = SUM - (A[i][k]*A[l][m]);
  187. 00183 }
  188. 00184 }
  189. 00185
  190. 00186 /* Matrix not positive definite */
  191. 00187 if (j == NCP1)
  192. 00188 {
  193. 00189 if (A[i][j]+SUM*RN <= A[i][j])
  194. 00190 {
  195. 00191 printf("\nSPLINE >> Matrix not positive definite\n");
  196. 00192 errorAction(N, Y, ZF);
  197. 00193 return;
  198. 00194 }
  199. 00195
  200. 00196 A[i][j] = 1.0/sqrt(SUM);
  201. 00197
  202. 00198 /* Update determinant */
  203. 00199 D1 = D1*SUM;
  204. 00200 while (fabs(D1) > 1.0)
  205. 00201 {
  206. 00202 D1 = D1*0.0625;
  207. 00203 D2 = D2+4.0;
  208. 00204 }
  209. 00205
  210. 00206 while (fabs(D1) <= 0.0625)
  211. 00207 {
  212. 00208 D1 = D1*16.0;
  213. 00209 D2 = D2-4.0;
  214. 00210 }
  215. 00211 continue;
  216. 00212 }
  217. 00213 A[i][j] = SUM*A[l][NCP1];
  218. 00214 }
  219. 00215 }
  220. 00216 /* End LUDAPB */
  221. 00217
  222. 00218 /* Begin LUELPB */
  223. 00219 /* Solution LY = B */
  224. 00220 NC1 = NC + 1;
  225. 00221 IW = 0;
  226. 00222 l = 0;
  227. 00223
  228. 00224 for(i = 1; i <= N-2; i++)
  229. 00225 {
  230. 00226 SUM = A[i][4];
  231. 00227 if (NC > 0) {
  232. 00228 if (IW != 0) {
  233. 00229 l = l + 1;
  234. 00230 if (l > NC)
  235. 00231 {
  236. 00232 l = NC;
  237. 00233 }
  238. 00234 k = NC1 - l;
  239. 00235 KL = i - l;
  240. 00236
  241. 00237 for(j = k; j <= NC; j++)
  242. 00238 {
  243. 00239 SUM = SUM - (A[KL][4]*A[i][j]);
  244. 00240 KL = KL + 1;
  245. 00241 }
  246. 00242 } else if (SUM != 0.0)
  247. 00243 {
  248. 00244 IW = 1;
  249. 00245 }
  250. 00246 }
  251. 00247 A[i][4] = SUM*A[i][NC1];
  252. 00248 }
  253. 00249
  254. 00250 /* Solution UX = Y */
  255. 00251 A[N-2][4] = A[N-2][4]*A[N-2][NC1];
  256. 00252 N1 = N-2+1;
  257. 00253
  258. 00254 for(i = 2; i <= N-2; i++)
  259. 00255 {
  260. 00256 k = N1 - i;
  261. 00257 SUM = A[k][4];
  262. 00258 if (NC > 0)
  263. 00259 {
  264. 00260 KL = k +1;
  265. 00261 K1 = (N-2 < k+NC? N-2: k+NC);
  266. 00262 l = 1;
  267. 00263 for(j = KL; j <= K1; j++)
  268. 00264 {
  269. 00265 SUM = SUM - A[j][4]*A[j][NC1-l];
  270. 00266 l = l + 1;
  271. 00267 }
  272. 00268 }
  273. 00269 A[k][4] = SUM*A[k][NC1];
  274. 00270 }
  275. 00271 /* End LUELPB */
  276. 00272
  277. 00273 /* Calculate Spline Curve */
  278. 00274 for(i = 3; i <= N-2; i++)
  279. 00275 F[i] = A[i-2][4]+C1[4]*A[i-1][4]+A[i][4];
  280. 00276
  281. 00277 F[1] = A[1][4];
  282. 00278 F[2] = C1[4]*A[1][4]+A[2][4];
  283. 00279 F[N-1] = A[N-2-1][4]+C1[4]*A[N-2][4];
  284. 00280 F[N] = A[N-2][4];
  285. 00281
  286. 00282 for(i = 1; i <= N; i++)
  287. 00283 ZF[i-1] = Y[i] - F[i];
  288. 00284
  289. 00285 return;
  290. 00286 }
  291. 00287
  292. 00288
  293. 00289
  294. 00290
  295. 00291
  296.  
  297. Generated on Wed Apr 9 08:56:14 2003 for TREES by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002
Add Comment
Please, Sign In to add comment