CMS 3D CMS Logo

Spline.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: MVAComputer
4 // Class : Spline
5 //
6 
7 // Implementation:
8 // Simple cubic spline implementation for equidistant points in x.
9 //
10 // Author: Christophe Saout
11 // Created: Sat Apr 24 15:18 CEST 2007
12 //
13 
14 #include <cstring>
15 #include <cmath>
16 
18 
19 namespace PhysicsTools {
20 
21  float Spline::Segment::eval(float x) const {
22  float tmp;
23  float y = 0.0;
24  y += coeffs[0];
25  tmp = x;
26  y += coeffs[1] * tmp;
27  tmp *= x;
28  y += coeffs[2] * tmp;
29  tmp *= x;
30  y += coeffs[3] * tmp;
31  return y;
32  }
33 
34  float Spline::Segment::deriv(float x) const {
35  float tmp;
36  float d = 0.0;
37  d += coeffs[1];
38  tmp = x;
39  d += coeffs[2] * tmp * 2.0;
40  tmp *= x;
41  d += coeffs[3] * tmp * 3.0;
42  return d;
43  }
44 
45  float Spline::Segment::integral(float x) const {
46  float tmp = x;
47  float area = this->area;
48  area += coeffs[0] * tmp;
49  tmp *= x;
50  area += coeffs[1] * tmp * (1.0 / 2.0);
51  tmp *= x;
52  area += coeffs[2] * tmp * (1.0 / 3.0);
53  tmp *= x;
54  area += coeffs[3] * tmp * (1.0 / 4.0);
55  return area;
56  }
57 
58  Spline::Spline() : n(0), segments(nullptr), area(0.0) {}
59 
60  Spline::Spline(const Spline &orig) : n(orig.n), area(orig.area) {
61  segments = new Segment[n];
62  std::memcpy(segments, orig.segments, sizeof(Segment) * n);
63  }
64 
65  Spline::Spline(unsigned int n_, const double *vals) : n(0), segments(nullptr), area(0.0) { set(n_, vals); }
66 
67  void Spline::set(unsigned int n_, const double *vals) {
68  n = n_ - 1;
69  area = 0.0;
70 
71  delete[] segments;
72  segments = new Segment[n];
73 
74  if (n == 1) {
75  Segment *seg = &segments[0];
76  seg->coeffs[0] = vals[0];
77  seg->coeffs[1] = vals[1] - vals[0];
78  seg->coeffs[2] = 0.0;
79  seg->coeffs[3] = 0.0;
80  seg->area = 0.0;
81  area = seg->integral(1.0);
82  return;
83  }
84 
85  float m0, m1;
86  Segment *seg = &segments[0];
87  m0 = 0.0, m1 = 0.5 * (vals[2] - vals[0]);
88  seg->coeffs[0] = vals[0];
89  seg->coeffs[1] = -2.0 * vals[0] + 2.0 * vals[1] - m1;
90  seg->coeffs[2] = vals[0] - vals[1] + m1;
91  seg->coeffs[3] = 0.0;
92  seg->area = 0.0;
93  area = seg->integral(1.0);
94  m0 = m1;
95  seg++, vals++;
96 
97  for (unsigned int i = 1; i < n - 1; i++, seg++, vals++) {
98  m1 = 0.5 * (vals[2] - vals[0]);
99  seg->coeffs[0] = vals[0];
100  seg->coeffs[1] = m0;
101  seg->coeffs[2] = -3.0 * vals[0] - 2.0 * m0 + 3.0 * vals[1] - m1;
102  seg->coeffs[3] = 2.0 * vals[0] + m0 - 2.0 * vals[1] + m1;
103  seg->area = area;
104  area = seg->integral(1.0);
105  m0 = m1;
106  }
107 
108  seg->coeffs[0] = vals[0];
109  seg->coeffs[1] = m0;
110  seg->coeffs[2] = -vals[0] - m0 + vals[1];
111  seg->coeffs[3] = 0.0;
112  seg->area = area;
113  area = seg->integral(1.0);
114  }
115 
116  Spline::~Spline() { delete[] segments; }
117 
119  delete[] segments;
120  n = orig.n;
121  segments = new Segment[n];
122  std::memcpy(segments, orig.segments, sizeof(Segment) * n);
123  area = orig.area;
124  return *this;
125  }
126 
127  float Spline::eval(float x) const {
128  if (x <= 0.0)
129  return segments[0].eval(0.0);
130  if (x >= 1.0)
131  return segments[n - 1].eval(1.0);
132 
133  float total;
134  float rest = std::modf(x * n, &total);
135 
136  return segments[(unsigned int)total].eval(rest);
137  }
138 
139  float Spline::deriv(float x) const {
140  if (x < 0.0 || x > 1.0)
141  return 0.0;
142  else if (x == 0.0)
143  return segments[0].deriv(0.0);
144  else if (x == 1.0)
145  return segments[n - 1].deriv(1.0);
146 
147  float total;
148  float rest = std::modf(x * n, &total);
149 
150  return segments[(unsigned int)total].deriv(rest);
151  }
152 
153  float Spline::integral(float x) const {
154  if (x <= 0.0)
155  return 0.0;
156  if (x >= 1.0)
157  return 1.0;
158 
159  if (area < 1.0e-9)
160  return 0.0;
161 
162  float total;
163  float rest = std::modf(x * n, &total);
164 
165  return segments[(unsigned int)total].integral(rest) / area;
166  }
167 
168 } // namespace PhysicsTools
float deriv(float x) const
compute the derivate at x coordinate x
Definition: Spline.cc:139
unsigned int n
Definition: Spline.h:65
float integral(float x) const
Definition: Spline.cc:45
Spline & operator=(const Spline &orig)
Definition: Spline.cc:118
void set(unsigned int n, const double *vals)
initialize spline from n y coordinates in array vals
Definition: Spline.cc:67
float eval(float x) const
Definition: Spline.cc:21
internal class describing a "segment" (between two x points)
Definition: Spline.h:56
d
Definition: ztail.py:151
float integral(float x) const
compute integral under curve between 0 and x
Definition: Spline.cc:153
float deriv(float x) const
Definition: Spline.cc:34
float eval(float x) const
compute y coordinate at x coordinate x
Definition: Spline.cc:127
float x
tmp
align.sh
Definition: createJobs.py:716
A simple class for cubic splines.
Definition: Spline.h:25
Segment * segments
Definition: Spline.h:66