// Laptev Eugene's (ztv@imp.kiev.ua) // Fast Expression Evaluator. // ///MODIFICATIONS BY ROB // // // // Message-Id: <35D7EAF6.9395E082@imp.kiev.ua> // Date: Mon, 17 Aug 1998 09:33:58 +0100 // From: Eugene Laptev // Organization: IMP // X-Mailer: Mozilla 4.05 [en] (WinNT; I) // Mime-Version: 1.0 // To: Rob Salgado // Subject: Re: EE source // // // Hello, Rob Salgado! // // // Here the source code. // Use it in whatever programs you want. // It is not fully readable. But the sense was to convert // mathematical expression from infix to postfix form. // // // Sincerely, // _____________________________________ // Eugene Laptev mailto: ztv@imp.kiev.ua #include #include #include /***defines**************************************************************/ #define max3(x,y,z) (max(x,max(y,z))) //ee types #define ADDRESS 0 #define NUMBER 1 #define ARGUMENT 2 #define OPERATOR 3 //ee operators #define SUM 1 #define SUB 2 #define MUL 3 #define DIV 4 #define MOD 5 #define POW 6 #define NEG 7 //ee.h #define EE_OK 0 #define EE_SYNTAXERROR 1 #define EE_UNPAIRED 2 #define EE_UNKNOWNFUNCTION 3 #define EE_UNKNOWNARGUMENT 4 #define EE_WRONGARGUMENTS 5 #define EE_SMALLBUFFER 6 #define EE_PARTIAL 7 #define EE_UNUSEABLE 8 /***constants************************************************************/ const int stacksize=100; const int maxnumberofarguments=100; const int errorstringsize=128; /***types****************************************************************/ typedef double floattype; typedef void (*pf)(void); struct fundb //functions data base { char *name; pf fn; int commas; }; struct condb //constants data base { char *name; floattype value; }; const char *adb[maxnumberofarguments]; //arguments data base /***globals**************************************************************/ int ip,sp,buildresult,waserrors,pushsuccess; floattype *im; floattype stack[stacksize+12]; char *usererror; const char *errorpos; /***ee functions*********************************************************/ void zz_abs() {{ stack[sp]=fabs(stack[sp]); }} /******/ void zz_acos() {{ stack[sp]=acosl(stack[sp]); }} /******/ void zz_asin() {{ stack[sp]=asinl(stack[sp]); }} /******/ void zz_atan() {{ stack[sp]=atanl(stack[sp]); }} /******/ void zz_atan2() {{ sp--; stack[sp]=atan2l(stack[sp],stack[sp+1]); }} /******/ void zz_ceil() {{ stack[sp]=ceill(stack[sp]); }} /******/ void zz_cos() {{ stack[sp]=cosl(stack[sp]); }} /******/ void zz_cosh() {{ stack[sp]=coshl(stack[sp]); }} /******/ void zz_deg() {{ stack[sp]=stack[sp]*180.0/3.1415926535897932385; }} /******/ void zz_exp() {{ stack[sp]=expl(stack[sp]); }} /******/ void zz_floor() {{ stack[sp]=floorl(stack[sp]); }} /******/ void zz_hypot() {{ sp--; //stack[sp]=_hypotl((stack[sp]),(stack[sp+1])); stack[sp]=sqrt((stack[sp])*(stack[sp])+(stack[sp+1])*(stack[sp+1])); }} /******/ void zz_j0() {{ stack[sp]=_j0(stack[sp]); }} /******/ void zz_j1() {{ stack[sp]=_j1(stack[sp]); }} /******/ void zz_jn() {{ sp--; stack[sp]=_jn((int)(stack[sp]),stack[sp+1]); }} /******/ void zz_max() {{ sp--; stack[sp]=max(stack[sp],stack[sp+1]); }} /******/ void zz_min() {{ sp--; stack[sp]=min(stack[sp],stack[sp+1]); }} /******/ void zz_mod() {{ sp--; stack[sp]=fmodl(stack[sp],stack[sp+1]); }} /******/ void zz_log(void) {{ stack[sp]=logl(stack[sp]); }} /******/ void zz_log10(void) {{ stack[sp]=log10l(stack[sp]); }} /******/ void zz_pow(void) {{ sp--; stack[sp]=powl(stack[sp],stack[sp+1]); }} /******/ void zz_rad() {{ stack[sp]=stack[sp]/180.0*3.1415926535897932385; }} /******/ void zz_sign(void) {{ int t; t=_fpclass(stack[sp]); if(t&(_FPCLASS_NINF|_FPCLASS_NN|_FPCLASS_ND)) { stack[sp]=-1; return; } if(t&(_FPCLASS_PINF|_FPCLASS_PN|_FPCLASS_PD)) { stack[sp]=1; return; } if(t&(_FPCLASS_NZ|_FPCLASS_PZ)) { stack[sp]=0; return; } }} /******/ void zz_sin(void) {{ stack[sp]=sinl(stack[sp]); }} /******/ void zz_sinh(void) {{ stack[sp]=sinhl(stack[sp]); }} /******/ void zz_tan() {{ stack[sp]=tanl(stack[sp]); }} /******/ void zz_tanh(void) {{ stack[sp]=tanhl(stack[sp]); }} /******/ void zz_step(void) {{ int t; t=_fpclass(stack[sp]); if(t&(_FPCLASS_NINF|_FPCLASS_NN|_FPCLASS_ND)) { stack[sp]=0; return; } if(t&(_FPCLASS_NZ|_FPCLASS_PZ|_FPCLASS_PINF|_FPCLASS_PN|_FPCLASS_PD)) { stack[sp]=1; return; } }} /******/ void zz_sqrt(void) {{ stack[sp]=sqrtl(stack[sp]); }} /******/ void zz_y0() {{ stack[sp]=_y0(stack[sp]); }} /******/ void zz_y1() {{ stack[sp]=_y1(stack[sp]); }} /******/ void zz_yn() {{ sp--; stack[sp]=_yn((int)(stack[sp]),stack[sp+1]); }} /************************************************************************/ void zz_sum() {{ sp--; stack[sp]+=stack[sp+1]; }} /******/ void zz_sub() {{ sp--; stack[sp]-=stack[sp+1]; }} /******/ void zz_mul() {{ sp--; stack[sp]*=stack[sp+1]; }} /******/ void zz_div() {{ sp--; stack[sp]/=stack[sp+1]; }} /******/ void zz_neg() {{ stack[sp]=-stack[sp]; }} /************************************************************************/ fundb fdb[]= { {"abs",zz_abs}, {"acos",zz_acos}, {"asin",zz_asin}, {"atan",zz_atan}, {"atan2",zz_atan2,1}, {"ceil",zz_ceil}, {"cos",zz_cos}, {"cosh",zz_cosh}, {"deg",zz_deg}, {"exp",zz_exp}, {"floor",zz_floor}, {"hypot",zz_hypot,1}, {"j0",zz_j0}, {"j1",zz_j1}, {"jn",zz_jn,1}, {"max",zz_max,1}, {"min",zz_min,1}, {"mod",zz_mod,1}, {"ln",zz_log}, {"log",zz_log}, {"log10",zz_log10}, {"pow",zz_pow,1}, {"rad",zz_rad}, {"sign",zz_sign}, {"sin",zz_sin}, {"sinh",zz_sinh}, {"step",zz_step}, {"sqrt",zz_sqrt}, {"tan",zz_tan}, {"tanh",zz_tanh}, {"y0",zz_y0}, {"y1",zz_y1}, {"yn",zz_yn,1}, {"laptev",zz_log} }; condb cdb[]= { {"pi",3.1415926535897932385l}, {"e", 2.7182818284590452354l} }; int nof=sizeof(fdb)/sizeof(fdb[0]); int noc=sizeof(cdb)/sizeof(cdb[0]); int noa; /************************************************************************/ void error(const char *message) {{ if(usererror!=NULL) { strncpy(usererror,message,errorstringsize-1); usererror[errorstringsize-1]=0; } waserrors=1; }} /************************************************************************/ void error2(const char *m1,const char *m2, int hm) {{ int maxcat; if(usererror!=NULL) { strncpy(usererror,m1,errorstringsize-2); usererror[errorstringsize-1]=0; maxcat=errorstringsize-strlen(usererror)-2; if(maxcat>hm) maxcat=hm; if(maxcat>0) strncat(usererror,m2,maxcat); usererror[errorstringsize-1]=0; } waserrors=1; }} /************************************************************************/ int inline isoperator(char c) {{ if(c=='+'||c=='-'||c=='*'||c=='/'||c=='^'||c==','||c=='%') return 1; return 0; }} /************************************************************************/ void push(int type, floattype data) {{ if(ip<*(int*)im) { *((int*)(im+ip))=type; if(type==OPERATOR) { *((int*)(im+ip))=ADDRESS; switch((int)data) { case SUM: { *(pf*)(im+ip+1)=zz_sum; break; } case SUB: { *(pf*)(im+ip+1)=zz_sub; break; } case MUL: { *(pf*)(im+ip+1)=zz_mul; break; } case DIV: { *(pf*)(im+ip+1)=zz_div; break; } case MOD: { *(pf*)(im+ip+1)=zz_mod; break; } case POW: { *(pf*)(im+ip+1)=zz_pow; break; } case NEG: { *(pf*)(im+ip+1)=zz_neg; break; } } ip+=2; return; } if(type==ARGUMENT) *(int*)(im+ip+1)=(int)data; else im[ip+1]=data; ip+=2; } else { ip+=2; pushsuccess=0; } }} /************************************************************************/ int inline getaddress(const char *fn, const char *last) {{ static int i,k,hm; for(i=0;i=0;i--) if(f[i]==')') { c1=f+i; break; } while(1) { if(n0==0) //,,,,,,,,,, { k1=k2=k3=0; for(i=p;i>nr;i--) { if(f[i]==')') { count=1; for(i--;i>0;i--) { if(f[i]==')') { count++; continue; } if(f[i]=='(')count--; if(count==0)break; } continue; } if(f[i]==',') { n0=i; if(n0>nr)nr=i; goto label0; } if(k1)continue; if(f[i]=='+') if((i<2)|| ((f[i-1]!='e')&&(f[i-1]!='E')&&(f[i-1]!='d')&&(f[i-1]!='D'))|| (!isdigit(f[i-2]))&&(f[i-2]!='.')) { count=i-1; while(isspace(f[count])&&count>0)count--; if(isoperator(f[count])||isspace(f[count])) continue; k1=SUM; n1=i; continue; } if(f[i]=='-') if((i<2)|| ((f[i-1]!='e')&&(f[i-1]!='E')&&(f[i-1]!='d')&&(f[i-1]!='D'))|| (!isdigit(f[i-2]))&&(f[i-2]!='.')) { count=i-1; while(isspace(f[count])&&count>0)count--; if(isoperator(f[count])||isspace(f[count])) continue; k1=SUB; n1=i; continue; } if(k2)continue; if(f[i]=='*') { k2=MUL; n2=i; continue; } if(f[i]=='/') { k2=DIV; n2=i; continue; } if(f[i]=='%') { k2=MOD; n2=i; continue; } if(k3)continue; if(f[i]=='^') { k3=POW; n3=i; continue; } } if(i==0)n0=-1; label0: if(k1)push(OPERATOR,k1); if(k2)push(OPERATOR,k2); if(k3)push(OPERATOR,k3); if(n3>nr)nr=n3; else if(n2>nr)nr=n2; else if(n1>nr)nr=n1; } else if(n1==0) //++++++++++++ ------------ { k2=k3=0; for(i=p;i>nr;i--) { if(f[i]==')') { count=1; for(i--;i>0;i--) { if(f[i]==')') { count++; continue; } if(f[i]=='(')count--; if(count==0)break; } continue; } if(f[i]=='+') if((i<2)|| ((f[i-1]!='e')&&(f[i-1]!='E')&&(f[i-1]!='d')&&(f[i-1]!='D'))|| (!isdigit(f[i-2]))&&(f[i-2]!='.')) { count=i-1; while(isspace(f[count])&&count>0)count--; if(isoperator(f[count])||isspace(f[count])) continue; push(OPERATOR,SUM); n1=i; if(n1>nr)nr=i; goto label1; } if(f[i]=='-') if((i<2)|| ((f[i-1]!='e')&&(f[i-1]!='E')&&(f[i-1]!='d')&&(f[i-1]!='D'))|| (!isdigit(f[i-2]))&&(f[i-2]!='.')) { count=i-1; while(isspace(f[count])&&count>0)count--; if(isoperator(f[count])||isspace(f[count])) continue; push(OPERATOR,SUB); n1=i; if(n1>nr)nr=i; goto label1; } if(k2)continue; if(f[i]=='*') { k2=MUL; n2=i; continue; } if(f[i]=='/') { k2=DIV; n2=i; continue; } if(f[i]=='%') { k2=MOD; n2=i; continue; } if(k3)continue; if(f[i]=='^') { k3=POW; n3=i; continue; } } if(i==0)n1=-1; label1:; if(k2)push(OPERATOR,k2); if(k3)push(OPERATOR,k3); if(n3>nr)nr=n3; else if(n2>nr)nr=n2; } else if(n2==0) //********** ////////// %%%%%%%%%% { k3=0; for(i=p;i>nr;i--) { if(f[i]==')') { count=1; for(i--;i>0;i--) { if(f[i]==')') { count++; continue; } if(f[i]=='(')count--; if(count==0)break; } continue; } if(f[i]=='*') { push(OPERATOR,MUL); n2=i; if(n2>nr)nr=i; goto label2; } if(f[i]=='/') { push(OPERATOR,DIV); n2=i; if(n2>nr)nr=i; goto label2; } if(f[i]=='%') { push(OPERATOR,MOD); n2=i; if(n2>nr)nr=i; goto label2; } if(k3)continue; if(f[i]=='^') { k3=POW; n3=i; continue; } } if(i==0)n2=-1; label2:; if(k3)push(OPERATOR,k3); if(n3>nr)nr=n3; } else if(n3==0) //^^^^^^^^^^ for(i=p;i>nr;i--) { if(f[i]==')') { count=1; for(i--;i>0;i--) { if(f[i]==')') { count++; continue; } if(f[i]=='(')count--; if(count==0)break; } continue; } if(f[i]=='^') { push(OPERATOR,POW); n3=i; if(n3>nr)nr=i; break; } } if(c1>f+nr) //parentheses processing { count=1; commas=0; i=c1-f+1; while(isspace(f[i]))i++; if(i!=last-f) { error2("Must be an operator after ) before ",c1+1,last-c1-1); errorpos=c1+1; buildresult=EE_SYNTAXERROR; return buildresult; } for(i=c1-f-1;i>=0;i--) { if(f[i]==')') { count++; continue; } if(f[i]==','&&count==1) { commas++; continue; } if(f[i]=='(') count--; if(count==0) { if(nr==0)ch=f; else ch=f+nr+1; while(isspace(*ch))ch++; if(ch[0]=='-') { push(OPERATOR,NEG); ch++; } else if(ch[0]=='+') ch++; while(isspace(*ch))ch++; if(ch!=f+i) { func=getaddress(ch,f+i); if(func!=-1) { if(commas!=fdb[func].commas) { error2("Wrong number of arguments in ",ch,i-(ch-f)); errorpos=ch; buildresult=EE_WRONGARGUMENTS; return buildresult; } *(pf*)(&ft)=fdb[func].fn; push(ADDRESS,ft); } else { error2("Unknown function: ",ch,i-(ch-f)); errorpos=ch; buildresult=EE_UNKNOWNFUNCTION; return buildresult; } } else if(commas!=0) { error("Wrong comma within these parentheses."); errorpos=f+i+1; buildresult=EE_SYNTAXERROR; return buildresult; } if(buildimage(f+i+1,c1-f-2-i)!=EE_OK)return buildresult; break; } } if(count!=0) { error("Unpaired parenthesis!"); buildresult=EE_UNPAIRED; return buildresult; } if(nr==0)break; p=nr-1; c1=NULL; for(i=p;i>0;i--) if(f[i]==')') { c1=f+i; break; } last=f+nr; if(n1==nr) { n1=0; nr=max3(n0,n2,n3); continue; } if(n2==nr) { n2=0; nr=max3(n0,n1,n3); continue; } if(n3==nr) { n3=0; nr=max3(n0,n1,n2); if(nr<0)nr=0; continue; } if(n0==nr) { n0=0; nr=max3(n1,n2,n3); continue; } } else { if(nr==0) ch=f; else(ch=f+nr+1); if(read(ch,last,&ft)) { if(_finite(ft)) push(NUMBER,ft); else { error2("Number is too big: ",ch,last-ch); errorpos=ch; buildresult=EE_SYNTAXERROR; return buildresult; } } else { while(isspace(*ch))ch++; if(ch[0]=='-') { push(OPERATOR,NEG); ch++; } else if(ch[0]=='+') ch++; while(isspace(*ch))ch++; if(chtype) { case _DOMAIN: { error2("DOMAIN ERROR in ",except->name,10); return 1; } case _SING: { error2("SINGULARITY in ",except->name,10); return 1; } case _OVERFLOW: { error2("OVERFLOW in ",except->name,10); return 1; } case _TLOSS: { error2("TOTAL LOSS OF PRECISION in ",except->name,10); return 1; } case _PLOSS: { error2("PARTIAL LOSS OF PRECISION in ",except->name,10); return 1; } } return 0; }} /************************************************************************/ int inline test(floattype *ima) {{ int i,size; sp=9; size=*(int*)ima/(sizeof(floattype)*2)*2; for(i=2;istacksize+8) return 0; } if(sp!=10) return 0; return 1; }} /************************************************************************/ int inline simlifybeginning(void *image) {{ int i,k,size,con,t,firstsize; floattype *ima; ima=(floattype*)image; firstsize=*(int*)ima; size=*(int*)ima/sizeof(floattype)-2; con=0; sp=-1; for(i=2;i<=size;i+=2) { t=*(int*)(ima+i); if(t==ADDRESS) (*(pf*)(ima+i+1))(); else { sp++; if(t==NUMBER) stack[sp]=ima[i+1]; else //ARGUMENT { con=1; break; } } } if(con==0) { *(int*)ima=4*sizeof(floattype); *(int*)(ima+2)=NUMBER; ima[3]=*stack; return firstsize-*(int*)ima; } else { k=2; for(t=0;t<=sp-1;t++) { *(int*)(ima+k)=NUMBER; ima[k+1]=stack[t]; k+=2; } for(;i<=size+1;i++) { ima[k]=ima[i]; k++; } *(int*)ima=k*sizeof(floattype); return firstsize-*(int*)ima; } }} /************************************************************************/ int getcommas(floattype ft) {{ int i; for(i=0;i=2) if(*(int*)(ima+i)==NUMBER && *(int*)(ima+i+2)==ADDRESS) if(getcommas(ima[i+3])==0) { stack[0]=ima[i+1]; sp=0; (*(pf*)(ima+i+3))(); ima[i+1]=stack[0]; memmove(ima+i+2,ima+i+4,(last-i-2)*sizeof(floattype)); last-=2; } *(int*)ima-=(firstlast-last)*sizeof(floattype); return (firstlast-last)*sizeof(floattype); }} /************************************************************************/ int inline simplifysums(void *image) {{ int i,last,firstlast; floattype *ima; ima=(floattype*)image; last=*(int*)ima/sizeof(floattype)-2; firstlast=last; for(i=2;i<=last-6;i+=2) if(*(int*)(ima+i)==NUMBER && *(int*)(ima+i+2)==ADDRESS && *(int*)(ima+i+4)==NUMBER && *(int*)(ima+i+6)==ADDRESS) { if(*(pf*)(ima+i+3)==zz_sum && *(pf*)(ima+i+7)==zz_sum|| *(pf*)(ima+i+3)==zz_sub && *(pf*)(ima+i+7)==zz_sub) { ima[i+1]+=ima[i+5]; memmove(ima+i+4,ima+i+8,(last-i-6)*sizeof(floattype)); last-=4; i-=2; continue; } if(*(pf*)(ima+i+3)==zz_sum && *(pf*)(ima+i+7)==zz_sub|| *(pf*)(ima+i+3)==zz_sub && *(pf*)(ima+i+7)==zz_sum) { ima[i+1]-=ima[i+5]; memmove(ima+i+4,ima+i+8,(last-i-6)*sizeof(floattype)); last-=4; i-=2; continue; } if(*(pf*)(ima+i+3)==zz_mul && *(pf*)(ima+i+7)==zz_mul|| *(pf*)(ima+i+3)==zz_div && *(pf*)(ima+i+7)==zz_div|| *(pf*)(ima+i+3)==zz_pow && *(pf*)(ima+i+7)==zz_pow) { ima[i+1]*=ima[i+5]; memmove(ima+i+4,ima+i+8,(last-i-6)*sizeof(floattype)); last-=4; i-=2; continue; } if(*(pf*)(ima+i+3)==zz_mul && *(pf*)(ima+i+7)==zz_div|| *(pf*)(ima+i+3)==zz_div && *(pf*)(ima+i+7)==zz_mul) { ima[i+1]/=ima[i+5]; memmove(ima+i+4,ima+i+8,(last-i-6)*sizeof(floattype)); last-=4; i-=2; continue; } } *(int*)ima-=(firstlast-last)*sizeof(floattype); return (firstlast-last)*sizeof(floattype); }} /************************************************************************/ int MakeImage(void *image, int size, const char *formula, char *errorstring, int *errorposition, const char* argnames) {{ int i; usererror=errorstring; if(usererror!=NULL) *usererror=0; errorpos=NULL; if(errorposition!=NULL)*errorposition=-1; buildresult=EE_OK; i=0; noa=0; if(argnames!=NULL) while(noa