home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   sci.math.symbolic      Symbolic algebra discussion      10,432 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 8,665 of 10,432   
   Peter Spellucci to Bart Goddard   
   Re: How to find a if there is a zero or    
   16 Sep 14 13:09:02   
   
   XPost: sci.math, sci.math.num-analysis   
   From: spellucci@fb04633.mathematik.tu-darmstadt.de   
      
   Bart Goddard  writes:   
   >pnachtwey  wrote in news:d47c3576-ea88-4d27-   
   >be75-18dd8ddf6033@w24g2000prd.googlegroups.com:   
   >   
   >> I need to determine if there is a zero or root between two points   
   >for   
   >> a polynomial y=f(x).  f(x) is a fourth order polynomial and the   
   >> 'forbidden zone'  is between x0 to x1 where x0 is always at 0.  I   
   >> don't need to know where the root is. I just need to quickly find   
   >if   
   >> there is a root in the 'forbidden zone'. What makes this a little   
   >> harder is that there will normally be roots at x0 and x1.   I can   
   >find   
   >> the number of positive roots by counting the sign changes of the   
   >> coefficients of the polynomial.  I can offset the time by x1-eps   
   >and   
   >> find the number of roots again. If the count is different then I   
   >know   
   >> a root exists between 0 and x1.   
   >   
   >If x0 and x1 are, in fact, roots, you can divide g(x) by   
   >x-x0 and x-x1, leaving a quadratic, which is easily solved   
   >for the other two roots.   
      
   for a fourth order polynomial there is an ''direct''   
   solution formula for all roots. well, this is not quite   
   super w.r.t. to ist roundoff behaviour, but fir this purpose it   
   should work. In netlib/toms there is a code (pdf file as copy of   
   a CACM publication) for this.   
      
   and here a -code (frm my annotations)   
      
   /*   
    *  Roots3And4.c   
    *   
    *  Utility functions to find cubic and quartic roots,   
    *  coefficients are passed like this:   
    *   
    *      c[0] + c[1]*x + c[2]*x^2 + c[3]*x^3 + c[4]*x^4 = 0   
    *   
    *  The functions return the number of non-complex roots and   
    *  put the values into the s array.   
    *   
    *  Author:         Jochen Schwarze (schwarze@isa.de)   
    *   
    *  Jan 26, 1990    Version for Graphics Gems   
    *  Oct 11, 1990    Fixed sign problem for negative q's in SolveQuartic   
    *                  (reported by Mark Podlipec),   
    *                  Old-style function definitions,   
    *                  IsZero() as a macro   
    *  Nov 23, 1990    Some systems do not declare acos() and cbrt() in   
    *                  , though the functions exist in the library.   
    *                  If large coefficients are used, EQN_EPS should be   
    *                  reduced considerably (e.g. to 1E-30), results will be   
    *                  correct but multiple roots might be reported more   
    *                  than once.   
    */   
      
   #include       
   #ifndef M_PI   
   #define M_PI          3.14159265358979323846   
   #endif   
   extern double   sqrt(), cbrt(), cos(), acos();   
      
   /* epsilon surrounding for near zero values */   
      
   #define     EQN_EPS     1e-9   
   #define     IsZero(x)   ((x) > -EQN_EPS && (x) < EQN_EPS)   
      
   #ifdef NOCBRT   
   #define     cbrt(x)     ((x) > 0.0 ? pow((double)(x), 1.0/3.0) : \   
                             ((x) < 0.0 ? -pow((double)-(x), 1.0/3.0) : 0.0))   
   #endif   
      
   int SolveQuadric(c, s)   
       double c[ 3 ];   
       double s[ 2 ];   
   {   
       double p, q, D;   
      
       /* normal form: x^2 + px + q = 0 */   
      
       p = c[ 1 ] / (2 * c[ 2 ]);   
       q = c[ 0 ] / c[ 2 ];   
      
       D = p * p - q;   
      
       if (IsZero(D))   
       {   
           s[ 0 ] = - p;   
           return 1;   
       }   
       else if (D < 0)   
       {   
           return 0;   
       }   
       else if (D > 0)   
       {   
           double sqrt_D = sqrt(D);   
           s[ 0 ] =   sqrt_D - p;   
           s[ 1 ] = - sqrt_D - p;   
           return 2;   
       }   
   }   
      
      
   int SolveCubic(c, s)   
       double c[ 4 ];   
       double s[ 3 ];   
   {   
       int     i, num;   
       double  sub;   
       double  A, B, C;   
       double  sq_A, p, q;   
       double  cb_p, D;   
      
       /* normal form: x^3 + Ax^2 + Bx + C = 0 */   
      
       A = c[ 2 ] / c[ 3 ];   
       B = c[ 1 ] / c[ 3 ];   
       C = c[ 0 ] / c[ 3 ];   
       /*  substitute x = y - A/3 to eliminate quadric term:   
           x^3 +px + q = 0 */   
      
       sq_A = A * A;   
       p = 1.0/3 * (- 1.0/3 * sq_A + B);   
       q = 1.0/2 * (2.0/27 * A * sq_A - 1.0/3 * A * B + C);   
      
       /* use Cardano's formula */   
      
       cb_p = p * p * p;   
       D = q * q + cb_p;   
      
       if (IsZero(D))   
       {   
           if (IsZero(q)) /* one triple solution */   
           {   
               s[ 0 ] = 0;   
               num = 1;   
           }   
           else /* one single and one double solution */   
           {   
               double u = cbrt(-q);   
               s[ 0 ] = 2 * u;   
               s[ 1 ] = - u;   
               num = 2;   
           }   
       }   
       else if (D < 0) /* Casus irreducibilis: three real solutions */   
       {   
           double phi = 1.0/3 * acos(-q / sqrt(-cb_p));   
           double t = 2 * sqrt(-p);   
      
           s[ 0 ] =   t * cos(phi);   
           s[ 1 ] = - t * cos(phi + M_PI / 3);   
           s[ 2 ] = - t * cos(phi - M_PI / 3);   
           num = 3;   
       }   
       else /* one real solution */   
       {   
           double sqrt_D = sqrt(D);   
           double u = cbrt(sqrt_D - q);   
           double v = - cbrt(sqrt_D + q);   
           s[ 0 ] = u + v;   
           num = 1;   
       }   
      
       /* resubstitute */   
      
       sub = 1.0/3 * A;   
      
       for (i = 0; i < num; ++i)   
           s[ i ] -= sub;   
      
       return num;   
   }   
      
      
   int SolveQuartic(c, s)   
       double c[ 5 ];   
       double s[ 4 ];   
   {   
       double  coeffs[ 4 ];   
       double  z, u, v, sub;   
       double  A, B, C, D;   
       double  sq_A, p, q, r;   
       int     i, num;   
      
       /* normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0 */   
      
       A = c[ 3 ] / c[ 4 ];   
       B = c[ 2 ] / c[ 4 ];   
       C = c[ 1 ] / c[ 4 ];   
       D = c[ 0 ] / c[ 4 ];   
      
       /*  substitute x = y - A/4 to eliminate cubic term:   
           x^4 + px^2 + qx + r = 0 */   
      
       sq_A = A * A;   
       p = - 3.0/8 * sq_A + B;   
       q = 1.0/8 * sq_A * A - 1.0/2 * A * B + C;   
       r = - 3.0/256*sq_A*sq_A + 1.0/16*sq_A*B - 1.0/4*A*C + D;   
      
       if (IsZero(r))   
       {   
           /* no absolute term: y(y^3 + py + q) = 0 */   
           coeffs[ 0 ] = q;   
           coeffs[ 1 ] = p;   
           coeffs[ 2 ] = 0;   
           coeffs[ 3 ] = 1;   
      
           num = SolveCubic(coeffs, s);   
      
           s[ num++ ] = 0;   
       }   
       else   
       {   
           /* solve the resolvent cubic ... */   
      
           coeffs[ 0 ] = 1.0/2 * r * p - 1.0/8 * q * q;   
           coeffs[ 1 ] = - r;   
           coeffs[ 2 ] = - 1.0/2 * p;   
           coeffs[ 3 ] = 1;   
      
           (void) SolveCubic(coeffs, s);   
      
           /* ... and take the one real solution ... */   
           z = s[ 0 ];   
      
           /* ... to build two quadric equations */   
      
           u = z * z - r;   
           v = 2 * z - p;   
      
           if (IsZero(u))   
               u = 0;   
           else if (u > 0)   
               u = sqrt(u);   
           else   
               return 0;   
      
           if (IsZero(v))   
               v = 0;   
           else if (v > 0)   
               v = sqrt(v);   
           else   
               return 0;   
      
           coeffs[ 0 ] = z - u;   
           coeffs[ 1 ] = q < 0 ? -v : v;   
           coeffs[ 2 ] = 1;   
      
           num = SolveQuadric(coeffs, s);   
      
           coeffs[ 0 ]= z + u;   
           coeffs[ 1 ] = q < 0 ? v : -v;   
           coeffs[ 2 ] = 1;   
      
           num += SolveQuadric(coeffs, s + num);   
       }   
      
       /* resubstitute */   
      
       sub = 1.0/4 * A;   
      
       for (i = 0; i < num; ++i)   
           s[ i ] -= sub;   
      
       return num;   
   }   
      
   hope it works   
   Peter   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca