Geant4-11
G4CascadeInterpolator.icc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26#ifndef G4CASCADE_INTERPOLATOR_ICC
27#define G4CASCADE_INTERPOLATOR_ICC
28//
29// Author: Michael Kelsey <kelsey@slac.stanford.edu>
30//
31// Simple linear interpolation class, more lightweight than
32// G4PhysicsVector. Templated on number of X-axis (usually energy)
33// bins, constructor takes a C-array of bin edges as input, and an
34// optional flag whether to truncate or extrapolate (the default) values
35// beyond the bin boundaries.
36//
37// The interpolation action returns a simple double: the integer part
38// is the bin index, and the fractional part is, obviously, the
39// fractional part.
40//
41// 20100517 M. Kelsey -- Bug fix in interpolate: If bin position is _exactly_
42// at upper edge (== last + 0.0), just return bin value.
43// 20100520 M. Kelsey -- Second bug fix: Loop in bin search should start at
44// i=1, not i=0 (since i-1 is the key).
45// 20100803 M. Kelsey -- Add printBins() function for debugging
46// 20101019 M. Kelsey -- CoVerity reports: recursive #include, index overrun
47// 20110728 M. Kelsey -- Fix Coverity #20238, recursive #include.
48// 20110923 M. Kelsey -- Add optional ostream& argument to printBins()
49
50#include <iomanip>
51
52
53// Find bin position (index and fraction) using input argument and array
54
55template <int NBINS>
56G4double G4CascadeInterpolator<NBINS>::getBin(const G4double x) const {
57 if (x == lastX) return lastVal; // Avoid unnecessary work
58
59 G4double xindex, xdiff, xbin;
60
61 lastX = x;
62 if (x < xBins[0]) { // Handle boundaries first
63 xindex = 0.;
64 xbin = xBins[1]-xBins[0];
65 xdiff = doExtrapolation ? x-xBins[0] : 0.; // Less than zero
66 } else if (x >= xBins[last]) {
67 xindex = last;
68 xbin = xBins[last]-xBins[last-1];
69 xdiff = doExtrapolation ? x-xBins[last] : 0.;
70 } else { // Assume nBins small; linear search
71 int i;
72 for (i=1; i<last && x>xBins[i]; i++) {;} // Stops when x within bin i-1
73 xindex = i-1;
74 xbin = xBins[i] - xBins[i-1];
75 xdiff = x - xBins[i-1];
76 }
77
78#ifdef G4CASCADE_DEBUG_SAMPLER
79 G4cout << " G4CascadeInterpolator<" << NBINS << ">: x=" << x
80 << " index=" << xindex << " fraction=" << xdiff/xbin << G4endl;
81#endif
82
83 return (lastVal = xindex + xdiff/xbin); // Save return value for later
84}
85
86
87// Apply interpolation of input argument to user array
88
89template <int NBINS>
90G4double G4CascadeInterpolator<NBINS>::
91interpolate(const G4double x, const G4double (&yb)[nBins]) const {
92 getBin(x);
93 return interpolate(yb);
94}
95
96// Apply last found interpolation to user array
97
98template <int NBINS>
99G4double G4CascadeInterpolator<NBINS>::
100interpolate(const G4double (&yb)[nBins]) const {
101 // Treat boundary extrapolations specially, otherwise just truncate
102 G4int i = (lastVal<0) ? 0 : (lastVal>G4double(last)) ? last-1 : G4int(lastVal);
103 G4double frac = lastVal - G4double(i); // May be <0 or >1 if extrapolating
104
105 // Special case: if exactly on upper bin edge, just return value
106 return (i==last) ? yb[last] : (yb[i] + frac*(yb[i+1]-yb[i]));
107}
108
109
110// Print bin edges for debugging
111
112template <int NBINS>
113void G4CascadeInterpolator<NBINS>::printBins(std::ostream& os) const {
114 os << " G4CascadeInterpolator<" << NBINS << "> : " << G4endl;
115 for (G4int k=0; k<NBINS; k++) {
116 os << " " << std::setw(6) << xBins[k];
117 if ((k+1)%10 == 0) os << G4endl;
118 }
119 os << G4endl;
120}
121
122#endif /* G4CASCADE_INTERPOLATOR_ICC */