3 ** FUNCS.C A module to be included with EVAL.C that handles
4 ** the manipulation of functions.
6 ** Originally written 5/89 in ANSI C
8 ** To add/change the functions in Eval:
9 ** --------------------------------------------------------------
10 ** 1. If the name of your function is longer than MAXFLEN, or the
11 ** argument list string is longer than MAXALEN, then increase the
12 ** size of these defines (MAXFLEN in eval.h, MAXALEN in funcs.c).
13 ** 1. Update the value of NUMFUNCS in eval.h (total number of functions).
14 ** 2. Add a #define for any new functions to the list of #defines
15 ** below. You do not need to keep the list in alphabetic order.
16 ** 3. Add the function ID (#define tag), name, argument list, and a
17 ** brief descripton to the flist[] array below. Please keep the list
18 ** in alphabetic order by function name.
19 ** 4. Add the actual function code to the func_eval function below.
20 ** Follow the examples of other functions.
21 ** 5. If necessary, add the C-code for new math functions to emath.c,
22 ** and add prototypes for new C math functions to eval.h
23 ** NOTICE: Read the disclaimer about adding code to emath.c in
24 ** the comments of emath.c.
25 ** 6. Recompile ALL modules.
28 ** Eval is a floating point expression evaluator.
29 ** This is version 1.12
30 ** Copyright (C) 1993 Will Menninger
32 ** This program is free software; you can redistribute it and/or modify it
33 ** under the terms of the GNU General Public License as published by the
34 ** Free Software Foundation; either version 2 of the License, or any
37 ** This program is distributed in the hope that it will be useful, but
38 ** WITHOUT ANY WARRANTY; without even the implied warranty of
39 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40 ** General Public License for more details.
42 ** You should have received a copy of the GNU General Public License along
43 ** with this program; if not, write to the Free Software Foundation, Inc.,
44 ** 675 Mass Ave, Cambridge, MA 02139, USA.
46 ** The author until 9/93 can be contacted at:
47 ** e-mail: willus@ilm.pfc.mit.edu
48 ** U.S. mail: Will Menninger, 45 River St., #2, Boston, MA 02108-1124
60 char argspec
[MAXALEN
+1];
95 static FUNC flist
[NUMFUNCS
] =
97 {ABSVAL
,"abs", "x", "absolute value" },
98 {ACOS
, "acos", "x", "arccosine, return value in radians" },
99 {ACOSH
, "acosh", "x", "inverse hyperbolic cosine" },
100 {ASIN
, "asin", "x", "arcsine, return value in radians" },
101 {ASINH
, "asinh", "x", "inverse hyperbolic sine" },
102 {ATAN
, "atan", "x", "arctangent, return value in radians" },
103 {ATAN2
, "atan2", "y,x","arctangent of y/x, return value in radians" },
104 {ATANH
, "atanh", "x", "inverse hyperbolic tangent" },
105 {BESSI
, "bessi", "m,x","bessel function Im(x)" },
106 {BESSJ
, "bessj", "m,x","bessel function Jm(x)" },
107 {BESSK
, "bessk", "m,x","bessel function Km(x)" },
108 {CEIL
, "ceil", "x", "round up" },
109 {COS
, "cos", "x", "cosine, x in radians" },
110 {COSH
, "cosh", "x", "hyperbolic cosine" },
111 {DBESSI
,"dbessi", "m,x","derivative of bessel function: Im'(x)" },
112 {DBESSJ
,"dbessj", "m,x","derivative of bessel function: Jm'(x)" },
113 {DBESSK
,"dbessk", "m,x","derivative of bessel function: Km'(x)" },
114 {DJROOT
,"djroot", "m,n","nth non-zero root of Jm'(x)" },
115 {EXP
, "exp", "x", "e (2.718..) raised to the power of x" },
116 {FACT
, "fact", "n", "factorial (n!)" },
117 {FLOOR
, "floor", "x", "round down" },
118 {JROOT
, "jroot", "m,n","nth non-zero root of Jm(x)" },
119 {LN
, "ln", "x", "natural logarithm (base e)" },
120 {LOG
, "log", "x", "logarithm to the base 10" },
121 {SIGN
, "sgn", "x", "-1 if x<0, 0 if x=0, +1 if x>0" },
122 {SIN
, "sin", "x", "sine, x in radians" },
123 {SINH
, "sinh", "x", "hyperbolic sine" },
124 {SQRT
, "sqrt", "x", "squareroot" },
125 {TAN
, "tan", "x", "tangent, x in radians" },
126 {TANH
, "tanh", "x", "hyperbolic tangent" }
130 static BOOLEAN
func_error(int,int);
131 static int maxfunclen(FUNCPTR
);
134 ** print_funclist(FILE *s,char *input,int d)
136 ** Prints a list of the functions
139 int print_funclist(FILE *s
,char *input
,int d
)
142 char line
[MAXALEN
+MAXFLEN
+MAXDLEN
+10];
143 int i
,j
,k
,l
,n
,m1
,nc
,cw
,nr
,li
,c
;
145 m1
=maxfunclen(flist
)+2;
155 nr
=(NUMFUNCS
+nc
-1)/nc
;
164 for (l
=0;(c
=flist
[k
].name
[l
])!=EOS
;l
++)
167 for (l
++,n
=l
;(c
=flist
[k
].argspec
[l
-n
])!=EOS
;l
++)
177 strcat(line
,flist
[k
].desc
);
187 if (s
==stdin
&& i
!=nr
-1 && ((i
+3)%NLINES
)==0)
189 printf("\nPress <ENTER> for more...\n");
192 fgets(input
,MAXINPUT
,s
);
205 ** maxfunclen(FUNCPTR flist)
207 ** returns the length of the longest function name plus arguments
208 ** (used for printing)
212 static int maxfunclen(FUNCPTR flist
)
217 for (max
=strlen(flist
[0].name
)+strlen(flist
[0].argspec
),i
=1;i
<NUMFUNCS
;i
++)
218 if ((len
=strlen(flist
[i
].name
)+strlen(flist
[i
].argspec
))>max
)
224 int func_code(char *s
)
241 if (!(c
=strcmp(s
,flist
[i
].name
)))
259 int func_nargs(int code
)
262 return((int)((strlen(flist
[code
-1].argspec
)+1)/2));
266 char *func_name(int code
)
269 return(flist
[code
-1].name
);
273 BOOLEAN
func_eval(int code
,double *args
,double *ret_val
)
276 switch (flist
[code
-1].id
)
279 (*ret_val
)=fabs(args
[0]);
282 if (args
[0]<-1 || args
[0]>1)
283 return(func_error(code
,0));
284 (*ret_val
)=acos(args
[0]);
288 return(func_error(code
,0));
289 (*ret_val
)=acosh(args
[0]);
292 if (args
[0]<-1 || args
[0]>1)
293 return(func_error(code
,0));
294 (*ret_val
)=asin(args
[0]);
297 (*ret_val
)=asinh(args
[0]);
300 (*ret_val
)=atan(args
[0]);
303 (*ret_val
)=atan2(args
[0],args
[1]);
306 if (args
[0]<=-1 || args
[0]>=1)
307 return(func_error(code
,0));
308 (*ret_val
)=atanh(args
[0]);
311 if (args
[0]!=((int)args
[0]))
312 return(func_error(code
,1));
313 (*ret_val
)=bessi((int)args
[0],args
[1]);
316 if (args
[0]!=((int)args
[0]))
317 return(func_error(code
,1));
318 (*ret_val
)=bessj((int)args
[0],args
[1]);
321 if (args
[0]!=((int)args
[0]))
322 return(func_error(code
,1));
323 (*ret_val
)=bessk((int)args
[0],args
[1]);
326 (*ret_val
)=ceil(args
[0]);
329 (*ret_val
)=cos(args
[0]);
332 (*ret_val
)=cosh(args
[0]);
335 if (args
[0]!=((int)args
[0]))
336 return(func_error(code
,1));
337 (*ret_val
)=dbessi((int)args
[0],args
[1]);
340 if (args
[0]!=((int)args
[0]))
341 return(func_error(code
,1));
342 (*ret_val
)=dbessj((int)args
[0],args
[1]);
345 if (args
[0]!=((int)args
[0]))
346 return(func_error(code
,1));
347 (*ret_val
)=dbessk((int)args
[0],args
[1]);
350 if (args
[0]!=((int)args
[0]))
351 return(func_error(code
,1));
352 if (args
[1]!=((int)args
[1]) || args
[1]<1)
353 return(func_error(code
,2));
354 (*ret_val
)=djroot((int)args
[0],(int)args
[1]);
357 (*ret_val
)=exp(args
[0]);
361 return(func_error(code
,5));
362 if (args
[0]!=((int)args
[0]))
363 return(func_error(code
,3));
364 (*ret_val
)=factorial((int)args
[0]);
367 (*ret_val
)=floor(args
[0]);
370 if (args
[0]!=((int)args
[0]))
371 return(func_error(code
,1));
372 if (args
[1]!=((int)args
[1]) || args
[1]<1)
373 return(func_error(code
,2));
374 (*ret_val
)=jroot((int)args
[0],(int)args
[1]);
378 return(func_error(code
,4));
379 (*ret_val
)=log(args
[0]);
383 return(func_error(code
,4));
384 (*ret_val
)=log10(args
[0]);
387 (*ret_val
)=SGN(args
[0]);
390 (*ret_val
)=sin(args
[0]);
393 (*ret_val
)=sinh(args
[0]);
397 return(func_error(code
,5));
398 (*ret_val
)=sqrt(args
[0]);
401 (*ret_val
)=tan(args
[0]);
404 (*ret_val
)=tanh(args
[0]);
407 printf("Unknown function code.\n");
412 static BOOLEAN
func_error(int code
,int error
)
415 static char *error_code
[] = {
416 "argument out of range",
417 "first argument must be an integer",
418 "second argument must be a positive integer",
419 "argument must be an integer",
420 "argument must be positive",
421 "argument must be non-negative",
423 printf("%s: %s.\n",flist
[code
-1].name
,error_code
[error
]);