diff options
| author | Franklin Wei <me@fwei.tk> | 2018-05-19 22:25:33 -0400 |
|---|---|---|
| committer | Franklin Wei <me@fwei.tk> | 2018-05-19 22:25:33 -0400 |
| commit | 91edb3a29c403c689c4fcc3c5d3890ce9e2ee056 (patch) | |
| tree | 89ac06bb085bea7cd128aab76d1e7f5ff5507f11 | |
| parent | 5abd87353784e6afb5ee232bd9ab1cec6192b19a (diff) | |
| download | yacas-91edb3a29c403c689c4fcc3c5d3890ce9e2ee056.zip yacas-91edb3a29c403c689c4fcc3c5d3890ce9e2ee056.tar.gz yacas-91edb3a29c403c689c4fcc3c5d3890ce9e2ee056.tar.bz2 yacas-91edb3a29c403c689c4fcc3c5d3890ce9e2ee056.tar.xz | |
make more robust
| -rw-r--r-- | yacas.c | 71 |
1 files changed, 70 insertions, 1 deletions
@@ -1,3 +1,68 @@ +/* + * Franklin Wei + * 19 May 2018 + * Northwest Guilford High School + * yaCAS - "Yet Another Computer Algebra System" + * + * This is a program to manipulate algebraic expressions. It features + * a way of representing arbitrary expressions in memory, a parser to + * convert to and from standard mathematical notation, and functions + * to simplify, differentiate, and integrate such + * expressions. Additionally, it can function as a simple numerical + * calculator. + * + * Expressions are represented by an abstract syntax tree, a node of + * which is represented by a "struct expression" object (see + * definition below). Expressions are passed by reference to most + * functions, but most functions will allocate an entirely new + * expression tree to return their results. This results in a not + * insignificant amount of overhead as memory allocations and frees + * take place, but also greatly simplifies the memory model. + * + * Variables are supported through a simple hash map. Strings are + * mapped to expression trees through the "struct variable" object, + * and the expression trees are then substituted into the computation + * as needed. There is a special variable called . that stores the + * result of the previous computation. + * + * Differentiation is performed recursively on the expression + * tree. The differentiation of most expressions is performed by + * recursing down the tree, applying the basic rules of + * differentiation to combine the derivatives of child nodes. See the + * "diff" function for implementation. + * + * The expression parser is rather limited when it comes to + * tokenization. In its current form, it relies on tokens in the + * expression, say, "x ^ 2", being separated with spaces. That is, + * typing an expression like "x^2", without spaces between tokens, + * will result in undesired behavior (in this case, the parser wil + * view the token "x^2" as a variable name, not an expression). Just + * be sure to always separate tokens with a space, and all will be + * well. + * + * Finally, when using the exponential function, the form "exp ( x )" + * is preferred over "e ^ x", since the parser will recognize exp() as + * a special function and know about its special properties, while e^x + * will be treated as some constant raised to a power, without the + * special features of the exp() being recognized. + * + * Please note that this is a work in progress. The simplification, + * equality checking, and integration algorithms used are rudimentary + * at best, although differentiation should be relatively robust. + * + * Usage instructions: compile with no optimization, as this may cause + * undefined behavior, and link with -lm and -lreadline: + * + * cc -O0 yacas.c -o yacas -lm -lreadline + * + * Then run with no arguments and you should be presented with a + * "yaCAS> " prompt. From here, you can type "help" at the command + * line for an overview of the basic syntax. + * + * Readline can be disabled by commenting out the #define below (in + * which case the getline() function will be used instead): + */ + #define USE_READLINE #include <assert.h> @@ -5,8 +70,8 @@ #include <math.h> #include <setjmp.h> #include <stdbool.h> -#include <stdio.h> #include <stdint.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> @@ -18,6 +83,8 @@ #endif /* tool for manipulating algebraic expressions */ + +/* packed to save memory with large expressions */ struct expression { char type; /* T_* */ union { @@ -747,6 +814,7 @@ struct expression *eval_expr(struct expression *expr) case T_CONST: return new_const(expr->constant); case T_VAR: + /* this could fail upon a circular reference */ if(is_var(expr->varname)) return eval_expr(getvar(expr->varname)); @@ -1648,6 +1716,7 @@ int main(int argc, char *argv[]) setvar("pi", new_const(M_PI), true); setvar("e", new_const(M_E), true); setvar("memdiag", new_const(0), false); + setvar(".", new_const(0), false); while(1) { |