Changeset 7999 for trunk/MagicSoft/Mars/mbase/MMath.cc
- Timestamp:
- 10/01/06 22:19:55 (18 years ago)
- File:
-
- 1 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 }
Note:
See TracChangeset
for help on using the changeset viewer.