Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <cstring>
00016 #include <cmath>
00017
00018 #include "PhysicsTools/MVAComputer/interface/Spline.h"
00019
00020 namespace PhysicsTools {
00021
00022 double Spline::Segment::eval(double x) const
00023 {
00024 double tmp;
00025 double y = 0.0;
00026 y += coeffs[0]; tmp = x;
00027 y += coeffs[1] * tmp; tmp *= x;
00028 y += coeffs[2] * tmp; tmp *= x;
00029 y += coeffs[3] * tmp;
00030 return y;
00031 }
00032
00033 double Spline::Segment::deriv(double x) const
00034 {
00035 double tmp;
00036 double d = 0.0;
00037 d += coeffs[1]; tmp = x;
00038 d += coeffs[2] * tmp * 2.0; tmp *= x;
00039 d += coeffs[3] * tmp * 3.0;
00040 return d;
00041 }
00042
00043 double Spline::Segment::integral(double x) const
00044 {
00045 double tmp = x;
00046 double area = this->area;
00047 area += coeffs[0] * tmp; tmp *= x;
00048 area += coeffs[1] * tmp * (1.0 / 2.0); tmp *= x;
00049 area += coeffs[2] * tmp * (1.0 / 3.0); tmp *= x;
00050 area += coeffs[3] * tmp * (1.0 / 4.0);
00051 return area;
00052 }
00053
00054 Spline::Spline() : n(0), segments(0), area(0.0)
00055 {}
00056
00057 Spline::Spline(const Spline &orig) : n(orig.n), area(orig.area)
00058 {
00059 segments = new Segment[n];
00060 std::memcpy(segments, orig.segments, sizeof(Segment) * n);
00061 }
00062
00063 Spline::Spline(unsigned int n_, const double *vals) :
00064 n(0), segments(0), area(0.0)
00065 { set(n_, vals); }
00066
00067 void Spline::set(unsigned int n_, const double *vals)
00068 {
00069 n = n_ - 1;
00070 area = 0.0;
00071
00072 delete[] segments;
00073 segments = new Segment[n];
00074
00075 if (n == 1) {
00076 Segment *seg = &segments[0];
00077 seg->coeffs[0] = vals[0];
00078 seg->coeffs[1] = vals[1] - vals[0];
00079 seg->coeffs[2] = 0.0;
00080 seg->coeffs[3] = 0.0;
00081 seg->area = 0.0;
00082 area = seg->integral(1.0);
00083 return;
00084 }
00085
00086 double m0, m1;
00087 Segment *seg = &segments[0];
00088 m0 = 0.0, m1 = 0.5 * (vals[2] - vals[0]);
00089 seg->coeffs[0] = vals[0];
00090 seg->coeffs[1] = -2.0 * vals[0] + 2.0 * vals[1] - m1;
00091 seg->coeffs[2] = vals[0] - vals[1] + m1;
00092 seg->coeffs[3] = 0.0;
00093 seg->area = 0.0;
00094 area = seg->integral(1.0);
00095 m0 = m1;
00096 seg++, vals++;
00097
00098 for(unsigned int i = 1; i < n - 1; i++, seg++, vals++) {
00099 m1 = 0.5 * (vals[2] - vals[0]);
00100 seg->coeffs[0] = vals[0];
00101 seg->coeffs[1] = m0;
00102 seg->coeffs[2] = -3.0 * vals[0] - 2.0 * m0 + 3.0 * vals[1] - m1;
00103 seg->coeffs[3] = 2.0 * vals[0] + m0 - 2.0 * vals[1] + m1;
00104 seg->area = area;
00105 area = seg->integral(1.0);
00106 m0 = m1;
00107 }
00108
00109 seg->coeffs[0] = vals[0];
00110 seg->coeffs[1] = m0;
00111 seg->coeffs[2] = - vals[0] - m0 + vals[1];
00112 seg->coeffs[3] = 0.0;
00113 seg->area = area;
00114 area = seg->integral(1.0);
00115 }
00116
00117 Spline::~Spline()
00118 {
00119 delete[] segments;
00120 }
00121
00122 Spline &Spline::operator = (const Spline &orig)
00123 {
00124 delete[] segments;
00125 n = orig.n;
00126 segments = new Segment[n];
00127 std::memcpy(segments, orig.segments, sizeof(Segment) * n);
00128 area = orig.area;
00129 return *this;
00130 }
00131
00132 double Spline::eval(double x) const
00133 {
00134 if (x <= 0.0)
00135 return segments[0].eval(0.0);
00136 if (x >= 1.0)
00137 return segments[n - 1].eval(1.0);
00138
00139 double total;
00140 double rest = std::modf(x * n, &total);
00141
00142 return segments[(unsigned int)total].eval(rest);
00143 }
00144
00145 double Spline::deriv(double x) const
00146 {
00147 if (x < 0.0 || x > 1.0)
00148 return 0.0;
00149 else if (x == 0.0)
00150 return segments[0].deriv(0.0);
00151 else if (x == 1.0)
00152 return segments[n - 1].deriv(1.0);
00153
00154 double total;
00155 double rest = std::modf(x * n, &total);
00156
00157 return segments[(unsigned int)total].deriv(rest);
00158 }
00159
00160 double Spline::integral(double x) const
00161 {
00162 if (x <= 0.0)
00163 return 0.0;
00164 if (x >= 1.0)
00165 return 1.0;
00166
00167 if (area < 1.0e-9)
00168 return 0.0;
00169
00170 double total;
00171 double rest = std::modf(x * n, &total);
00172
00173 return segments[(unsigned int)total].integral(rest) / area;
00174 }
00175
00176 }