CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 // $Id: Spline.cc,v 1.4 2009/06/03 09:50:14 saout Exp $
13 //
14 
15 #include <cstring>
16 #include <cmath>
17 
19 
20 namespace PhysicsTools {
21 
22 double Spline::Segment::eval(double x) const
23 {
24  double tmp;
25  double y = 0.0;
26  y += coeffs[0]; tmp = x;
27  y += coeffs[1] * tmp; tmp *= x;
28  y += coeffs[2] * tmp; tmp *= x;
29  y += coeffs[3] * tmp;
30  return y;
31 }
32 
33 double Spline::Segment::deriv(double x) const
34 {
35  double tmp;
36  double d = 0.0;
37  d += coeffs[1]; tmp = x;
38  d += coeffs[2] * tmp * 2.0; tmp *= x;
39  d += coeffs[3] * tmp * 3.0;
40  return d;
41 }
42 
43 double Spline::Segment::integral(double x) const
44 {
45  double tmp = x;
46  double area = this->area;
47  area += coeffs[0] * tmp; tmp *= x;
48  area += coeffs[1] * tmp * (1.0 / 2.0); tmp *= x;
49  area += coeffs[2] * tmp * (1.0 / 3.0); tmp *= x;
50  area += coeffs[3] * tmp * (1.0 / 4.0);
51  return area;
52 }
53 
54 Spline::Spline() : n(0), segments(0), area(0.0)
55 {}
56 
57 Spline::Spline(const Spline &orig) : n(orig.n), area(orig.area)
58 {
59  segments = new Segment[n];
60  std::memcpy(segments, orig.segments, sizeof(Segment) * n);
61 }
62 
63 Spline::Spline(unsigned int n_, const double *vals) :
64  n(0), segments(0), area(0.0)
65 { set(n_, vals); }
66 
67 void Spline::set(unsigned int n_, const double *vals)
68 {
69  n = n_ - 1;
70  area = 0.0;
71 
72  delete[] segments;
73  segments = new Segment[n];
74 
75  if (n == 1) {
76  Segment *seg = &segments[0];
77  seg->coeffs[0] = vals[0];
78  seg->coeffs[1] = vals[1] - vals[0];
79  seg->coeffs[2] = 0.0;
80  seg->coeffs[3] = 0.0;
81  seg->area = 0.0;
82  area = seg->integral(1.0);
83  return;
84  }
85 
86  double m0, m1;
87  Segment *seg = &segments[0];
88  m0 = 0.0, m1 = 0.5 * (vals[2] - vals[0]);
89  seg->coeffs[0] = vals[0];
90  seg->coeffs[1] = -2.0 * vals[0] + 2.0 * vals[1] - m1;
91  seg->coeffs[2] = vals[0] - vals[1] + m1;
92  seg->coeffs[3] = 0.0;
93  seg->area = 0.0;
94  area = seg->integral(1.0);
95  m0 = m1;
96  seg++, vals++;
97 
98  for(unsigned int i = 1; i < n - 1; i++, seg++, vals++) {
99  m1 = 0.5 * (vals[2] - vals[0]);
100  seg->coeffs[0] = vals[0];
101  seg->coeffs[1] = m0;
102  seg->coeffs[2] = -3.0 * vals[0] - 2.0 * m0 + 3.0 * vals[1] - m1;
103  seg->coeffs[3] = 2.0 * vals[0] + m0 - 2.0 * vals[1] + m1;
104  seg->area = area;
105  area = seg->integral(1.0);
106  m0 = m1;
107  }
108 
109  seg->coeffs[0] = vals[0];
110  seg->coeffs[1] = m0;
111  seg->coeffs[2] = - vals[0] - m0 + vals[1];
112  seg->coeffs[3] = 0.0;
113  seg->area = area;
114  area = seg->integral(1.0);
115 }
116 
118 {
119  delete[] segments;
120 }
121 
123 {
124  delete[] segments;
125  n = orig.n;
126  segments = new Segment[n];
127  std::memcpy(segments, orig.segments, sizeof(Segment) * n);
128  area = orig.area;
129  return *this;
130 }
131 
132 double Spline::eval(double x) const
133 {
134  if (x <= 0.0)
135  return segments[0].eval(0.0);
136  if (x >= 1.0)
137  return segments[n - 1].eval(1.0);
138 
139  double total;
140  double rest = std::modf(x * n, &total);
141 
142  return segments[(unsigned int)total].eval(rest);
143 }
144 
145 double Spline::deriv(double x) const
146 {
147  if (x < 0.0 || x > 1.0)
148  return 0.0;
149  else if (x == 0.0)
150  return segments[0].deriv(0.0);
151  else if (x == 1.0)
152  return segments[n - 1].deriv(1.0);
153 
154  double total;
155  double rest = std::modf(x * n, &total);
156 
157  return segments[(unsigned int)total].deriv(rest);
158 }
159 
160 double Spline::integral(double x) const
161 {
162  if (x <= 0.0)
163  return 0.0;
164  if (x >= 1.0)
165  return 1.0;
166 
167  if (area < 1.0e-9)
168  return 0.0;
169 
170  double total;
171  double rest = std::modf(x * n, &total);
172 
173  return segments[(unsigned int)total].integral(rest) / area;
174 }
175 
176 } // namespace PhysicsTools
int i
Definition: DBlmapReader.cc:9
unsigned int n
Definition: Spline.h:66
double eval(double x) const
Definition: Spline.cc:22
Spline & operator=(const Spline &orig)
Definition: Spline.cc:122
double integral(double x) const
compute integral under curve between 0 and x
Definition: Spline.cc:160
void set(unsigned int n, const double *vals)
initialize spline from n y coordinates in array vals
Definition: Spline.cc:67
double integral(double x) const
Definition: Spline.cc:43
internal class describing a &quot;segment&quot; (between two x points)
Definition: Spline.h:57
double deriv(double x) const
compute the derivate at x coordinate x
Definition: Spline.cc:145
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
double eval(double x) const
compute y coordinate at x coordinate x
Definition: Spline.cc:132
double deriv(double x) const
Definition: Spline.cc:33
x
Definition: VDTMath.h:216
A simple class for cubic splines.
Definition: Spline.h:26
Segment * segments
Definition: Spline.h:67