⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 quarcube.c

📁 [Game.Programming].Academic - Graphics Gems (6 books source code)
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   doquartic.c   a test of a quartic solving routine   Don Herbison-Evans   24 June 1994*/#include <stdio.h>double nought;double doub1,doub2;double doub3,doub4;double doub6,doub12;double doub24;double doubmax;       /* approx square root of max double number */double doubmin;       /* smallest double number */double doubtol;       /* tolerance of double numbers */double rt3;double inv2,inv3,inv4;void setcns();int descartes();double exp(),log(),sqrt(),cos(),acos();double cubic();int qudrtc();int quartic();int ferrari();int neumark();void errors();main(){   double a,b,c,d;   double rts[4];   double rterr[4];   int nr;   setcns();   a = -(double)10;   b = (double)35;   c = -(double)50;   d = (double)24;   nr = descartes(a,b,c,d,rts);   errors(a,b,c,d,rts,rterr,nr);   nr = ferrari(a,b,c,d,rts);   errors(a,b,c,d,rts,rterr,nr);   nr = neumark(a,b,c,d,rts);   errors(a,b,c,d,rts,rterr,nr);   exit(0);}/****************************************************/void setcns()/*      set up constants */{      int j;      nought = (double)0;      doub1 = (double)1;      doub2 = (double)2;      doub3 = (double)3;      doub4 = (double)4;      doub6 = (double)6;      doub12 = (double)12;      doub24 = (double)24;      inv2 = doub1/(double)2;      inv3 = doub1/(double)3;      inv4 = doub1/(double)4;      rt3 = sqrt(doub3) ;      doubtol = doub1;      for (  j = 1 ; doub1+doubtol > doub1 ; ++ j )      {          doubtol *= inv2;      }      doubtol = sqrt(doubtol);      doubmin = inv2 ;      for (  j = 1 ; j <= 100 ; ++ j )      {          doubmin=doubmin*doubmin ;          if ((doubmin*doubmin) <= (doubmin*doubmin*inv2))              break;      }      doubmax=0.7/sqrt(doubmin) ;} /* setcns *//***********************************/int quartic(a,b,c,d,rts,rterr)double a,b,c,d,rts[4],rterr[4];/*   Solve quartic equation using either   quadratic, Ferrari's or Neumark's algorithm.   called by    calls  qudrtc, ferrari, neumark.     21 Jan 1989  Don Herbison-Evans*/{   int qudrtc(),ferrari(),neumark();   int j,k,nq,nr;   double odd, even;   double roots[4];   if (a < nought) odd = -a; else odd = a;   if (c < nought) odd -= c; else odd += c;   if (b < nought) even = -b; else even = b;   if (d < nought) even -= d; else even += d;   if (odd < even*doubtol)   {      nq = qudrtc(b,d,roots,b*b-doub4*d);      j = 0;      for (k = 0; k < nq; ++k)      {         if (roots[k] > nought)         {            rts[j] = sqrt(roots[k]);            rts[j+1] = -rts[j];            ++j; ++j;         }      }      nr = j;   }   else   {      if (a < nought) k = 1; else k = 0;      if (b < nought) k += k+1; else k +=k;       if (c < nought) k += k+1; else k +=k;       if (d < nought) k += k+1; else k +=k;       switch (k)      {              case 0 : nr = ferrari(a,b,c,d,rts) ; break;              case 1 : nr = neumark(a,b,c,d,rts) ; break;              case 2 : nr = neumark(a,b,c,d,rts) ; break;              case 3 : nr = ferrari(a,b,c,d,rts) ; break;              case 4 : nr = ferrari(a,b,c,d,rts) ; break;              case 5 : nr = neumark(a,b,c,d,rts) ; break;              case 6 : nr = ferrari(a,b,c,d,rts) ; break;              case 7 : nr = ferrari(a,b,c,d,rts) ; break;              case 8 : nr = neumark(a,b,c,d,rts) ; break;              case 9 : nr = ferrari(a,b,c,d,rts) ; break;              case 10 : nr = ferrari(a,b,c,d,rts) ; break;              case 11 : nr = neumark(a,b,c,d,rts) ; break;              case 12 : nr = ferrari(a,b,c,d,rts) ; break;              case 13 : nr = ferrari(a,b,c,d,rts) ; break;              case 14 : nr = ferrari(a,b,c,d,rts) ; break;              case 15 : nr = ferrari(a,b,c,d,rts) ; break;      }   }   errors(a,b,c,d,rts,rterr,nr);   return(nr);} /* quartic *//*****************************************/int ferrari(a,b,c,d,rts)   double a,b,c,d,rts[4];/*      solve the quartic equation -    x**4 + a*x**3 + b*x**2 + c*x + d = 0    called by quartic   calls     cubic, qudrtc.     input -    a,b,c,e - coeffs of equation.      output -    nquar - number of real roots.    rts - array of root values.      method :  Ferrari - Lagrange     Theory of Equations, H.W. Turnbull p. 140 (1947)     calls  cubic, qudrtc */{   double cubic();   int qudrtc();   int nquar,n1,n2 ;   double asq,ainv2;   double v1[4],v2[4] ;   double p,q,r ;   double y;   double e,f,esq,fsq,ef ;   double g,gg,h,hh;   fprintf(stderr,"\nFerrari %g %g %g %g\n",a,b,c,d);   asq = a*a;   p = b ;   q = a*c-doub4*d ;   r = (asq - doub4*b)*d + c*c ;   y = cubic(p,q,r) ;   esq = inv4*asq - b - y;   if (esq < nought) return(0);   else   {      fsq = inv4*y*y - d;      if (fsq < nought) return(0);      else      {         ef = -(inv4*a*y + inv2*c);         if ( ((a > nought)&&(y > nought)&&(c > nought))           || ((a > nought)&&(y < nought)&&(c < nought))           || ((a < nought)&&(y > nought)&&(c < nought))           || ((a < nought)&&(y < nought)&&(c > nought))           ||  (a == nought)||(y == nought)||(c == nought)         )/* use ef - */         {            if ((b < nought)&&(y < nought)&&(esq > nought))            {               e = sqrt(esq);               f = ef/e;            }            else if ((d < nought) && (fsq > nought))            {               f = sqrt(fsq);               e = ef/f;            }            else            {               e = sqrt(esq);               f = sqrt(fsq);               if (ef < nought) f = -f;            }         }         else         {            e = sqrt(esq);            f = sqrt(fsq);            if (ef < nought) f = -f;         }/* note that e >= nought */         ainv2 = a*inv2;         g = ainv2 - e;         gg = ainv2 + e;         if ( ((b > nought)&&(y > nought))           || ((b < nought)&&(y < nought)) )         {            if (( a > nought) && (e != nought)) g = (b + y)/gg;               else if (e != nought) gg = (b + y)/g;         }         if ((y == nought)&&(f == nought))         {            h = nought;            hh = nought;         }         else if ( ((f > nought)&&(y < nought))                || ((f < nought)&&(y > nought)) )         {            hh = -inv2*y + f;            h = d/hh;         }         else         {            h = -inv2*y - f;            hh = d/h;         }         n1 = qudrtc(gg,hh,v1, gg*gg - doub4*hh) ;         n2 = qudrtc(g,h,v2, g*g - doub4*h) ;         nquar = n1+n2 ;         rts[0] = v1[0] ;         rts[1] = v1[1] ;         rts[n1+0] = v2[0] ;         rts[n1+1] = v2[1] ;         return(nquar);      }   }} /* ferrari *//*****************************************/int neumark(a,b,c,d,rts)   double a,b,c,d,rts[4];/*      solve the quartic equation -    x**4 + a*x**3 + b*x**2 + c*x + d = 0    called by quartic   calls     cubic, qudrtc.     input parameters -    a,b,c,e - coeffs of equation.      output parameters -    nquar - number of real roots.    rts - array of root values.      method -  S. Neumark      Solution of Cubic and Quartic Equations - Pergamon 1965         translated to C with help of Shawn Neely*/{   int nquar,n1,n2 ;   double y,g,gg,h,hh,gdis,gdisrt,hdis,hdisrt,g1,g2,h1,h2 ;   double bmy,gerr,herr,y4,d4,bmysq ;   double v1[4],v2[4] ;   double asq ;   double p,q,r ;   double hmax,gmax ;   double cubic();   int qudrtc();   fprintf(stderr,"\nNeumark %g %g %g %g\n",a,b,c,d);   asq = a*a ;   p =  -b*doub2 ;   q = b*b + a*c - doub4*d ;   r = (c - a*b)*c + asq*d ;   y = cubic(p,q,r) ;   bmy = b - y ;   y4 = y*doub4 ;   d4 = d*doub4 ;   bmysq = bmy*bmy ;   gdis = asq - y4 ;   hdis = bmysq - d4 ;   if ((gdis < nought) || (hdis < nought)) return(0);   else   {      g1 = a*inv2 ;      h1 = bmy*inv2 ;      gerr = asq + y4 ;      herr = hdis ;      if (d > nought) herr = bmysq + d4 ;      if ((y < nought) || (herr*gdis > gerr*hdis))      {         gdisrt = sqrt(gdis) ;         g2 = gdisrt*inv2 ;         if (gdisrt != nought) h2 = (a*h1 - c)/gdisrt ;            else h2 = nought;      }      else      {         hdisrt = sqrt(hdis) ;         h2 = hdisrt*inv2 ;         if (hdisrt != nought) g2 = (a*h1 - c)/hdisrt ;            else g2 = nought;      }/*      note that in the following, the tests ensure non-zero      denominators -  */      h = h1 - h2 ;      hh = h1 + h2 ;      hmax = hh ;      if (hmax < nought) hmax =  -hmax ;      if (hmax < h) hmax = h ;      if (hmax <  -h) hmax =  -h ;      if ((h1 > nought)&&(h2 > nought)) h = d/hh ;      if ((h1 < nought)&&(h2 < nought)) h = d/hh ;      if ((h1 > nought)&&(h2 < nought)) hh = d/h ;      if ((h1 < nought)&&(h2 > nought)) hh = d/h ;      if (h > hmax) h = hmax ;      if (h <  -hmax) h =  -hmax ;      if (hh > hmax) hh = hmax ;      if (hh <  -hmax) hh =  -hmax ;      g = g1 - g2 ;      gg = g1 + g2 ;      gmax = gg ;      if (gmax < nought) gmax =  -gmax ;      if (gmax < g) gmax = g ;      if (gmax <  -g) gmax =  -g ;      if ((g1 > nought)&&(g2 > nought)) g = y/gg ;      if ((g1 < nought)&&(g2 < nought)) g = y/gg ;      if ((g1 > nought)&&(g2 < nought)) gg = y/g ;      if ((g1 < nought)&&(g2 > nought)) gg = y/g ;      if (g > gmax) g = gmax ;      if (g <  -gmax) g =  -gmax ;      if (gg > gmax) gg = gmax ;      if (gg <  -gmax) gg =  -gmax ;       n1 = qudrtc(gg,hh,v1, gg*gg - doub4*hh) ;      n2 = qudrtc(g,h,v2, g*g - doub4*h) ;      nquar = n1+n2 ;      rts[0] = v1[0] ;      rts[1] = v1[1] ;      rts[n1+0] = v2[0] ;      rts[n1+1] = v2[1] ;       return(nquar);   }} /* neumark *//****************************************************/void errors(a,b,c,d,rts,rterr,nrts)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -