CMS 3D CMS Logo

HcalCubicInterpolator.cc
Go to the documentation of this file.
1 #include <algorithm>
3 
5 
7 
8 HcalCubicInterpolator::HcalCubicInterpolator(const std::vector<Triple>& points) {
9  const std::size_t sz = points.size();
10  if (sz) {
11  std::vector<Triple> tmp(points);
12  std::sort(tmp.begin(), tmp.end());
13  abscissae_.reserve(sz);
14  values_.reserve(sz);
15  derivatives_.reserve(sz);
16  for (std::size_t i = 0; i < sz; ++i) {
17  const Triple& t(tmp[i]);
18  abscissae_.push_back(std::get<0>(t));
19  values_.push_back(std::get<1>(t));
20  derivatives_.push_back(std::get<2>(t));
21  }
22  const std::size_t szm1 = sz - 1;
23  for (std::size_t i = 0; i < szm1; ++i)
24  if (abscissae_[i] == abscissae_[i + 1])
25  throw cms::Exception(
26  "In HcalCubicInterpolator constructor:"
27  " abscissae must not coincide");
28  }
29 }
30 
31 double HcalCubicInterpolator::operator()(const double x) const {
32  double result = 0.0;
33  const std::size_t sz = abscissae_.size();
34  if (sz) {
35  if (sz > 1) {
36  const std::size_t szm1 = sz - 1;
37  if (x >= abscissae_[szm1])
38  result = values_[szm1] + derivatives_[szm1] * (x - abscissae_[szm1]);
39  else if (x <= abscissae_[0])
40  result = values_[0] + derivatives_[0] * (x - abscissae_[0]);
41  else {
42  const std::size_t cell = std::upper_bound(abscissae_.begin(), abscissae_.end(), x) - abscissae_.begin() - 1;
43  const std::size_t cellp1 = cell + 1;
44  const double dx = abscissae_[cellp1] - abscissae_[cell];
45  const double t = (x - abscissae_[cell]) / dx;
46  const double onemt = 1.0 - t;
47  const double h00 = onemt * onemt * (1.0 + 2.0 * t);
48  const double h10 = onemt * onemt * t;
49  const double h01 = t * t * (3.0 - 2.0 * t);
50  const double h11 = t * t * onemt;
51  result = h00 * values_[cell] + h10 * dx * derivatives_[cell] + h01 * values_[cellp1] -
52  h11 * dx * derivatives_[cellp1];
53  }
54  } else
55  result = values_[0] + derivatives_[0] * (x - abscissae_[0]);
56  }
57  return result;
58 }
59 
61  double result = 0.0;
62  if (!abscissae_.empty())
63  result = abscissae_[0];
64  return result;
65 }
66 
68  double result = 0.0;
69  if (!abscissae_.empty())
70  result = abscissae_.back();
71  return result;
72 }
73 
75  const bool monotonous =
76  isStrictlyIncreasing(values_.begin(), values_.end()) || isStrictlyDecreasing(values_.begin(), values_.end());
77  if (!monotonous)
78  throw cms::Exception(
79  "In HcalCubicInterpolator::inverse:"
80  " can't invert non-monotonous functor");
81  const std::size_t sz = abscissae_.size();
82  std::vector<Triple> points;
83  points.reserve(sz);
84  for (std::size_t i = 0; i < sz; ++i) {
85  const double dydx = derivatives_[i];
86  if (dydx == 0.0)
87  throw cms::Exception(
88  "In HcalCubicInterpolator::inverse:"
89  " can't invert functor with derivatives of 0");
90  points.push_back(Triple(values_[i], abscissae_[i], 1.0 / dydx));
91  }
92  return HcalCubicInterpolator(points);
93 }
94 
95 BOOST_CLASS_EXPORT_IMPLEMENT(HcalCubicInterpolator)
std::tuple< double, double, double > Triple
HcalCubicInterpolator approximateInverse() const
double xmax() const override
std::vector< double > abscissae_
static bool isStrictlyIncreasing(Iter begin, Iter const end)
double xmin() const override
static bool isStrictlyDecreasing(Iter begin, Iter const end)
std::vector< double > values_
double operator()(double x) const override
std::vector< double > derivatives_
float x
tmp
align.sh
Definition: createJobs.py:716