home *** CD-ROM | disk | FTP | other *** search
- /* FORMULC.DOC as of 8/21/94 (v2.1) */
- /* Copyright (c) 1994 Harald Helfgott (E-MAIL: seiere@uwyo.edu) */
- /* This file must be distributed with its corresponding
- README.DOC. You should read it, for you will find my regular
- address and the copyright and availability information there. */
-
- Overview of the FORMULC 2.0 functions
- -------- -- --- ------- --- ---------
-
-
- The FORMULC set of functions is written in ANSI C. It has
- been tested in a 386SX running GNU CC (DJGPP 1.11), in another
- 386SX running Turbo C++ v3.0 and in a VAX/VMS, but it will probably
- run in any machine with an ANSI C compiler. The functions enable
- the user of a C program to enter mathematical functions and to
- evaluate them very rapidly. This project was undertaken for the
- Finite Elements Laboratory of the School of Mathematics in the
- Universidad Mayor de San Marcos, Lima, Peru.
-
- Any programmer who handles mathematical problems must
- sometimes require the users of his or her programs to enter a
- mathematical function by the keyboard. Embedding the function in
- the program is time-consuming and not user friendly. Consequently,
- there is a large number of programs in C and Pascal that parse
- strings representing mathematical formulas. In fact, most good
- Pascal and C books have a more or less inchoate parser. However,
- all the formula interpreters I have seen are extremely slow.
-
- On May 1993, a mathematics professor in Lima, Peru asked me
- whether I could write a quick formula interpreter. His program
- needed to compute a formula entered by the user hundreds of
- thousands of times. I decided, therefore, to write a two-stage
- interpreter. First, a string containing a mathematical function is
- translated into another string in a postfix format. Every formula
- goes through this stage once. Then, the string in postfix format is
- interpreted whenever one wants to evaluate the mathematical
- function. Since this string's structure makes the use of a stack
- rapid, lacks white space and has additional characters to ensure
- that the computer understands the formula swiftly, interpretation
- is little time consuming. Although extra space is needed for the
- intermediate string, the velocity of the two-stage method
- compensates the space overhead.
-
- The FORMULC routines are easy to use. They are all in one
- file, FORMULC.C; one only needs to type
- #include "formula.h"
- and to link FORMULC with one's program to use the functions.
- There are no initialization routines. There are utilities that
- describe and extend the types of expressions that the formula
- interpreter can understand. Moreover, I expect the program to be
- error free and resistant to the human fallibility of the users.
-
-
- Please read TIME.DOC to know about the velocity of my formula
- interpreter. My address, the instructions for reporting bugs, the
- statement of what you are allowed to do with the program and the
- registration information are in README.DOC.
-
-
- Description of the functions
- ----------- -- --- ---------
-
- unsigned char *translate(char *source, char *args, int *length,
- int *error);
-
- Examples:
- f = translate("x^2 + sin(3*x) + 0.1", "x", plength, perror);
-
- f = translate("1E+5 * x/x \n", "x", plength, perror);
-
- gets(gsource);
- g=translate(gsource, "xyz", plength, perror);
- /* g is a function of x, y and z */
-
- This function transforms a legible mathematical function in
- string source[] into a coded function which is returned. The
- arguments of source are in string arg[]; they must be lower-case
- letters. If source uses an undeclared argument, translate stops
- coding and returns the index of the argument in *error. In fact,
- if any error occurs, *error contains an approximation of the index
- of the character in source[] that causes the error, *length acquires
- the value 0 and translate returns NULL. However, if source[] contains
- a valid mathematical function, the transformation occurs, *length
- contains the length of function[] (not including the final \0) and
- *error contains -1.
-
- The result string is dynamically allocated. It is likely to be
- far larger than source[]. If it does not fit in memory, or if any other
- out-of-memory error occurs, translate returns NULL, but *error contains
- -1. The result string can always be deallocated using free().
-
- source[] | Length of function[]
- | (VMS 5.5 CC)
- |
- "4", "4.0" or "4.0E-3" | 9 chars
- "x" | 2 chars
- "(x+3)^2" | 22 chars
- "(x+3)*(x+3)" | 25 chars
- "atan2(x^2,sqrt(x)-x))" | 21 chars
- "acos(cos(x)-x)" | 9 chars
-
-
- The syntax of source is the following one (in Extended
- Backus-Naur Form):
-
- source = expression "\0"
- expression = [-] summand {("+" | "-") summand}
- summand = factor {("*" | "/") factor}
- /*Please, don't forget "*" ! */
- factor = base {"^" base}
- base = "(" expression ")" | function "(" expression ")" |
- number | parameter
- function = a string in the function table
- parameter = a lower-case letter mentioned by arg[]
- number = any nonnegative number /* the sign is considered in
- the definition of expression */
- /* please write 3.5E-3, not 3.5e-3 */
-
- This description of the syntax mimics the algorithm in
- translate(...). It must be noticed that -3+5*6 and 3+5*(-6) are
- allowed, but 3+5*-6 and 3+-5*6 are not. Moreover, following standard
- C notation, -x^2 and -6^2 mean (-x)^2 and (-6)^2, the unary minus
- operator having higher precedence than the power operator.
-
- White space is ignored. Moreover, translate(...) is not case-
- sensitive.
-
- translate(...) works recursively. First, it locates the
- operator with the lowest order of precedence. Then, it calls
- itself to translate each operand. Thereafter, it adds the operator
- at the end and stops. If both operands are constants, translate
- executes fval to evaluate the expression at "compile time". (Beware
- of overflows! They can be perceived by the standard methods.) If
- there is no operator, translate(...) checks whether its input is
- a variable or a constant. If the input is invalid, translate(...)
- points out the error. Otherwise, *error contains -1.
-
- The coded function in string function uses postfix notation.
- The syntax is the following one:
-
- coded function = ce "\0"
- ce = ("" | ce | (ce ce) | (ce ce ce) ) operator |
- parameter | number
- parameter = "V" lower-case letter
- number = "D" any real number in double format
- operator = "^" | "+" | "*" | "-" | "/" | "M" /*i.e. unary minus */
-
- | function
- /*each operand has a characteristic number of operands
- (i.e. ce's) */
-
- function = "F" index of a function in the table (one char)
- /* Be careful! The index may be represented as \0 */
- /* Trust only the result of translate when finding */
- /* out the length of the coded function. */
- /* Since there can be more than 128 functions, */
- /* please declare function[] as an array of unsigned */
- /* char */
- No blanks exist.
- The standard functions are exp(), ln(x), sin(), cos(), tan(),
- asin(), acos(), atan(), abs(), pi() (without parameters inside the
- brackets) and sqrt(). One can add new functions by using fnew(..);
- the name of each function obeys C regulations but can be as long as
- needed. If a new function is used, fnew(..) must be called in the
- same run as translate(..); one must not call fnew, translate a
- function, store the coded function and call a program that uses
- fnew(..) and loads the coded function. Moreover, no random-number
- generator should be added with fnew.
-
- double fval(unsigned char *function, char *args, ...);
- Examples:
-
- translate(f,"x^2+sin(cos(x))","x");
- result=fval(f,"x",3.0); /* 3.0, not 3 */
- /* returns 3^2+sin(cos(3)) */
-
-
- translate(g,"n*m","nm");
- for(p=0; p<100; p++)
- for(q=0; q<1000; q++)
- a[p][q]=fval(g,"nm",(double) p,(double) q);
- /* the arguments must always be double */
-
- fval(...) calculates the value of a coded mathematical function
- in string function[] when the arguments, whose names are in string
- args[], are given. If there are not enough parameters or if the
- parameters don't belong to the function, the result is undefined.
- If there are any mathematical errors such as trying to obtain the
- square root of -5, errno is EDOM (domain error) or ERANGE (range
- error), the results are Infinity and Not-A-Number, or the program
- stops, depending on the compiler and how you use it.
-
- double f_x_val(unsigned char *function, double x);
-
- Examples:
- result=f_x_val(f,3); /* calculates f(3) if f is a function
- of x */
-
- A shorthand version of fval(..) for functions of x. It is
- about as rapid as fval(..) .
-
- int fnew(char *name, void *f, int n_pars);
-
- Examples:
-
- fnew("sinh",(void *) sinh,1); /* sinh has been declared as
- double sinh(double); */
- /* The (void *) cast is necessary
- only if you use C++ */
- fnew("logb",(void *)logb,2); /* logb has been declared as
- double logb(double, double); */
-
- fnew(...) adds a user-defined C function with double parameters
- to the library of FORMULA. The C function can have from 0 to 3
- parameters. fnew(...) returns 0 if the library is full (255
- functions) or if other error occurs. Otherwise, it returns 1.
-
- Please, do not call any function 'E' !
-
- int read_table(int i, char *name, int *n_of_pars);
-
- Example:
- i=0;
- while(read_table(i++, name, &n_pars)
- printf("%s %d",name,n_pars);
-
- read_table copies the name and the number of parameters of
- function #i onto name[] and *n_of_pars. If function #i does not
- exist, read_table returns 0. Otherwise, it returns a positive
- number.
- int where_table(char *name);
-
- Example:
- if(where_table("sinh") == -1)
- printf("Hyperbolic sine not defined.");
-
- If there is a mathematical function called name[],
- where_table(..) returns its index in the table of functions.
- Otherwise, where_table(..) returns -1. Use fnew(..) to define
- mathematical functions which are not in FORMULA's standard
- library.
-
- int fdel(char *name);
-
- Example:
- if(where_table("sinh" != -1)
- fdel("sinh");
-
- If there is a mathematical function called name[], fdel deletes
- it. If fdel is succesful, it returns a non-negative number;
- otherwise, it returns -1.