source: trunk/MagicSoft/Mars/mtools/MCubicCoeff.cc@ 3077

Last change on this file since 3077 was 3022, checked in by raducci, 21 years ago
*** empty log message ***
File size: 5.9 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Sebastian Raducci 01/2004 <mailto:raducci@fisica.uniud.it>
19!
20! Copyright: MAGIC Software Development, 2001-2004
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26// //
27// Cubic Spline Interpolation //
28// //
29//////////////////////////////////////////////////////////////////////////////
30
31#include "MCubicCoeff.h"
32
33#include "TMath.h"
34
35#include "MLog.h"
36#include "MLogManip.h"
37
38ClassImp(MCubicCoeff);
39
40using namespace std;
41
42//----------------------------------------------------------------------------
43//
44// Constructor (The spline is: fA(x-fX)3+fB(x-fX)2+fC(x-fX)+fY
45// where x is the independent variable, 2 and 3 are exponents
46//
47
48MCubicCoeff::MCubicCoeff(Double_t x, Double_t xNext, Double_t y, Double_t yNext,
49 Double_t a, Double_t b, Double_t c) :
50 fX(x), fXNext(xNext), fA(a), fB(b), fC(c), fY(y), fYNext(yNext)
51{
52 fH = fXNext - fX;
53 if(!EvalMinMax())
54 {
55 gLog << warn << "Failed to eval interval Minimum and Maximum, returning zeros" << endl;
56 fMin = 0;
57 fMax = 0;
58 }
59}
60
61//----------------------------------------------------------------------------
62//
63// Evaluate the spline at a given point
64//
65
66Double_t MCubicCoeff::Eval(Double_t x)
67{
68 Double_t dx = x - fX;
69 return (fY+dx*(fC+dx*(fB+dx*fA)));
70}
71
72//----------------------------------------------------------------------------
73//
74// Find min and max using derivatives. The min and max could be at the begin
75// or at the end of the interval or somewhere inside the interval (in this case
76// a comparison between the first derivative and zero is made)
77// The first derivative coefficients are obviously: 3*fA, 2*fB, fC
78//
79Bool_t MCubicCoeff::EvalMinMax()
80{
81 fMin = fMax = fY;
82 fAbMin = fAbMax = fX;
83 if (fYNext < fMin)
84 {
85 fMin = fYNext;
86 fAbMin = fXNext;
87 }
88 if (fYNext > fMax)
89 {
90 fMax = fYNext;
91 fAbMax = fXNext;
92 }
93 Double_t tempMinMax;
94 Double_t delta = 4.0*fB*fB - 12.0*fA*fC;
95 if (delta >= 0.0 && fA != 0.0)
96 {
97 Double_t sqrtDelta = sqrt(delta);
98 Double_t xPlus = (-2.0*fB + sqrtDelta)/(6.0*fA);
99 Double_t xMinus = (-2.0*fB - sqrtDelta)/(6.0*fA);
100 if (xPlus >= 0.0 && xPlus <= fH)
101 {
102 tempMinMax = this->Eval(fX+xPlus);
103 if (tempMinMax < fMin)
104 {
105 fMin = tempMinMax;
106 fAbMin = fX + xPlus;
107 }
108 if (tempMinMax > fMax)
109 {
110 fMax = tempMinMax;
111 fAbMax = fX + xPlus;
112 }
113 }
114 if (xMinus >= 0.0 && xMinus <= fH)
115 {
116 tempMinMax = this->Eval(fX+xMinus);
117 if (tempMinMax < fMin)
118 {
119 fMin = tempMinMax;
120 fAbMin = fX + xMinus;
121 }
122 if (tempMinMax > fMax)
123 {
124 fMax = tempMinMax;
125 fAbMax = fX + xMinus;
126 }
127 }
128 }
129/* if fA is zero then we have only one possible solution */
130 else if (fA == 0.0 && fB != 0.0)
131 {
132 Double_t xSolo = - (fC/(2.0*fB));
133 if (xSolo >= 0.0 && xSolo <= fH)
134 {
135 tempMinMax = this->Eval(fX+xSolo);
136 if (tempMinMax < fMin)
137 {
138 fMin = tempMinMax;
139 fAbMin = fX + xSolo;
140 }
141 if (tempMinMax > fMax)
142 {
143 fMax = tempMinMax;
144 fAbMax = fX + xSolo;
145 }
146 }
147 }
148 return kTRUE;
149}
150//-------------------------------------------------------------------------
151//
152// Given y finds x using the cubic (cardan) formula.
153//
154// we consider the following form: x3 + ax2 + bx + c = 0 where
155// a = fB/fA, b = fC/fA, c = (fY - y)/fA
156//
157// There could be three or one real solutions
158//
159
160Short_t MCubicCoeff::FindCardanRoot(Double_t y, Double_t *x)
161{
162
163 Short_t whichRoot = -1;
164
165 Double_t a = fB/fA;
166 Double_t b = fC/fA;
167 Double_t c = (fY - y)/fA;
168
169 Double_t q = (a*a-3.0*b)/9.0;
170 Double_t r = (2.0*a*a*a-9.0*a*b+27.0*c)/54.0;
171
172 Double_t aOver3 = a/3.0;
173 Double_t r2 = r*r;
174 Double_t q3 = q*q*q;
175
176 if (r2 < q3) //3 real sol
177 {
178 Double_t sqrtQ = TMath::Sqrt(q);
179 Double_t min2SqQ = -2.0*sqrtQ;
180 Double_t theta = TMath::ACos(r/(sqrtQ*sqrtQ*sqrtQ));
181
182 x[0] = min2SqQ * TMath::Cos(theta/3.0) - aOver3;
183 x[1] = min2SqQ * TMath::Cos((theta+TMath::TwoPi())/3.0) - aOver3;
184 x[2] = min2SqQ * TMath::Cos((theta-TMath::TwoPi())/3.0) - aOver3;
185 for (Int_t i = 0; i < 3; i++)
186 if (x[i] >= 0.0 && x[i] <= fH)
187 {
188 x[i] = x[i] + fX;
189 whichRoot = i;
190 break;
191 }
192 }
193 else //only 1 real sol
194 {
195 Double_t s;
196 if (r == 0.0)
197 s = 0.0;
198 else if (r < 0.0)
199 s = TMath::Power(TMath::Abs(r) + TMath::Sqrt(r2 - q3),1.0/3.0);
200 else // r > 0.0
201 s = - TMath::Power(TMath::Abs(r) + TMath::Sqrt(r2 - q3),1.0/3.0);
202 if (s == 0.0)
203 x[0] = - aOver3;
204 else
205 x[0] = (s + q/s) - aOver3;
206 if (x[0] >= 0.0 && x[0] <= fH)
207 {
208 x[0] = x[0] + fX;
209 whichRoot = 0;
210 }
211 }
212 return whichRoot;
213}
214
215//------------------------------------------------------------------------------------
216//
217// return true if x is in this interval
218//
219
220Bool_t MCubicCoeff :: IsIn(Double_t x)
221{
222 if (x >= fX && x <= fXNext)
223 return kTRUE;
224 else
225 return kFALSE;
226}
Note: See TracBrowser for help on using the repository browser.