eigenmath/eval.cpp

610 lines
10 KiB
C++
Raw Permalink Normal View History

2008-06-13 06:26:19 +02:00
// Evaluate an expression, for example...
//
// push(p1)
// eval()
// p2 = pop()
2007-07-21 23:48:01 +02:00
2004-03-03 21:24:06 +01:00
#include "stdafx.h"
#include "defs.h"
2005-10-27 23:18:32 +02:00
2006-01-04 03:30:50 +01:00
void
eval(void)
{
2006-10-09 21:13:45 +02:00
check_esc_flag();
2006-01-04 03:30:50 +01:00
save();
p1 = pop();
switch (p1->k) {
case CONS:
eval_cons();
break;
case NUM:
2006-10-11 23:26:01 +02:00
push(p1);
2006-01-04 03:30:50 +01:00
break;
case DOUBLE:
push(p1);
break;
case STR:
push(p1);
break;
case TENSOR:
eval_tensor();
break;
case SYM:
2006-05-06 01:27:26 +02:00
eval_sym();
2006-01-04 03:30:50 +01:00
break;
default:
2008-05-18 22:16:03 +02:00
stop("atom?");
2006-01-04 03:30:50 +01:00
break;
}
restore();
}
2006-05-06 01:27:26 +02:00
void
eval_sym(void)
{
// bare keyword?
2007-05-08 20:58:41 +02:00
if (iskeyword(p1)) {
2006-05-06 01:27:26 +02:00
push(p1);
push(symbol(LAST));
list(2);
eval();
return;
}
2008-06-09 01:14:21 +02:00
// evaluate symbol's binding
2008-05-18 21:34:03 +02:00
2008-05-18 20:28:56 +02:00
p2 = get_binding(p1);
2008-05-18 21:34:03 +02:00
push(p2);
2008-08-23 21:24:20 +02:00
if (p1 != p2)
eval();
2006-05-06 01:27:26 +02:00
}
2006-01-04 03:30:50 +01:00
void
eval_cons(void)
{
2008-05-18 22:16:03 +02:00
if (!issymbol(car(p1)))
stop("cons?");
2007-05-08 20:58:41 +02:00
switch (symnum(car(p1))) {
2006-01-04 03:30:50 +01:00
case ABS: eval_abs(); break;
case ADD: eval_add(); break;
case ADJ: eval_adj(); break;
case AND: eval_and(); break;
case ARCCOS: eval_arccos(); break;
case ARCCOSH: eval_arccosh(); break;
case ARCSIN: eval_arcsin(); break;
case ARCSINH: eval_arcsinh(); break;
case ARCTAN: eval_arctan(); break;
case ARCTANH: eval_arctanh(); break;
case ARG: eval_arg(); break;
case BESSELJ: eval_besselj(); break;
case BESSELY: eval_bessely(); break;
2008-08-10 21:06:41 +02:00
case BINDING: eval_binding(); break;
2006-01-04 03:30:50 +01:00
case BINOMIAL: eval_binomial(); break;
case CEILING: eval_ceiling(); break;
case CHECK: eval_check(); break;
2006-10-13 17:43:11 +02:00
case CHOOSE: eval_choose(); break;
2006-05-06 01:27:26 +02:00
case CIRCEXP: eval_circexp(); break;
2006-01-04 03:30:50 +01:00
case CLEAR: eval_clear(); break;
2007-05-09 02:06:24 +02:00
case CLOCK: eval_clock(); break;
2006-01-04 03:30:50 +01:00
case COEFF: eval_coeff(); break;
2006-01-06 04:13:23 +01:00
case COFACTOR: eval_cofactor(); break;
2006-01-04 03:30:50 +01:00
case CONDENSE: eval_condense(); break;
case CONJ: eval_conj(); break;
case CONTRACT: eval_contract(); break;
case COS: eval_cos(); break;
case COSH: eval_cosh(); break;
2006-05-12 22:17:48 +02:00
case DECOMP: eval_decomp(); break;
2006-01-04 03:30:50 +01:00
case DEGREE: eval_degree(); break;
2007-05-15 18:20:30 +02:00
case DEFINT: eval_defint(); break;
2006-01-04 03:30:50 +01:00
case DENOMINATOR: eval_denominator(); break;
case DERIVATIVE: eval_derivative(); break;
case DET: eval_det(); break;
case DIM: eval_dim(); break;
case DIRAC: eval_dirac(); break;
case DISPLAY: eval_display(); break;
case DIVISORS: eval_divisors(); break;
case DO: eval_do(); break;
case DOT: eval_inner(); break;
case DRAW: eval_draw(); break;
case DSOLVE: eval_dsolve(); break;
case EIGEN: eval_eigen(); break;
case EIGENVAL: eval_eigenval(); break;
case EIGENVEC: eval_eigenvec(); break;
case ERF: eval_erf(); break;
case ERFC: eval_erfc(); break;
case EVAL: eval_eval(); break;
case EXP: eval_exp(); break;
case EXPAND: eval_expand(); break;
case EXPCOS: eval_expcos(); break;
case EXPSIN: eval_expsin(); break;
case FACTOR: eval_factor(); break;
case FACTORIAL: eval_factorial(); break;
case FACTORPOLY: eval_factorpoly(); break;
case FILTER: eval_filter(); break;
case FLOATF: eval_float(); break;
case FLOOR: eval_floor(); break;
case FOR: eval_for(); break;
case GAMMA: eval_gamma(); break;
case GCD: eval_gcd(); break;
case HERMITE: eval_hermite(); break;
case HILBERT: eval_hilbert(); break;
case IMAG: eval_imag(); break;
case INDEX: eval_index(); break;
case INNER: eval_inner(); break;
case INTEGRAL: eval_integral(); break;
case INV: eval_inv(); break;
case INVG: eval_invg(); break;
case ISINTEGER: eval_isinteger(); break;
case ISPRIME: eval_isprime(); break;
case LAGUERRE: eval_laguerre(); break;
2008-08-23 22:30:37 +02:00
// case LAPLACE: eval_laplace(); break;
2006-01-04 03:30:50 +01:00
case LCM: eval_lcm(); break;
2008-05-03 07:23:17 +02:00
case LEADING: eval_leading(); break;
2006-01-04 03:30:50 +01:00
case LEGENDRE: eval_legendre(); break;
case LOG: eval_log(); break;
case MAG: eval_mag(); break;
case MOD: eval_mod(); break;
case MULTIPLY: eval_multiply(); break;
case NOT: eval_not(); break;
2007-11-18 02:08:12 +01:00
case NROOTS: eval_nroots(); break;
2006-01-13 21:52:59 +01:00
case NUMBER: eval_number(); break;
2006-01-04 03:30:50 +01:00
case NUMERATOR: eval_numerator(); break;
case OPERATOR: eval_operator(); break;
case OR: eval_or(); break;
case OUTER: eval_outer(); break;
2006-02-10 20:24:36 +01:00
case POLAR: eval_polar(); break;
2006-01-04 03:30:50 +01:00
case POWER: eval_power(); break;
case PRIME: eval_prime(); break;
2007-07-21 21:53:56 +02:00
case PRINT: eval_display(); break;
2006-01-04 03:30:50 +01:00
case PRODUCT: eval_product(); break;
case QUOTE: eval_quote(); break;
2006-02-10 01:55:47 +01:00
case QUOTIENT: eval_quotient(); break;
2006-01-04 03:30:50 +01:00
case RANK: eval_rank(); break;
case RATIONALIZE: eval_rationalize(); break;
case REAL: eval_real(); break;
case YYRECT: eval_rect(); break;
case ROOTS: eval_roots(); break;
case SETQ: eval_setq(); break;
case SGN: eval_sgn(); break;
case SIMPLIFY: eval_simplify(); break;
case SIN: eval_sin(); break;
case SINH: eval_sinh(); break;
case SQRT: eval_sqrt(); break;
case STOP: eval_stop(); break;
case SUBST: eval_subst(); break;
case SUM: eval_sum(); break;
case TAN: eval_tan(); break;
case TANH: eval_tanh(); break;
case TAYLOR: eval_taylor(); break;
case TEST: eval_test(); break;
case TESTEQ: eval_testeq(); break;
case TESTGE: eval_testge(); break;
case TESTGT: eval_testgt(); break;
case TESTLE: eval_testle(); break;
case TESTLT: eval_testlt(); break;
case TRANSPOSE: eval_transpose(); break;
case UNIT: eval_unit(); break;
case ZERO: eval_zero(); break;
default: eval_user_function(); break;
}
}
2008-08-10 21:06:41 +02:00
void
eval_binding(void)
{
push(get_binding(cadr(p1)));
}
2006-01-11 00:30:19 +01:00
// checks a predicate, i.e. check(A = B)
2004-03-03 21:24:06 +01:00
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_check(void)
{
2005-09-02 21:41:19 +02:00
push(cadr(p1));
eval_predicate();
2004-03-03 21:24:06 +01:00
p1 = pop();
2006-01-11 00:30:19 +01:00
if (iszero(p1))
stop("check(arg): arg is zero");
2006-02-12 14:19:18 +01:00
push(symbol(NIL)); // no result is printed
2004-03-03 21:24:06 +01:00
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_det(void)
{
push(cadr(p1));
eval();
det();
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_dim(void)
{
int n;
push(cadr(p1));
eval();
p2 = pop();
if (iscons(cddr(p1))) {
push(caddr(p1));
eval();
n = pop_integer();
} else
n = 1;
2007-11-22 01:28:04 +01:00
if (!istensor(p2))
push_integer(1); // dim of scalar is 1
else if (n < 1 || n > p2->u.tensor->ndim)
2004-03-03 21:24:06 +01:00
push(p1);
else
push_integer(p2->u.tensor->dim[n - 1]);
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_divisors(void)
{
push(cadr(p1));
eval();
divisors();
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_do(void)
{
push(car(p1));
p1 = cdr(p1);
while (iscons(p1)) {
pop();
push(car(p1));
eval();
p1 = cdr(p1);
}
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_dsolve(void)
{
push(cadr(p1));
eval();
push(caddr(p1));
eval();
push(cadddr(p1));
eval();
dsolve();
}
2007-05-15 18:20:30 +02:00
// for example, eval(f,x,2)
2006-10-02 01:35:54 +02:00
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_eval(void)
{
push(cadr(p1));
eval();
2006-10-06 01:47:54 +02:00
p1 = cddr(p1);
while (iscons(p1)) {
push(car(p1));
2006-10-02 01:35:54 +02:00
eval();
2006-10-06 01:47:54 +02:00
push(cadr(p1));
2006-10-02 01:35:54 +02:00
eval();
2006-10-06 01:47:54 +02:00
subst();
2006-10-06 20:28:26 +02:00
p1 = cddr(p1);
2006-10-02 01:35:54 +02:00
}
2004-03-03 21:24:06 +01:00
eval();
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_exp(void)
{
push(cadr(p1));
eval();
exponential();
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_factorial(void)
{
push(cadr(p1));
eval();
factorial();
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_factorpoly(void)
{
p1 = cdr(p1);
push(car(p1));
eval();
p1 = cdr(p1);
push(car(p1));
eval();
factorpoly();
p1 = cdr(p1);
while (iscons(p1)) {
push(car(p1));
eval();
factorpoly();
p1 = cdr(p1);
}
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_hermite(void)
{
push(cadr(p1));
eval();
push(caddr(p1));
eval();
hermite();
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_hilbert(void)
{
push(cadr(p1));
eval();
hilbert();
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_index(void)
{
int h;
h = tos;
p1 = cdr(p1);
while (iscons(p1)) {
push(car(p1));
eval();
p1 = cdr(p1);
}
index_function(tos - h);
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_inv(void)
{
push(cadr(p1));
eval();
inv();
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_invg(void)
{
push(cadr(p1));
eval();
invg();
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_isinteger(void)
{
int n;
push(cadr(p1));
eval();
p1 = pop();
2005-08-06 22:57:37 +02:00
if (isrational(p1)) {
2004-03-03 21:24:06 +01:00
if (isinteger(p1))
2004-06-25 22:45:15 +02:00
push(one);
2004-03-03 21:24:06 +01:00
else
2004-06-25 22:45:15 +02:00
push(zero);
2004-03-03 21:24:06 +01:00
return;
}
2005-08-06 22:57:37 +02:00
if (isdouble(p1)) {
2004-03-03 21:24:06 +01:00
n = (int) p1->u.d;
if (n == p1->u.d)
2004-06-25 22:45:15 +02:00
push(one);
2004-03-03 21:24:06 +01:00
else
2004-06-25 22:45:15 +02:00
push(zero);
2004-03-03 21:24:06 +01:00
return;
}
push_symbol(ISINTEGER);
push(p1);
list(2);
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_multiply(void)
{
push(cadr(p1));
eval();
p1 = cddr(p1);
while (iscons(p1)) {
push(car(p1));
eval();
multiply();
p1 = cdr(p1);
}
}
2006-01-13 21:52:59 +01:00
void
eval_number(void)
{
push(cadr(p1));
eval();
p1 = pop();
if (p1->k == NUM || p1->k == DOUBLE)
push_integer(1);
else
push_integer(0);
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_operator(void)
{
int h = tos;
push_symbol(OPERATOR);
p1 = cdr(p1);
while (iscons(p1)) {
push(car(p1));
eval();
p1 = cdr(p1);
}
list(tos - h);
}
2004-06-09 04:45:50 +02:00
void
2004-03-03 21:24:06 +01:00
eval_print(void)
{
p1 = cdr(p1);
while (iscons(p1)) {
push(car(p1));
eval();
2007-07-21 23:48:01 +02:00
if (equaln(get_binding(symbol(TTY)), 1))
printline(pop());
else
display(pop());
2004-03-03 21:24:06 +01:00
p1 = cdr(p1);
}
2006-01-16 20:37:31 +01:00
push(symbol(NIL));
2004-03-03 21:24:06 +01:00
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_quote(void)
{
push(cadr(p1));
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_rank(void)
{
push(cadr(p1));
eval();
p1 = pop();
2005-08-06 22:57:37 +02:00
if (istensor(p1))
push_integer(p1->u.tensor->ndim);
else
2004-06-25 22:45:15 +02:00
push(zero);
2004-03-03 21:24:06 +01:00
}
//-----------------------------------------------------------------------------
//
// Example: a[1] = b
//
// p1 *-------*-----------------------*
// | | |
// setq *-------*-------* b
// | | |
// index a 1
//
// cadadr(p1) -> a
//
//-----------------------------------------------------------------------------
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
setq_indexed(void)
{
int h;
p4 = cadadr(p1);
2005-08-06 22:57:37 +02:00
if (!issymbol(p4))
2004-03-03 21:24:06 +01:00
stop("indexed assignment: error in symbol");
h = tos;
push(caddr(p1));
eval();
p2 = cdadr(p1);
while (iscons(p2)) {
push(car(p2));
eval();
p2 = cdr(p2);
}
set_component(tos - h);
p3 = pop();
2007-06-29 00:34:34 +02:00
set_binding(p4, p3);
2006-01-16 20:37:31 +01:00
push(symbol(NIL));
2004-03-03 21:24:06 +01:00
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_setq(void)
{
if (caadr(p1) == symbol(INDEX)) {
setq_indexed();
return;
}
if (iscons(cadr(p1))) {
define_user_function();
return;
}
2005-08-06 22:57:37 +02:00
if (!issymbol(cadr(p1)))
2004-03-03 21:24:06 +01:00
stop("symbol assignment: error in symbol");
push(caddr(p1));
eval();
p2 = pop();
2007-06-29 00:34:34 +02:00
set_binding(cadr(p1), p2);
2004-03-03 21:24:06 +01:00
2006-01-16 20:37:31 +01:00
push(symbol(NIL));
2004-03-03 21:24:06 +01:00
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_sqrt(void)
{
push(cadr(p1));
eval();
push_rational(1, 2);
power();
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_stop(void)
{
stop("user stop");
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_subst(void)
{
push(cadddr(p1));
eval();
push(caddr(p1));
eval();
push(cadr(p1));
eval();
subst();
2006-09-19 23:04:36 +02:00
eval(); // normalize
2004-03-03 21:24:06 +01:00
}
2006-01-04 03:30:50 +01:00
void
2004-03-03 21:24:06 +01:00
eval_unit(void)
{
int i, n;
push(cadr(p1));
eval();
n = pop_integer();
if (n < 2) {
push(p1);
return;
}
p1 = alloc_tensor(n * n);
p1->u.tensor->ndim = 2;
p1->u.tensor->dim[0] = n;
p1->u.tensor->dim[1] = n;
for (i = 0; i < n; i++)
2004-06-25 22:45:15 +02:00
p1->u.tensor->elem[n * i + i] = one;
2004-03-03 21:24:06 +01:00
push(p1);
}
void
eval_noexpand(void)
{
int x = expanding;
expanding = 0;
eval();
expanding = x;
}
2005-08-21 03:19:56 +02:00
// like eval() except "=" is evaluated as "=="
void
eval_predicate(void)
{
save();
p1 = pop();
if (car(p1) == symbol(SETQ))
eval_testeq();
else {
push(p1);
eval();
}
restore();
2005-08-21 03:27:28 +02:00
}