Changeset 7999 for trunk/MagicSoft/Mars/mbase
- Timestamp:
- 10/01/06 22:19:55 (18 years ago)
- Location:
- trunk/MagicSoft/Mars/mbase
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/MagicSoft/Mars/mbase/MMath.cc
r7899 r7999 39 39 #include <TArrayD.h> 40 40 #endif 41 42 #ifndef ROOT_TComplex 43 #include <TComplex.h> 44 #endif 45 41 46 // -------------------------------------------------------------------------- 42 47 // … … 495 500 return rc; 496 501 } 502 503 Int_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 // 527 static 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 // 593 Int_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 47 47 Double_t InterpolParabCos(const TVector3 &vx, const TVector3 &vy, Double_t x); 48 48 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 49 68 TArrayD LeastSqFitExpW1(Int_t n, Double_t *x, Double_t *y); 50 69 TArrayD LeastSqFitExp(Int_t n, Double_t *x, Double_t *y); … … 54 73 inline Int_t ModF(Double_t dbl, Double_t &frac) { Double_t rc; frac = modf(dbl, &rc); return TMath::Nint(rc); } 55 74 75 inline Double_t Sqrt3(Double_t x) { return TMath::Sign(TMath::Power(TMath::Abs(x), 1./3), x); } 76 56 77 inline Double_t Sgn(Double_t d) { return d<0 ? -1 : 1; } 57 78 }
Note:
See TracChangeset
for help on using the changeset viewer.