Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
arsenal.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file arsenal.cpp
1 // Ver 1.7.0
2 // Zhi Qiu
3 /*==========================================================================================
4 Change logs: see arsenal.h
5 ==========================================================================================*/
6 
7 #include <vector>
8 #include <iostream>
9 #include <string>
10 #include <sstream>
11 #include <stdlib.h>
12 #include <cmath>
13 #include <iomanip>
14 #include <cstdarg>
15 
16 #include "arsenal.h"
17 
18 #define OUTPUT_PRECISION 10
19 
20 // for log_gamma function
21 #define D1 -0.5772156649015328605195174
22 #define D2 0.4227843350984671393993777
23 #define D4 1.791759469228055000094023
24 #define SQRTPI 0.9189385332046727417803297
25 #define FRTBIG 1.42E+09
26 #define PNT68 0.6796875
27 #define XBIG 4.08E+36
28 #define MACHINE_EPSILON 2.22044604925031e-016
29 
30 using namespace std;
31 
32 //**********************************************************************
33 double sixPoint2dInterp(double x, double y,
34  double v00, double v01, double v02, double v10, double v11, double v20)
35 {
36  /* Assume a 2d function f(x,y) has a quadratic form:
37  f(x,y) = axx*x^2 + axy*x*y + ayy*y^2 + bx*x + by*y + c
38  Also assume that:
39  f(0,0)=v00, f(0,1)=v01, f(0,2)=v02, f(1,0)=v10, f(1,1)=v11, f(2,0)=v20
40  Then its value at (x,y) can be solved.
41  The best result is produced if x and y are between 0 and 1.
42  */
43 
44  // Calculate coefficients:
45  double axx = 1.0/2.0*(v00 - 2*v10 + v20);
46  double axy = v00 - v01 - v10 + v11;
47  double ayy = 1.0/2.0*(v00 - 2*v01 + v02);
48  double bx = 1.0/2.0*(-3.0*v00 + 4*v10 - v20);
49  double by = 1.0/2.0*(-3.0*v00 + 4*v01 - v02);
50  double c = v00;
51 
52  // Calcualte f(x,y):
53  return axx*x*x + axy*x*y + ayy*y*y + bx*x + by*y + c;
54 }
55 
56 
57 //**********************************************************************
58 double interpCubicDirect(vector<double>* x, vector<double>* y, double x0)
59 // Returns the interpreted value of y=y(x) at x=x0 using cubic polynomial interpolation method.
60 // -- x,y: the independent and dependent double x0ables; x is assumed to be equal spaced and increasing
61 // -- x0: where the interpolation should be performed
62 {
63  long size = x->size();
64  if (size==1) {cout<<"interpCubicDirect warning: table size = 1"; return (*y)[0];}
65  double dx = (*x)[1]-(*x)[0]; // increment in x
66 
67  // if close to left end:
68  if (abs(x0-(*x)[0])<dx*1e-30) return (*y)[0];
69 
70  // find x's integer index
71  long idx = floor((x0-(*x)[0])/dx);
72 
73  if (idx<0 || idx>=size-1)
74  {
75  cout << "interpCubicDirect: x0 out of bounds." << endl
76  << "x ranges from " << (*x)[0] << " to " << (*x)[size-1] << ", "
77  << "x0=" << x0 << ", " << "dx=" << dx << ", " << "idx=" << idx << endl;
78  exit(-1);
79  }
80 
81  if (idx==0)
82  {
83  // use quadratic interpolation at left end
84  double A0 = (*y)[0], A1 = (*y)[1], A2 = (*y)[2], deltaX = x0 - (*x)[0]; // deltaX is the increment of x0 compared to the closest lattice point
85  return (A0-2.0*A1+A2)/(2.0*dx*dx)*deltaX*deltaX - (3.0*A0-4.0*A1+A2)/(2.0*dx)*deltaX + A0;
86  }
87  else if (idx==size-2)
88  {
89  // use quadratic interpolation at right end
90  double A0 = (*y)[size-3], A1 = (*y)[size-2], A2 = (*y)[size-1], deltaX = x0 - ((*x)[0] + (idx-1)*dx);
91  return (A0-2.0*A1+A2)/(2.0*dx*dx)*deltaX*deltaX - (3.0*A0-4.0*A1+A2)/(2.0*dx)*deltaX + A0;
92  }
93  else
94  {
95  // use cubic interpolation
96  double A0 = (*y)[idx-1], A1 = (*y)[idx], A2 = (*y)[idx+1], A3 = (*y)[idx+2], deltaX = x0 - ((*x)[0] + idx*dx);
97  //cout << A0 << " " << A1 << " " << A2 << " " << A3 << endl;
98  return (-A0+3.0*A1-3.0*A2+A3)/(6.0*dx*dx*dx)*deltaX*deltaX*deltaX
99  + (A0-2.0*A1+A2)/(2.0*dx*dx)*deltaX*deltaX
100  - (2.0*A0+3.0*A1-6.0*A2+A3)/(6.0*dx)*deltaX
101  + A1;
102  }
103 
104 }
105 
106 
107 
108 
109 //**********************************************************************
110 double interpLinearDirect(vector<double>* x, vector<double>* y, double x0)
111 // Returns the interpreted value of y=y(x) at x=x0 using linear interpolation method.
112 // -- x,y: the independent and dependent double x0ables; x is assumed to be equal spaced and increasing
113 // -- x0: where the interpolation should be performed
114 {
115  long size = x->size();
116  if (size==1) {cout<<"interpLinearDirect warning: table size = 1"<<endl; return (*y)[0];}
117  double dx = (*x)[1]-(*x)[0]; // increment in x
118 
119  // if close to left end:
120  if (abs(x0-(*x)[0])<dx*1e-30) return (*y)[0];
121 
122  // find x's integer index
123  long idx = floor((x0-(*x)[0])/dx);
124 
125  if (idx<0 || idx>=size-1)
126  {
127  cout << "interpLinearDirect: x0 out of bounds." << endl
128  << "x ranges from " << (*x)[0] << " to " << (*x)[size-1] << ", "
129  << "x0=" << x0 << ", " << "dx=" << dx << ", " << "idx=" << idx << endl;
130  exit(-1);
131  }
132 
133  return (*y)[idx] + ((*y)[idx+1]-(*y)[idx])/dx*(x0-(*x)[idx]);
134 
135 }
136 
137 
138 
139 
140 //**********************************************************************
141 double interpNearestDirect(vector<double>* x, vector<double>* y, double x0)
142 // Returns the interpreted value of y=y(x) at x=x0 using nearest interpolation method.
143 // -- x,y: the independent and dependent double x0ables; x is assumed to be equal spaced and increasing
144 // -- x0: where the interpolation should be performed
145 {
146  long size = x->size();
147  if (size==1) {cout<<"interpNearestDirect warning: table size = 1"<<endl; return (*y)[0];}
148  double dx = (*x)[1]-(*x)[0]; // increment in x
149 
150  // if close to left end:
151  if (abs(x0-(*x)[0])<dx*1e-30) return (*y)[0];
152 
153  // find x's integer index
154  long idx = floor((x0-(*x)[0])/dx);
155 
156  if (idx<0 || idx>=size-1)
157  {
158  cout << "interpNearestDirect: x0 out of bounds." << endl
159  << "x ranges from " << (*x)[0] << " to " << (*x)[size-1] << ", "
160  << "x0=" << x0 << ", " << "dx=" << dx << ", " << "idx=" << idx << endl;
161  exit(-1);
162  }
163 
164  return x0-(*x)[idx]>dx/2 ? (*y)[idx+1] : (*y)[idx];
165 
166 }
167 
168 
169 
170 
171 //**********************************************************************
172 double interpCubicMono(vector<double>* x, vector<double>* y, double xx)
173 // Note that this function does NOT perform well with small x and y table spacing; in which case use "direct" version instead.
174 // Returns the interpreted value of y=y(x) at x=x0 using cubic polynomial interpolation method.
175 // -- x,y: the independent and dependent double x0ables; x is *NOT* assumed to be equal spaced but it has to be increasing
176 // -- xx: where the interpolation should be performed
177 {
178  long size = x->size();
179  if (size==1) {cout<<"interpCubicMono warning: table size = 1"<<endl; return (*y)[0];}
180 
181  // if close to left end:
182  if (abs(xx-(*x)[0])<((*x)[1]-(*x)[0])*1e-30) return (*y)[0];
183 
184  // find x's integer index
185  long idx = binarySearch(x, xx);
186 
187  if (idx<0 || idx>=size-1)
188  {
189  cout << "interpCubicMono: x0 out of bounds." << endl
190  << "x ranges from " << (*x)[0] << " to " << (*x)[size-1] << ", "
191  << "xx=" << xx << ", " << "idx=" << idx << endl;
192  exit(-1);
193  }
194 
195  if (idx==0)
196  {
197  // use linear interpolation at the left end
198  return (*y)[0] + ( (*y)[1]-(*y)[0] )/( (*x)[1]-(*x)[0] )*( xx-(*x)[0] );
199  }
200  else if (idx==size-2)
201  {
202  // use linear interpolation at the right end
203  return (*y)[size-2] + ( (*y)[size-1]-(*y)[size-2] )/( (*x)[size-1]-(*x)[size-2] )*( xx-(*x)[size-2] );
204  }
205  else
206  {
207  // use cubic interpolation
208  long double y0 = (*y)[idx-1], y1 = (*y)[idx], y2 = (*y)[idx+1], y3 = (*y)[idx+2];
209  long double y01=y0-y1, y02=y0-y2, y03=y0-y3, y12=y1-y2, y13=y1-y3, y23=y2-y3;
210  long double x0 = (*x)[idx-1], x1 = (*x)[idx], x2 = (*x)[idx+1], x3 = (*x)[idx+2];
211  long double x01=x0-x1, x02=x0-x2, x03=x0-x3, x12=x1-x2, x13=x1-x3, x23=x2-x3;
212  long double x0s=x0*x0, x1s=x1*x1, x2s=x2*x2, x3s=x3*x3;
213  long double denominator = x01*x02*x12*x03*x13*x23;
214  long double C0, C1, C2, C3;
215  C0 = (x0*x02*x2*x03*x23*x3*y1
216  + x1*x1s*(x0*x03*x3*y2+x2s*(-x3*y0+x0*y3)+x2*(x3s*y0-x0s*y3))
217  + x1*(x0s*x03*x3s*y2+x2*x2s*(-x3s*y0+x0s*y3)+x2s*(x3*x3s*y0-x0*x0s*y3))
218  + x1s*(x0*x3*(-x0s+x3s)*y2+x2*x2s*(x3*y0-x0*y3)+x2*(-x3*x3s*y0+x0*x0s*y3))
219  )/denominator;
220  C1 = (x0s*x03*x3s*y12
221  + x2*x2s*(x3s*y01+x0s*y13)
222  + x1s*(x3*x3s*y02+x0*x0s*y23-x2*x2s*y03)
223  + x2s*(-x3*x3s*y01-x0*x0s*y13)
224  + x1*x1s*(-x3s*y02+x2s*y03-x0s*y23)
225  )/denominator;
226  C2 = (-x0*x3*(x0s-x3s)*y12
227  + x2*(x3*x3s*y01+x0*x0s*y13)
228  + x1*x1s*(x3*y02+x0*y23-x2*y03)
229  + x2*x2s*(-x3*y01-x0*y13)
230  + x1*(-x3*x3s*y02+x2*x2s*y03-x0*x0s*y23)
231  )/denominator;
232  C3 = (x0*x03*x3*y12
233  + x2s*(x3*y01+x0*y13)
234  + x1*(x3s*y02+x0s*y23-x2s*y03)
235  + x2*(-x3s*y01-x0s*y13)
236  + x1s*(-x3*y02+x2*y03-x0*y23)
237  )/denominator;
238 /* cout << x0s*x03*x3s*y12 << " "
239  << x2*x2s*(x3s*y01+x0s*y13) << " "
240  << x1s*(x3*x3s*y02+x0*x0s*y23-x2*x2s*y03) << " "
241  << x2s*(-x3*x3s*y01-x0*x0s*y13) << " "
242  << x1*x1s*(-x3s*y02+x2s*y03-x0s*y23) << endl;
243  cout << denominator << endl;
244 
245  cout << x0 << " " << x1 << " " << x2 << " " << x3 << endl;
246  cout << y0 << " " << y1 << " " << y2 << " " << y3 << endl;
247  cout << C0 << " " << C1 << " " << C2 << " " << C3 << endl;*/
248  return C0 + C1*xx + C2*xx*xx + C3*xx*xx*xx;
249  }
250 
251 }
252 
253 
254 
255 
256 
257 //**********************************************************************
258 double interpLinearMono(vector<double>* x, vector<double>* y, double xx)
259 // Returns the interpreted value of y=y(x) at x=x0 using linear interpolation method.
260 // -- x,y: the independent and dependent double x0ables; x is *NOT* assumed to be equal spaced but it has to be increasing
261 // -- xx: where the interpolation should be performed
262 {
263  long size = x->size();
264  if (size==1) {cout<<"interpLinearMono warning: table size = 1"<<endl; return (*y)[0];}
265 
266  // if close to left end:
267  if (abs(xx-(*x)[0])<((*x)[1]-(*x)[0])*1e-30) return (*y)[0];
268 
269  // find x's integer index
270  long idx = binarySearch(x, xx);
271 
272  if (idx<0 || idx>=size-1)
273  {
274  cout << "interpLinearMono: x0 out of bounds." << endl
275  << "x ranges from " << (*x)[0] << " to " << (*x)[size-1] << ", "
276  << "xx=" << xx << ", " << "idx=" << idx << endl;
277  exit(-1);
278  }
279 
280  return (*y)[idx] + ( (*y)[idx+1]-(*y)[idx] )/( (*x)[idx+1]-(*x)[idx] )*( xx-(*x)[idx] );
281 
282 }
283 
284 
285 
286 
287 //**********************************************************************
288 double interpNearestMono(vector<double>* x, vector<double>* y, double xx)
289 // Returns the interpreted value of y=y(x) at x=x0 using nearest interpolation method.
290 // -- x,y: the independent and dependent double x0ables; x is *NOT* assumed to be equal spaced but it has to be increasing
291 // -- xx: where the interpolation should be performed
292 {
293  long size = x->size();
294  if (size==1) {cout<<"interpNearestMono warning: table size = 1"<<endl; return (*y)[0];}
295 
296  // if close to left end:
297  if (abs(xx-(*x)[0])<((*x)[1]-(*x)[0])*1e-30) return (*y)[0];
298 
299  // find x's integer index
300  long idx = binarySearch(x, xx);
301 
302  if (idx<0 || idx>=size-1)
303  {
304  cout << "interpNearestMono: x0 out of bounds." << endl
305  << "x ranges from " << (*x)[0] << " to " << (*x)[size-1] << ", "
306  << "xx=" << xx << ", " << "idx=" << idx << endl;
307  exit(-1);
308  }
309 
310  return xx-(*x)[idx] > (*x)[idx+1]-xx ? (*y)[idx+1] : (*y)[idx];
311 
312 }
313 
314 
315 
316 
317 //**********************************************************************
318 double invertFunc(double (*func)(double), double y, double xL, double xR, double dx, double x0, double relative_accuracy)
319 //Purpose:
320 // Return x=func^(-1)(y) using Newton method.
321 // -- func: double 1-argument function to be inverted
322 // -- xL: left boundary (for numeric derivative)
323 // -- xR: right boundary (for numeric derivative)
324 // -- dx: step (for numeric derivative)
325 // -- x0: initial value
326 // -- y: the value to be inverted
327 // -- Returns inverted value
328 //Solve: f(x)=0 with f(x)=table(x)-y => f'(x)=table'(x)
329 {
330  double accuracy;
331  int tolerance;
332 
333  double XX1, XX2; // used in iterations
334  double F0, F1, F2, F3, X1, X2; // intermedia variables
335  int impatience; // number of iterations
336 
337 
338  // initialize parameters
339  accuracy = dx*relative_accuracy;
340 
341  tolerance = 60;
342  impatience = 0;
343 
344  // initial value, left point and midxle point
345  XX2 = x0;
346  XX1 = XX2-10*accuracy; // this value 10*accuracy is meanless, just to make sure the check in the while statement goes through
347 
348  while (abs(XX2-XX1)>accuracy)
349  {
350  XX1 = XX2; // copy values
351 
352  // value of function at XX
353  F0 = (*func)(XX1) - y; // the value of the function at this point
354 
355  // decide X1 and X2 for differentiation
356  if (XX1>xL+dx)
357  X1 = XX1 - dx;
358  else
359  X1 = xL;
360 
361  if (XX1<xR-dx)
362  X2 = XX1 + dx;
363  else
364  X2 = xR;
365 
366  // get values at X1 and X2
367  F1 = (*func)(X1);
368  F2 = (*func)(X2);
369  F3 = (F1-F2)/(X1-X2); // derivative at XX1
370 
371  XX2 = XX1 - F0/F3; // Newton's mysterious method
372 
373  impatience = impatience + 1;
374  //cout << "impatience=" << impatience << endl;
375  if (impatience>tolerance)
376  {
377  cout << "invertFunc: " << "max number of iterations reached." << endl;
378  exit(-1);
379  }
380 
381  } // <=> abs(XX2-XX1)>accuracy
382 
383  return XX2;
384 }
385 
386 
387 
388 //**********************************************************************
389 vector<double> *zq_x_global, *zq_y_global;
391 double invertTableDirect(vector<double>* x, vector<double>* y, double y0, double x0, double relative_accuracy)
392 // Return x0=y^(-1)(y0) for y=y(x); use interpCubic and invertFunc.
393 // -- x,y: the independent and dependent variables. x is assumed to be equal-spaced.
394 // -- y0: where the inversion should be performed.
395 // -- x0: initial guess
396 {
397  long size = x->size();
398  if (size==1) return (*y)[0];
399  zq_x_global = x; zq_y_global = y;
400  return invertFunc(&invertTableDirect_hook, y0, (*x)[0], (*x)[size-1], (*x)[1]-(*x)[0], x0, relative_accuracy);
401 }
402 
403 
404 
405 
406 //**********************************************************************
407 vector<double> stringToDoubles(string str)
408 // Return a vector of doubles from the string "str". "str" should
409 // be a string containing a line of data.
410 {
411  stringstream sst(str+" "); // add a blank at the end so the last data will be read
412  vector<double> valueList;
413  double val;
414  sst >> val;
415  while (sst.eof()==false)
416  {
417  valueList.push_back(val);
418  sst >> val;
419  }
420  return valueList;
421 }
422 
423 
424 //**********************************************************************
425 double stringToDouble(string str)
426 // Return the 1st doubles number read from the string "str". "str" should be a string containing a line of data.
427 {
428  stringstream sst(str+" "); // add a blank at the end so the last data will be read
429  double val;
430  sst >> val;
431  return val;
432 }
433 
434 
435 
436 //**********************************************************************
437 vector< vector<double>* >* readBlockData(istream &stream_in)
438 // Return a nested vector of vector<double>* object. Each column of data
439 // is stored in a vector<double> array and the collection is the returned
440 // object. Data are read from the input stream "stream_in". Each line
441 // of data is processed by the stringToDoubles function. Note that the
442 // data block is dynamicall allocated and is not release within the
443 // function.
444 // Note that all "vectors" are "new" so don't forget to delete them.
445 // Warning that also check if the last line is read correctly. Some files
446 // are not endded properly and the last line is not read.
447 {
448  vector< vector<double>* >* data;
449  vector<double> valuesInEachLine;
450  long lineSize;
451  long i; // temp variable
452  char buffer[99999]; // each line should be shorter than this
453 
454  // first line:
455  stream_in.getline(buffer,99999);
456  valuesInEachLine = stringToDoubles(buffer);
457  // see if it is empty:
458  lineSize = valuesInEachLine.size();
459  if (lineSize==0)
460  {
461  // empty:
462  cout << "readBlockData warning: input stream has empty first row; no data read" << endl;
463  return NULL;
464  }
465  else
466  {
467  // not empty; allocate memory:
468  data = new vector< vector<double>* >(lineSize);
469  for (i=0; i<lineSize; i++) (*data)[i] = new vector<double>;
470  }
471 
472  // rest of the lines:
473  while (stream_in.eof()==false)
474  {
475  // set values:
476  for (i=0; i<lineSize; i++) (*(*data)[i]).push_back(valuesInEachLine[i]);
477  // next line:
478  stream_in.getline(buffer,99999);
479  valuesInEachLine = stringToDoubles(buffer);
480  }
481 
482  return data;
483 }
484 
485 
486 //**********************************************************************
487 void releaseBlockData(vector< vector<double>* >* data)
488 // Use to delete the data block allocated by readBlockData function.
489 {
490  if (data)
491  {
492  for (unsigned long i=0; i<data->size(); i++) delete (*data)[i];
493  delete data;
494  }
495 }
496 
497 
498 //**********************************************************************
499 // From Wikipedia --- the free encyclopeida
500 //
501 // Recursive auxiliary function for adaptiveSimpsons() function below
502 //
503 double adaptiveSimpsonsAux(double (*f)(double), double a, double b, double epsilon,
504  double S, double fa, double fb, double fc, int bottom) {
505  double c = (a + b)/2, h = b - a;
506  double d = (a + c)/2, e = (c + b)/2;
507  double fd = f(d), fe = f(e);
508  double Sleft = (h/12)*(fa + 4*fd + fc);
509  double Sright = (h/12)*(fc + 4*fe + fb);
510  double S2 = Sleft + Sright;
511  if (bottom <= 0 || fabs(S2 - S) <= 15*epsilon)
512  return S2 + (S2 - S)/15;
513  return adaptiveSimpsonsAux(f, a, c, epsilon/2, Sleft, fa, fc, fd, bottom-1) +
514  adaptiveSimpsonsAux(f, c, b, epsilon/2, Sright, fc, fb, fe, bottom-1);
515 }
516 //
517 // Adaptive Simpson's Rule
518 //
519 double adaptiveSimpsons(double (*f)(double), // ptr to function
520  double a, double b, // interval [a,b]
521  double epsilon, // error tolerance
522  int maxRecursionDepth) { // recursion cap
523  double c = (a + b)/2, h = b - a;
524  double fa = f(a), fb = f(b), fc = f(c);
525  double S = (h/6)*(fa + 4*fc + fb);
526  return adaptiveSimpsonsAux(f, a, b, epsilon, S, fa, fb, fc, maxRecursionDepth);
527 }
528 
529 
530 //**********************************************************************
531 double qiu_simpsons(double (*f)(double), // ptr to function
532  double a, double b, // interval [a,b]
533  double epsilon, int maxRecursionDepth) // recursion maximum
534 // My version of the adaptive simpsons integration method.
535 {
536  double f_1=f(a)+f(b), f_2=0., f_4=0.; // sum of values of f(x) that will be weighted by 1, 2, 4 respectively, depending on where x is
537  double sum_previous=0., sum_current=0.; // previous and current sum (intgrated value)
538 
539  long count = 1; // how many new mid-points are there
540  double length = (b-a), // helf length of the interval
541  step = length/count; // mid-points are located at a+(i+0.5)*step, i=0..count-1
542 
543  int currentRecursionDepth = 1;
544 
545  f_4 = f(a+0.5*step); // mid point of [a,b]
546  sum_current = (length/6)*(f_1 + f_2*2. + f_4*4.); // get the current sum
547 
548  do
549  {
550  sum_previous = sum_current; // record the old sum
551  f_2 += f_4; // old mid-points with weight 4 will be new mid-points with weight 2
552 
553  count*=2; // increase number of mid-points
554  step/=2.0; // decrease jumping step by half
555  f_4 = 0.; // prepare to sum up f_4
556  for (int i=0; i<count; i++) f_4 += f(a+step*(i+0.5)); // sum up f_4
557 
558  sum_current = (length/6/count)*(f_1 + f_2*2. + f_4*4.); // calculate current sum
559  //cout << sum_current << endl;
560 
561  if (currentRecursionDepth>maxRecursionDepth)
562  {
563  cout << endl << "Warning qiu_simpsons: maximum recursion depth reached!" << endl << endl;
564  break; // safety treatment
565  }
566  else currentRecursionDepth++;
567 
568  } while (abs(sum_current-sum_previous)>epsilon);
569 
570  return sum_current;
571 }
572 
573 //**********************************************************************
574 double qiu_simpsonsRel(double (*f)(double), // ptr to function
575  double a, double b, // interval [a,b]
576  double epsilon, int maxRecursionDepth) // recursion maximum
577 // My version of the adaptive simpsons integration method.
578 {
579  double f_1=f(a)+f(b), f_2=0., f_4=0.; // sum of values of f(x) that will be weighted by 1, 2, 4 respectively, depending on where x is
580  double sum_previous=0., sum_current=0.; // previous and current sum (intgrated value)
581 
582  long count = 1; // how many new mid-points are there
583  double length = (b-a), // helf length of the interval
584  step = length/count; // mid-points are located at a+(i+0.5)*step, i=0..count-1
585 
586  int currentRecursionDepth = 1;
587 
588  f_4 = f(a+0.5*step); // mid point of [a,b]
589  sum_current = (length/6)*(f_1 + f_2*2. + f_4*4.); // get the current sum
590 
591  do
592  {
593  sum_previous = sum_current; // record the old sum
594  f_2 += f_4; // old mid-points with weight 4 will be new mid-points with weight 2
595 
596  count*=2; // increase number of mid-points
597  step/=2.0; // decrease jumping step by half
598  f_4 = 0.; // prepare to sum up f_4
599  for (int i=0; i<count; i++) f_4 += f(a+step*(i+0.5)); // sum up f_4
600 
601  sum_current = (length/6/count)*(f_1 + f_2*2. + f_4*4.); // calculate current sum
602  //cout << sum_current << endl;
603 
604  if (currentRecursionDepth>maxRecursionDepth)
605  {
606  cout << endl << "Warning qiu_simpsons: maximum recursion depth reached!" << endl << endl;
607  break; // safety treatment
608  }
609  else currentRecursionDepth++;
610 
611  } while (abs(sum_current-sum_previous)/(sum_current-sum_previous)>epsilon);
612 
613  return sum_current;
614 }
615 
616 
617 //**********************************************************************
618 string toLower(string str)
619 // Convert all character in string to lower case
620 {
621  string tmp = str;
622  for (string::iterator it=tmp.begin(); it<=tmp.end(); it++) *it = tolower(*it);
623  return tmp;
624 }
625 
626 //**********************************************************************
627 string trim(string str)
628 // Convert all character in string to lower case
629 {
630  string tmp = str;
631  long number_of_char = 0;
632  for (size_t ii=0; ii<str.size(); ii++)
633  if (str[ii]!=' ' && str[ii]!='\t')
634  {
635  tmp[number_of_char]=str[ii];
636  number_of_char++;
637  }
638  tmp.resize(number_of_char);
639  return tmp;
640 }
641 
642 
643 //**********************************************************************
644 long binarySearch(vector<double>* A, double value, bool skip_out_of_range)
645 // Return the index of the largest number less than value in the list A
646 // using binary search. Index starts with 0.
647 // If skip_out_of_range is set to true, then it will return -1 for those
648 // samples that are out of the table range.
649 {
650  int length = A->size();
651  int idx_i, idx_f, idx;
652  idx_i = 0;
653  idx_f = length-1;
654  if(value > (*A)[idx_f])
655  {
656  if (skip_out_of_range) return -1;
657  cout << "binarySearch: desired value is too large, exceeding the end of the table." << endl;
658  exit(-1);
659  }
660  if(value < (*A)[idx_i])
661  {
662  if (skip_out_of_range) return -1;
663  cout << "binarySearch: desired value is too small, exceeding the beginning of table." << endl;
664  exit(-1);
665  }
666  idx = (int) floor((idx_f+idx_i)/2.);
667  while((idx_f-idx_i) > 1)
668  {
669  if((*A)[idx] < value)
670  idx_i = idx;
671  else
672  idx_f = idx;
673  idx = (int) floor((idx_f+idx_i)/2.);
674  }
675  return(idx_i);
676 }
677 
678 
679 //**********************************************************************
680 long double gamma_function(long double x)
681 // gamma.cpp -- computation of gamma function.
682 // Algorithms and coefficient values from "Computation of Special
683 // Functions", Zhang and Jin, John Wiley and Sons, 1996.
684 // Returns gamma function of argument 'x'.
685 //
686 // NOTE: Returns 1e308 if argument is a negative integer or 0,
687 // or if argument exceeds 171.
688 {
689  int i,k,m;
690  long double ga,gr,r=0,z;
691 
692  static long double g[] = {
693  1.0,
694  0.5772156649015329,
695  -0.6558780715202538,
696  -0.420026350340952e-1,
697  0.1665386113822915,
698  -0.421977345555443e-1,
699  -0.9621971527877e-2,
700  0.7218943246663e-2,
701  -0.11651675918591e-2,
702  -0.2152416741149e-3,
703  0.1280502823882e-3,
704  -0.201348547807e-4,
705  -0.12504934821e-5,
706  0.1133027232e-5,
707  -0.2056338417e-6,
708  0.6116095e-8,
709  0.50020075e-8,
710  -0.11812746e-8,
711  0.1043427e-9,
712  0.77823e-11,
713  -0.36968e-11,
714  0.51e-12,
715  -0.206e-13,
716  -0.54e-14,
717  0.14e-14};
718 
719  if (x > 171.0) return 1e308; // This value is an overflow flag.
720  if (x == (int)x) {
721  if (x > 0.0) {
722  ga = 1.0; // use factorial
723  for (i=2;i<x;i++) {
724  ga *= i;
725  }
726  }
727  else
728  ga = 1e308;
729  }
730  else {
731  if (fabs(x) > 1.0) {
732  z = fabs(x);
733  m = (int)z;
734  r = 1.0;
735  for (k=1;k<=m;k++) {
736  r *= (z-k);
737  }
738  z -= m;
739  }
740  else
741  z = x;
742  gr = g[24];
743  for (k=23;k>=0;k--) {
744  gr = gr*z+g[k];
745  }
746  ga = 1.0/(gr*z);
747  if (fabs(x) > 1.0) {
748  ga *= r;
749  if (x < 0.0) {
750  ga = -M_PI/(x*ga*sin(M_PI*x));
751  }
752  }
753  }
754  return ga;
755 }
756 
757 
758 
759 
760 
761 
762 //**********************************************************************
763 long double log_gamma_function(long double x)
764 // Return ln(Gamma(x)).
765 // Courtesy to Codecog.org.
766 // This funcion is under GP license.
767 {
768  if (x <= 0 || x > XBIG)
769  return HUGE_VAL;
770 
771  if (x <= MACHINE_EPSILON)
772  return -log(x);
773 
774  if (x <= 4)
775  {
776  double
777  p1[8] =
778  {
779  4.945235359296727046734888E+00, 2.018112620856775083915565E+02, 2.290838373831346393026739E+03,
780  1.131967205903380828685045E+04, 2.855724635671635335736389E+04, 3.848496228443793359990269E+04,
781  2.637748787624195437963534E+04, 7.225813979700288197698961E+03
782  },
783  q1[8] =
784  {
785  6.748212550303777196073036E+01, 1.113332393857199323513008E+03, 7.738757056935398733233834E+03,
786  2.763987074403340708898585E+04, 5.499310206226157329794414E+04, 6.161122180066002127833352E+04,
787  3.635127591501940507276287E+04, 8.785536302431013170870835E+03
788  },
789  p2[8] =
790  {
791  4.974607845568932035012064E+00, 5.424138599891070494101986E+02, 1.550693864978364947665077E+04,
792  1.847932904445632425417223E+05, 1.088204769468828767498470E+06, 3.338152967987029735917223E+06,
793  5.106661678927352456275255E+06, 3.074109054850539556250927E+06
794  },
795  q2[8] =
796  {
797  1.830328399370592604055942E+02, 7.765049321445005871323047E+03, 1.331903827966074194402448E+05,
798  1.136705821321969608938755E+06, 5.267964117437946917577538E+06, 1.346701454311101692290052E+07,
799  1.782736530353274213975932E+07, 9.533095591844353613395747E+06
800  };
801 
802  double corr = x >= PNT68 ? 0 : -log(x);
803  double xden = 1, xnum = 0, xm = x <= 1.5 ? (x > 0.5 ? x - 1 : x) : x - 2;
804  bool flag = false;
805  if (x <= 1.5 && (x <= 0.5 || x >= PNT68)) flag = true;
806  double *p = flag ? p1 : p2, *q = flag ? q1 : q2;
807 
808  xnum = xnum * xm + p[0], xden = xden * xm + q[0];
809  xnum = xnum * xm + p[1], xden = xden * xm + q[1];
810  xnum = xnum * xm + p[2], xden = xden * xm + q[2];
811  xnum = xnum * xm + p[3], xden = xden * xm + q[3];
812  xnum = xnum * xm + p[4], xden = xden * xm + q[4];
813  xnum = xnum * xm + p[5], xden = xden * xm + q[5];
814  xnum = xnum * xm + p[6], xden = xden * xm + q[6];
815  xnum = xnum * xm + p[7], xden = xden * xm + q[7];
816 
817  return (x > 1.5 ? 0 : corr) + xm * ((flag ? D1 : D2) + xm * (xnum / xden));
818  }
819 
820  if (x <= 12)
821  {
822  double xm = x - 4, xden = -1, xnum = 0,
823  p[8] =
824  {
825  1.474502166059939948905062E+04, 2.426813369486704502836312E+06, 1.214755574045093227939592E+08,
826  2.663432449630976949898078E+09, 2.940378956634553899906876E+010,1.702665737765398868392998E+011,
827  4.926125793377430887588120E+011, 5.606251856223951465078242E+011
828  },
829  q[8] =
830  {
831  2.690530175870899333379843E+03, 6.393885654300092398984238E+05, 4.135599930241388052042842E+07,
832  1.120872109616147941376570E+09, 1.488613728678813811542398E+010, 1.016803586272438228077304E+011,
833  3.417476345507377132798597E+011, 4.463158187419713286462081E+011
834  };
835 
836  xnum = xnum * xm + p[0], xden = xden * xm + q[0];
837  xnum = xnum * xm + p[1], xden = xden * xm + q[1];
838  xnum = xnum * xm + p[2], xden = xden * xm + q[2];
839  xnum = xnum * xm + p[3], xden = xden * xm + q[3];
840  xnum = xnum * xm + p[4], xden = xden * xm + q[4];
841  xnum = xnum * xm + p[5], xden = xden * xm + q[5];
842  xnum = xnum * xm + p[6], xden = xden * xm + q[6];
843  xnum = xnum * xm + p[7], xden = xden * xm + q[7];
844 
845  return D4 + xm * (xnum / xden);
846  }
847 
848  double res = 0;
849  if (x <= FRTBIG)
850  {
851  double xsq = x * x,
852  c[7] =
853  {
854  -1.910444077728E-03, 8.4171387781295E-04, -5.952379913043012E-04, 7.93650793500350248E-04,
855  -2.777777777777681622553E-03, 8.333333333333333331554247E-02, 5.7083835261E-03
856  };
857  res = c[6];
858  res = res / xsq + c[0];
859  res = res / xsq + c[1];
860  res = res / xsq + c[2];
861  res = res / xsq + c[3];
862  res = res / xsq + c[4];
863  res = res / xsq + c[5];
864  }
865  double corr = log(x);
866  res /= x, res += SQRTPI - corr / 2 + x * (corr - 1);
867  return res;
868 }
869 
870 
871 
872 
873 
874 //**********************************************************************
875 double beta_function(double x, double y)
876 // B(x,y):=Gamma(x)Gamma(y)/Gamma(x+y)
877 {
879 }
880 
881 
882 
883 
884 
885 //**********************************************************************
886 double binomial_coefficient(double n, double k)
887 // Returns the binomial coefficient
888 // C_n^k := Gamma(n+1) / (Gamma(k+1)*Gamma(n-k+1))
889 {
890  return 1.0/(n+1)/beta_function(k+1,n-k+1);
891 }
892 
893 
894 
895 
896 
897 //**********************************************************************
898 void print_progressbar(double percentage, int length, string symbol)
899 // Print out a progress bar with the given percentage. Use a negative value to reset the progress bar.
900 {
901  static int status=0;
902  static int previous_stop=0;
903 
904  if (percentage<0)
905  {
906  // reset
907  status = 0;
908  previous_stop = 0;
909  }
910 
911  // initializing progressbar
912  if (status==0)
913  {
914  cout << "\r";
915  cout << "[";
916  for (int i=1; i<=length; i++) cout << " ";
917  cout << "]";
918  cout << "\r";
919  cout << "[";
920  }
921 
922  // plot status
923  int stop;
924  if (percentage>=0.99) stop=0.99*length;
925  else stop = percentage*length;
926  for (int i=previous_stop; i<stop; i++) cout << symbol;
927  if (previous_stop<stop) previous_stop=stop;
928 
929  // simulate a rotating bar
930  if (status==0) cout << "-";
931  switch (status)
932  {
933  case 1: cout << "\\"; break;
934  case 2: cout << "|"; break;
935  case 3: cout << "/"; break;
936  case 4: cout << "-"; break;
937  }
938  cout << "\b";
939  status++;
940  if (status==5) status=1;
941  cout.flush();
942 }
943 
944 
945 //**********************************************************************
946 void formatedPrint(ostream& os, int count, ...)
947 // For easier scientific data outputing.
948 {
949  va_list ap;
950  va_start(ap, count); //Requires the last fixed parameter (to get the address)
951  for(int j=0; j<count; j++)
952  os << scientific << setprecision(OUTPUT_PRECISION) << " " << va_arg(ap, double); //Requires the type to cast to. Increments ap to the next argument.
953  va_end(ap);
954  os << endl;
955 }
956 
957 
958 
959 //**********************************************************************
960 void display_logo(int which)
961 // Personal amusement.
962 {
963  switch (which)
964  {
965  case 1:
966  cout << " ____ ____ _ " << endl;
967  cout << "|_ || _| (_) " << endl;
968  cout << " | |__| | .---. __ _ .--. ____ " << endl;
969  cout << " | __ | / /__\\\\ [ | [ `.-. | [_ ] " << endl;
970  cout << " _| | | |_ | \\__., | | | | | | .' /_ " << endl;
971  cout << "|____||____| '.__.' [___] [___||__] [_____]" << endl;
972  cout << " " << endl;
973  break;
974 
975  case 2:
976  cout << "::: ::: :::::::::: ::::::::::: :::: ::: :::::::::" << endl;
977  cout << ":+: :+: :+: :+: :+:+: :+: :+: " << endl;
978  cout << "+:+ +:+ +:+ +:+ :+:+:+ +:+ +:+ " << endl;
979  cout << "+#++:++#++ +#++:++# +#+ +#+ +:+ +#+ +#+ " << endl;
980  cout << "+#+ +#+ +#+ +#+ +#+ +#+#+# +#+ " << endl;
981  cout << "#+# #+# #+# #+# #+# #+#+# #+# " << endl;
982  cout << "### ### ########## ########### ### #### #########" << endl;
983  break;
984 
985  case 3:
986  cout << " __ __ ______ __ __ __ _____ " << endl;
987  cout << "/\\ \\_\\ \\ /\\ ___\\ /\\ \\ /\\ '-.\\ \\ /\\___ \\ " << endl;
988  cout << "\\ \\ __ \\ \\ \\ __\\ \\ \\ \\ \\ \\ \\-. \\ \\/_/ /__ " << endl;
989  cout << " \\ \\_\\ \\_\\ \\ \\_____\\ \\ \\_\\ \\ \\_\\\\'\\_\\ /\\_____\\" << endl;
990  cout << " \\/_/\\/_/ \\/_____/ \\/_/ \\/_/ \\/_/ \\/_____/" << endl;
991  break;
992 
993  }
994 
995 }
996 
997 
998 
999 //**********************************************************************
1000 void GaussLegendre_getWeight(int npts,double* xg,double* wg, double A, double B, int iop)
1001 // Calculate the sampling location and weight for Gauss-Legendre quadrature
1002 // -- From Hirano and Nara's MC-KLN code.
1003 {
1004 //ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
1005 // gauss.f: Points and weights for Gaussian quadrature c
1006 // c
1007 // taken from: "Projects in Computational Physics" by Landau and Paez c
1008 // copyrighted by John Wiley and Sons, New York c
1009 // c
1010 // written by: Oregon State University Nuclear Theory Group c
1011 // Guangliang He & Rubin H. Landau c
1012 // supported by: US National Science Foundation, Northwest Alliance c
1013 // for Computational Science and Engineering (NACSE), c
1014 // US Department of Energy c
1015 // c
1016 // comment: error message occurs if subroutine called without a main c
1017 // comment: this file has to reside in the same directory as integ.c c
1018 //ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
1019 
1020  static const double EPS = 3.0e-14;
1021  int m=(npts+1)/2;
1022  for(int i=0;i<m;i++) {
1023  double t=cos(M_PI*(i+1-0.25)/(npts+0.5));
1024  double t1=t;
1025  double pp;
1026  do {
1027  double p1=1.0;
1028  double p2=0.0;
1029  double aj=0.0;
1030  for(int j=0;j<npts;j++) {
1031  double p3=p2;
1032  p2=p1;
1033  aj += 1.0;
1034  p1=((2.0*aj-1.0)*t*p2-(aj-1.0)*p3)/aj;
1035  }
1036  pp=npts*(t*p1-p2)/(t*t-1.0);
1037  t1=t;
1038  t=t1-p1/pp;
1039  } while(abs(t-t1)>EPS);
1040  xg[i]=-t;
1041  xg[npts-1-i]=t;
1042  wg[i]=2.0/((1.0-t*t)*pp*pp);
1043  wg[npts-1-i]=wg[i];
1044  }
1045 
1046 //GaussLegendre::GaussRange(int N,int iop,double A,double B,
1047 // double* xg1,double* wg1)
1048 //{
1049 // transform gausspoints to other range than [-1;1]
1050 // iop = 1 [A,B] uniform
1051 // iop = 2 [0,inf] A is midpoint
1052 // opt = 3 [-inf,inf] scale is A
1053 // opt = 4 [B,inf] A+2B is midoint
1054 // opt = 5 [0,B] AB/(A+B)+ is midoint
1055 
1056  int N=npts;
1057  double xp, wp;
1058  for(int i=0; i<N; i++) {
1059  if(iop == 1) {
1060  //...... A to B
1061  xp=(B+A)/2+(B-A)/2*xg[i];
1062  wp=(B-A)/2*wg[i];
1063  } else if(iop == -1) {
1064  //...... A to B
1065  xp=(B+A)/2+(B-A)/2*xg[i];
1066  if(i <= N/2)
1067  xp=(A+B)/2-(xp-A);
1068  else
1069  xp=(A+B)/2+(B-xp);
1070  wp=(B-A)/2*wg[i];
1071  } else if(iop == 2) {
1072  //...... zero to infinity
1073  xp=A*(1+xg[i])/(1-xg[i]);
1074  double tmp=(1-xg[i]);
1075  wp=2.*A/(tmp*tmp)*wg[i];
1076  } else if(iop == 3) {
1077  //...... -inf to inf scale A
1078  xp=A*(xg[i])/(1-xg[i]*xg[i]);
1079  double tmp=1-xg[i]*xg[i];
1080  wp=A*(1+xg[i]*xg[i])/(tmp*tmp)*wg[i];
1081  } else if(iop == 4) {
1082  //...... B to inf, A+2B is midoint
1083  xp=(A+2*B+A*xg[i])/(1-xg[i]);
1084  double tmp=1-xg[i];
1085  wp=2.*(B+A)/(tmp*tmp)*wg[i];
1086  } else if(iop == 5) {
1087  //...... -A to A , scale B
1088  //xp=A*pow(abs(xg[i]),B) *sign(1.0,xg(i));
1089  double tmp = xg[i] >= 0 ? 1.0 : -1.0;
1090  xp=A*pow(abs(xg[i]),B) * tmp;
1091  //xp=A*pow(abs(xg[i]),B) *sign(1.0,xg(i));
1092  wp=A*B*pow(abs(xg[i]),(B-1))*wg[i];
1093  } else if(iop == 6) {
1094  //...... 0 to B , AB/(A+B) is midpoint
1095  xp=A*B*(1+xg[i])/(B+A-(B-A)*xg[i]);
1096  double tmp = B+A-(B-A)*xg[i];
1097  wp=2*A*B*B/(tmp*tmp)*wg[i];
1098  } else {
1099  cerr << " invalid option iop = " << iop << endl;
1100  exit(-1);
1101  }
1102  xg[i]=xp;
1103  wg[i]=wp;
1104  }
1105 }
1106 
1107 
1108 
1109 
1110 
1111 //**********************************************************************
1112 void get_bin_average_and_count(istream& is, ostream& os, vector<double>* bins, long col_to_bin, void (*func)(vector<double>*), long wanted_data_columns, bool silence)
1113 // Group data into bins by set by the "bins". The data in the column
1114 // "col_to_bin" read from "is" are the ones used to determine the binning.
1115 // Once the binning is decided, the averages of all data are calculated.
1116 // The result, which has the same number of rows and the number of bins,
1117 // will be outputted to "os". The i-th line of the output data contains the
1118 // average of data from each column, for the i-th bin. The output will
1119 // have 2 more columns; the 1st being the number count N and the 2nd being
1120 // dN/dx where dx is the bin width.
1121 // The values given in "bins" define the boundaries of bins and is assumed
1122 // to be non-decreasing.
1123 // After each line is decided to go into which bin, the function specified
1124 // by "func" will be called to transform data. It is the transformed data
1125 // that will be averaged. The transformed data can have different number of
1126 // columns than the data passed in, in which case its number of columns
1127 // is specified by "wanted_data_columns". The counting info will still
1128 // be always written in the last two columns.
1129 // The function specified by "func" should accepts a vector of doubles
1130 // which is one line of data, and then modify it as returned result. The
1131 // data vector passed in already has the desired length so it can be modified
1132 // directly.
1133 // The argument "col_to_bin" starts with 1.
1134 // Refer also to getBinnedAverageAndCount MATLAB program.
1135 {
1136  // initialization
1137  char* buffer = new char[99999]; // each line should be shorter than this
1138  // get first line and continue initialization
1139  is.getline(buffer, 99999);
1140  vector<double> line_data = stringToDoubles(buffer);
1141  long number_of_cols = line_data.size();
1142  long number_of_bins = bins->size()-1;
1143 
1144  if (number_of_cols==0)
1145  {
1146  cout << "get_bin_average_and_count error: the input data is empty!" << endl;
1147  exit(-1);
1148  }
1149 
1150  // create the counting array
1151  if (wanted_data_columns>0) number_of_cols = wanted_data_columns;
1152  double bin_total_and_count[number_of_bins][number_of_cols+2];
1153  for (long i=0; i<number_of_bins; i++)
1154  for (long j=0; j<number_of_cols+2; j++)
1155  {
1156  bin_total_and_count[i][j] = 0;
1157  }
1158 
1159  // add up all data
1160  long number_of_lines=1;
1161  while (is.eof()==false)
1162  {
1163  // determine which bin
1164  long bin_idx = binarySearch(bins, line_data[col_to_bin-1], true);
1165  if (bin_idx!=-1)
1166  {
1167  // transform data
1168  line_data.resize(number_of_cols, 0);
1169  if (func) (*func) (&line_data);
1170  // add to the counting matrix
1171  for (long j=0; j<number_of_cols; j++) bin_total_and_count[bin_idx][j] += line_data[j];
1172  // also the counting column
1173  bin_total_and_count[bin_idx][number_of_cols] ++;
1174  }
1175  // next iteration
1176  is.getline(buffer, 99999);
1177  line_data = stringToDoubles(buffer);
1178  if (number_of_lines % 100000 == 0 && !silence) cout << "Line " << number_of_lines << " reached." << endl;
1179  number_of_lines++;
1180  }
1181 
1182  // find the averages
1183  for (long i=0; i<number_of_bins; i++)
1184  for (long j=0; j<number_of_cols; j++)
1185  {
1186  if (bin_total_and_count[i][number_of_cols]<1e-15) continue;
1187  bin_total_and_count[i][j] /= bin_total_and_count[i][number_of_cols];
1188  }
1189 
1190 
1191  // get dN/(d bin_width)
1192  for (long i=0; i<number_of_bins; i++)
1193  {
1194  if (bin_total_and_count[i][number_of_cols]<1e-15) continue;
1195  bin_total_and_count[i][number_of_cols+1] = bin_total_and_count[i][number_of_cols]/((*bins)[i+1]-(*bins)[i]);
1196  }
1197 
1198  // output
1199  for (long i=0; i<number_of_bins; i++)
1200  {
1201  for (long j=0; j<number_of_cols+2; j++)
1202  {
1203  os << scientific << scientific << setprecision(OUTPUT_PRECISION) << bin_total_and_count[i][j] << " ";
1204  }
1205  os << endl;
1206  }
1207 
1208 }