Exemple #1
0
void CPoly<T>::cdivid( const T ar, const T ai, const T br, const T bi, T *cr, T *ci )
   {
   T r, d, t, infin;

   if( br == 0 && bi == 0 )
      {
      // Division by zero, c = infinity
      mcon( &t, &infin, &t, &t );
      *cr = infin;
      *ci = infin;
      return;
      }

   if( std::abs( br ) < std::abs( bi ) )
      {
      r = br/ bi;
      d = bi + r * br;
      *cr = ( ar * r + ai ) / d;
      *ci = ( ai * r - ar ) / d;
      return;
      }

   r = bi / br;
   d = br + r * bi;
   *cr = ( ar + ai * r ) / d;
   *ci = ( ai - ar * r ) / d;
   }
Exemple #2
0
static int init(int nncr)
{
  static int nmax=0;

  if (nmax == 0) {
    /* Set up once-off constants */
    mcon();

    /* are, mre - Error bounds on complex addition and multiplication,
       cf e.g. errev() above */
    are = eta;
    mre = 2.0L*sqrt(2.0L)*eta;

  } else if (nmax >= nncr) {
    return TRUE;            /* Present arrays are big enough */
  } else {
    /* Free old arrays (no need to preserve contents */
    free(shi); free(shr); free(qhi); free(qhr); 
    free(qpi); free(qpr); free(hi); free(hr); free(pi); free(pr);
  }

  nmax = nncr;

  pr  = (double *) malloc(nmax*sizeof(double));
  pi  = (double *) malloc(nmax*sizeof(double));
  hr  = (double *) malloc(nmax*sizeof(double));
  hi  = (double *) malloc(nmax*sizeof(double));
  qpr = (double *) malloc(nmax*sizeof(double));
  qpi = (double *) malloc(nmax*sizeof(double));
  qhr = (double *) malloc(nmax*sizeof(double));
  qhi = (double *) malloc(nmax*sizeof(double));
  shr = (double *) malloc(nmax*sizeof(double));
  shi = (double *) malloc(nmax*sizeof(double));

  if (!(pr && pi && hr && hi && qpr && qpi && qhr && qhi && shr && shi)) {
    fprintf(stderr,"Couldn't allocate space for cpoly\n");
    return FALSE;
  } else {
    return TRUE;
  }
}
Exemple #3
0
int CPoly<T>::findRoots( const T *opr, const T *opi, int degree, T *zeror, T *zeroi )
   {
   int cnt1, cnt2, idnn2, i, conv;
   T xx, yy, cosr, sinr, smalno, base, xxx, zr, zi, bnd;

   mcon( &eta, &infin, &smalno, &base );
   are = eta;
   mre = (T) (2.0 * sqrt( 2.0 ) * eta);
   xx = (T) 0.70710678;
   yy = -xx;
   cosr = (T) -0.060756474;
   sinr = (T) -0.99756405;
   nn = degree;

   // Algorithm fails if the leading coefficient is zero, or degree is zero.
   if( nn < 1 || (opr[ 0 ] == 0 && opi[ 0 ] == 0) )
      return -1;


   // Remove the zeros at the origin if any
   while( opr[ nn ] == 0 && opi[ nn ] == 0 )
      {
      idnn2 = degree - nn;
      zeror[ idnn2 ] = 0;
      zeroi[ idnn2 ] = 0;
      nn--;
      }

   // sherm 20130410: If all coefficients but the leading one were zero, then
   // all solutions are zero; should be a successful (if boring) return.
   if (nn == 0)
      return degree;

   // Allocate arrays
   pr = new T [ degree+1 ];
   pi = new T [ degree+1 ];
   hr = new T [ degree+1 ];
   hi = new T [ degree+1 ];
   qpr= new T [ degree+1 ];
   qpi= new T [ degree+1 ];
   qhr= new T [ degree+1 ];
   qhi= new T [ degree+1 ];
   shr= new T [ degree+1 ];
   shi= new T [ degree+1 ];

   // Make a copy of the coefficients
   for( i = 0; i <= nn; i++ )
      {
      pr[ i ] = opr[ i ];
      pi[ i ] = opi[ i ];
      shr[ i ] = cmod( pr[ i ], pi[ i ] );
      }

   // Scale the polynomial
   bnd = scale( nn, shr, eta, infin, smalno, base );
   if( bnd != 1 )
      for( i = 0; i <= nn; i++ )
         {
         pr[ i ] *= bnd;
         pi[ i ] *= bnd;
         }

search:
   if( nn <= 1 )
      {
      cdivid( -pr[ 1 ], -pi[ 1 ], pr[ 0 ], pi[ 0 ], &zeror[ degree-1 ], &zeroi[ degree-1 ] );
      goto finish;
      }

   // Calculate bnd, alower bound on the modulus of the zeros
   for( i = 0; i<= nn; i++ )
      shr[ i ] = cmod( pr[ i ], pi[ i ] );

   cauchy( nn, shr, shi, &bnd );

   // Outer loop to control 2 Major passes with different sequences of shifts
   for( cnt1 = 1; cnt1 <= 2; cnt1++ )
      {
      // First stage  calculation , no shift
      noshft( 5 );

      // Inner loop to select a shift
      for( cnt2 = 1; cnt2 <= 9; cnt2++ )
         {
         // Shift is chosen with modulus bnd and amplitude rotated by 94 degree from the previous shif
         xxx = cosr * xx - sinr * yy;
         yy = sinr * xx + cosr * yy;
         xx = xxx;
         sr = bnd * xx;
         si = bnd * yy;

         // Second stage calculation, fixed shift
         fxshft( 10 * cnt2, &zr, &zi, &conv );
         if( conv )
            {
            // The second stage jumps directly to the third stage ieration
            // If successful the zero is stored and the polynomial deflated
            idnn2 = degree - nn;
            zeror[ idnn2 ] = zr;
            zeroi[ idnn2 ] = zi;
            nn--;
            for( i = 0; i <= nn; i++ )
               {
               pr[ i ] = qpr[ i ];
               pi[ i ] = qpi[ i ];
               }
            goto search;
            }
         // If the iteration is unsuccessful another shift is chosen
         }
      // if 9 shifts fail, the outer loop is repeated with another sequence of shifts
      }

   // The zerofinder has failed on two major passes
   // return empty handed with the number of roots found (less than the original degree)
   degree -= nn;

finish:
   // Deallocate arrays
   delete [] pr;
   delete [] pi;
   delete [] hr;
   delete [] hi;
   delete [] qpr;
   delete [] qpi;
   delete [] qhr;
   delete [] qhi;
   delete [] shr;
   delete [] shi;

   return degree;
   }