LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
PhotonPropagationUtils.cxx
Go to the documentation of this file.
1 // Description:
3 // Utility functions
6 #include <cmath>
7 
8 namespace phot {
9 
10  //......................................................................
11  // fast approximation to acos, This implementation foillows the functional
12  // form from C. Hastings, Jr., "Approximations for Digital Computers",
13  // Princeton University Press, 1955.
14  // This differs from that version by using a new fit to the same functional
15  // form, but done in double precision. The resulting parameters differ, and
16  // result in the same calculation speed but yield a better approximation.
17  //
18  // The functional form for the fit is:
19  // acos(x) = sqrt(1-x) * a0 * (x + a1 * (x + a2 * (x + a3)))
20  // The fit done is *not* a least squares fit.
21  // It is a fit that minimizes the value of the maximum absolute deviation
22  // between the fitted function and the C math library's implementation of
23  // acos(double).
24  //
25  double fast_acos(double xin)
26  {
27  double const a3 = -2.08730442907856008e-02;
28  double const a2 = 7.68769404161671888e-02;
29  double const a1 = -2.12871094165645952e-01;
30  double const a0 = 1.57075835365209659e+00;
31  double const x = std::abs(xin);
32  double ret = a3;
33  ret *= x;
34  ret += a2;
35  ret *= x;
36  ret += a1;
37  ret *= x;
38  ret += a0;
39  ret *= std::sqrt(1.0 - x);
40  if (xin >= 0) return ret;
41  return M_PI - ret;
42  }
43 
44  //......................................................................
45  // Returns interpolated value at x from parallel arrays ( xData, yData )
46  // Assumes that xData has at least two elements, is sorted and is strictly
47  // monotonic increasing boolean argument extrapolate determines behaviour
48  // beyond ends of array (if needed)
49  double interpolate(const std::vector<double>& xData,
50  const std::vector<double>& yData,
51  const double x,
52  const bool extrapolate,
53  size_t i)
54  {
55  if (i == 0) {
56  size_t size = xData.size();
57  if (x >= xData[size - 2]) { // special case: beyond right end
58  i = size - 2;
59  }
60  else {
61  while (x > xData[i + 1])
62  i++;
63  }
64  }
65  double xL = xData[i];
66  double xR = xData[i + 1];
67  double yL = yData[i];
68  double yR = yData[i + 1]; // points on either side (unless beyond ends)
69  if (!extrapolate) { // if beyond ends of array and not extrapolating
70  if (x < xL) return yL;
71  if (x > xR) return yL;
72  }
73  const double dydx = (yR - yL) / (xR - xL); // gradient
74  return yL + dydx * (x - xL); // linear interpolation
75  }
76 
77  double interpolate2(const std::vector<double>& xDistances,
78  const std::vector<double>& rDistances,
79  const std::vector<std::vector<std::vector<double>>>& parameters,
80  const double x,
81  const double r,
82  const size_t k)
83  {
84  // interpolate in x for each r bin, for angle bin k
85  const size_t nbins_r = parameters[k].size();
86  std::vector<double> interp_vals(nbins_r, 0.);
87 
88  size_t idx = 0;
89  size_t size = xDistances.size();
90  if (x >= xDistances[size - 2])
91  idx = size - 2;
92  else {
93  while (x > xDistances[idx + 1])
94  idx++;
95  }
96  for (size_t i = 0; i < nbins_r; ++i) {
97  interp_vals[i] = interpolate(xDistances, parameters[k][i], x, false, idx);
98  }
99 
100  // interpolate in r
101  double border_correction = interpolate(rDistances, interp_vals, r, false);
102  return border_correction;
103  }
104 
105  //......................................................................
106  void interpolate3(std::array<double, 3>& inter,
107  const std::vector<double>& xData,
108  const std::vector<double>& yData1,
109  const std::vector<double>& yData2,
110  const std::vector<double>& yData3,
111  const double x,
112  const bool extrapolate)
113  {
114  size_t size = xData.size();
115  size_t i = 0; // find left end of interval for interpolation
116  if (x >= xData[size - 2]) { // special case: beyond right end
117  i = size - 2;
118  }
119  else {
120  while (x > xData[i + 1])
121  i++;
122  }
123  double xL = xData[i];
124  double xR = xData[i + 1]; // points on either side (unless beyond ends)
125  double yL1 = yData1[i];
126  double yR1 = yData1[i + 1];
127  double yL2 = yData2[i];
128  double yR2 = yData2[i + 1];
129  double yL3 = yData3[i];
130  double yR3 = yData3[i + 1];
131 
132  if (!extrapolate) { // if beyond ends of array and not extrapolating
133  if (x < xL) {
134  inter[0] = yL1;
135  inter[1] = yL2;
136  inter[2] = yL3;
137  return;
138  }
139  if (x > xR) {
140  inter[0] = yL1;
141  inter[1] = yL2;
142  inter[2] = yL3;
143  return;
144  }
145  }
146  const double m = (x - xL) / (xR - xL);
147  inter[0] = m * (yR1 - yL1) + yL1;
148  inter[1] = m * (yR2 - yL2) + yL2;
149  inter[2] = m * (yR3 - yL3) + yL3;
150  }
151 
152 } // namespace phot
Float_t x
Definition: compare.C:6
TRandom r
Definition: spectrum.C:23
void interpolate3(std::array< double, 3 > &inter, const std::vector< double > &xData, const std::vector< double > &yData1, const std::vector< double > &yData2, const std::vector< double > &yData3, const double x, const bool extrapolate)
#define a0
constexpr auto abs(T v)
Returns the absolute value of the argument.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
#define a2
#define a3
double fast_acos(double xin)
double interpolate2(const std::vector< double > &xDistances, const std::vector< double > &rDistances, const std::vector< std::vector< std::vector< double >>> &parameters, const double x, const double r, const size_t k)
General LArSoft Utilities.
double interpolate(const std::vector< double > &xData, const std::vector< double > &yData, const double x, const bool extrapolate, size_t i)
#define a1