CMS 3D CMS Logo

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