Changeset 0de55f in git


Ignore:
Timestamp:
Nov 12, 2001, 11:58:55 AM (22 years ago)
Author:
Wilfred Pohl <pohl@…>
Branches:
(u'spielwiese', '873fc1222e995d7cb33f79d8f1792ce418c8c72c')
Children:
f10ed0814ad98586667a25efc8f510ed3f74f091
Parents:
64eab4b23570b354e7a397b76509eefccddf3919
Message:
new implementation for Laguerre's method


git-svn-id: file:///usr/local/Singular/svn/trunk@5675 2c84dea3-7e68-4137-9b89-c4e89433aadc
Location:
Singular
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • Singular/mpr_numeric.cc

    r64eab4 r0de55f  
    33****************************************/
    44
    5 /* $Id: mpr_numeric.cc,v 1.16 2001-08-27 14:47:15 Singular Exp $ */
     5/* $Id: mpr_numeric.cc,v 1.17 2001-11-12 10:58:55 pohl Exp $ */
    66
    77/*
     
    265265//-> definitions
    266266#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
    273271
    274272//-> rootContainer::rootContainer()
     
    462460
    463461  // 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
    494467  for ( i=0; i <= tdg; i++ ) delete ad[i];
    495468  omFreeSize( (ADDRESS) ad, (tdg+1)*sizeof(gmp_complex*) );
     
    502475bool rootContainer::laguer_driver(gmp_complex ** a, gmp_complex ** roots, bool polish )
    503476{
    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;
    508481
    509482  gmp_complex ** ad= (gmp_complex**)omAlloc( (tdg+1)*sizeof(gmp_complex*) );
    510483  for ( i=0; i <= tdg; i++ ) ad[i]= new gmp_complex( *a[i] );
    511484
    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  {
    516490    // 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    }
    518499
    519500    mprSTICKYPROT(ST_ROOTS_LGSTEP);
    520     if ( its > MAXIT ) {  // error
     501    if ( its > MAXIT )
     502    {  // error
    521503      WarnS("rootContainer::laguer_driver: To many iterations!");
    522504      ret= false;
    523505      goto theend;
    524506    }
    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);
    550510      if ( its > MAXIT )
    551511      {  // error
    552         WarnS("rootContainer::laguer_driver: To many iterations!");
     512        WarnS("rootContainer::laguer_driver: To many iterations in polish!");
    553513        ret= false;
    554514        goto theend;
    555515      }
    556516    }
    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
     548theend:
    571549  mprSTICKYPROT("\n");
    572550  for ( i=0; i <= tdg; i++ ) delete ad[i];
     
    578556
    579557//-> void rootContainer::laguer(...)
    580 void rootContainer::laguer(gmp_complex ** a, int m, gmp_complex *x, int *its)
     558void rootContainer::laguer(gmp_complex ** a, int m, gmp_complex *x, int *its, bool type)
    581559{
    582560  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;
    584563  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());
    588568
    589569  for ( iter= 1; iter <= MAXIT; iter++ )
    590570  {
    591571    mprSTICKYPROT(ST_ROOTS_LG);
    592 
    593572    *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);
    612577    err_g *= epss; // EPSS;
    613578
    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    }
    615586
    616587    g= d / b;
    617588    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));
    620591    gp= g + sq;
    621592    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    }
    632610    x1= *x - dx;
    633611
    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 ] );
    640618  }
    641619
    642620  *its= MAXIT+1;
    643   return;
    644 }
    645 //<-
     621ende:
     622  checkimag(x,epss);
     623}
     624
     625void 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
     633bool 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
     646void 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
     666void 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
     690void 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
     735void 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
     754void 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
     801void 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
     822void 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}
    646842
    647843//-----------------------------------------------------------------------------
  • Singular/mpr_numeric.h

    r64eab4 r0de55f  
    55****************************************/
    66
    7 /* $Id: mpr_numeric.h,v 1.6 2001-10-09 16:36:11 Singular Exp $ */
     7/* $Id: mpr_numeric.h,v 1.7 2001-11-12 10:58:52 pohl Exp $ */
    88
    99/*
     
    107107   */
    108108  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);
    109115
    110116  /** Given the degree m and the m+1 complex coefficients a[0..m] of the
     
    114120   * returned at its.
    115121   */
    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);
    117130
    118131  int var;
Note: See TracChangeset for help on using the changeset viewer.