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 {
23  float tmp;
24  float y = 0.0;
25  y += coeffs[0]; tmp = x;
26  y += coeffs[1] * tmp; tmp *= x;
27  y += coeffs[2] * tmp; tmp *= x;
28  y += coeffs[3] * tmp;
29  return y;
30 }
31 
32 float Spline::Segment::deriv(float x) const
33 {
34  float tmp;
35  float d = 0.0;
36  d += coeffs[1]; tmp = x;
37  d += coeffs[2] * tmp * 2.0; tmp *= x;
38  d += coeffs[3] * tmp * 3.0;
39  return d;
40 }
41 
42 float Spline::Segment::integral(float x) const
43 {
44  float tmp = x;
45  float area = this->area;
46  area += coeffs[0] * tmp; tmp *= x;
47  area += coeffs[1] * tmp * (1.0 / 2.0); tmp *= x;
48  area += coeffs[2] * tmp * (1.0 / 3.0); tmp *= x;
49  area += coeffs[3] * tmp * (1.0 / 4.0);
50  return area;
51 }
52 
54 {}
55 
56 Spline::Spline(const Spline &orig) : n(orig.n), area(orig.area)
57 {
58  segments = new Segment[n];
59  std::memcpy(segments, orig.segments, sizeof(Segment) * n);
60 }
61 
62 Spline::Spline(unsigned int n_, const double *vals) :
63  n(0), segments(nullptr), area(0.0)
64 { set(n_, vals); }
65 
66 void Spline::set(unsigned int n_, const double *vals)
67 {
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 
117 {
118  delete[] segments;
119 }
120 
122 {
123  delete[] segments;
124  n = orig.n;
125  segments = new Segment[n];
126  std::memcpy(segments, orig.segments, sizeof(Segment) * n);
127  area = orig.area;
128  return *this;
129 }
130 
131 float Spline::eval(float x) const
132 {
133  if (x <= 0.0)
134  return segments[0].eval(0.0);
135  if (x >= 1.0)
136  return segments[n - 1].eval(1.0);
137 
138  float total;
139  float rest = std::modf(x * n, &total);
140 
141  return segments[(unsigned int)total].eval(rest);
142 }
143 
144 float Spline::deriv(float x) const
145 {
146  if (x < 0.0 || x > 1.0)
147  return 0.0;
148  else if (x == 0.0)
149  return segments[0].deriv(0.0);
150  else if (x == 1.0)
151  return segments[n - 1].deriv(1.0);
152 
153  float total;
154  float rest = std::modf(x * n, &total);
155 
156  return segments[(unsigned int)total].deriv(rest);
157 }
158 
159 float Spline::integral(float x) const
160 {
161  if (x <= 0.0)
162  return 0.0;
163  if (x >= 1.0)
164  return 1.0;
165 
166  if (area < 1.0e-9)
167  return 0.0;
168 
169  float total;
170  float rest = std::modf(x * n, &total);
171 
172  return segments[(unsigned int)total].integral(rest) / area;
173 }
174 
175 } // namespace PhysicsTools
unsigned int n
Definition: Spline.h:65
float integral(float x) const
Definition: Spline.cc:42
Spline & operator=(const Spline &orig)
Definition: Spline.cc:121
#define nullptr
float eval(float x) const
compute y coordinate at x coordinate x
Definition: Spline.cc:131
void set(unsigned int n, const double *vals)
initialize spline from n y coordinates in array vals
Definition: Spline.cc:66
float eval(float x) const
Definition: Spline.cc:21
internal class describing a "segment" (between two x points)
Definition: Spline.h:56
float deriv(float x) const
Definition: Spline.cc:32
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
float deriv(float x) const
compute the derivate at x coordinate x
Definition: Spline.cc:144
float integral(float x) const
compute integral under curve between 0 and x
Definition: Spline.cc:159
A simple class for cubic splines.
Definition: Spline.h:25
Segment * segments
Definition: Spline.h:66