/* package to implement complex arithmetic in C muller's root solver for multiple complex roots from Handbook of C tools for scientists and engineers by L. Baker */ #include "complex.h" /* #include "libc.h" #include "math.h" */ struct complex ci,c1,c0,o,o2,ir; int iterp;/* global to return count used*/ /* #define min(a,b) (((a)<(b))? (a): (b)) */ #define max(a,b) (((a)>(b))? (a): (b)) #define abs(x) ((x)? (x):-(x)) double argmt(y,x) double x,y; {/* returns answer between 0 and twopi, as needed in complex principal argument*/ /* caveat- Aztec C returns 0,not + or -halfpi if x=0., y nonzero*/ double ans,ratio,twopi=6.283185307,pi=3.14159265358979,halfpi=1.570796327; double atan(),undef=0.0;/* change if desired*/ if (x==0.){if(y>0.) return(halfpi); if(y<0.) return(pi+halfpi); return(undef); }; /* if -pi to pi: return (halfpi*sign(y));*/ ratio=(y/x);ans=atan(ratio); /*atan returns answer between -halfpi and halfpi*/ /* now move to correct quadrant between -pi and pi*/ if (ratio>0.){/* ratio, ans>0. */ if (x>0.) return(ans);/* quadrant I*/ /* else x<0.,y<0. quadrant III*/ return (pi+ans); }; /* else ratio,ans<0.*/ if(x>0.)return(twopi+ans);/*quadrant IV*/ /*else x<0.,y>0., quadrant II*/ return(pi+ans); /* if answer bwtn -pi and pi desired: if ans<=pi accept ans unchanged else ans-twopi this will affect quadrant III,IV only. change: III: pi+ans to ans-pi IV: twopi+ans to ans */ } /*------------- complex logarithm function ---------------*/ clog(x,ans) struct complex *x,*ans; { double r,argmt(),sqrt(),log(),angle; r= sqrt( CNORM(*x) ); angle=argmt(x->y,x->x); ans->x=log(r); ans->y=angle; return; } /* ----------------- complex square root --------------------*/ csqrt(z,ans) struct complex *z,*ans; { double x,y,r,sqrt(),argmt(),angle; r= sqrt(sqrt( CNORM(*z) ) ); angle=.5*argmt(z->y,z->x); polarxy(r,angle,&x,&y); ans->x=x; ans->y=y; return; } /* ------- convert from polar to rectangular coordinates---- */ polarxy(r,angle,x,y) double r,angle,*x,*y; {double sin(),cos(); *x=r*cos(angle); *y=r*sin(angle); return; } main (argc,argv) int argc; char **argv; { double ep1,ep2; struct complex rts[12],delta; int i, maxit=20,kn,n,fnreal, fn(); kn=0;n=3;fnreal=0; ep1=1.e-8; ep2=1.e-8; delta.x=.5;delta.y=0.; for(i=0;ix,x->y); return; } /*------------------ muller's method based on FORTRAN program of Conte and DeBoor-----------*/ muller(kn,n,rts,maxit,ep1,ep2,fn,fnreal,delt) int fnreal,n,kn,maxit; double ep1,ep2; int (*fn)(); struct complex *delt,rts[]; { double sqrt(),eps1,eps2,real; int i,j,kount,ibeg,iend,zerodiv,setfr(); struct complex rt,h,delfpr,frtdef,lambda,delta, cdum,cdu1,delf,dfprlm,num,den,g,sqr,frt,frtprv,*root; struct complex *kptr,kludge; /* tolerences*/ eps1= max(ep1,1.e-12); eps2= max(ep2,1.e-20); /* skip any previously found roots*/ ibeg=kn; iend=kn+n; CASSN(delta,delt); /*printf(" muller ");printc(delt);printc(&delta); printf("\n"); for(i=0;imaxit) goto fini; while(1) { kount++; setfr(&frtdef,fn,&rt,i,rts,eps2,&zerodiv,&delta); if(zerodiv)goto start; if( cabs(h)0) {/*deflate for found roots*/ for (j=0;j0*/ /*printf(" return from setfr\n");*/ return; } /*----------- complex exponential function--------------*/ cexp( x,ans) struct complex *x,*ans; { double cos(),sin(),y,z; struct complex c1,c2; y = exp ( x->x); c2.x= cos (x->y); c2.y= sin (x->y); CTREAL(c1,c2,y); /*printf(" cexp ");printc(&c1);printc(x);printf("\n");*/ CLET(*ans,c1); return; }