Ignore:
Timestamp:
10/01/06 22:19:55 (18 years ago)
Author:
tbretz
Message:
*** empty log message ***
Location:
trunk/MagicSoft/Mars/mbase
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/MagicSoft/Mars/mbase/MMath.cc

    r7899 r7999  
    3939#include <TArrayD.h>
    4040#endif
     41
     42#ifndef ROOT_TComplex
     43#include <TComplex.h>
     44#endif
     45
    4146// --------------------------------------------------------------------------
    4247//
     
    495500    return rc;
    496501}
     502
     503Int_t MMath::SolvePol2(Double_t a, Double_t b, Double_t &x1, Double_t &x2)
     504{
     505    const Double_t r = a*a - 4*b;
     506    if (r<0)
     507        return 0;
     508
     509    if (r==0)
     510    {
     511        x1 = -a/2;
     512        return 1;
     513    }
     514
     515    const Double_t s = TMath::Sqrt(r);
     516
     517    x1 = (-a+s)/2;
     518    x2 = (-a-s)/2;
     519
     520    return 2;
     521}
     522
     523// --------------------------------------------------------------------------
     524//
     525// This is a helper function making the execution of SolverPol3 a bit faster
     526//
     527static inline Double_t ReMul(const TComplex &c1, const TComplex &th)
     528{
     529    const TComplex c2 = TComplex::Cos(th/3.);
     530    return c1.Re() * c2.Re() - c1.Im() * c2.Im();
     531}
     532
     533// --------------------------------------------------------------------------
     534//
     535// Solves: x^3 + ax^2 + bx + c = 0;
     536// Return number of the real solutions returns as z1, z2, z3
     537//
     538// Algorithm adapted from http://home.att.net/~srschmitt/cubizen.heml
     539// Which is based on the solution given in
     540//    http://mathworld.wolfram.com/CubicEquation.html
     541//
     542// -------------------------------------------------------------------------
     543//
     544// Exact solutions of cubic polynomial equations
     545// by Stephen R. Schmitt Algorithm
     546//
     547// An exact solution of the cubic polynomial equation:
     548//
     549// x^3 + a*x^2 + b*x + c = 0
     550//
     551// was first published by Gerolamo Cardano (1501-1576) in his treatise,
     552// Ars Magna. He did not discoverer of the solution; a professor of
     553// mathematics at the University of Bologna named Scipione del Ferro (ca.
     554// 1465-1526) is credited as the first to find an exact solution. In the
     555// years since, several improvements to the original solution have been
     556// discovered. Zeno source code
     557//
     558// % compute real or complex roots of cubic polynomial
     559// function cubic( var z1, z2, z3 : real, a, b, c : real ) : real
     560//
     561//     var Q, R, D, S, T : real
     562//     var im, th : real
     563//
     564//     Q := (3*b - a^2)/9
     565//     R := (9*b*a - 27*c - 2*a^3)/54
     566//     D := Q^3 + R^2                          % polynomial discriminant
     567//
     568//     if (D >= 0) then                        % complex or duplicate roots
     569//
     570//         S := sgn(R + sqrt(D))*abs(R + sqrt(D))^(1/3)
     571//         T := sgn(R - sqrt(D))*abs(R - sqrt(D))^(1/3)
     572//
     573//         z1 := -a/3 + (S + T)               % real root
     574//         z2 := -a/3 - (S + T)/2             % real part of complex root
     575//         z3 := -a/3 - (S + T)/2             % real part of complex root
     576//         im := abs(sqrt(3)*(S - T)/2)       % complex part of root pair
     577//
     578//     else                                    % distinct real roots
     579//
     580//         th := arccos(R/sqrt( -Q^3))
     581//         
     582//         z1 := 2*sqrt(-Q)*cos(th/3) - a/3
     583//         z2 := 2*sqrt(-Q)*cos((th + 2*pi)/3) - a/3
     584//         z3 := 2*sqrt(-Q)*cos((th + 4*pi)/3) - a/3
     585//         im := 0
     586//
     587//     end if
     588//
     589//     return im                               % imaginary part
     590//
     591// end function
     592//
     593Int_t MMath::SolvePol3(Double_t a, Double_t b, Double_t c,
     594                       Double_t &x1, Double_t &x2, Double_t &x3)
     595{
     596    const Double_t Q = (a*a - 3*b)/9;
     597    const Double_t R = (9*b*a - 27*c - 2*a*a*a)/54;
     598    const Double_t D = R*R - Q*Q*Q;             // polynomial discriminant
     599
     600    // ----- The single-real / duplicate-roots solution -----
     601
     602    if (D==0)
     603    {
     604        const Double_t r = MMath::Sqrt3(R);
     605
     606        x1 = 2*r - a/3.;               // real root
     607        x2 =   r - a/3.;               // real root
     608
     609        return 2;
     610    }
     611
     612    if (D>0)                                    // complex or duplicate roots
     613    {
     614        const Double_t sqrtd = TMath::Sqrt(D);
     615
     616        const Double_t S = MMath::Sqrt3(R + sqrtd);
     617        const Double_t T = MMath::Sqrt3(R - sqrtd);
     618
     619        x1 = (S+T) - a/3.;               // real root
     620
     621        return 1;
     622
     623        //z2 = (S + T)/2 - a/3.;            // real part of complex root
     624        //z3 = (S + T)/2 - a/3.;            // real part of complex root
     625        //im = fabs(sqrt(3)*(S - T)/2)      // complex part of root pair
     626    }
     627
     628    // ----- The general solution with three roots ---
     629
     630    if (Q==0)
     631        return 0;
     632
     633    if (Q>0) // This is here for speed reasons
     634    {
     635        const Double_t sqrtq = TMath::Sqrt(Q);
     636        const Double_t rq    = R/TMath::Abs(Q);
     637
     638        const Double_t th1 = TMath::ACos(rq/sqrtq);
     639        const Double_t th2 = th1 + TMath::TwoPi();
     640        const Double_t th3 = th2 + TMath::TwoPi();
     641
     642        x1 = 2.*sqrtq * TMath::Cos(th1/3.) - a/3.;
     643        x2 = 2.*sqrtq * TMath::Cos(th2/3.) - a/3.;
     644        x3 = 2.*sqrtq * TMath::Cos(th3/3.) - a/3.;
     645
     646        return 3;
     647    }
     648
     649    const TComplex sqrtq = TComplex::Sqrt(Q);
     650    const Double_t rq    = R/TMath::Abs(Q);
     651
     652    const TComplex th1 = TComplex::ACos(rq/sqrtq);
     653    const TComplex th2 = th1 + TMath::TwoPi();
     654    const TComplex th3 = th2 + TMath::TwoPi();
     655
     656    // For ReMul, see bove
     657    x1 = ReMul(2.*sqrtq, th1) - a/3.;
     658    x2 = ReMul(2.*sqrtq, th2) - a/3.;
     659    x3 = ReMul(2.*sqrtq, th3) - a/3.;
     660
     661    return 3;
     662}
  • trunk/MagicSoft/Mars/mbase/MMath.h

    r7971 r7999  
    4747    Double_t InterpolParabCos(const TVector3 &vx, const TVector3 &vy, Double_t x);
    4848
     49    inline Int_t SolvePol1(Double_t c, Double_t d, Double_t &x1)
     50    {
     51        if (c==0)
     52            return 0;
     53
     54        x1 = -d/c;
     55        return 1;
     56    }
     57    Int_t SolvePol2(Double_t c, Double_t d, Double_t &x1, Double_t &x2);
     58    inline Int_t SolvePol2(Double_t b, Double_t c, Double_t d, Double_t &x1, Double_t &x2)
     59    {
     60        return b==0 ? SolvePol1(c, d, x1) : SolvePol2(c/b, d/b, x1, x2);
     61    }
     62    Int_t SolvePol3(Double_t b, Double_t c, Double_t d, Double_t &x1, Double_t &x2, Double_t &x3);
     63    inline Int_t SolvePol3(Double_t a, Double_t b, Double_t c, Double_t d, Double_t &x1, Double_t &x2, Double_t &x3)
     64    {
     65        return a==0 ? SolvePol2(b, c, d, x1, x2) : SolvePol3(b/a, c/a, d/a, x1, x2, x3);
     66    }
     67
    4968    TArrayD LeastSqFitExpW1(Int_t n, Double_t *x, Double_t *y);
    5069    TArrayD LeastSqFitExp(Int_t n, Double_t *x, Double_t *y);
     
    5473    inline Int_t ModF(Double_t dbl, Double_t &frac) { Double_t rc; frac = modf(dbl, &rc); return TMath::Nint(rc); }
    5574
     75    inline Double_t Sqrt3(Double_t x) { return TMath::Sign(TMath::Power(TMath::Abs(x), 1./3), x); }
     76
    5677    inline Double_t Sgn(Double_t d) { return d<0 ? -1 : 1; }
    5778}
Note: See TracChangeset for help on using the changeset viewer.