Changeset 0de55f in git
- Timestamp:
- Nov 12, 2001, 11:58:55 AM (22 years ago)
- Branches:
- (u'spielwiese', '873fc1222e995d7cb33f79d8f1792ce418c8c72c')
- Children:
- f10ed0814ad98586667a25efc8f510ed3f74f091
- Parents:
- 64eab4b23570b354e7a397b76509eefccddf3919
- Location:
- Singular
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/mpr_numeric.cc
r64eab4 r0de55f 3 3 ****************************************/ 4 4 5 /* $Id: mpr_numeric.cc,v 1.1 6 2001-08-27 14:47:15 SingularExp $ */5 /* $Id: mpr_numeric.cc,v 1.17 2001-11-12 10:58:55 pohl Exp $ */ 6 6 7 7 /* … … 265 265 //-> definitions 266 266 #define MR 8 // never change this value 267 #define MT 20 268 #define MAXIT (MT*MR) // max number of iterations in laguer root finder 269 270 // set these values according to gmp_default_prec_bits and gmp_equalupto_bits! 271 #define EPS 2.0e-34 // used by rootContainer::laguer_driver(), imag() == 0.0 ??? 272 //<- 267 #define MT 5 268 #define MMOD (MT*MR) 269 #define MAXIT (5*MMOD) // max number of iterations in laguer root finder 270 273 271 274 272 //-> rootContainer::rootContainer() … … 462 460 463 461 // now solve 464 switch (polishmode) 465 { 466 case PM_NONE: 467 case PM_POLISH: 468 found_roots= laguer_driver( ad, theroots, polishmode == PM_POLISH ); 469 if (!found_roots) 470 { 471 WarnS("rootContainer::solver: No roots found!"); 472 goto solverend; 473 } 474 break; 475 case PM_CORRUPT: 476 found_roots= laguer_driver( ad, theroots, false ); 477 // corrupt the roots 478 for ( i= 0; i < tdg; i++ ) 479 *theroots[i]= *theroots[i] * (gmp_float)(1.0+0.01*(mprfloat)i); 480 // and interpolate again 481 found_roots= laguer_driver( ad, theroots, true ); 482 if (!found_roots) 483 { 484 WarnS("rootContainer::solver: No roots found!"); 485 goto solverend; 486 } 487 break; 488 default: 489 Warn("rootContainer::solver: Unsupported polish mode %d! Valid are [0,1,2].",polishmode); 490 found_roots= false; 491 } // switch 492 493 solverend: 462 found_roots= laguer_driver( ad, theroots, polishmode != 0 ); 463 if (!found_roots) 464 WarnS("rootContainer::solver: No roots found!"); 465 466 // free memory 494 467 for ( i=0; i <= tdg; i++ ) delete ad[i]; 495 468 omFreeSize( (ADDRESS) ad, (tdg+1)*sizeof(gmp_complex*) ); … … 502 475 bool rootContainer::laguer_driver(gmp_complex ** a, gmp_complex ** roots, bool polish ) 503 476 { 504 int i,j, jj;505 int its;506 gmp_complex x ,b,c;507 bool ret= true ;477 int i,j,k,its; 478 gmp_float zero(0.0); 479 gmp_complex x(0.0),o(1.0); 480 bool ret= true, isf=isfloat(a), type=true; 508 481 509 482 gmp_complex ** ad= (gmp_complex**)omAlloc( (tdg+1)*sizeof(gmp_complex*) ); 510 483 for ( i=0; i <= tdg; i++ ) ad[i]= new gmp_complex( *a[i] ); 511 484 512 for ( j= tdg; j >= 1; j-- ) 513 { 514 x= gmp_complex(); 515 485 k = 0; 486 i = tdg; 487 j = i-1; 488 while (i>2) 489 { 516 490 // run laguer alg 517 laguer(ad, j, &x, &its); 491 x = zero; 492 laguer(ad, i, &x, &its, type); 493 if ( its > MAXIT ) 494 { 495 type = !type; 496 x = zero; 497 laguer(ad, i, &x, &its, type); 498 } 518 499 519 500 mprSTICKYPROT(ST_ROOTS_LGSTEP); 520 if ( its > MAXIT ) { // error 501 if ( its > MAXIT ) 502 { // error 521 503 WarnS("rootContainer::laguer_driver: To many iterations!"); 522 504 ret= false; 523 505 goto theend; 524 506 } 525 if ( abs(x.imag()) <= (gmp_float)(2.0*EPS)*abs(x.real())) 526 { 527 x= gmp_complex( x.real() ); 528 } 529 *roots[j-1]= x; 530 b= *ad[j]; 531 for ( jj= j-1; jj >= 0; jj-- ) 532 { 533 c= *ad[jj]; 534 *ad[jj]= b; 535 b= ( x * b ) + c; 536 } 537 } 538 539 if ( polish ) 540 { 541 mprSTICKYPROT(ST_ROOTS_LGPOLISH); 542 for ( i=0; i <= tdg; i++ ) *ad[i]=*a[i]; 543 544 for ( j= 1; j <= tdg; j++ ) 545 { 546 // run laguer alg with corrupted roots 547 laguer( ad, tdg, roots[j-1], &its ); 548 549 mprSTICKYPROT(ST_ROOTS_LGSTEP); 507 if ( polish ) 508 { 509 laguer( a, tdg, &x, &its , type); 550 510 if ( its > MAXIT ) 551 511 { // error 552 WarnS("rootContainer::laguer_driver: To many iterations !");512 WarnS("rootContainer::laguer_driver: To many iterations in polish!"); 553 513 ret= false; 554 514 goto theend; 555 515 } 556 516 } 557 for ( j= 2; j <= tdg; j++ ) 558 { 559 // sort root by their absolute real parts by straight insertion 560 x= *roots[j-1]; 561 for ( i= j-1; i >= 1; i-- ) 562 { 563 if ( abs(roots[i-1]->real()) <= abs(x.real()) ) break; 564 *roots[i]= *roots[i-1]; 565 } 566 *roots[i]= x; 567 } 568 } 569 570 theend: 517 if (!type) x = o/x; 518 if (x.imag() == zero) 519 { 520 *roots[k] = x; 521 k++; 522 divlin(ad,x,i); 523 i--; 524 } 525 else 526 { 527 if(isf) 528 { 529 *roots[j] = x; 530 *roots[j-1]= gmp_complex(x.real(),-x.imag()); 531 j -= 2; 532 divquad(ad,x,i); 533 i -= 2; 534 } 535 else 536 { 537 *roots[j] = x; 538 j--; 539 divlin(ad,x,i); 540 i--; 541 } 542 } 543 type = !type; 544 } 545 solvequad(ad,roots,k,j); 546 sortroots(roots,k,j,isf); 547 548 theend: 571 549 mprSTICKYPROT("\n"); 572 550 for ( i=0; i <= tdg; i++ ) delete ad[i]; … … 578 556 579 557 //-> void rootContainer::laguer(...) 580 void rootContainer::laguer(gmp_complex ** a, int m, gmp_complex *x, int *its )558 void rootContainer::laguer(gmp_complex ** a, int m, gmp_complex *x, int *its, bool type) 581 559 { 582 560 int iter,j; 583 gmp_float abx_g, abp_g, abm_g, err_g; 561 gmp_float zero(0.0),one(1.0),deg(m); 562 gmp_float abx_g, err_g, fabs; 584 563 gmp_complex dx, x1, b, d, f, g, h, sq, gp, gm, g2; 585 static gmp_float frac_g[MR+1] = { 0.0, 0.5, 0.25, 0.75, 0.13, 0.38, 0.62, 0.88, 1.0 }; 586 587 gmp_float epss(1.0/pow(10.0,(int)(gmp_output_digits+gmp_output_digits/4))); 564 gmp_float frac_g[MR+1] = { 0.0, 0.5, 0.25, 0.75, 0.125, 0.375, 0.625, 0.875, 1.0 }; 565 566 gmp_float epss(0.1); 567 mpf_pow_ui(*epss._mpfp(),*epss.mpfp(),getGMPFloatDigits()); 588 568 589 569 for ( iter= 1; iter <= MAXIT; iter++ ) 590 570 { 591 571 mprSTICKYPROT(ST_ROOTS_LG); 592 593 572 *its=iter; 594 595 b= *a[m]; 596 err_g= abs(b); 597 d= gmp_complex(); 598 f= gmp_complex(); 599 abx_g= abs(*x); 600 601 // gcc 2.95.2 on the dec alpha chokes on this 602 #if defined(__GNUC__) 603 #if ! (defined(__alpha) && __GNUC__ == 2 && __GNUC_MINOR__ == 95) 604 for ( j= m-1; j >= 0; j-- ) 605 { 606 f= ( *x * f ) + d; 607 d= ( *x * d ) + b; 608 b= ( *x * b ) + *a[j]; 609 err_g= abs( b ) + ( abx_g * err_g ); 610 } 611 573 if (type) 574 computefx(a,*x,m,b,d,f,abx_g,err_g); 575 else 576 computegx(a,*x,m,b,d,f,abx_g,err_g); 612 577 err_g *= epss; // EPSS; 613 578 614 if ( abs(b) <= err_g ) return; 579 fabs = abs(b); 580 if (fabs <= err_g) 581 { 582 if ((fabs==zero) || (abs(d)==zero)) return; 583 *x -= (b/d); // a last newton-step 584 goto ende; 585 } 615 586 616 587 g= d / b; 617 588 g2 = g * g; 618 h= g2 - ( ( f / b ) * (gmp_float)2.0);619 sq= sqrt(( ( h * (gmp_float)m ) - g2 ) * (gmp_float)(m - 1));589 h= g2 - (((f+f) / b )); 590 sq= sqrt(( ( h * deg ) - g2 ) * (deg - one)); 620 591 gp= g + sq; 621 592 gm= g - sq; 622 abp_g= abs( gp ); 623 abm_g= abs( gm ); 624 625 if ( abp_g < abm_g ) gp= gm; 626 627 dx = ( (max(abp_g,abm_g) > (gmp_float)0.0) 628 ? ( gmp_complex( (mprfloat)m ) / gp ) 629 : ( gmp_complex( cos((mprfloat)iter),sin((mprfloat)iter)) 630 * exp(log((gmp_float)1.0+abx_g))) ); 631 593 if (abs(gp)<abs(gm)) 594 { 595 dx = deg/gm; 596 } 597 else 598 { 599 if((gp.real()==zero)&&(gp.imag()==zero)) 600 { 601 dx.real(cos((mprfloat)iter)); 602 dx.imag(sin((mprfloat)iter)); 603 dx = dx*(one+abx_g); 604 } 605 else 606 { 607 dx = deg/gp; 608 } 609 } 632 610 x1= *x - dx; 633 611 634 if ( (*x == x1) ) return;635 636 if ( iter % MT ) *x= x1;637 else *x -= ( dx * frac_g[ iter / MT ] );638 #endif 639 #endif 612 if (*x == x1) goto ende; 613 614 j = iter%MMOD; 615 if (j==0) j=MT; 616 if ( j % MT ) *x= x1; 617 else *x -= ( dx * frac_g[ j / MT ] ); 640 618 } 641 619 642 620 *its= MAXIT+1; 643 return; 644 } 645 //<- 621 ende: 622 checkimag(x,epss); 623 } 624 625 void rootContainer::checkimag(gmp_complex *x, gmp_float &e) 626 { 627 if(abs(x->imag())<abs(x->real())*e) 628 { 629 x->imag(0.0); 630 } 631 } 632 633 bool rootContainer::isfloat(gmp_complex **a) 634 { 635 gmp_float z(0.0); 636 gmp_complex *b; 637 for (int i=tdg; i >= 0; i-- ) 638 { 639 b = &(*a[i]); 640 if (!(b->imag()==z)) 641 return false; 642 } 643 return true; 644 } 645 646 void rootContainer::divlin(gmp_complex **a, gmp_complex x, int j) 647 { 648 int i; 649 gmp_float o(1.0); 650 651 if (abs(x)<o) 652 { 653 for (i= j-1; i > 0; i-- ) 654 *a[i] += (*a[i+1]*x); 655 for (i= 0; i < j; i++ ) 656 *a[i] = *a[i+1]; 657 } 658 else 659 { 660 gmp_complex y(o/x); 661 for (i= 1; i < j; i++) 662 *a[i] += (*a[i-1]*y); 663 } 664 } 665 666 void rootContainer::divquad(gmp_complex **a, gmp_complex x, int j) 667 { 668 int i; 669 gmp_float o(1.0),p(x.real()+x.real()), 670 q((x.real()*x.real())+(x.imag()*x.imag())); 671 672 if (abs(x)<o) 673 { 674 *a[j-1] += (*a[j]*p); 675 for (i= j-2; i > 1; i-- ) 676 *a[i] += ((*a[i+1]*p)-(*a[i+2]*q)); 677 for (i= 0; i < j-1; i++ ) 678 *a[i] = *a[i+2]; 679 } 680 else 681 { 682 p = p/q; 683 q = o/q; 684 *a[1] += (*a[0]*p); 685 for (i= 2; i < j-1; i++) 686 *a[i] += ((*a[i-1]*p)-(*a[i-2]*q)); 687 } 688 } 689 690 void rootContainer::solvequad(gmp_complex **a, gmp_complex **r, int &k, int &j) 691 { 692 gmp_float zero(0.0); 693 694 if (j>k) 695 { 696 gmp_complex sq(zero); 697 gmp_complex h1(*a[1]/(*a[2] + *a[2])), h2(*a[0] / *a[2]); 698 gmp_complex disk((h1 * h1) - h2); 699 if (disk.imag()==zero) 700 { 701 if (disk.real()<zero) 702 { 703 sq.real(zero); 704 sq.imag(sqrt(-disk.real())); 705 } 706 else 707 sq = (gmp_complex)sqrt(disk.real()); 708 } 709 else 710 sq = sqrt(disk); 711 *r[k+1] = sq - h1; 712 sq += h1; 713 *r[k] = (gmp_complex)0.0-sq; 714 if(sq.imag()==zero) 715 { 716 k = j; 717 j++; 718 } 719 else 720 { 721 j = k; 722 k--; 723 } 724 } 725 else 726 { 727 *r[k]= (gmp_complex)0.0-(*a[0] / *a[1]); 728 if(r[k]->imag()==zero) 729 j++; 730 else 731 k--; 732 } 733 } 734 735 void rootContainer::sortroots(gmp_complex **ro, int r, int c, bool isf) 736 { 737 int j; 738 739 for (j=0; j<r; j++) // the real roots 740 sortre(ro, j, r, 1); 741 if (c>=tdg) return; 742 if (isf) 743 { 744 for (j=c; j+2<tdg; j+=2) // the complex roots for a real poly 745 sortre(ro, j, tdg-1, 2); 746 } 747 else 748 { 749 for (j=c; j+1<tdg; j++) // the complex roots for a general poly 750 sortre(ro, j, tdg-1, 1); 751 } 752 } 753 754 void rootContainer::sortre(gmp_complex **r, int l, int u, int inc) 755 { 756 int pos,i; 757 gmp_complex *x,*y; 758 759 pos = l; 760 x = r[pos]; 761 for (i=l+inc; i<=u; i+=inc) 762 { 763 if (r[i]->real()<x->real()) 764 { 765 pos = i; 766 x = r[pos]; 767 } 768 } 769 if (pos>l) 770 { 771 if (inc==1) 772 { 773 for (i=pos; i>l; i--) 774 r[i] = r[i-1]; 775 r[l] = x; 776 } 777 else 778 { 779 y = r[pos+1]; 780 for (i=pos+1; i+1>l; i--) 781 r[i] = r[i-2]; 782 if (x->imag()>y->imag()) 783 { 784 r[l] = x; 785 r[l+1] = y; 786 } 787 else 788 { 789 r[l] = y; 790 r[l+1] = x; 791 } 792 } 793 } 794 else if ((inc==2)&&(x->imag()<r[l+1]->imag())) 795 { 796 r[l] = r[l+1]; 797 r[l+1] = x; 798 } 799 } 800 801 void rootContainer::computefx(gmp_complex **a, gmp_complex x, int m, 802 gmp_complex &f0, gmp_complex &f1, gmp_complex &f2, 803 gmp_float &ex, gmp_float &ef) 804 { 805 int k; 806 807 f0= *a[m]; 808 ef= abs(f0); 809 f1= gmp_complex(0.0); 810 f2= f1; 811 ex= abs(x); 812 813 for ( k= m-1; k >= 0; k-- ) 814 { 815 f2 = ( x * f2 ) + f1; 816 f1 = ( x * f1 ) + f0; 817 f0 = ( x * f0 ) + *a[k]; 818 ef = abs( f0 ) + ( ex * ef ); 819 } 820 } 821 822 void rootContainer::computegx(gmp_complex **a, gmp_complex x, int m, 823 gmp_complex &f0, gmp_complex &f1, gmp_complex &f2, 824 gmp_float &ex, gmp_float &ef) 825 { 826 int k; 827 828 f0= *a[0]; 829 ef= abs(f0); 830 f1= gmp_complex(0.0); 831 f2= f1; 832 ex= abs(x); 833 834 for ( k= 1; k <= m; k++ ) 835 { 836 f2 = ( x * f2 ) + f1; 837 f1 = ( x * f1 ) + f0; 838 f0 = ( x * f0 ) + *a[k]; 839 ef = abs( f0 ) + ( ex * ef ); 840 } 841 } 646 842 647 843 //----------------------------------------------------------------------------- -
Singular/mpr_numeric.h
r64eab4 r0de55f 5 5 ****************************************/ 6 6 7 /* $Id: mpr_numeric.h,v 1. 6 2001-10-09 16:36:11 SingularExp $ */7 /* $Id: mpr_numeric.h,v 1.7 2001-11-12 10:58:52 pohl Exp $ */ 8 8 9 9 /* … … 107 107 */ 108 108 bool laguer_driver( gmp_complex ** a, gmp_complex ** roots, bool polish = true ); 109 bool isfloat(gmp_complex **a); 110 void divlin(gmp_complex **a, gmp_complex x, int j); 111 void divquad(gmp_complex **a, gmp_complex x, int j); 112 void solvequad(gmp_complex **a, gmp_complex **r, int &k, int &j); 113 void sortroots(gmp_complex **roots, int r, int c, bool isf); 114 void sortre(gmp_complex **r, int l, int u, int inc); 109 115 110 116 /** Given the degree m and the m+1 complex coefficients a[0..m] of the … … 114 120 * returned at its. 115 121 */ 116 void laguer(gmp_complex ** a, int m, gmp_complex * x, int * its); 122 void laguer(gmp_complex ** a, int m, gmp_complex * x, int * its, bool type); 123 void computefx(gmp_complex **a, gmp_complex x, int m, 124 gmp_complex &f0, gmp_complex &f1, gmp_complex &f2, 125 gmp_float &ex, gmp_float &ef); 126 void computegx(gmp_complex **a, gmp_complex x, int m, 127 gmp_complex &f0, gmp_complex &f1, gmp_complex &f2, 128 gmp_float &ex, gmp_float &ef); 129 void checkimag(gmp_complex *x, gmp_float &e); 117 130 118 131 int var;
Note: See TracChangeset
for help on using the changeset viewer.