#if ED // see autodif.h static char **_IndepName=NULL; // List of indep vars static int _IndepNum=0; static FILE *EDStream_; // Output for External Differentiator #endif /* ED */ int _Niv_; // Number of Independent Variables int _Hod_; // Highest order of derivatives #define MAXDEP_ 10 // max static depth of calls to u.d.f. #define MAXCALLS_ 256 // max number of static calls to u.d.f. typedef char Set[MAXCALLS_/8]; typedef struct { int Max; Set CurSet; Set OrSet; } SetOfIndex, *SetOfIndexPtr; static int FuncLevel_; // Level of u.d.f. calls static SetOfIndex sf_set[MAXDEP_]; // reserved indices to sv__ and sd__ static SetOfIndex uf_set[MAXDEP_]; // reserved indices to value_ and grad_ static void ResetIndex(void); static int sfGetIndex(void); #define Der0 Expr #define GetDer0_ GetExpr_ // A bit of psudo-science. // Let _Niv_ be the number of independent variables v(i), i=0,...,_Niv_-1. // The map ind2_(i,j)=i+j*(j+1)/2 maps indices of the variables to the // interval [0..ind2(_Niv_-1,_Niv_-1)] provided that i<=j. // The map ind3_(i,j,k)=i+j*(j+1)/2+k*(k+1)*(k+2)/6 maps indices of the variables to the // interval [0..ind3(_Niv_-1,_Niv_-1,_Niv_-1)] provided that i<=j<=k. // Maps subscripts of indep vars to a subscript of appropriate second derivative static int ind2(int i, int j) { return ind2_(i,j); } // Maps subscripts of indep vars to a subscript of appropriate third derivative static int ind3(int i, int j, int k) { return ind3_(i,j,k); } #if ED static int ind4(int i, int j, int k, int l) { return ind4_(i,j,k,l); } static int ind5(int i, int j, int k, int l, int m) { return ind5_(i,j,k,l,m); } #endif /* ED */ //======================================================== // Constructors // NB: varno can be nonzero only if kind==INDEP Gradient::Gradient(char *name, int varno, int vardim, VarKind kind) { char ***p; int i; char buf[100]; Index=0; Vardim=vardim; Kind=kind; Parent=(Gradient *)(name ? this : NULL); Expr=(char **)MemNewN((int)(vardim*sizeof(char *))); *buf='\0'; if (vardim>1) for (i=0; i3) { /* Create list of names of independent variables */ char **p; int i; if (_IndepNum5 || _Hod_<1 ***\n"); #else /* ED */ default: fprintf(MStream_,"#error *** _Hod_>3 || _Hod_<1 ***\n"); #endif /* ED */ } if (kind==TEMP) { fprintf(MStream_," double"); switch (_Hod_) { case 3: if (vardim>1) fprintf(MStream_," d3_%s[%i][%i],",name,vardim,n3); else fprintf(MStream_," d3_%s[%i],",name,n3); case 2: if (vardim>1) fprintf(MStream_," d2_%s[%i][%i],",name,vardim,n2); else fprintf(MStream_," d2_%s[%i],",name,n2); case 1: if (vardim>1) fprintf(MStream_," %s[%i],d1_%s[%i][%i];\n",name,vardim,name,vardim,_Niv_); else fprintf(MStream_," %s,d1_%s[%i];\n",name,name,_Niv_); } } } // f is a double const Gradient::Gradient(double c) { char buf[20]; Index=0; Vardim=1; Kind=DEF; Parent=NULL; Expr=(char **)MemNewN(sizeof(char *)); sprintf(buf,"%g",c); Expr[0]=(char *)StringSave(buf); switch (_Hod_) { case 3: n3=ind3(_Niv_-1,_Niv_-1,_Niv_-1)+1; Der3=(char ***)MemNew((int)((n3+1)*sizeof(char *))); Der3[0]=(char **)Der3+1; case 2: n2=ind2(_Niv_-1,_Niv_-1)+1; Der2=(char ***)MemNew((int)((n2+1)*sizeof(char *))); Der2[0]=(char **)Der2+1; case 1: Der1=(char ***)MemNew((int)((_Niv_+1)*sizeof(char *))); Der1[0]=(char **)Der1+1; break; case 4: case 5: break; #if ED default: fprintf(MStream_,"#error *** _Hod_>5 || _Hod_<1 ***\n"); #else /* ED */ default: fprintf(MStream_,"#error *** _Hod_>3 || _Hod_<1 ***\n"); #endif /* ED */ } } // f is an int const Gradient::Gradient(int i) { char buf[20]; Index=0; Vardim=1; Kind=DEF; Parent=NULL; Expr=(char **)MemNewN(sizeof(char *)); sprintf(buf,"%i",i); Expr[0]=(char *)StringSave(buf); switch (_Hod_) { case 3: n3=ind3(_Niv_-1,_Niv_-1,_Niv_-1)+1; Der3=(char ***)MemNew((int)((n3+1)*sizeof(char *))); Der3[0]=(char **)Der3+1; case 2: n2=ind2(_Niv_-1,_Niv_-1)+1; Der2=(char ***)MemNew((int)((n2+1)*sizeof(char *))); Der2[0]=(char **)Der2+1; case 1: Der1=(char ***)MemNew((int)((_Niv_+1)*sizeof(char *))); Der1[0]=(char **)Der1+1; break; case 4: case 5: break; #if ED default: fprintf(MStream_,"#error *** _Hod_>5 || _Hod_<1 ***\n"); #else /* ED */ default: fprintf(MStream_,"#error *** _Hod_>3 || _Hod_<1 ***\n"); #endif /* ED */ } } // Copy constructor Gradient::Gradient(const Gradient &g) { char ***p; int i,j; Vardim=g.Vardim; Index=g.Index; Kind=g.Kind; Parent=g.Parent; n2=g.n2; n3=g.n3; if (g.Expr) { Expr=(char **)MemNewN((int)(g.Vardim*sizeof(char *))); for (i=0; i","<",">=","<=",0}; static char lPrtyRel[]={ 1, 1, 2, 2}; static char *PrtyEqu[]={"==","!=",0}; static char lPrtyEqu[]={ 2, 2}; static char *PrtyAnd[]={"&&",0}; static char lPrtyAnd[]={ 2}; static char *PrtyOr[]={"||",0}; static char lPrtyOr[]={ 2}; static char *PrtyCont[]={"?",0}; static char lPrtyCont[]={ 1}; static char *PrtyAss[]={"=","+=","-=","*=","/=",0}; static char lPrtyAss[]={ 1, 2, 2, 2, 2}; static char **Prty[PRTY_]={ PrtyUnary, PrtyMult, PrtyAdd, PrtyRel, PrtyEqu, PrtyAnd, PrtyOr, PrtyCont, PrtyAss }; static char *lPrty[PRTY_]={ lPrtyUnary, lPrtyMult, lPrtyAdd, lPrtyRel, lPrtyEqu, lPrtyAnd, lPrtyOr, lPrtyCont, lPrtyAss }; static int NeedParentheses(char *p, int priority) { int i,len,level,prty,o; char c; for (i=level=0, len=(int)StringLen(p); iDer3[Index][ind3(i,j,k)]); if (p) { fprintf(MStream_," d3_%s[%i]=%s;\n",Expr[Index],ind3(i,j,k),p); sprintf(buf,"d3_%s[%i]",Expr[Index],ind3(i,j,k)); Parent->Der3[Index][ind3(i,j,k)]=(char *)StringSave(buf); } else Parent->Der3[Index][ind3(i,j,k)]=NULL; } case 2: for (i=0; i<_Niv_; i++) for (j=i; j<_Niv_; j++) { p=f.Der2[f.Index][ind2(i,j)]; MemFree(Parent->Der2[Index][ind2(i,j)]); if (p) { fprintf(MStream_," d2_%s[%i]=%s;\n",Expr[Index],ind2(i,j),p); sprintf(buf,"d2_%s[%i]",Expr[Index],ind2(i,j)); Parent->Der2[Index][ind2(i,j)]=(char *)StringSave(buf); } else Parent->Der2[Index][ind2(i,j)]=NULL; } case 1: for (i=0; i<_Niv_; i++) { p=f.Der1[f.Index][i]; MemFree(Parent->Der1[Index][i]); if (p) { fprintf(MStream_," d1_%s[%i]=%s;\n",Expr[Index],i,p); sprintf(buf,"d1_%s[%i]",Expr[Index],i); Parent->Der1[Index][i]=(char *)StringSave(buf); } else Parent->Der1[Index][i]=NULL; } } fprintf(MStream_,"\n"); break; case GRAD: // Output assignment operators #if ED p=f.Expr[f.Index]; switch (_Hod_) { case 4: // Maple fprintf(EDStream_,"\n"); // Specal processing if name is an array i1=StrLen(Expr[Index])-1; if (Expr[Index][i1]==']') { sscanf(Expr[Index],"%[^[][%i]",name,&i2); fprintf(EDStream_,"%s:=array(0..%i,0..%i):\n", name,i2,ind4(_Niv_,_Niv_,_Niv_,_Niv_)); sprintf(name,"%.*s,",i1,Expr[Index]); } else { sprintf(name,"%s[",Expr[Index]); fprintf(EDStream_,"%s:=array(0..%i):\n",Expr[Index],ind4(_Niv_,_Niv_,_Niv_,_Niv_)); } fprintf(EDStream_,"_expr_:=%s: _list_:=[]:\n\n",p ? p : "0"); // expr to differentiate for (i1=0; i1<_Niv_; i1++) { fprintf(EDStream_,"_d1_:=diff(_expr_,%s):\n",_IndepName[i1]); for (i2=i1; i2<_Niv_; i2++) { fprintf(EDStream_," _d2_:=diff(_d1_,%s):\n",_IndepName[i2]); for (i3=i2; i3<_Niv_; i3++) { fprintf(EDStream_," _d3_:=diff(_d2_,%s):\n",_IndepName[i3]); for (i4=i3; i4<_Niv_; i4++) { fprintf(EDStream_," _d4_:=diff(_d3_,%s):\n",_IndepName[i4]); fprintf(EDStream_," if _d4_<>0.0 then _list_:=[op(_list_),%s%i]=_d4_]: fi:\n", name,ind4(i1,i2,i3,i4)); } } } } fprintf(EDStream_,"if _list_<>[] then C(_list_,optimized): fi:\n"); return *this; case 5: // Maple fprintf(EDStream_,"\n"); // Specal processing if name is an array i1=StrLen(Expr[Index])-1; if (Expr[Index][i1]==']') { sscanf(Expr[Index],"%[^[][%i]",name,&i2); fprintf(EDStream_,"%s:=array(0..%i,0..%i):\n", name,i2,ind5(_Niv_,_Niv_,_Niv_,_Niv_,_Niv_)); sprintf(name,"%.*s,",i1,Expr[Index]); } else { sprintf(name,"%s[",Expr[Index]); fprintf(EDStream_,"%s:=array(0..%i):\n",Expr[Index],ind5(_Niv_,_Niv_,_Niv_,_Niv_,_Niv_)); } fprintf(EDStream_,"_expr_:=%s: _list_:=[]:\n\n",p ? p : "0"); // expr to differentiate for (i1=0; i1<_Niv_; i1++) { fprintf(EDStream_,"_d1_:=diff(_expr_,%s):\n",_IndepName[i1]); for (i2=i1; i2<_Niv_; i2++) { fprintf(EDStream_," _d2_:=diff(_d1_,%s):\n",_IndepName[i2]); for (i3=i2; i3<_Niv_; i3++) { fprintf(EDStream_," _d3_:=diff(_d2_,%s):\n",_IndepName[i3]); for (i4=i3; i4<_Niv_; i4++) { fprintf(EDStream_," _d4_:=diff(_d3_,%s):\n",_IndepName[i4]); for (i5=i4; i5<_Niv_; i5++) { fprintf(EDStream_," _d5_:=diff(_d4_,%s):\n",_IndepName[i5]); fprintf(EDStream_," if _d5_<>0.0 then _list_:=[op(_list_),%s%i]=_d5_]: fi:\n", name,ind5(i1,i2,i3,i4,i5)); } } } } } fprintf(EDStream_,"if _list_<>[] then C(_list_,optimized): fi:\n"); return *this; } #endif /* ED */ // Gradient: just copy // NB: Don't assign zero because all the gradient vars are initially set to 0 switch (_Hod_) { case 3: for (i=0; i<_Niv_; i++) for (j=i; j<_Niv_; j++) for (k=j; k<_Niv_; k++) { p=f.Der3[f.Index][ind3(i,j,k)]; if (p) fprintf(MStream_," %s[%i]=%s; /* /d%id%id%i */\n",Expr[Index],ind3(i,j,k),p,i,j,k); MemFree(Parent->Der3[Index][ind3(i,j,k)]); Parent->Der3[Index][ind3(i,j,k)]=(char *)StringSave(p); } break; case 2: for (i=0; i<_Niv_; i++) for (j=i; j<_Niv_; j++) { p=f.Der2[f.Index][ind2(i,j)]; if (p) fprintf(MStream_," %s[%i]=%s; /* /d%id%i */\n",Expr[Index],ind2(i,j),p,i,j); MemFree(Parent->Der2[Index][ind2(i,j)]); Parent->Der2[Index][ind2(i,j)]=(char *)StringSave(p); } break; case 1: for (i=0; i<_Niv_; i++) { p=f.Der1[f.Index][i]; if (p) fprintf(MStream_," %s[%i]=%s;\n",Expr[Index],i,p); MemFree(Parent->Der1[Index][i]); Parent->Der1[Index][i]=(char *)StringSave(p); } fprintf(MStream_,"\n"); } break; case DEF: // don't output assign statements switch (_Hod_) { case 3: for (i=0; i<_Niv_; i++) for (j=i; j<_Niv_; j++) for (k=j; k<_Niv_; k++) { MemFree(Der3[Index][ind3(i,j,k)]); Der3[Index][ind3(i,j,k)]=(char *)StringSave(f.Der3[f.Index][ind3(i,j,k)]); } break; case 2: for (i=0; i<_Niv_; i++) for (j=i; j<_Niv_; j++) { MemFree(Der2[Index][ind2(i,j)]); Der2[Index][ind2(i,j)]=(char *)StringSave(f.Der2[f.Index][ind2(i,j)]); } break; case 1: for (i=0; i<_Niv_; i++) { MemFree(Der1[Index][i]); Der1[Index][i]=(char *)StringSave(f.Der1[f.Index][i]); } } MemFree(Expr[Index]); Expr[Index]=(char *)StringSave(f.Expr[f.Index]); break; default:; } ResetIndex(); return *this; } // v=const Gradient & Gradient::operator=(double c) { Gradient t(c); *this=t; return *this; } // v=intconst Gradient & Gradient::operator=(int ic) { *this=(double)ic; return *this; } // v+=f; Gradient & Gradient::operator+=(const Gradient &f) { *this=*this+f; return *this; } // v+=const Gradient & Gradient::operator+=(double c) { *this=*this+c; return *this; } // v+=intconst Gradient & Gradient::operator+=(int ic) { *this=*this+ic; return *this; } // v-=f Gradient & Gradient::operator-=(const Gradient &f) { *this=*this-f; return *this; } // v-=const Gradient & Gradient::operator-=(double c) { *this=*this-c; return *this; } // v-=intconst Gradient & Gradient::operator-=(int ic) { *this=*this-ic; return *this; } // v*=f Gradient & Gradient::operator*=(const Gradient &f) { *this=*this*f; return *this; } // v*=const Gradient & Gradient::operator*=(double c) { *this=*this*c; return *this; } // v*=intconst Gradient & Gradient::operator*=(int ic) { *this=*this*ic; return *this; } // v/=f Gradient & Gradient::operator/=(const Gradient &f) { *this=*this/f; return *this; } // v/=const Gradient & Gradient::operator/=(double c) { *this=*this/c; return *this; } // v/=intconst Gradient & Gradient::operator/=(int ic) { *this=*this/ic; return *this; } //======= F u n c t i o n s ===================== // Creates texts of all partial derivatives of stdfun(arg) assuming that // d1=dstdfun/darg, d2=d2stdfun/darg2, d3=d3stdfun/darg3 static void DerText(Gradient &res, const Gradient &arg, char *d1, char *d2, char *d3) { char *p; char *q; char *w; switch (_Hod_) { case 3: for (i=0; i<_Niv_; i++) for (j=i; j<_Niv_; j++) for (k=j; k<_Niv_; k++) { desc="$1=$f1i*$f1j" "$1=$1*$f1k"; //arg'x*arg'y*arg'z p=Interpret(arg,arg); p=Mult(p,d3,'l'); q=Mult(GetDer3T_(arg,i,j,k),d1,0); p=Add(p,q,'b'); //D'''*arg'x*arg'y*arg'z+D'*arg'''xyz if (i==k) { // i==j==k desc="$1=$c3*$f1i" "$1=$1*$f2ii"; q=Interpret(arg,arg); } else if (i==j) { // i==j3) return t; #endif /* ED */ d1=(char *)MemNewN(l+14); sprintf(d1,"(%s>=0 ? 1 : -1)",f.Expr[f.Index]); DerText(t,f,d1,NULL,NULL); MemFree(d1); return t; } Gradient exp(const Gradient &f) { Gradient t; #if ED if (_Hod_>3) { int l=(int)StringLen(f.Expr[f.Index])+1; t.Expr[0]=(char *)MemNewN(l+5); sprintf(t.Expr[0],"exp(%s)",f.Expr[f.Index]); return t; } #endif /* ED */ Arrays(); // assign "sv__[]" to val_buf fprintf(MStream_," %s=exp(%s);\n",val_buf,f.Expr[f.Index]); t.Expr[0]=(char *)StrSave(val_buf); DerText(t,f,"1","1","1"); MultAll(t,val_buf); return t; } Gradient log(const Gradient &f) { Gradient t; char *d1; char *d2; char *d3; t.Expr[0]=(char *)MemNewN((int)StringLen(f.Expr[f.Index])+5+1); sprintf(t.Expr[0],"log(%s)",f.Expr[f.Index]); #if ED if (_Hod_>3) return t; #endif /* ED */ desc="$1=$c1/$f0"; // log'(u)=1/u d1=Interpret(f,f); desc="$1=$f0*$f0" "$1=$c1/$1" "$1=$c0-$1"; // log''(u)=-1/(u*u) d2=Interpret(f,f); desc="$1=$f0*$f0" "$1=$1*$f0" "$1=$c2/$1"; // log'''(u)=2/(u*u*u) d3=Interpret(f,f); DerText(t,f,d1,d2,d3); MemFree(d1); MemFree(d2); MemFree(d3); return t; } Gradient sqrt(const Gradient &f) { char *d1; char *d2; char *d3; Gradient t; #if ED if (_Hod_>3) { int l=(int)StringLen(f.Expr[f.Index])+1; t.Expr[0]=(char *)MemNewN(l+6); sprintf(t.Expr[0],"sqrt(%s)",f.Expr[f.Index]); return t; } #endif /* ED */ Arrays(); // assign "sv__[]" to val_buf and "sd__[]" to grad_buf fprintf(MStream_," %s=sqrt(%s);\n",val_buf,f.Expr[f.Index]); t.Expr[0]=(char *)StrSave(val_buf); fprintf(MStream_," %s=1/(2*%s);\n",grad_buf,val_buf); //mult is 1/(2sqrt(u)) d1="1"; // sqrt'(u)=1*mult desc="$1=$c2*$f0" "$1=$c1/$1" "$1=$c0-$1"; // sqrt''(u)=-1/(2u)*mult d2=Interpret(f,t); desc="$1=$f0*$f0" "$1=$1*$c4" "$1=$c3/$1"; // sqrt'''(u)=3/(4*u*u)*mult d3=Interpret(f,f); DerText(t,f,d1,d2,d3); MultAll(t,grad_buf); MemFree(d2); MemFree(d3); return t; } Gradient pow(const Gradient &f, double p) { char *d1; char *d2; char *d3; char *mult; char buf[20]; Gradient t; #if ED if (_Hod_>3) { int l=(int)StringLen(f.Expr[f.Index])+1; t.Expr[0]=(char *)MemNewN(l+60); sprintf(t.Expr[0],"pow(%s,%g)",f.Expr[f.Index],p); return t; } #endif /* ED */ if (p==2) { desc="$1=$f0*$f0"; t.Expr[0]=Interpret(f,f); } else { sprintf(buf,"%g",p); t.Expr[0]=(char *)MemNewN((int)StringLen(f.Expr[f.Index])+(int)StringLen(buf)+6+1); sprintf(t.Expr[0],"pow(%s,%s)",f.Expr[f.Index],buf); } d1="1"; if (p==1) { mult=d2=d3=NULL; } else if (p==2) { mult=Mult("2",f.Expr[f.Index],0); d2=Div("1",f.Expr[f.Index],0); d3=NULL; } else { Arrays(); // send "sd__[]" to grad_buf fprintf(MStream_," %s=%g*pow(%s,%g);\n",grad_buf,p,f.Expr[f.Index],p-1); mult=(char *)StrSave(grad_buf); sprintf(buf,"%g",p-1); d2=Div(buf,f.Expr[f.Index],0); sprintf(buf,"%g",(p-1)*(p-2)); d3=Div(buf,Mult(f.Expr[f.Index],f.Expr[f.Index],0),'r'); } DerText(t,f,d1,d2,d3); if (p!=1) MultAll(t,mult); MemFree(mult); MemFree(d2); MemFree(d3); return t; } Gradient pow(const Gradient &f, int ic) { return pow(f,(double)ic); } Gradient pow(const Gradient &f, const Gradient &g) { return exp(g*log(f)); } Gradient sin(const Gradient &f) { char *d1; char *d2; char *d3; Gradient t; #if ED if (_Hod_>3) { int l=(int)StringLen(f.Expr[f.Index])+1; t.Expr[0]=(char *)MemNewN(l+5); sprintf(t.Expr[0],"sin(%s)",f.Expr[f.Index]); return t; } #endif /* ED */ Arrays(); // "sv__[]" to val_buf and "sd__[]" to grad_buf fprintf(MStream_," %s=sin(%s);\n",val_buf,f.Expr[f.Index]); t.Expr[0]=(char *)StrSave(val_buf); fprintf(MStream_," %s=cos(%s);\n",grad_buf,f.Expr[f.Index]); d1=grad_buf; // sin'=cos d2=Sub(NULL,val_buf,0); // sin''=-sin d3=Sub(NULL,grad_buf,0); // sin'''=-cos DerText(t,f,d1,d2,d3); MemFree(d2); MemFree(d3); return t; } Gradient cos(const Gradient &f) { char *d1; char *d2; char *d3; Gradient t; #if ED if (_Hod_>3) { int l=(int)StringLen(f.Expr[f.Index])+1; t.Expr[0]=(char *)MemNewN(l+5); sprintf(t.Expr[0],"cos(%s)",f.Expr[f.Index]); return t; } #endif /* ED */ Arrays(); // "sv__[]" to val_buf and "sd__[]" to grad_buf fprintf(MStream_," %s=cos(%s);\n",val_buf,f.Expr[f.Index]); t.Expr[0]=(char *)StrSave(val_buf); fprintf(MStream_," %s=-sin(%s);\n",grad_buf,f.Expr[f.Index]); d1=grad_buf; // cos'=-sin d2=Sub(NULL,val_buf,0); // cos''=-cos d3=Sub(NULL,grad_buf,0); // cos'''=sin DerText(t,f,d1,d2,d3); MemFree(d2); MemFree(d3); return t; } Gradient tan(const Gradient &f) { char *d1; char *d2; char *d3; Gradient t; #if ED if (_Hod_>3) { int l=(int)StringLen(f.Expr[f.Index])+1; t.Expr[0]=(char *)MemNewN(l+5); sprintf(t.Expr[0],"tan(%s)",f.Expr[f.Index]); return t; } #endif /* ED */ Arrays(); // "sv__[]" to val_buf and "sd__[]" to grad_buf fprintf(MStream_," %s=tan(%s);\n",val_buf,f.Expr[f.Index]); t.Expr[0]=(char *)StrSave(val_buf); fprintf(MStream_," %s=1+tan(%s)*tan(%s);\n",grad_buf,f.Expr[f.Index],f.Expr[f.Index]); // mult is 1+tan*tan d1="1"; // tan'=1*mult d2=Mult("2",val_buf,0); // tan''=(2*tan)*mult d3=Sub(Mult("6",grad_buf,0),"4",'l'); // tan'''=(6*mult-4)*mult DerText(t,f,d1,d2,d3); MultAll(t,grad_buf); MemFree(d2); MemFree(d3); return t; } Gradient atan(const Gradient &f) { char *d1; char *d2; char *d3; Gradient t; #if ED if (_Hod_>3) { int l=(int)StringLen(f.Expr[f.Index])+1; t.Expr[0]=(char *)MemNewN(l+8); sprintf(t.Expr[0],"arctan(%s)",f.Expr[f.Index]); return t; } #endif /* ED */ Arrays(); // "sd__[]" to grad_buf t.Expr[0]=(char *)MemNewN((int)StringLen(f.Expr[f.Index])+6+1); sprintf(t.Expr[0],"atan(%s)",f.Expr[f.Index]); fprintf(MStream_," %s=1/(1+(%s)*(%s));\n",grad_buf,f.Expr[f.Index],f.Expr[f.Index]); // mult is 1/(1+u*u) d1="1"; // atan'(u)=1*mult d2=Mult("-2",Mult(f.Expr[f.Index],grad_buf,0),'r'); // atan''(u)=(-2*u*mult)*mult d3=Mult(grad_buf,Sub("6",Mult("8",grad_buf,0),'r'),'r'); // atan'''(u)=(mult(6-8mult))mult DerText(t,f,d1,d2,d3); MultAll(t,grad_buf); MemFree(d2); MemFree(d3); return t; } Gradient asin(const Gradient &f) { char *d1; char *d2; char *d3; Gradient t; #if ED if (_Hod_>3) { int l=(int)StringLen(f.Expr[f.Index])+1; t.Expr[0]=(char *)MemNewN(l+8); sprintf(t.Expr[0],"arcsin(%s)",f.Expr[f.Index]); return t; } #endif /* ED */ Arrays(); // "sv__[]" to val_buf and "sd__[]" to grad_buf t.Expr[0]=(char *)MemNewN((int)StringLen(f.Expr[f.Index])+6+1); sprintf(t.Expr[0],"asin(%s)",f.Expr[f.Index]); fprintf(MStream_," %s=1-(%s)*(%s);\n",val_buf,f.Expr[f.Index],f.Expr[f.Index]); fprintf(MStream_," %s=1/sqrt(%s);\n",grad_buf,val_buf); // mult is 1/sqrt(1-u*u) d1="1"; // asin'(u)=1*mult d2=Div(f.Expr[f.Index],val_buf,0); // atan''(u)=u/(1-u*u)*mult d3=Sub("3",Mult("2",val_buf,0),'r'); d3=Div(Div(d3,val_buf,'l'),val_buf,'l'); // asin'''(u)=(3-2(1-u*u)/(1-u*u)*(1-u*u))*mult DerText(t,f,d1,d2,d3); MultAll(t,grad_buf); MemFree(d2); MemFree(d3); return t; } Gradient acos(const Gradient &f) { return -asin(f); } // iff(c,f,g) is equivalent to c ? f : g Gradient iff(const Gradient &c, const Gradient &f, const Gradient &g) { Gradient t; char *fp; char *gp; char *p; int len; len=(int)StringLen(c.Expr[c.Index])+1; t.Expr[0]=(char *)MemNewN((int)(len+StringLen(f.Expr[f.Index])+StringLen(g.Expr[g.Index])+7)); sprintf(t.Expr[0],"iff(%s,%s,%s)",c.Expr[c.Index],f.Expr[f.Index],g.Expr[g.Index]); switch (_Hod_) { case 3: for (i=0; i<_Niv_; i++) for (j=i; j<_Niv_; j++) for (k=j; k<_Niv_; k++) { fp=GetDer3T_(f,i,j,k); gp=GetDer3T_(g,i,j,k); if (fp || gp) { p=(char *)MemNewN((int)(len+StringLen(fp)+StringLen(gp)+7)); sprintf(p,"iff(%s,%s,%s)",c.Expr[c.Index],fp ? fp : "0",gp ? gp : "0"); t.SetDer3(i,j,k,p); } } case 2: for (i=0; i<_Niv_; i++) for (j=i; j<_Niv_; j++) { fp=GetDer2T_(f,i,j); gp=GetDer2T_(g,i,j); if (fp || gp) { p=(char *)MemNewN((int)(len+StringLen(fp)+StringLen(gp)+7)); sprintf(p,"iff(%s,%s,%s)",c.Expr[c.Index],fp ? fp : "0",gp ? gp : "0"); t.SetDer2(i,j,p); } } case 1: for (i=0; i<_Niv_; i++) { fp=GetDer1T_(f,i); gp=GetDer1T_(g,i); if (fp || gp) { p=(char *)MemNewN((int)(len+StringLen(fp)+StringLen(gp)+7)); sprintf(p,"iff(%s,%s,%s)",c.Expr[c.Index],GetDer1_(f,i),GetDer1_(g,i)); t.SetDer1(i,p); } } } return t; } //======= R E L A T I O N S ( I F F ) ======== static char *rel(char *p, char *q, char *op, int prty) { char *r; char *f; int len,lneed,rneed; len=(int)(StringLen(p)+StrLen(op)+StringLen(q)+1); lneed=NeedParentheses(p,prty); rneed=NeedParentheses(q,prty); len+=lneed+rneed; r=(char *)MemNewN(len+lneed+rneed); f=(char *) (lneed ? (rneed ? "(%s)%s(%s)" : "(%s)%s%s") : (rneed ? "%s%s(%s)" : "%s%s%s")); sprintf(r,f,p,op,q); return r; } // p q is < <= > >= #define Rel(p,q,op) rel(p,q,op,PRTY_REL) // p q is == != #define Equ(p,q,op) rel(p,q,op,PRTY_EQU) // f>g Gradient operator>(const Gradient &f, const Gradient &g) { Gradient t; t.Expr[0]=Rel(f.Expr[f.Index],g.Expr[g.Index],">"); return t; } // f>const Gradient operator>(const Gradient &f, double c) { Gradient t; char b[20]; sprintf(b,"%g",c); t.Expr[0]=Rel(f.Expr[f.Index],b,">"); return t; } // f>intconst Gradient operator>(const Gradient &f, int ic) { return f>(double)ic; } // const>f Gradient operator>(double c, const Gradient &f) { Gradient t; char b[20]; sprintf(b,"%g",c); t.Expr[0]=Rel(b,f.Expr[f.Index],">"); return t; } // intconst>f Gradient operator>(int ic, const Gradient &f) { return (double)ic>f; } // f>=g Gradient operator>=(const Gradient &f, const Gradient &g) { Gradient t; t.Expr[0]=Rel(f.Expr[f.Index],g.Expr[g.Index],">="); return t; } // f>=const Gradient operator>=(const Gradient &f, double c) { Gradient t; char b[20]; sprintf(b,"%g",c); t.Expr[0]=Rel(f.Expr[f.Index],b,">="); return t; } // f>=intconst Gradient operator>=(const Gradient &f, int ic) { return f>=(double)ic; } // const>=f Gradient operator>=(double c, const Gradient &f) { Gradient t; char b[20]; sprintf(b,"%g",c); t.Expr[0]=Rel(b,f.Expr[f.Index],">="); return t; } // intconst>=f Gradient operator>=(int ic, const Gradient &f) { return (double)ic>=f; } // fExpr[this->Index]); this->Expr[this->Index]=(char *)StringSave(newtext); } // caller must not change or freeptrs memory char *GetDer1_(const Gradient &f, int ic) { char *p; p=f.Der1[f.Index][ic]; return (char *) (p ? p : "0"); } char *GetDer1T_(const Gradient &f, int ic) { return f.Der1[f.Index][ic]; } void Gradient::SetDer1(int ic, char *newtext) { MemFree(this->Der1[this->Index][ic]); this->Der1[this->Index][ic]=(char *)StringSave(newtext); } // caller must not change or freeptrs memory char *GetDer2_(const Gradient &f, int ic, int jc) { char *p; p=f.Der2[f.Index][ind2(ic,jc)]; return (char *) (p ? p : "0"); } char *GetDer2T_(const Gradient &f, int ic, int jc) { return f.Der2[f.Index][ind2(ic,jc)]; } void Gradient::SetDer2(int ic, int jc, char *newtext) { int indx=ind2(ic,jc); MemFree(this->Der2[this->Index][indx]); this->Der2[this->Index][indx]=(char *)StringSave(newtext); } // caller must not change or freeptrs memory char *GetDer3_(const Gradient &f, int ic, int jc, int kc) { char *p; p=f.Der3[f.Index][ind3(ic,jc,kc)]; return (char *) (p ? p : "0"); } char *GetDer3T_(const Gradient &f, int ic, int jc, int kc) { return f.Der3[f.Index][ind3(ic,jc,kc)]; } void Gradient::SetDer3(int ic, int jc, int kc, char *newtext) { int indx=ind3(ic,jc,kc); MemFree(this->Der3[this->Index][indx]); this->Der3[this->Index][indx]=(char *)StringSave(newtext); } // Interpret a sequence of assignments // Left-hand side: $1, $2, $3, $4 // Right-hand side: binary operation (+,-,*,/), operands may be // $1, $2, $3, $4, $cn (n is any integer, n>0), $f0, $g0, // $f1d, $g1d, $f2dd, $g2dd, $f3ddd, $g3ddd // where d may by any letter i,j,k static char Letter[]={0,'r','l','b'}; static char *Interpret(const Gradient &f, const Gradient &g) { char *tmp[4]; char *op[2]; char *(*Oper)(char*,char*,char); int o,ii,jj,pos; char freeptrs[2]; char buf[10]; while (*desc) { ii=desc[1]-'1'; desc+=4; for (jj=0; 1; jj++) { switch (*desc) { case 'f': case 'g': o=desc[1]-'0'; switch (o) { case 0: op[jj]=GetExprT_(*desc=='f' ? f : g); break; case 1: op[jj]=GetDer1T_(*desc=='f' ? f : g,IndeX[desc[2]-'i']); break; case 2: op[jj]=GetDer2T_(*desc=='f' ? f : g,IndeX[desc[2]-'i'],IndeX[desc[3]-'i']); break; case 3: op[jj]=GetDer3T_(*desc=='f' ? f : g,IndeX[desc[2]-'i'],IndeX[desc[3]-'i'],IndeX[desc[4]-'i']); break; } desc+=o+2; freeptrs[jj]=0; break; case 'c': sscanf(desc+1,"%[0-9]%n",buf,&pos); if (StrCmp(buf,"0")) op[jj]=(char *)StringSave(buf); else op[jj]=0; desc+=pos+1; freeptrs[jj]=1; break; default: /* must be '1', '2', '3', or '4' */ op[jj]=tmp[*desc-'1']; desc+=1; freeptrs[jj]=1; } if (jj) break; else { switch (*desc) { case '+': Oper=Add; break; case '-': Oper=Sub; break; case '*': Oper=Mult; break; case '/': Oper=Div; break; } desc+=2; } } tmp[ii]=Oper(op[0],op[1],Letter[2*freeptrs[0]+freeptrs[1]]); } return tmp[ii]; } //***********************************// // C++ run-time processing functions // //***********************************// static FILE *SaveStream[MAXDEP_]; // Initializes run-time support void rtInit_(FILE *m, FILE *f) { MStream_=m; FStream_=f; FuncLevel_=0; #if ED if (_Hod_<=3) /* skip for External Differentiator (i.e. Maple) */ #endif sf_set[0].Max=uf_set[0].Max=1; Memset(sf_set[0].CurSet,0,sizeof(Set)); Memset(sf_set[0].OrSet,0,sizeof(Set)); Memset(uf_set[0].CurSet,0,sizeof(Set)); Memset(uf_set[0].OrSet,0,sizeof(Set)); } // Terminates run-time support void rtTerm_(void) { #if ED { int ii; if (_IndepNum) { for (ii=0; ii<_IndepNum; ii++) { MemFree(_IndepName[ii]); } MemFree(_IndepName); _IndepName=NULL; _IndepNum=0; } } #endif /* ED */ } #if ED // Called before (PreProc==1) or after (PreProc==0) generation of // the text for External Differentiator void rtExtDiff_(char *mio, int PreProc) { switch (PreProc) { case 1: // before output // Open EDStream_=fopen(mio,"wt"); if (!EDStream_) { fprintf(MStream_,"#error Cannot open file '%s'\n",mio); return; } // Maple-specific fprintf(EDStream_,"readlib(C):\n"); fprintf(EDStream_,"pow:=(x,d)->x^d:\n"); fprintf(EDStream_,"fabs:=(x)->abs(x):\n"); fprintf(EDStream_,"iff:=proc(c,e1,e2) if c<>0 then e1 else e2 fi end:\n"); break; case 0: // after output if (!EDStream_) return; // Maple-specific fprintf(EDStream_,"quit:\n"); // Close fclose(EDStream_); break; } } #endif /* ED */ void rtFuncEntry_(void) { int ii,jj; char buf[30]; if (FuncLevel_CurSet); ii++) { c=s[FuncLevel_].CurSet[ii] | s[FuncLevel_].OrSet[ii]; if (c!=0xff) { for (jj=0; c&1; jj++,c>>=1); s[FuncLevel_].CurSet[ii]|=1<s[0].Max) s[0].Max=n+1; return n; } } // all are reserved return -1; // let it to crash } // Get Index for user-defined functions int rtGetIndex_(void) { return GetIndex(uf_set); } // Get Index for standard functions static int sfGetIndex(void) { return GetIndex(sf_set); } int rtGetMaxsf_(void) { return sf_set[0].Max; } int rtGetMaxuf_(void) { #if DEB d_check(); #endif return uf_set[0].Max; } // void MemFree__(void *p) { MemFree(p); } char *Add__(char *op1, char *op2, char freemem) { return Add(op1,op2,freemem); } char *Mult__(char *op1, char *op2, char freemem) { return Mult(op1,op2,freemem); }