Changeset 3148 for trunk/MagicSoft/Mars/mtools
- Timestamp:
- 02/14/04 11:48:43 (21 years ago)
- Location:
- trunk/MagicSoft/Mars/mtools
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/MagicSoft/Mars/mtools/MCubicCoeff.cc
r3022 r3148 24 24 25 25 ////////////////////////////////////////////////////////////////////////////// 26 // //27 // Cubic Spline Interpolation //28 // //26 // 27 // Cubic Spline Interpolation 28 // 29 29 ////////////////////////////////////////////////////////////////////////////// 30 31 30 #include "MCubicCoeff.h" 32 31 33 #include "TMath.h"32 #include <TMath.h> 34 33 35 34 #include "MLog.h" … … 45 44 // where x is the independent variable, 2 and 3 are exponents 46 45 // 47 48 46 MCubicCoeff::MCubicCoeff(Double_t x, Double_t xNext, Double_t y, Double_t yNext, 49 47 Double_t a, Double_t b, Double_t c) : … … 51 49 { 52 50 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 }51 if (EvalMinMax()) 52 return; 53 54 gLog << warn << "Failed to eval interval Minimum and Maximum, returning zeros" << endl; 55 fMin = 0; 56 fMax = 0; 59 57 } 60 58 … … 66 64 Double_t MCubicCoeff::Eval(Double_t x) 67 65 { 68 Double_t dx = x - fX;69 return (fY+dx*(fC+dx*(fB+dx*fA)));66 const Double_t dx = x - fX; 67 return fY + dx*(fC + dx*(fB + dx*fA)); 70 68 } 71 69 … … 79 77 Bool_t MCubicCoeff::EvalMinMax() 80 78 { 81 fMin = fMax = fY; 82 fAbMin = fAbMax = fX; 79 fMin = fY; 80 fMax = fY; 81 82 fAbMin = fX; 83 fAbMax = fX; 84 83 85 if (fYNext < fMin) 84 86 { 85 fMin = fYNext;87 fMin = fYNext; 86 88 fAbMin = fXNext; 87 89 } 88 90 if (fYNext > fMax) 89 91 { 90 fMax = fYNext;92 fMax = fYNext; 91 93 fAbMax = fXNext; 92 94 } 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 } 95 96 const Double_t delta = fB*fB*4 - fA*fC*12; 97 if (delta >= 0 && fA != 0) 98 { 99 const Double_t sqrtDelta = TMath::Sqrt(delta); 100 101 const Double_t xPlus = (-fB*2 + sqrtDelta)/(fA*6); 102 const Double_t xMinus = (-fB*2 - sqrtDelta)/(fA*6); 103 104 if (xPlus >= 0 && xPlus <= fH) 105 { 106 const Double_t tempMinMax = Eval(fX+xPlus); 107 if (tempMinMax < fMin) 108 { 109 fMin = tempMinMax; 110 fAbMin = fX + xPlus; 111 } 112 if (tempMinMax > fMax) 113 { 114 fMax = tempMinMax; 115 fAbMax = fX + xPlus; 116 } 117 } 118 if (xMinus >= 0 && xMinus <= fH) 119 { 120 const Double_t tempMinMax = Eval(fX+xMinus); 121 if (tempMinMax < fMin) 122 { 123 fMin = tempMinMax; 124 fAbMin = fX + xMinus; 125 } 126 if (tempMinMax > fMax) 127 { 128 fMax = tempMinMax; 129 fAbMax = fX + xMinus; 130 } 131 } 132 return kTRUE; 133 } 134 135 /* if fA is zero then we have only one possible solution */ 136 if (fA == 0 && fB != 0) 137 { 138 const Double_t xSolo = -fC/(fB*2); 139 140 if (xSolo < 0 || xSolo > fH) 141 return kTRUE; 142 143 const Double_t tempMinMax = Eval(fX+xSolo); 144 if (tempMinMax < fMin) 145 { 146 fMin = tempMinMax; 147 fAbMin = fX + xSolo; 148 } 149 if (tempMinMax > fMax) 150 { 151 fMax = tempMinMax; 152 fAbMax = fX + xSolo; 153 } 154 return kTRUE; 155 } 156 148 157 return kTRUE; 149 158 } … … 157 166 // There could be three or one real solutions 158 167 // 159 160 168 Short_t MCubicCoeff::FindCardanRoot(Double_t y, Double_t *x) 161 169 { 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; 170 const Double_t a = fB/fA; 171 const Double_t b = fC/fA; 172 const Double_t c = (fY - y)/fA; 173 174 const Double_t q = (a*a - b*3)/9; 175 const Double_t r = (a*a*a*2 - a*b*9 + c*27)/54; 176 177 const Double_t aOver3 = a/3; 178 const Double_t r2 = r*r; 179 const Double_t q3 = q*q*q; 175 180 176 181 if (r2 < q3) //3 real sol 177 182 { 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; 183 const Double_t sqrtQ = TMath::Sqrt(q); 184 const Double_t min2SqQ = -sqrtQ*2; 185 const Double_t theta = TMath::ACos(r/(sqrtQ*sqrtQ*sqrtQ)); 186 187 x[0] = min2SqQ * TMath::Cos(theta/3) - aOver3; 188 x[1] = min2SqQ * TMath::Cos((theta+TMath::TwoPi())/3) - aOver3; 189 x[2] = min2SqQ * TMath::Cos((theta-TMath::TwoPi())/3) - aOver3; 190 185 191 for (Int_t i = 0; i < 3; i++) 186 if (x[i] >= 0 .0&& x[i] <= fH)192 if (x[i] >= 0 && x[i] <= fH) 187 193 { 188 x[i] = x[i] + fX; 189 whichRoot = i; 190 break; 194 x[i] += fX; 195 return i; 191 196 } 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; 197 return -1; 198 } 199 200 const Double_t s = r==0 ? 0 : -TMath::Sign(TMath::Power(TMath::Abs(r) + TMath::Sqrt(r2 - q3), 1./3), r); 201 202 x[0] = s==0 ? - aOver3 : (s + q/s) - aOver3; 203 204 if (x[0] < 0 || x[0] > fH) 205 return -1; 206 207 x[0] += fX; 208 return 0; 213 209 } 214 210 … … 220 216 Bool_t MCubicCoeff :: IsIn(Double_t x) 221 217 { 222 if (x >= fX && x <= fXNext) 223 return kTRUE; 224 else 225 return kFALSE; 226 } 218 return x >= fX && x <= fXNext; 219 } -
trunk/MagicSoft/Mars/mtools/MCubicSpline.cc
r3022 r3148 24 24 25 25 ////////////////////////////////////////////////////////////////////////////// 26 // //27 // Cubic Spline Interpolation //28 // //26 // 27 // Cubic Spline Interpolation 28 // 29 29 ////////////////////////////////////////////////////////////////////////////// 30 31 30 #include "MCubicSpline.h" 32 31 33 #include "MCubicCoeff.h" 34 35 #include "TMath.h" 32 #include <TMath.h> 36 33 37 34 #include "MLog.h" 38 35 #include "MLogManip.h" 39 36 37 #include "MCubicCoeff.h" 38 40 39 ClassImp(MCubicSpline); 41 40 … … 48 47 // 49 48 MCubicSpline::MCubicSpline(Byte_t *y, Byte_t *x, Bool_t areAllEq, 50 Int_t n, Double_t begSD, Double_t endSD): 51 fN(n) 49 Int_t n, Double_t begSD, Double_t endSD) 52 50 { 53 51 Init(y,x,areAllEq,n,begSD,endSD); … … 62 60 { 63 61 Byte_t x[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E}; 64 fN = 15;65 62 Init(y,x,kTRUE,15,0.0,0.0); 66 63 } … … 75 72 76 73 { 77 Double_t *temp = new Double_t[fN-1]; 78 Double_t *ysd = new Double_t[fN-1]; 79 Double_t p,h; 80 MCubicCoeff *tempCoeff; 81 fCoeff = new TObjArray(fN-1,0); 74 Double_t *temp = new Double_t[n-1]; 75 Double_t *ysd = new Double_t[n-1]; 76 77 fCoeff = new TObjArray(n-1,0); 78 79 ysd[0] =begSD; 80 temp[0] =begSD; 81 ysd[n-1]=endSD; 82 82 83 Double_t h = x[1]-x[0]; 84 83 85 if (areAllEq) 84 86 { 85 h = x[1]-x[0];86 ysd[0]=temp[0]=begSD;87 ysd[n-1]=endSD;88 87 for(Int_t i = 1; i < n-1; i++) 89 88 { 90 p = 0.5*ysd[i-1]+2.0; 91 ysd[i] = (-0.5)/p; 92 temp[i] = (y[i+1]-2*y[i]+y[i-1])/h; 93 temp[i] = (6.0*temp[i]/h-0.5*temp[i-1])/p; 94 } 95 for(Int_t i = n-2; i > 0; i--) 96 ysd[i]=ysd[i]*ysd[i+1]+temp[i]; 97 for(Int_t i = 0; i < n-1; i++) 98 { 99 tempCoeff = new MCubicCoeff(x[i],x[i+1],y[i],y[i+1],(ysd[i+1]-ysd[i])/(6*h), 100 ysd[i]/2.0,(y[i+1]-y[i])/h-(h*(ysd[i+1]+2*ysd[i]))/6); 101 fCoeff->AddAt(tempCoeff,i); 102 } 103 delete [] temp; 104 delete [] ysd; 89 const Double_t p = ysd[i-1]/2+2; 90 91 ysd[i] = -0.5/p; 92 temp[i] = (y[i+1] - y[i]*2 + y[i-1])/h; 93 temp[i] = (temp[i]*6/h-temp[i-1]/2)/p; 94 } 105 95 } 106 96 else 107 97 { 108 Double_t sig;109 ysd[0]=temp[0]=begSD;110 ysd[n-1]=endSD;111 98 for(Int_t i = 1; i < n-1; i++) 112 99 { 113 sig = (x[i]-x[i-1])/(x[i+1]-x[i-1]); 114 p = sig*ysd[i-1]+2.0; 115 ysd[i] = (sig-1.0)/p; 100 const Double_t sig = (x[i]-x[i-1])/(x[i+1]-x[i-1]); 101 102 const Double_t p = sig*ysd[i-1]+2; 103 104 ysd[i] = (sig-1.0)/p; 116 105 temp[i] = (y[i+1]-y[i])/(x[i+1]-x[i])-(y[i]-y[i-1])/(x[i]-x[i-1]); 117 temp[i] = ( 6.0*temp[i]/(x[i+1]-x[i-1])-sig*temp[i-1])/p;106 temp[i] = (temp[i]*6/(x[i+1]-x[i-1])-sig*temp[i-1])/p; 118 107 } 119 for(Int_t i = n-2; i > 0; i--) 120 ysd[i]=ysd[i]*ysd[i+1]+temp[i]; 121 for(Int_t i = 0; i < n-1; i++) 122 { 123 h = x[i+1]-x[i]; 124 tempCoeff = new MCubicCoeff(x[i],x[i+1],y[i],y[i+1],(ysd[i+1]-ysd[i])/(6*h), 125 ysd[i]/2.0,(y[i+1]-y[i])/h-(h*(ysd[i+1]+2*ysd[i]))/6); 126 fCoeff->AddAt(tempCoeff,i); 127 } 128 delete [] temp; 129 delete [] ysd; 130 } 108 } 109 110 for(Int_t i = n-2; i > 0; i--) 111 ysd[i] = ysd[i]*ysd[i+1] + temp[i]; 112 113 for(Int_t i = 0; i < n-1; i++) 114 { 115 if (!areAllEq) 116 h = x[i+1]-x[i]; 117 118 MCubicCoeff *c = new MCubicCoeff(x[i], x[i+1], y[i], y[i+1], (ysd[i+1]-ysd[i])/(h*6), 119 ysd[i]/2, (y[i+1]-y[i])/h-(h*(ysd[i+1]+ysd[i]*2))/6); 120 fCoeff->AddAt(c, i); 121 } 122 123 delete [] temp; 124 delete [] ysd; 131 125 } 132 126 … … 134 128 { 135 129 fCoeff->Delete(); 130 delete fCoeff; 136 131 } 137 132 … … 142 137 Double_t MCubicSpline :: Eval(Double_t x) 143 138 { 144 for (Int_t i = 0; i < fN-1; i++) 145 if (((MCubicCoeff*)fCoeff->At(i))->IsIn(x)) 146 return ((MCubicCoeff*)fCoeff->At(i))->Eval(x); 139 const Int_t n = fCoeff->GetSize()-1; 140 for (Int_t i = 0; i < n; i++) 141 { 142 MCubicCoeff *c = (MCubicCoeff*)fCoeff->UncheckedAt(i); 143 if (c->IsIn(x)) 144 return c->Eval(x); 145 } 146 147 147 gLog << warn << "Cannot evaluate Spline at " << x << "; returning 0"; 148 return 0.0; 148 149 return 0; 149 150 } 150 151 … … 155 156 Double_t MCubicSpline :: EvalMax() 156 157 { 157 Double_t temp_max; 158 Double_t max = ((MCubicCoeff*)fCoeff->At(0))->GetMax(); 159 for (Int_t i = 1; i < fN-1; i++) 160 { 161 temp_max = ((MCubicCoeff*)fCoeff->At(i))->GetMax(); 162 if (temp_max > max) 163 max = temp_max; 164 } 158 Double_t max = -FLT_MAX; 159 160 TIter Next(fCoeff); 161 MCubicCoeff *c; 162 while ((c=(MCubicCoeff*)Next())) 163 max = TMath::Max(max, c->GetMax()); 164 165 165 return max; 166 166 } … … 172 172 Double_t MCubicSpline :: EvalMin() 173 173 { 174 Double_t temp_min; 175 Double_t min = ((MCubicCoeff*)fCoeff->At(0))->GetMin(); 176 for (Int_t i = 1; i < fN-1; i++) 177 { 178 temp_min = ((MCubicCoeff*)fCoeff->At(i))->GetMin(); 179 if (temp_min < min) 180 min = temp_min; 181 } 174 Double_t min = FLT_MAX; 175 176 TIter Next(fCoeff); 177 MCubicCoeff *c; 178 while ((c=(MCubicCoeff*)Next())) 179 min = TMath::Min(min, c->GetMax()); 180 182 181 return min; 183 182 } … … 189 188 Double_t MCubicSpline :: EvalAbMax() 190 189 { 191 Double_t temp_max; 192 Double_t abMax = ((MCubicCoeff*)fCoeff->At(0))->GetAbMax(); 193 Double_t max = ((MCubicCoeff*)fCoeff->At(0))->GetMax(); 194 for (Int_t i = 1; i < fN-1; i++) 195 { 196 temp_max = ((MCubicCoeff*)fCoeff->At(i))->GetMax(); 197 if (temp_max > max) 198 { 199 max = temp_max; 200 abMax = ((MCubicCoeff*)fCoeff->At(i))->GetAbMax(); 201 } 202 } 203 return abMax; 190 Double_t max = -FLT_MAX; 191 192 TIter Next(fCoeff); 193 194 MCubicCoeff *c; 195 MCubicCoeff *cmax=0; 196 197 while ((c=(MCubicCoeff*)Next())) 198 { 199 const Double_t temp = c->GetMax(); 200 if (temp <= max) 201 continue; 202 203 max = temp; 204 cmax = c; 205 } 206 207 return cmax ? cmax->GetAbMax() : -FLT_MAX; 204 208 } 205 209 … … 210 214 Double_t MCubicSpline :: EvalAbMin() 211 215 { 212 Double_t temp_min; 213 Double_t abMin = ((MCubicCoeff*)fCoeff->At(0))->GetAbMin(); 214 Double_t min = ((MCubicCoeff*)fCoeff->At(0))->GetMin(); 215 for (Int_t i = 1; i < fN-1; i++) 216 { 217 temp_min = ((MCubicCoeff*)fCoeff->At(i))->GetMin(); 218 if (temp_min < min) 219 { 220 min = temp_min; 221 abMin = ((MCubicCoeff*)fCoeff->At(i))->GetAbMin(); 222 } 223 } 224 return abMin; 216 Double_t min = FLT_MAX; 217 218 TIter Next(fCoeff); 219 220 MCubicCoeff *c; 221 MCubicCoeff *cmin=0; 222 223 while ((c=(MCubicCoeff*)Next())) 224 { 225 const Double_t temp = c->GetMax(); 226 if (temp >= min) 227 continue; 228 229 min = temp; 230 cmin = c; 231 } 232 233 return cmin ? cmin->GetAbMax() : FLT_MAX; 225 234 } 226 235 … … 233 242 Double_t MCubicSpline :: FindVal(Double_t y, Double_t x0, Char_t direction = 'l') 234 243 { 235 Short_t whichRoot; 236 Double_t tempRoot; 237 Double_t *roots = new Double_t[3]; 238 239 for (Int_t i = 0; i < fN-1; i++) 240 { 241 if(((MCubicCoeff*)fCoeff->At(i))->IsIn(x0)) 242 { 243 if(direction == 'l') 244 { 245 for (Int_t j = i; j >= 0; j--) 246 { 247 whichRoot = ((MCubicCoeff*)fCoeff->At(j))->FindCardanRoot(y, roots); 248 if (whichRoot >= 0 ) 249 { 250 tempRoot = roots[whichRoot]; 251 delete [] roots; 252 return tempRoot; 253 } 254 } 255 } 256 if(direction == 'r') 257 { 258 for (Int_t j = i; j < fN-1; j++) 259 { 260 whichRoot = ((MCubicCoeff*)fCoeff->At(j))->FindCardanRoot(y, roots); 261 if (whichRoot >= 0) 262 { 263 tempRoot = roots[whichRoot]; 264 delete [] roots; 265 return tempRoot; 266 } 267 } 268 } 269 } 270 } 244 Double_t roots[3] = { 0, 0, 0 }; 245 246 const Int_t n = fCoeff->GetSize()-1; 247 248 for (Int_t i = 0; i < n; i++) 249 { 250 if (!((MCubicCoeff*)fCoeff->At(i))->IsIn(x0)) 251 continue; 252 253 switch (direction) 254 { 255 case 'l': 256 for (Int_t j = i; j >= 0; j--) 257 { 258 const Int_t whichRoot = ((MCubicCoeff*)fCoeff->At(j))->FindCardanRoot(y, roots); 259 if (whichRoot >= 0 ) 260 return roots[whichRoot]; 261 } 262 break; 263 264 case 'r': 265 for (Int_t j = i; j < n; j++) 266 { 267 const Int_t whichRoot = ((MCubicCoeff*)fCoeff->At(j))->FindCardanRoot(y, roots); 268 if (whichRoot >= 0) 269 return roots[whichRoot]; 270 } 271 break; 272 } 273 } 274 271 275 gLog << warn << "Nothing found calling MCubicSpline :: FindVal(), returning 0" << endl; 272 return 0.0; 273 } 276 277 return 0; 278 } -
trunk/MagicSoft/Mars/mtools/MCubicSpline.h
r3022 r3148 16 16 private: 17 17 TObjArray *fCoeff; //array of the coefficients 18 Int_t fN; //number of points 18 19 19 void Init(Byte_t *y, Byte_t *x, Bool_t areAllEq, Int_t n, Double_t begSD, Double_t endSD); 20 20
Note:
See TracChangeset
for help on using the changeset viewer.