OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
linfit.cpp
Go to the documentation of this file.
1 /* linfit.C
2  linear fitting routines
3 
4  NUMERICAL RECIPES IN C: THE ART OF SCIENTIFIC COMPUTING (ISBN 0-521-43108-5)
5 
6  Revision history
7  Date Description Programmer
8  ------------ -------------------------------------------- ------------
9  30/04/1992 Copied from "numerical recipies" Rene Bakker
10 
11 */
12 
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <math.h>
16 
19 
20 #include <math.h>
21 /* Internal functions
22  ========================================================================= */
23 
24 static double sqrarg;
25 #define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)
26 
27 /* gcf()
28  */
29 #define ITMAX 100
30 #define EPS 3.0e-7
31 #define FPMIN 1.0e-30
32 
33 /* gammln()
34  Returns the ln-value of the gamma function ln[G(xx)] for xx > 0.
35 */
36 static double gammln(double xx) {
37  double x, y, tmp, ser;
38  static double cof[6] = {76.18009172947146, -86.50532032941677,
39  24.01409824083091, -1.231739572450155,
40  0.1208650973866179e-2, -0.5395239384953e-5
41  };
42  int j;
43 
44  y = x = xx;
45  tmp = x + 5.5;
46  tmp -= (x + 0.5) * log(tmp);
47  ser = 1.000000000190015;
48  for(j = 0; j <= 5; j++) ser += cof[j] / ++y;
49  return -tmp + log(2.5066282746310005 * ser / x);
50 } /* gammln */
51 
52 
53 /* gcf()
54 
55  Returns the incomplete gamma function Q(a, x) evaluated by its
56  continued fraction representation as gammcf. Also returns Gamma(a) as
57  gln.
58 */
59 
60 static void gcf(double *gammcf, double a, double x, double *gln) {
61  int i;
62  double an, b, c, d, del, h;
63 
64  *gln = gammln(a);
65  b = x + 1.0 - a;
66  c = 1.0 / FPMIN;
67  d = 1.0 / b;
68  h = d;
69  for(i = 1; i <= ITMAX; i++) {
70  an = -i * (i - a);
71  b += 2.0;
72  d = an * d + b;
73  if(fabs(d) < FPMIN) d = FPMIN;
74  c = b + an / c;
75  if(fabs(c) < FPMIN) c = FPMIN;
76  d = 1.0 / d;
77  del = d * c;
78  h *= del;
79  if(fabs(del - 1.0) < EPS) break;
80  }
81  if(i > ITMAX) {
82  // writeBetError(errModeAll,errFatal,
83  // "linfit-->gfc(): a (%le) too large, ITMAX (%d) too small",
84  // a,ITMAX);
85  writeBetError("linfit-->gfc");
86  }
87  *gammcf = exp(-x + a * log(x) - (*gln)) * h;
88 } /* gcf */
89 
90 
91 /* gser() Returns the incomplete gamma function P(a,x) evaluated by
92  its series representation as gamser. Also returns ln Gamma(a) as gln.
93 */
94 static void gser(double *gamser, double a, double x, double *gln) {
95  int n;
96  double sum, del, ap;
97 
98  *gln = gammln(a);
99  if(x <= 0.0) {
100  if(x < 0.0) {
101  //writeBetError(errModeAll,errFatal,
102  // "linfit-->gser(): x (%lf) less than 0",
103  // x);
104  writeBetError("linfit-->gser");
105  }
106  *gamser = 0.0;
107  return;
108  } else {
109  ap = a;
110  del = sum = 1.0 / a;
111  for(n = 1; n <= ITMAX; n++) {
112  ++ap;
113  del *= x / ap;
114  sum += del;
115  if(fabs(del) < fabs(sum)*EPS) {
116  *gamser = sum * exp(-x + a * log(x) - (*gln));
117  return;
118  }
119  }
120  //writeBetError(errModeAll,errFatal,
121  // "linfit-->gser(): a (%le) too large, ITMAX (%d) too small",
122  // a,ITMAX);
123  writeBetError("linfit-->gser");
124  return;
125  }
126 } /* gser */
127 
128 #undef ITMAX
129 #undef EPS
130 #undef FPMIN
131 
132 
133 /* gammq()
134  Returns the incomplete gamma function Q(a, x) = 1 - P(a, x). */
135 
136 static double gammq(double a, double x) {
137  double gamser = 0.0, gammcf, gln;
138 
139  if(x < 0.0 || a <= 0.0) {
140  //writeBetError(errModeAll,errFatal,
141  // "lintfit-->gammq(): Invalid arguments in routine gammq");
142  writeBetError("linfit-->gammg");
143  }
144  if(x < (a + 1.0)) {
145  gser(&gamser, a, x, &gln);
146  return 1.0 - gamser;
147  } else {
148  gcf(&gammcf, a, x, &gln);
149  return gammcf;
150  }
151 } /* gammq */
152 
153 /* external functions
154  ========================================================================= */
155 
156 /* linfit() Given a set of data points x[0..ndata-1],y[0..ndata-1] with
157  individual standard deviations sig[0..ndata-1], fit them to a
158  straight line y = a + bx by minimizing chi2. Returned are a,b and
159  their respective probable uncertainties siga and sigb, the
160  chi-square chi2, and the goodness-of-fit probability q (that the
161  fit would have chi2 this large or larger). If mwt=0 on input, then
162  the standard deviations are assumed to be unavailable: q is
163  returned as 1.0 and the normalization of chi2 is to unit standard
164  deviation on all points.
165 */
166 
167 void linfit(double x[], double y[], int ndata,
168  double sig[], int mwt, double *a, double *b, double *siga,
169  double *sigb, double *chi2, double *q) {
170 
171  int
172  i;
173  double
174  wt, t, sxoss, sx = 0.0, sy = 0.0, st2 = 0.0, ss, sigdat;
175 
176  *b = 0.0;
177  if(mwt) {
178  ss = 0.0;
179  for(i = 0; i < ndata; i++) {
180  wt = 1.0 / SQR(sig[i]);
181  ss += wt;
182  sx += x[i] * wt;
183  sy += y[i] * wt;
184  }
185  } else {
186  for(i = 0; i < ndata; i++) {
187  sx += x[i];
188  sy += y[i];
189  }
190  ss = ndata;
191  }
192  sxoss = sx / ss;
193  if(mwt) {
194  for(i = 0; i < ndata; i++) {
195  t = (x[i] - sxoss) / sig[i];
196  st2 += t * t;
197  *b += t * y[i] / sig[i];
198  }
199  } else {
200  for(i = 0; i < ndata; i++) {
201  t = x[i] - sxoss;
202  st2 += t * t;
203  *b += t * y[i];
204  }
205  }
206  *b /= st2;
207  *a = (sy - sx * (*b)) / ss;
208  *siga = sqrt((1.0 + sx * sx / (ss * st2)) / ss);
209  *sigb = sqrt(1.0 / st2);
210  *chi2 = 0.0;
211  if(mwt == 0) {
212  for(i = 0; i < ndata; i++)
213  *chi2 += SQR(y[i] - (*a) - (*b) * x[i]);
214  *q = 1.0;
215  sigdat = sqrt((*chi2) / (ndata - 2));
216  *siga *= sigdat;
217  *sigb *= sigdat;
218  } else {
219  for(i = 0; i < ndata; i++)
220  *chi2 += SQR((y[i] - (*a) - (*b) * x[i]) / sig[i]);
221  *q = gammq(0.5 * (ndata - 2), 0.5 * (*chi2));
222  }
223 } /* linfit */
224 
225 /* linfit()
226  Given a set of data points x[0..ndata-1],y[0..ndata-1] with, fit
227  them to a straight line y = a + bx by minimizing chi2. Returned are
228  a,b and their respective probable uncertainties siga and sigb, and
229  the chi-square chi2.
230 */
231 void linfit(double x[], double y[], int ndata,
232  double *a, double *b, double *siga,
233  double *sigb, double *chi2) {
234 
235  int
236  i;
237  double
238  t, sxoss, sx, sy, st2, sigdat;
239 
240  *b = 0.0;
241  sx = 0.0;
242  sy = 0.0;
243  for(i = 0; i < ndata; i++) {
244  sx += x[i];
245  sy += y[i];
246  }
247 
248  sxoss = sx / ndata;
249 
250  st2 = 0.0;
251  for(i = 0; i < ndata; i++) {
252  t = x[i] - sxoss;
253  st2 += t * t;
254  *b += t * y[i];
255  }
256  *b /= st2;
257  *a = (sy - sx * (*b)) / ndata;
258  *siga = sqrt((1.0 + sx * sx / (ndata * st2)) / ndata);
259  *sigb = sqrt(1.0 / st2);
260  *chi2 = 0.0;
261 
262  for(i = 0; i < ndata; i++)
263  *chi2 += SQR(y[i] - (*a) - (*b) * x[i]);
264 
265  sigdat = sqrt((*chi2) / (ndata - 2));
266  *siga *= sigdat;
267  *sigb *= sigdat;
268 } /* linfit */
269 
270 
void writeBetError(std::string err)
Definition: BetError.cpp:36
PETE_TUTree< FnFabs, typename T::PETE_Expr_t > fabs(const PETE_Expr< T > &l)
Definition: PETE.h:815
Tps< T > exp(const Tps< T > &x)
Exponential.
Definition: TpsMath.h:165
#define FPMIN
Definition: linfit.cpp:31
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
Definition: PETE.h:1213
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Definition: TpsMath.h:182
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
void linfit(double x[], double y[], int ndata, double sig[], int mwt, double *a, double *b, double *siga, double *sigb, double *chi2, double *q)
Definition: linfit.cpp:167
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
#define EPS
Definition: linfit.cpp:30
#define SQR(a)
Definition: linfit.cpp:25
#define ITMAX
Definition: linfit.cpp:29