Linuxpops  3.01.04
Spectral Anaysis Package for Single Dish Data
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
grace_fit.c
Go to the documentation of this file.
1 /*
2 Copyright 2021 Arizona Board of Regents on behalf of the University of Arizona.
3 
4 For commercial uses, to obtain a license to sell and or sublicense copies of
5 the Software please contact the University of Arizona at Tech Launch Arizona:
6 lewish@tla.arizona.edu.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction for non-commercial use educational and
11 research purposes, including without limitation the rights to use, copy,
12 modify, merge, publish, distribute, and to permit persons to whom the Software
13 is furnished to do so, subject to the following conditions:
14 
15 The entire above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 SOFTWARE.
25 
26 1. Additional Required Provisions
27 
28 1.1. Arbitration. The parties agree that if a dispute arises between them
29 concerning this Agreement, the parties may be required to submit the matter to
30 arbitration pursuant to Arizona law.
31 
32 1.2. Applicable Law and Venue. This Agreement shall be interpreted pursuant
33 to the laws of the State of Arizona. Any arbitration or litigation between the
34 Parties shall be conducted in Pima County, ARIZONA, and LICENSEE hereby
35 submits to venue and jurisdiction in Pima County, ARIZONA.
36 
37 1.3. Non-Discrimination. The Parties agree to be bound by state and federal
38 laws and regulations governing equal opportunity and non-discrimination and
39 immigration.
40 
41 1.4. Appropriation of Funds. The Parties recognize that performance by
42 ARIZONA may depend upon appropriation of funds by the State Legislature of
43 ARIZONA. If the Legislature fails to appropriate the necessary funds, or if
44 ARIZONA’S appropriation is reduced during the fiscal year, ARIZONA may cancel
45 this Agreement without further duty or obligation. ARIZONA will notify
46 LICENSEE as soon as reasonably possible after it knows of the loss of funds.
47 
48 1.5. Conflict of Interest. This Agreement is subject to the provisions of
49 A.R.S. 38-511 and other conflict of interest regulations. Within three years
50 of the EFFECTIVE DATE, ARIZONA may cancel this Agreement if any person
51 significantly involved in initiating, negotiating, drafting, securing, or
52 creating this Agreement for or on behalf of ARIZONA becomes an employee or
53 consultant in any capacity of LICENSEE with respect to the subject matter of
54 this Agreement.
55 
56  */
57 
58 
59 #include "extern.h"
60 
61 /*
62  * Grace - Graphics for Exploratory Data Analysis
63  *
64  * Home page: http://plasma-gate.weizmann.ac.il/Grace/
65  *
66  * Copyright (c) 1991-95 Paul J Turner, Portland, OR
67  * Copyright (c) 1996-98 GRACE Development Team
68  *
69  * Maintained by Evgeny Stambulchik <fnevgeny@plasma-gate.weizmann.ac.il>
70  *
71  *
72  * All Rights Reserved
73  *
74  * This program is free software; you can redistribute it and/or modify
75  * it under the terms of the GNU General Public License as published by
76  * the Free Software Foundation; either version 2 of the License, or
77  * (at your option) any later version.
78  *
79  * This program is distributed in the hope that it will be useful,
80  * but WITHOUT ANY WARRANTY; without even the implied warranty of
81  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82  * GNU General Public License for more details.
83  *
84  * You should have received a copy of the GNU General Public License
85  * along with this program; if not, write to the Free Software
86  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
87  */
88 
89 /*
90  *
91  * curve fitting, and other numerical routines used in compose.
92  *
93  * Contents:
94  *
95  * void stasum() - compute mean and variance
96  * double leasev() - evaluate least squares polynomial
97  * int fitcurve() - compute coefficients for a polynomial fit of degree >1
98  * void runavg() - compute a running average
99  * void runstddev() - compute a running standard deviation
100  * void runmedian() - compute a running median
101  * void runminmax() - compute a running minimum or maximum
102  * void filterser() - apply a digital filter
103  * void linearconv() - convolve one set with another
104  * int crosscorr() - cross/auto correlation
105  * int linear_regression() - linear regression
106  * void spline() - compute a spline fit
107  * double seval() - evaluate the spline computed in spline()
108  */
109 
110 #include <../calc/config.h>
111 #include <math.h>
112 
113 #include "defines.h"
114 #include "utils.h"
115 #include "channels.h"
116 
117 int dofitcurve(int cnt, double *xd, double *yd, int nd, double *c);
118 
119 /*
120  * free and check for NULL pointer
121  */
122 void xfree(void *ptr)
123 {
124  if (ptr != NULL) {
125  free(ptr);
126  }
127 }
128 
129 
130 /*
131  * sort two arrays
132  */
133 void sort_xy(double *tmp1, double *tmp2, int up, int sorton, int stype)
134 {
135 
136  int d, i, j;
137  int lo = 0;
138  double t1, t2;
139 
140  if (sorton == 1) {
141  double *ttmp;
142 
143  ttmp = tmp1;
144  tmp1 = tmp2;
145  tmp2 = ttmp;
146  }
147  up--;
148 
149  for (d = up - lo + 1; d > 1;) {
150  if (d < 5)
151  d = 1;
152  else
153  d = (5 * d - 1) / 11;
154  for (i = up - d; i >= lo; i--) {
155  t1 = tmp1[i];
156  t2 = tmp2[i];
157  if (!stype) {
158  for (j = i + d; j <= up && (t1 > tmp1[j]); j += d) {
159  tmp1[j - d] = tmp1[j];
160  tmp2[j - d] = tmp2[j];
161  }
162  tmp1[j - d] = t1;
163  tmp2[j - d] = t2;
164  } else {
165  for (j = i + d; j <= up && (t1 < tmp1[j]); j += d) {
166  tmp1[j - d] = tmp1[j];
167  tmp2[j - d] = tmp2[j];
168  }
169  tmp1[j - d] = t1;
170  tmp2[j - d] = t2;
171  }
172  }
173  }
174 }
175 
176 
177 /*
178  compute mean and standard dev
179 */
180 void stasum(double *x, int n, double *xbar, double *sd)
181 {
182  int i;
183 
184  *xbar = 0;
185  *sd = 0;
186 
187  if (x == NULL) {
188  return;
189  }
190 
191  if (n < 1) {
192  return;
193  }
194 
195  for (i = 0; i < n; i++) {
196  *xbar = (*xbar) + x[i];
197  }
198  *xbar = (*xbar)/n;
199 
200  for (i = 0; i < n; i++) {
201  *sd = (*sd) + (x[i] - *xbar) * (x[i] - *xbar);
202  }
203  *sd = sqrt(*sd/n);
204 }
205 
206 
207 /*
208  evaluate least squares polynomial
209 */
210 double leasev(double *c, int degree, double x)
211 {
212  double temp;
213  int i;
214 
215  /*
216  * Commented out - refer to "Numerical Methods in C" for the
217  * reason, section 5.2! The revolution has begun.
218  temp = 0.0;
219  for (i = 0; i <= degree; i++) {
220  if ((i == 0) && (x == 0.0)) {
221  temp = temp + c[i];
222  } else {
223  temp = temp + c[i] * pow(x, (double) (i));
224  }
225  } */
226 
227  temp = c[degree];
228 
229  for(i=degree-1;i>=0;i--)
230  {
231  temp = c[i] + temp*x;
232  }
233 
234  return (temp);
235 }
236 
237 
238 /* polynomial curve fitting */
239 int fitcurve(double *x, double *y, int n, int ideg, double *coeff)
240 /*
241  * x - x values
242  * y - y values
243  * n - number of points
244  * ideg - degree of fit
245  * coeff - coefficients of fit
246  */
247 {
248  int i, ifail;
249 
250  ifail = 1;
251 
252  if(ideg > 1)
253  {
254  dofitcurve(n, x, y, ideg, coeff);
255  }
256  else
257  {
258  ifail = linear_regression(n, x, y, coeff);
259 
260  if(ifail == 1)
261  {
262  st_fail("Linear_regression entered with N < 2");
263  return ifail;
264  }
265  else
266  if(ifail == 2)
267  {
268  st_fail("Linear_regression - all values of x or y are the same");
269  return ifail;
270  }
271  }
272  /* check coefficients */
273  for(i=0;i<=ideg;i++)
274  {
275  if(!gsl_finite(coeff[i]))
276  {
277  st_fail("Linear_regression - all values of x or y are the same");
278  ifail = 3;
279  return ifail;
280  }
281  }
282 
283  ifail = 0;
284 
285  return(ifail);
286 }
287 
288 
289 /* compute a running average */
290 void runavg(double *x, double *y, double *ax, double *ay, int n, int ilen)
291 {
292  int i;
293  double sumy = 0.0;
294  double sumx = 0.0;
295 
296  for (i = 0; i < ilen; i++) {
297  sumx = sumx + x[i];
298  sumy = sumy + y[i];
299  }
300  ax[0] = sumx / ilen;
301  ay[0] = sumy / ilen;
302  for (i = 1; i < (n - ilen + 1); i++) {
303  sumx = x[i + ilen - 1] - x[i - 1] + sumx;
304  ax[i] = sumx / ilen;
305  sumy = y[i + ilen - 1] - y[i - 1] + sumy;
306  ay[i] = sumy / ilen;
307  }
308 }
309 
310 /*
311  compute a running standard deviation
312 */
313 void runstddev(double *x, double *y, double *ax, double *ay, int n, int ilen)
314 {
315  int i;
316  double ybar, ysd;
317  double sumx = 0.0;
318 
319  for (i = 0; i < ilen; i++) {
320  sumx = sumx + x[i];
321  }
322  ax[0] = sumx / ilen;
323  stasum(y, ilen, &ybar, &ysd);
324  ay[0] = ysd;
325  for (i = 1; i < (n - ilen + 1); i++) {
326  stasum(y + i, ilen, &ybar, &ysd);
327  sumx = x[i + ilen - 1] - x[i - 1] + sumx;
328  ax[i] = sumx / ilen;
329  ay[i] = ysd;
330  }
331 }
332 
333 /*
334  compute a running median
335 */
336 void runmedian(double *x, double *y, double *ax, double *ay, int n, int ilen)
337 {
338  int i, j, nlen = n - ilen + 1;
339  double *tmpx, *tmpy;
340 
341  tmpx = (double *) calloc(ilen, sizeof(double));
342  if (tmpx == NULL) {
343  st_fail("Can't calloc tmpx in runmedian");
344  return;
345  }
346  tmpy = (double *) calloc(ilen, sizeof(double));
347  if (tmpy == NULL) {
348  st_fail("Can't calloc tmpy in runmedian");
349  cxfree(tmpx);
350  return;
351  }
352  for (i = 0; i < nlen; i++) {
353  for (j = 0; j < ilen; j++) {
354  tmpx[j] = x[j + i];
355  tmpy[j] = y[j + i];
356  }
357  sort_xy(tmpx, tmpy, ilen, 1, 0);
358 
359  if (ilen % 2) {
360  ax[i] = x[i + (ilen / 2)];
361  ay[i] = tmpy[ilen / 2];
362  } else {
363  ax[i] = (x[i + ilen / 2] + x[i + (ilen - 1) / 2]) * 0.5;
364  ay[i] = (tmpy[ilen / 2] + tmpy[(ilen - 1) / 2]) * 0.5;
365  }
366  }
367  cxfree(tmpx);
368  cxfree(tmpy);
369 }
370 
371 /*
372  compute a running minimum or maximum
373 */
374 void runminmax(double *x, double *y, double *ax, double *ay, int n, int ilen, int type)
375 {
376  int i, j;
377  double min, max;
378  double sumx = 0.0;
379 
380  min = max = y[0];
381  for (i = 0; i < ilen; i++) {
382  sumx = sumx + x[i];
383  if (min > y[i])
384  min = y[i];
385  if (max < y[i])
386  max = y[i];
387  }
388  ax[0] = sumx / ilen;
389  if (type == 0) {
390  ay[0] = min;
391  } else if (type == 1) {
392  ay[0] = max;
393  } else {
394  st_fail("Unknown type in runminmax, setting type = min");
395  type = 0;
396  }
397  for (i = 1; i < (n - ilen + 1); i++) {
398  sumx = x[i + ilen - 1] - x[i - 1] + sumx;
399  ax[i] = sumx / ilen;
400  min = y[i];
401  max = y[i];
402  for (j = 0; j < ilen; j++) {
403  if (min > y[i + j])
404  min = y[i + j];
405  if (max < y[i + j])
406  max = y[i + j];
407  }
408  if (type == 0) {
409  ay[i] = min;
410  } else if (type == 1) {
411  ay[i] = max;
412  }
413  }
414 }
415 
416 /*
417  Apply a digital filter of length len to a set in x, y,
418  of length n with the results going to resx, resy.
419  the length of the result is set by the caller
420 */
421 void filterser(int n, double *x, double *y, double *resx, double *resy, double *h, int len)
422 {
423  int i, j, outlen, eo, ld2;
424  double sum;
425 
426  outlen = n - len + 1;
427  eo = len % 2;
428  ld2 = len / 2;
429  for (i = 0; i < outlen; i++) {
430  sum = 0.0;
431  for (j = 0; j < len; j++) {
432  sum = sum + h[j] * y[j + i];
433  }
434  resy[i] = sum;
435  if (eo)
436  resx[i] = x[i + ld2];
437  else
438  resx[i] = (x[i + ld2] + x[i + ld2 - 1]) / 2.0;
439  }
440 }
441 
442 /*
443  linear convolution of set x (length n) with h (length m) and
444  result to y. the length of y is set by the caller
445 */
446 void linearconv(double *x, double *h, double *y, int n, int m)
447 {
448  int i, j, itmp;
449 
450  for (i = 0; i < n + m - 1; i++) {
451  for (j = 0; j < m; j++) {
452  itmp = i - j;
453  if ((itmp >= 0) && (itmp < n)) {
454  y[i] = y[i] + h[j] * x[itmp];
455  }
456  }
457  }
458 }
459 
460 /*
461  * cross correlation
462  */
463 int crosscorr(double *x, double *y, int n, int maxlag, double *xcov, double *xcor)
464 {
465  double xbar, xsd;
466  double ybar, ysd;
467  int i, j;
468 
469  if (maxlag + 2 > n)
470  return 1;
471  for (i = 0; i <= maxlag; i++) {
472  stasum(&x[i], n - i, &xbar, &xsd);
473  if (xsd == 0.0)
474  return 2;
475  stasum(y, n - i, &ybar, &ysd);
476  if (ysd == 0.0)
477  return 3;
478  xcov[i] = 0.0;
479  for (j = 0; j < n - i; j++) {
480  xcov[i] += (y[j] - ybar) * (x[j + i] - xbar);
481  }
482  xcov[i] /= n - i;
483  xcor[i] = xcov[i] / (xsd * ysd);
484  }
485  return 0;
486 }
487 
488 /* References,
489 
490  _Aplied Linear Regression_, Weisberg
491  _Elements of Statistical Computing_, Thisted
492 
493  Fits y = coef*x + intercept + e
494 
495  uses a 2 pass method for means and variances
496 */
497 int linear_regression(int n, double *x, double *y, double *coeff)
498 {
499  double xbar, ybar; /* sample means */
500  double sdx, sdy; /* sample standard deviations */
501  double sxy, rxy; /* sample covariance and sample correlation */
502  double SXX, SYY, SXY; /* sums of squares */
503  double RSS; /* residual sum of squares */
504  double rms; /* residual mean square */
505 // double sereg; /* standard error of regression */
506  double seslope, seintercept;
507  double slope, intercept; /* */
508  double SSreg, F /*, R2*/;
509  int i;
510 
511  if(n < 2)
512  {
513  return(1);
514  }
515 
516  xbar = ybar = 0.0;
517  SXX = SYY = SXY = 0.0;
518 
519  for(i=0;i<n;i++)
520  {
521  xbar = xbar + x[i];
522  ybar = ybar + y[i];
523  }
524 
525  xbar = xbar / n;
526  ybar = ybar / n;
527 
528  for(i=0;i<n;i++)
529  {
530  SXX = SXX + (x[i] - xbar) * (x[i] - xbar);
531  SYY = SYY + (y[i] - ybar) * (y[i] - ybar);
532  SXY = SXY + (x[i] - xbar) * (y[i] - ybar);
533  }
534 
535  sdx = sqrt(SXX / (n - 1));
536  sdy = sqrt(SYY / (n - 1));
537 
538  if(sdx == 0.0)
539  {
540  return(2);
541  }
542 
543  if(sdy == 0.0)
544  {
545  return(2);
546  }
547 
548  sxy = SXY / (n - 1);
549  rxy = sxy / (sdx * sdy);
550  slope = SXY / SXX;
551  intercept = ybar - slope * xbar;
552  RSS = SYY - slope * SXY;
553 
554  if(isSet(PF_V_FLAG))
555  {
556  st_report("Number of observations\t\t = %d", n);
557  st_report("Mean of independent variable\t = %12.7f", xbar);
558  st_report("Mean of dependent variable\t\t = %12.7f", ybar);
559  st_report("Standard dev. of ind. variable\t = %12.7f", sdx);
560  st_report("Standard dev. of dep. variable\t = %12.7f", sdy);
561  st_report("Correlation coefficient\t\t = %12.7f", rxy);
562  st_report("Regression coefficient (SLOPE)\t = %12.7f", slope);
563  }
564 
565  if(n == 2)
566  {
567  coeff[1] = (y[1] - y[0])/(x[1] - x[0]);
568  coeff[0] = y[0] - coeff[1]*x[0];
569 
570  if(isSet(PF_V_FLAG))
571  {
572  st_report("Regression constant (INTERCEPT)\t = %12.7f\n", intercept);
573  }
574 
575  return(0);
576  }
577 
578  rms = RSS / (n - 2);
579 // sereg = sqrt(rms);
580  seintercept = sqrt(rms * (1.0 / n + xbar * xbar / SXX));
581  seslope = sqrt(rms / SXX);
582  SSreg = SYY - RSS;
583  F = SSreg / rms;
584 // R2 = SSreg / SYY;
585 
586  if(isSet(PF_V_FLAG))
587  {
588  st_report("Standard error of coefficient\t = %12.7f", seslope);
589  st_report("t - value for coefficient\t\t = %12.7f", slope / seslope);
590  st_report("Regression constant (INTERCEPT)\t = %12.7f", intercept);
591  st_report("Standard error of constant\t\t = %12.7f", seintercept);
592  st_report("t - value for constant\t\t = %12.7f", intercept / seintercept);
593  st_report("Analysis of variance");
594 
595  st_report("Source\t d.f\t Sum of squares\t Mean Square\t F");
596  st_report("Regression\t 1\t%12.7f\t%12.7f\t%12.7f", SSreg, SSreg, F);
597  st_report("Residual\t%5d\t%12.7f\t%12.7f", n - 2, RSS, rms);
598  st_report("Total\t%5d\t%12.7f", n - 1, SYY);
599  }
600 
601  for(i=0;i<n;i++)
602  {
603  coeff[0] = intercept;
604  coeff[1] = slope;
605  coeff[2] = rxy;
606  }
607 
608  return(0);
609 }
610 
611 /*
612  a literal translation of the spline routine in
613  Forsyth, Malcolm, and Moler
614 */
615 void spline(int n, double *x, double *y, double *b, double *c, double *d)
616 {
617 /*
618 c
619 c the coefficients b(i), c(i), and d(i), i=1,2,...,n are computed
620 c for a cubic interpolating spline
621 c
622 c s(x) = y(i) + b(i)*(x-x(i)) + c(i)*(x-x(i))**2 + d(i)*(x-x(i))**3
623 c
624 c for x(i) .le. x .le. x(i+1)
625 c
626 c input..
627 c
628 c n = the number of data points or knots (n.ge.2)
629 c x = the abscissas of the knots in strictly increasing order
630 c y = the ordinates of the knots
631 c
632 c output..
633 c
634 c b, c, d = arrays of spline coefficients as defined above.
635 c
636 c using p to denote differentiation,
637 c
638 c y(i) = s(x(i))
639 c b(i) = sp(x(i))
640 c c(i) = spp(x(i))/2
641 c d(i) = sppp(x(i))/6 (derivative from the right)
642 c
643 c the accompanying function subprogram seval can be used
644 c to evaluate the spline.
645 c
646 c
647 */
648 
649  int nm1, ib, i;
650  double t;
651 
652 /*
653 Gack!
654 */
655  x--;
656  y--;
657  b--;
658  c--;
659  d--;
660 
661 /*
662 Fortran 66
663 */
664  nm1 = n - 1;
665  if (n < 2)
666  return;
667  if (n < 3)
668  goto l50;
669 /*
670 c
671 c set up tridiagonal system
672 c
673 c b = diagonal, d = offdiagonal, c = right hand side.
674 c
675 */
676  d[1] = x[2] - x[1];
677  c[2] = (y[2] - y[1]) / d[1];
678  for (i = 2; i <= nm1; i++) {
679  d[i] = x[i + 1] - x[i];
680  b[i] = 2.0 * (d[i - 1] + d[i]);
681  c[i + 1] = (y[i + 1] - y[i]) / d[i];
682  c[i] = c[i + 1] - c[i];
683  }
684 /*
685 c
686 c end conditions. third derivatives at x(1) and x(n)
687 c obtained from divided differences
688 c
689 */
690  b[1] = -d[1];
691  b[n] = -d[n - 1];
692  c[1] = 0.0;
693  c[n] = 0.0;
694  if (n == 3)
695  goto l15;
696  c[1] = c[3] / (x[4] - x[2]) - c[2] / (x[3] - x[1]);
697  c[n] = c[n - 1] / (x[n] - x[n - 2]) - c[n - 2] / (x[n - 1] - x[n - 3]);
698  c[1] = c[1] * d[1] * d[1] / (x[4] - x[1]);
699  c[n] = -c[n] * d[n - 1] * d[n - 1] / (x[n] - x[n - 3]);
700 /*
701 c
702 c forward elimination
703 c
704 */
705 l15:;
706  for (i = 2; i <= n; i++) {
707  t = d[i - 1] / b[i - 1];
708  b[i] = b[i] - t * d[i - 1];
709  c[i] = c[i] - t * c[i - 1];
710  }
711 /*
712 c
713 c back substitution
714 c
715 */
716  c[n] = c[n] / b[n];
717  for (ib = 1; ib <= nm1; ib++) {
718  i = n - ib;
719  c[i] = (c[i] - d[i] * c[i + 1]) / b[i];
720  }
721 /*
722 c
723 c c(i) is now the sigma(i) of the text
724 c
725 c compute polynomial coefficients
726 c
727 */
728  b[n] = (y[n] - y[nm1]) / d[nm1] + d[nm1] * (c[nm1] + 2.0 * c[n]);
729  for (i = 1; i <= nm1; i++) {
730  b[i] = (y[i + 1] - y[i]) / d[i] - d[i] * (c[i + 1] + 2.0 * c[i]);
731  d[i] = (c[i + 1] - c[i]) / d[i];
732  c[i] = 3.0 * c[i];
733  }
734  c[n] = 3.0 * c[n];
735  d[n] = d[n - 1];
736  return;
737 
738 l50:;
739  b[1] = (y[2] - y[1]) / (x[2] - x[1]);
740  c[1] = 0.0;
741  d[1] = 0.0;
742  b[2] = b[1];
743  c[2] = 0.0;
744  d[2] = 0.0;
745  return;
746 }
747 
748 /***************************************************************************
749  * aspline - modified version of David Frey's spline.c *
750  * *
751  * aspline does an Akima spline interpolation. *
752  ***************************************************************************/
753 
754 void aspline(int n, double *x, double *y, double *b, double *c, double *d)
755 {
756  int i;
757 
758  double num, den;
759  double m_m1, m_m2, m_p1, m_p2;
760  double x_m1, x_m2, x_p1, x_p2;
761  double y_m1, y_m2, y_p1, y_p2;
762 
763 #define dx(i) (x[i+1]-x[i])
764 #define dy(i) (y[i+1]-y[i])
765 #define m(i) (dy(i)/dx(i))
766 
767  if (n > 0) /* we have data to process */
768  {
769 
770  /*
771  * calculate the coefficients of the spline
772  * (the Akima interpolation itself)
773  */
774 
775  /* b) interpolate the missing points: */
776 
777  x_m1 = x[0] + x[1] - x[2];
778  y_m1 = (x[0]-x_m1) * (m(1) - 2 * m(0)) + y[0];
779 
780  m_m1 = (y[0]-y_m1)/(x[0]-x_m1);
781 
782  x_m2 = 2 * x[0] - x[2];
783  y_m2 = (x_m1-x_m2) * (m(0) - 2 * m_m1) + y_m1;
784 
785  m_m2 = (y_m1-y_m2)/(x_m1-x_m2);
786 
787  x_p1 = x[n-1] + x[n-2] - x[n-3];
788  y_p1 = (2 * m(n-2) - m(n-3)) * (x_p1 - x[n-1]) + y[n-1];
789 
790  m_p1 = (y_p1-y[n-1])/(x_p1-x[n-1]);
791 
792  x_p2 = 2 * x[n-1] - x[n-3];
793  y_p2 = (2 * m_p1 - m(n-2)) * (x_p2 - x_p1) + y_p1;
794 
795  m_p2 = (y_p2-y_p1)/(x_p2-x_p1);
796 
797  /* i = 0 */
798  num=fabs(m(1) - m(0)) * m_m1 + fabs(m_m1 - m_m2) * m(0);
799  den=fabs(m(1) - m(0)) + fabs(m_m1 - m_m2);
800 
801  if (den != 0.0) b[0]=num / den;
802  else b[0]=0.0;
803 
804  /* i = 1 */
805  num=fabs(m(2) - m(1)) * m(0) + fabs(m(0) - m_m1) * m(1);
806  den=fabs(m(2) - m(1)) + fabs(m(0) - m_m1);
807 
808  if (den != 0.0) b[1]=num / den;
809  else b[1]=0.0;
810 
811  for (i=2; i < n-2; i++)
812  {
813 
814  num=fabs(m(i+1) - m(i)) * m(i-1) + fabs(m(i-1) - m(i-2)) * m(i);
815  den=fabs(m(i+1) - m(i)) + fabs(m(i-1) - m(i-2));
816 
817  if (den != 0.0) b[i]=num / den;
818  else b[i]=0.0;
819  }
820 
821  /* i = n - 2 */
822  num=fabs(m_p1 - m(n-2)) * m(n-3) + fabs(m(n-3) - m(n-4)) * m(n-2);
823  den=fabs(m_p1 - m(n-2)) + fabs(m(n-3) - m(n-4));
824 
825  if (den != 0.0) b[n-2]=num / den;
826  else b[n-2]=0.0;
827 
828  /* i = n - 1 */
829  num=fabs(m_p2 - m_p1) * m(n-2) + fabs(m(n-2) - m(n-3)) * m_p1;
830  den=fabs(m_p2 - m_p1) + fabs(m(n-2) - m(n-3));
831 
832  if (den != 0.0) b[n-1]=num / den;
833  else b[n-1]=0.0;
834 
835  for (i=0; i < n-1; i++)
836  {
837  double dxv = dx(i);
838  c[i]=(3 * m(i) - 2 * b[i] - b[i+1]) / dxv;
839  d[i]=(b[i] + b[i+1] - 2 * m(i)) / (dxv * dxv);
840  }
841  }
842 #undef dx
843 #undef dy
844 #undef m
845 }
846 
847 double seval(int n, double u, double *x, double *y, double *b, double *c, double *d)
848 {
849 /*
850 c
851 c this subroutine evaluates the cubic spline function
852 c
853 c seval = y(i) + b(i)*(u-x(i)) + c(i)*(u-x(i))**2 + d(i)*(u-x(i))**3
854 c
855 c where x(i) .lt. u .lt. x(i+1), using horner's rule
856 c
857 c if u .lt. x(1) then i = 1 is used.
858 c if u .ge. x(n) then i = n is used.
859 c
860 c input..
861 c
862 c n = the number of data points
863 c u = the abscissa at which the spline is to be evaluated
864 c x,y = the arrays of data abscissas and ordinates
865 c b,c,d = arrays of spline coefficients computed by spline
866 c
867 c if u is not in the same interval as the previous call, then a
868 c binary search is performed to determine the proper interval.
869 c
870 */
871  int j, k;
872  double dx;
873  int i;
874 
875 /*
876 c
877 c binary search
878 c
879 */
880  if (u < x[0]) {
881  i = 0;
882  } else if (u >= x[n - 1]) {
883  i = n - 1;
884  } else {
885  i = 0;
886  j = n;
887 l20: ;
888  k = (i + j) / 2;
889  if (u < x[k])
890  j = k;
891  if (u >= x[k])
892  i = k;
893  if (j > i + 1)
894  goto l20;
895  }
896 /*
897 c
898 c evaluate spline
899 c
900 */
901  dx = u - x[i];
902  return (y[i] + dx * (b[i] + dx * (c[i] + dx * d[i])));
903 }
904 
double seval(int n, double u, double *x, double *y, double *b, double *c, double *d)
Definition: grace_fit.c:847
void xfree(void *ptr)
Definition: grace_fit.c:122
#define cxfree(ptr)
Definition: utils.h:50
#define max(a, b)
Definition: cactus.h:115
#define min(a, b)
Definition: cactus.h:114
void runminmax(double *x, double *y, double *ax, double *ay, int n, int ilen, int type)
Definition: grace_fit.c:374
int crosscorr(double *x, double *y, int n, int maxlag, double *xcov, double *xcor)
Definition: grace_fit.c:463
int dofitcurve(int cnt, double *xd, double *yd, int nd, double *c)
Definition: grace_dofit.c:976
void runmedian(double *x, double *y, double *ax, double *ay, int n, int ilen)
Definition: grace_fit.c:336
double sum
Definition: beam.h:5
int isSet(int flag)
Definition: parse.c:646
int fitcurve(double *x, double *y, int n, int ideg, double *coeff)
Definition: grace_fit.c:239
void runstddev(double *x, double *y, double *ax, double *ay, int n, int ilen)
Definition: grace_fit.c:313
void runavg(double *x, double *y, double *ax, double *ay, int n, int ilen)
Definition: grace_fit.c:290
double leasev(double *c, int degree, double x)
Definition: grace_fit.c:210
void st_fail()
int linear_regression(int n, double *x, double *y, double *coeff)
Definition: grace_fit.c:497
void linearconv(double *x, double *h, double *y, int n, int m)
Definition: grace_fit.c:446
void st_report()
void stasum(double *x, int n, double *xbar, double *sd)
Definition: grace_fit.c:180
double rms
Definition: beam.h:5
#define m(i)
void filterser(int n, double *x, double *y, double *resx, double *resy, double *h, int len)
Definition: grace_fit.c:421
#define dx(i)
void spline(int n, double *x, double *y, double *b, double *c, double *d)
Definition: grace_fit.c:615
struct SPECDATA sd
Definition: otf.c:43
void sort_xy(double *tmp1, double *tmp2, int up, int sorton, int stype)
Definition: grace_fit.c:133
void aspline(int n, double *x, double *y, double *b, double *c, double *d)
Definition: grace_fit.c:754