TabulatedFunctionComplexLgAmpPhase.cc
Go to the documentation of this file.
1 
7 #include <iomanip>
8 #include <sstream>
9 #include <cmath>
10 #if !defined(__clang_major__) || __clang_major__ < 5
11 # include <ext/algorithm>
12 #endif
13 #include <utl/TabulatedFunctionComplexLgAmpPhase.h>
14 #include <utl/Test.h>
15 #include <utl/AugerException.h>
16 #include <utl/ErrorLogger.h>
17 #include <limits>
18 
19 using namespace std;
20 using namespace utl;
21 
24 
25 void
26 TabulatedFunctionComplexLgAmpPhase::FillTable(const Array& xValues,
27  const ArrayComplex& yValues)
28 {
29  const unsigned int xSize = xValues.size();
30 
31  if (xSize != yValues.size()) {
32  ostringstream err;
33  err << "Size of x and y arrays are different.";
34  ERROR(err);
35  throw OutOfBoundException(err.str());
36  }
37 
38  fX = xValues;
39  fY = yValues;
40 
41  if (is_sorted(fX.begin(), fX.end()))
42  return;
43 
44  // insertion sort
45  for (unsigned int i = 0; i < xSize; ++i) {
46  unsigned int mini = i;
47  double minx = fX[i];
48  for (unsigned int j = i+1; j < xSize; ++j) {
49  const double x = fX[j];
50  if (x < minx) {
51  minx = x;
52  mini = j;
53  }
54  }
55  if (mini != i) {
56  swap(fX[i], fX[mini]);
57  swap(fY[i], fY[mini]);
58  }
59  }
60 }
61 
62 
63 void
64 TabulatedFunctionComplexLgAmpPhase::PushBack(const double x, const ComplexLgAmpPhase& y)
65 {
66  // Check that same X value is not accidentally pushed twice in a row
67  // (a common error)
68  if (fX.size() && abs(fX.back() - x) < 1./numeric_limits<float>::max()) {
69  WARNING("Refusing to push the same x value twice.");
70  return;
71  }
72 
73  fX.push_back(x);
74  fY.push_back(y);
75 }
76 
77 
81 TabulatedFunctionComplexLgAmpPhase::Y(double x)
82  const
83 {
84  const unsigned int size = fX.size();
85 
86  if (!size) {
87  ostringstream msg;
88  msg << "No points in table.";
89  ERROR(msg);
90  throw OutOfBoundException(msg.str());
91  }
92 
93  if (size == 1)
94  return fY[0];
95 
96  if (x < fX[0] || x > fX[size-1]) {
97 
98  if (x < fX[0] && (fX[0] - x) / (fX[1] - fX[2]) < fBoundaryTolerance)
99  x = fX[0];
100  else if (x > fX[size-1] &&
101  (x - fX[size-1]) / (fX[size-1] - fX[size-2]) < fBoundaryTolerance)
102  x = fX[size-1];
103  else {
104  boost::format err("Value x=%.10f is out of table bounds [%.10f, %.12f].");
105  err % x % fX[0] % fX[size-1];
106  ERROR(err);
107  throw OutOfBoundException(err.str());
108  }
109 
110  }
111 
112  const Array::const_iterator xBegin = fX.begin();
113  const Array::const_iterator xIt = upper_bound(xBegin, fX.end(), x);
114  int index = xIt - xBegin - 1;
115  const double x1 = fX[index];
116  const ComplexLgAmpPhase y1 = fY[index];
117  if (x1 == x)
118  return y1;
119  ++index;
120  const double x2 = fX[index];
121  const ComplexLgAmpPhase y2 = fY[index];
122 
123  // linear interpolation done separately in log10(amplitude) and phase
124  return Interpolate(x1,y1,x2,y2,x);
125 }
126 
128 TabulatedFunctionComplexLgAmpPhase::FindX(const double x)
129  const
130 {
131  const Array::const_iterator xBegin = fX.begin();
132  const Array::const_iterator xEnd = fX.end();
133  const Array::const_iterator xIt = lower_bound(xBegin, xEnd, x);
134  if (xIt != xEnd && x == *xIt) {
135  const ArrayComplex::const_iterator yIt = fY.begin() + (xIt - xBegin);
137  } else
139 }
140 
141 
143 TabulatedFunctionComplexLgAmpPhase::FindY(const ComplexLgAmpPhase& y)
144  const
145 {
146  const ArrayComplex::const_iterator yIt = find(fY.begin(), fY.end(), y);
147  const Array::const_iterator xIt = (yIt != fY.end()) ?
148  fX.begin() + (yIt - fY.begin()) : fX.end();
150 }
151 
152 
154 TabulatedFunctionComplexLgAmpPhase::Insert(const double x, const ComplexLgAmpPhase& y)
155 {
156  const Array::iterator xIt = lower_bound(fX.begin(), fX.end(), x);
157  const ArrayComplex::iterator yIt = fY.begin() + (xIt - fX.begin());
158  const Array::iterator ixIt = fX.insert(xIt, x);
159  const ArrayComplex::iterator iyIt = fY.insert(yIt, y);
161 }
162 
163 
164 bool
165 TabulatedFunctionComplexLgAmpPhase::IsInValidRange(const double x)
166  const
167 {
168  return fX.front() <= x && x <= fX.back();
169 }
170 
171 
172 /*
173 TabulatedFunctionComplexLgAmpPhase
174 TabulatedFunctionComplexLgAmpPhase::operator*(const TabulatedFunctionComplexLgAmpPhase& rhs)
175  const
176 {
177  // to be written
178 }
179 */
180 
181 void
182 TabulatedFunctionComplexLgAmpPhase::Pow(const double power)
183 {
184  for (ArrayComplex::iterator it = YBegin(); it != YEnd(); ++it)
185  it->Pow(power);
186 }
187 
188 
190 TabulatedFunctionComplexLgAmpPhase::operator*=(const TabulatedFunctionComplexLgAmpPhase& rhs)
191 {
192 
193  // check if both tabulated functions have at least two elements
194  if (this->GetNPoints()<2) {
195  ostringstream err;
196  err << "LHS TabulatedFunctionComplexLgAmpPhase has less than 2 elements, cannot be multiplied.";
197  ERROR(err);
198  throw OutOfBoundException(err.str());
199  }
200 
201  if (rhs.GetNPoints()<2) {
202  ostringstream err;
203  err << "RHS TabulatedFunctionComplexLgAmpPhase has less than 2 elements, cannot be multiplied.";
204  ERROR(err);
205  throw OutOfBoundException(err.str());
206  }
207 
208  // determine the common range of the two TabulatedFunctionComplexLgAmpPhase
209  const double commonstart = max(*XBegin(),*rhs.XBegin());
210  const double commonend = min(this->GetX(this->GetNPoints()-1),rhs.GetX(rhs.GetNPoints()-1));
211 
212  /* comment out warning, it is not really useful and produces a lot of verbosity
213  // warn if the valid range of the combined TabulatedFunctionComplexLgAmpPhase is smaller than those of the two individual TabluatedFunctionComplex
214  if ( (Test<Not<CloseTo> >(*XBegin(),*rhs.XBegin()) )
215  || (Test<Not<CloseTo> >(this->GetX(this->GetNPoints()-1),rhs.GetX(rhs.GetNPoints()-1))) ) {
216  ostringstream warn;
217  warn << "Range of combined TabulatedFunctionComplexLgAmpPhase has been decreased to ["
218  << commonstart
219  << ":"
220  << commonend
221  << "]";
222  WARNING(warn);
223  }
224  */
225 
226  // initialize iterator for lhs TabulatedFunctionComplexLgAmpPhase and propagate it to the first element in the common range
227  Array::const_iterator lxIt = XBegin();
228  while (*lxIt < commonstart)
229  ++lxIt;
230 
231  // initialize iterator for lhs TabulatedFunctionComplexLgAmpPhase and propagate it to the first element in the common range
232  Array::const_iterator rxIt = rhs.XBegin();
233  while (*rxIt < commonstart)
234  ++rxIt;
235 
236  Array tempX;
237  ArrayComplex tempY;
238 
239  // create a union of the two x-arrays
240  do
241  {
242  // test if point is present in both tabulated functions
243  if (Test<CloseTo>(*lxIt,*rxIt)) {
244  tempX.push_back(*lxIt);
245  ++lxIt; // point has been used, go to next one
246  ++rxIt; // point has been used, go to next one
247  continue;
248  }
249 
250  // points were not the same, so test if lhs point is the next to be used
251  if (*lxIt < *rxIt) {
252  tempX.push_back(*lxIt);
253  ++lxIt; // point has been used, go to next one
254  continue;
255  }
256 
257  // if we arrive here, then the rhs point is the next to be used
258  tempX.push_back(*rxIt);
259  ++rxIt; // point has been used, go to next one
260 
261  } while ((*lxIt < commonend) || (*rxIt < commonend));
262  // can this comparison fail because of rounding errors? then we could read past the end of an xArray!
263 
264  // check if last point has to be added manually
265  if (Test<Not<CloseTo> >(tempX.back(),commonend))
266  tempX.push_back(commonend);
267 
268  // now create the corresponding array of Y values
269  tempY.reserve(tempX.size());
270  for (Array::const_iterator xIt = tempX.begin(); xIt != tempX.end(); ++xIt)
271  tempY.push_back(this->Y(*xIt)*rhs.Y(*xIt));
272 
273  // set the internal arrays to the temporary ones (swap is most efficient)
274  fX.swap(tempX);
275  fY.swap(tempY);
276 
277  return *this;
278 }
279 
280 
281 // Configure (x)emacs for this file ...
282 // Local Variables:
283 // mode: c++
284 // compile-command: "make -C .. -k"
285 // End:
void swap(utl::Trace< T > &t1, utl::Trace< T > &t2)
Definition: Trace.h:363
double Interpolate(const double dx, const double dy, const double x)
const phoenix::function< PowerToImpl > power
Definition: UnitGrammar.h:47
Exception for reporting variable out of valid range.
Definition: Test.h:180
#define max(a, b)
Class to hold collection (x,y) points and provide interpolation between them, where y are complex num...
double abs(const SVector< n, T > &v)
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
A class to store complex numbers which are internally represented by log10(amplitude) and phase (and ...
utl::ComplexLgAmpPhase Y(const double x) const
Get or interpolate the Y value that corresponds to parameter x.
const double & GetX(const unsigned int idx) const
std::vector< utl::ComplexLgAmpPhase > ArrayComplex
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
TabulatedPDF::Array Array
Definition: TabulatedPDF.cc:15
TabulatedFunctionComplexLgAmpPhase::ArrayComplex ArrayComplex

, generated on Tue Sep 26 2023.