/* ** ** FUNCS.C A module to be included with EVAL.C that handles ** the manipulation of functions. ** ** Originally written 5/89 in ANSI C ** ** To add/change the functions in Eval: ** -------------------------------------------------------------- ** 1. If the name of your function is longer than MAXFLEN, or the ** argument list string is longer than MAXALEN, then increase the ** size of these defines (MAXFLEN in eval.h, MAXALEN in funcs.c). ** 1. Update the value of NUMFUNCS in eval.h (total number of functions). ** 2. Add a #define for any new functions to the list of #defines ** below. You do not need to keep the list in alphabetic order. ** 3. Add the function ID (#define tag), name, argument list, and a ** brief descripton to the flist[] array below. Please keep the list ** in alphabetic order by function name. ** 4. Add the actual function code to the func_eval function below. ** Follow the examples of other functions. ** 5. If necessary, add the C-code for new math functions to emath.c, ** and add prototypes for new C math functions to eval.h ** NOTICE: Read the disclaimer about adding code to emath.c in ** the comments of emath.c. ** 6. Recompile ALL modules. ** ** ** Eval is a floating point expression evaluator. ** This file last updated in version 1.12 ** For the version number, see eval.h ** Copyright (C) 1993 Will Menninger ** ** This program is free software; you can redistribute it and/or modify it ** under the terms of the GNU General Public License as published by the ** Free Software Foundation; either version 2 of the License, or any ** later version. ** ** This program is distributed in the hope that it will be useful, but ** WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** ** You should have received a copy of the GNU General Public License along ** with this program; if not, write to the Free Software Foundation, Inc., ** 675 Mass Ave, Cambridge, MA 02139, USA. ** ** The author until 9/93 can be contacted at: ** e-mail: willus@ilm.pfc.mit.edu ** U.S. mail: Will Menninger, 45 River St., #2, Boston, MA 02108-1124 ** */ #include "eval.h" #define ABSVAL 1 #define ACOS 2 #define ACOSH 3 #define ASIN 4 #define ASINH 5 #define ATAN 6 #define ATAN2 7 #define ATANH 8 #define BESSI 9 #define BESSJ 10 #define BESSK 11 #define CEIL 12 #define COS 13 #define COSH 14 #define DBESSI 15 #define DBESSJ 16 #define DBESSK 17 #define DJROOT 18 #define EXP 19 #define FACT 20 #define FLOOR 21 #define JROOT 22 #define LN 23 #define LOG 24 #define SIGN 25 #define SIN 26 #define SINH 27 #define SQRT 28 #define TAN 29 #define TANH 30 FUNC flist[NUMFUNCS] = { {ABSVAL,"abs", "x", "absolute value" }, {ACOS, "acos", "x", "arccosine, return value in radians" }, {ACOSH, "acosh", "x", "inverse hyperbolic cosine" }, {ASIN, "asin", "x", "arcsine, return value in radians" }, {ASINH, "asinh", "x", "inverse hyperbolic sine" }, {ATAN, "atan", "x", "arctangent, return value in radians" }, {ATAN2, "atan2", "y,x","arctangent of y/x, return value in radians" }, {ATANH, "atanh", "x", "inverse hyperbolic tangent" }, {BESSI, "bessi", "m,x","bessel function Im(x)" }, {BESSJ, "bessj", "m,x","bessel function Jm(x)" }, {BESSK, "bessk", "m,x","bessel function Km(x)" }, {CEIL, "ceil", "x", "round up" }, {COS, "cos", "x", "cosine, x in radians" }, {COSH, "cosh", "x", "hyperbolic cosine" }, {DBESSI,"dbessi", "m,x","derivative of bessel function: Im'(x)" }, {DBESSJ,"dbessj", "m,x","derivative of bessel function: Jm'(x)" }, {DBESSK,"dbessk", "m,x","derivative of bessel function: Km'(x)" }, {DJROOT,"djroot", "m,n","nth non-zero root of Jm'(x)" }, {EXP, "exp", "x", "e (2.718..) raised to the power of x" }, {FACT, "fact", "n", "factorial (n!)" }, {FLOOR, "floor", "x", "round down" }, {JROOT, "jroot", "m,n","nth non-zero root of Jm(x)" }, {LN, "ln", "x", "natural logarithm (base e)" }, {LOG, "log", "x", "logarithm to the base 10" }, {SIGN, "sgn", "x", "-1 if x<0, 0 if x=0, +1 if x>0" }, {SIN, "sin", "x", "sine, x in radians" }, {SINH, "sinh", "x", "hyperbolic sine" }, {SQRT, "sqrt", "x", "squareroot" }, {TAN, "tan", "x", "tangent, x in radians" }, {TANH, "tanh", "x", "hyperbolic tangent" } }; static BOOLEAN func_error(int,int); static int maxfunclen(FUNCPTR); /* ** print_funclist(FILE *s,char *input,int d) ** ** Prints a list of the functions ** */ int print_funclist(FILE *s,char *input,int d) { char line[MAXALEN+MAXFLEN+MAXDLEN+10]; int i,j,k,l,n,m1,nc,cw,nr,li,c; m1=maxfunclen(flist)+2; cw=m1+2; if (d) nc=1; else { nc=(SCRWIDTH+3)/cw; if (nc<=0) nc=1; } nr=(NUMFUNCS+nc-1)/nc; for (i=0;i=NUMFUNCS) break; for (l=0;(c=flist[k].name[l])!=EOS;l++) line[li++]=c; line[li++]='('; for (l++,n=l;(c=flist[k].argspec[l-n])!=EOS;l++) line[li++]=c; line[li++]=')'; for (l++;l for more...\n"); printf("%s",PROMPT); input[0]=EOS; fgets(input,MAXINPUT,s); fixup(input); if (input[0]!=EOS) return(1); printf("\n"); } } printf("\n"); return(0); } /* ** maxfunclen(FUNCPTR flist) ** ** returns the length of the longest function name plus arguments ** (used for printing) ** */ static int maxfunclen(FUNCPTR flist) { int i,len,max; for (max=strlen(flist[0].name)+strlen(flist[0].argspec),i=1;imax) max=len; return(max); } int func_code(char *s) { int i,step,c,count; i=step=NUMFUNCS>>1; count=0; while (1) { if (step>1) step>>=1; else { count++; if (count>5) break; } if (!(c=strcmp(s,flist[i].name))) return(i+1); if (c>0) { if (i==NUMFUNCS-1) break; i=i+step; continue; } if (i==0) break; i=i-step; } return(0); } int func_nargs(int code) { return((int)((strlen(flist[code-1].argspec)+1)/2)); } char *func_name(int code) { return(flist[code-1].name); } BOOLEAN func_eval(int code,double *args,double *ret_val) { switch (flist[code-1].id) { case ABSVAL: (*ret_val)=fabs(args[0]); return(1); case ACOS: if (args[0]<-1 || args[0]>1) return(func_error(code,0)); (*ret_val)=acos(args[0]); return(1); case ACOSH: if (args[0]<1) return(func_error(code,0)); (*ret_val)=acosh(args[0]); return(1); case ASIN: if (args[0]<-1 || args[0]>1) return(func_error(code,0)); (*ret_val)=asin(args[0]); return(1); case ASINH: (*ret_val)=asinh(args[0]); return(1); case ATAN: (*ret_val)=atan(args[0]); return(1); case ATAN2: (*ret_val)=atan2(args[0],args[1]); return(1); case ATANH: if (args[0]<=-1 || args[0]>=1) return(func_error(code,0)); (*ret_val)=atanh(args[0]); return(1); case BESSI: if (args[0]!=((int)args[0])) return(func_error(code,1)); (*ret_val)=bessi((int)args[0],args[1]); return(1); case BESSJ: if (args[0]!=((int)args[0])) return(func_error(code,1)); (*ret_val)=bessj((int)args[0],args[1]); return(1); case BESSK: if (args[0]!=((int)args[0])) return(func_error(code,1)); (*ret_val)=bessk((int)args[0],args[1]); return(1); case CEIL: (*ret_val)=ceil(args[0]); return(1); case COS: (*ret_val)=cos(args[0]); return(1); case COSH: (*ret_val)=cosh(args[0]); return(1); case DBESSI: if (args[0]!=((int)args[0])) return(func_error(code,1)); (*ret_val)=dbessi((int)args[0],args[1]); return(1); case DBESSJ: if (args[0]!=((int)args[0])) return(func_error(code,1)); (*ret_val)=dbessj((int)args[0],args[1]); return(1); case DBESSK: if (args[0]!=((int)args[0])) return(func_error(code,1)); (*ret_val)=dbessk((int)args[0],args[1]); return(1); case DJROOT: if (args[0]!=((int)args[0])) return(func_error(code,1)); if (args[1]!=((int)args[1]) || args[1]<1) return(func_error(code,2)); (*ret_val)=djroot((int)args[0],(int)args[1]); return(1); case EXP: (*ret_val)=exp(args[0]); return(1); case FACT: if (args[0]<0) return(func_error(code,5)); if (args[0]!=((int)args[0])) return(func_error(code,3)); (*ret_val)=factorial((int)args[0]); return(1); case FLOOR: (*ret_val)=floor(args[0]); return(1); case JROOT: if (args[0]!=((int)args[0])) return(func_error(code,1)); if (args[1]!=((int)args[1]) || args[1]<1) return(func_error(code,2)); (*ret_val)=jroot((int)args[0],(int)args[1]); return(1); case LN: if (args[0]<=0) return(func_error(code,4)); (*ret_val)=log(args[0]); return(1); case LOG: if (args[0]<=0) return(func_error(code,4)); (*ret_val)=log10(args[0]); return(1); case SIGN: (*ret_val)=SGN(args[0]); return(1); case SIN: (*ret_val)=sin(args[0]); return(1); case SINH: (*ret_val)=sinh(args[0]); return(1); case SQRT: if (args[0]<0) return(func_error(code,5)); (*ret_val)=sqrt(args[0]); return(1); case TAN: (*ret_val)=tan(args[0]); return(1); case TANH: (*ret_val)=tanh(args[0]); return(1); } printf("Unknown function code.\n"); return(0); } static BOOLEAN func_error(int code,int error) { static char *error_code[] = { "argument out of range", "first argument must be an integer", "second argument must be a positive integer", "argument must be an integer", "argument must be positive", "argument must be non-negative", }; printf("%s: %s.\n",flist[code-1].name,error_code[error]); return(0); }