Ignore:
Timestamp:
02/14/04 11:48:43 (21 years ago)
Author:
tbretz
Message:
*** empty log message ***
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/MagicSoft/Mars/mtools/MCubicCoeff.cc

    r3022 r3148  
    2424
    2525//////////////////////////////////////////////////////////////////////////////
    26 //                                                                          //
    27 //  Cubic Spline Interpolation                                              //
    28 //                                                                          //
     26//
     27//  Cubic Spline Interpolation
     28//
    2929//////////////////////////////////////////////////////////////////////////////
    30 
    3130#include "MCubicCoeff.h"
    3231
    33 #include "TMath.h"
     32#include <TMath.h>
    3433
    3534#include "MLog.h"
     
    4544// where x is the independent variable, 2 and 3 are exponents
    4645//
    47 
    4846MCubicCoeff::MCubicCoeff(Double_t x, Double_t xNext, Double_t y, Double_t yNext,
    4947                         Double_t a, Double_t b, Double_t c) :
     
    5149{
    5250    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;
    5957}
    6058
     
    6664Double_t MCubicCoeff::Eval(Double_t x)
    6765{
    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));
    7068}
    7169
     
    7977Bool_t MCubicCoeff::EvalMinMax()
    8078{
    81     fMin = fMax = fY;
    82     fAbMin = fAbMax = fX;
     79    fMin = fY;
     80    fMax = fY;
     81
     82    fAbMin = fX;
     83    fAbMax = fX;
     84
    8385    if (fYNext < fMin)
    8486    {
    85         fMin = fYNext;
     87        fMin   = fYNext;
    8688        fAbMin = fXNext;
    8789    }
    8890    if (fYNext > fMax)
    8991    {
    90         fMax = fYNext;
     92        fMax   = fYNext;
    9193        fAbMax = fXNext;
    9294    }
    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
    148157    return kTRUE;
    149158}
     
    157166// There could be three or one real solutions
    158167//
    159 
    160168Short_t MCubicCoeff::FindCardanRoot(Double_t y, Double_t *x)
    161169{
    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;
    175180   
    176181    if (r2 < q3) //3 real sol
    177182    {
    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
    185191        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)
    187193            {
    188                 x[i] = x[i] + fX;
    189                 whichRoot = i;
    190                 break;
     194                x[i] += fX;
     195                return i;
    191196            }
    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;
    213209}
    214210
     
    220216Bool_t MCubicCoeff :: IsIn(Double_t x)
    221217{
    222     if (x >= fX && x <= fXNext)
    223         return kTRUE;
    224     else
    225         return kFALSE;
    226 }
     218    return x >= fX && x <= fXNext;
     219}
Note: See TracChangeset for help on using the changeset viewer.