615 lines
9.4 KiB
C++
615 lines
9.4 KiB
C++
#include "stdafx.h"
|
|
#include "defs.h"
|
|
|
|
extern int display_flag;
|
|
extern void displaychar(int);
|
|
|
|
int out_index, out_length;
|
|
char *out_str;
|
|
static int char_count, last_char;
|
|
|
|
static void print_expr(U *);
|
|
static void print_multiply_sign(void);
|
|
static void print_denom(U *, int);
|
|
static void print_a_over_b(U *);
|
|
static int is_denominator(U *);
|
|
static int any_denominators(U *);
|
|
int isnegativeterm(U *);
|
|
static void print_subexpr(U *);
|
|
static void print_index_function(U *);
|
|
static void print_factorial_function(U *);
|
|
static int sign_of_term(U *);
|
|
|
|
extern int test_flag;
|
|
|
|
char *power_str = "^";
|
|
|
|
void
|
|
print(U *p)
|
|
{
|
|
print_expr(p);
|
|
}
|
|
|
|
void
|
|
printline(U *p)
|
|
{
|
|
print_expr(p);
|
|
print_char('\n');
|
|
}
|
|
|
|
static void print_term(U *);
|
|
|
|
static void
|
|
print_subexpr(U *p)
|
|
{
|
|
print_char('(');
|
|
print_expr(p);
|
|
print_char(')');
|
|
}
|
|
|
|
static void
|
|
print_expr(U *p)
|
|
{
|
|
if (isadd(p)) {
|
|
p = cdr(p);
|
|
if (sign_of_term(car(p)) == '-')
|
|
print_str("-");
|
|
print_term(car(p));
|
|
p = cdr(p);
|
|
while (iscons(p)) {
|
|
if (sign_of_term(car(p)) == '+')
|
|
if (test_flag == 0)
|
|
print_str(" + ");
|
|
else
|
|
print_str("+");
|
|
else
|
|
if (test_flag == 0)
|
|
print_str(" - ");
|
|
else
|
|
print_str("-");
|
|
print_term(car(p));
|
|
p = cdr(p);
|
|
}
|
|
} else {
|
|
if (sign_of_term(p) == '-')
|
|
print_str("-");
|
|
print_term(p);
|
|
}
|
|
}
|
|
|
|
static int
|
|
sign_of_term(U *p)
|
|
{
|
|
if (car(p) == symbol(MULTIPLY) && isnum(cadr(p)) && lessp(cadr(p), _zero))
|
|
return '-';
|
|
else if (isnum(p) && lessp(p, _zero))
|
|
return '-';
|
|
else
|
|
return '+';
|
|
}
|
|
|
|
#define A p3
|
|
#define B p4
|
|
|
|
static void
|
|
print_a_over_b(U *p)
|
|
{
|
|
int flag, n, d;
|
|
U *p1, *p2;
|
|
|
|
save();
|
|
|
|
// count numerators and denominators
|
|
|
|
n = 0;
|
|
d = 0;
|
|
|
|
p1 = cdr(p);
|
|
p2 = car(p1);
|
|
|
|
if (p2->k == NUM) {
|
|
push(p2);
|
|
numerator();
|
|
absval();
|
|
A = pop();
|
|
push(p2);
|
|
denominator();
|
|
B = pop();
|
|
if (!isplusone(A))
|
|
n++;
|
|
if (!isplusone(B))
|
|
d++;
|
|
p1 = cdr(p1);
|
|
} else {
|
|
A = _one;
|
|
B = _one;
|
|
}
|
|
|
|
while (iscons(p1)) {
|
|
p2 = car(p1);
|
|
if (is_denominator(p2))
|
|
d++;
|
|
else
|
|
n++;
|
|
p1 = cdr(p1);
|
|
}
|
|
|
|
if (n == 0)
|
|
print_char('1');
|
|
else {
|
|
flag = 0;
|
|
p1 = cdr(p);
|
|
if (car(p1)->k == NUM)
|
|
p1 = cdr(p1);
|
|
if (!isplusone(A)) {
|
|
print_factor(A);
|
|
flag = 1;
|
|
}
|
|
while (iscons(p1)) {
|
|
p2 = car(p1);
|
|
if (is_denominator(p2))
|
|
;
|
|
else {
|
|
if (flag)
|
|
print_multiply_sign();
|
|
print_factor(p2);
|
|
flag = 1;
|
|
}
|
|
p1 = cdr(p1);
|
|
}
|
|
}
|
|
|
|
if (test_flag == 0)
|
|
print_str(" / ");
|
|
else
|
|
print_str("/");
|
|
|
|
if (d > 1)
|
|
print_char('(');
|
|
|
|
|
|
flag = 0;
|
|
p1 = cdr(p);
|
|
|
|
if (car(p1)->k == NUM)
|
|
p1 = cdr(p1);
|
|
|
|
if (!isplusone(B)) {
|
|
print_factor(B);
|
|
flag = 1;
|
|
}
|
|
|
|
while (iscons(p1)) {
|
|
p2 = car(p1);
|
|
if (is_denominator(p2)) {
|
|
if (flag)
|
|
print_multiply_sign();
|
|
print_denom(p2, d);
|
|
flag = 1;
|
|
}
|
|
p1 = cdr(p1);
|
|
}
|
|
|
|
if (d > 1)
|
|
print_char(')');
|
|
|
|
restore();
|
|
}
|
|
|
|
static void
|
|
print_term(U *p)
|
|
{
|
|
if (car(p) == symbol(MULTIPLY) && any_denominators(p)) {
|
|
print_a_over_b(p);
|
|
return;
|
|
}
|
|
|
|
if (car(p) == symbol(MULTIPLY)) {
|
|
p = cdr(p);
|
|
|
|
// coeff -1?
|
|
|
|
if (equal(car(p), _minus_one)) {
|
|
// print_char('-');
|
|
p = cdr(p);
|
|
}
|
|
|
|
print_factor(car(p));
|
|
p = cdr(p);
|
|
while (iscons(p)) {
|
|
print_multiply_sign();
|
|
print_factor(car(p));
|
|
p = cdr(p);
|
|
}
|
|
} else
|
|
print_factor(p);
|
|
}
|
|
|
|
// prints stuff after the divide symbol "/"
|
|
|
|
// d is the number of denominators
|
|
|
|
#define BASE p1
|
|
#define EXPO p2
|
|
|
|
static void
|
|
print_denom(U *p, int d)
|
|
{
|
|
save();
|
|
|
|
BASE = cadr(p);
|
|
EXPO = caddr(p);
|
|
|
|
// i.e. 1 / (2^(1/3))
|
|
|
|
if (d == 1 && !isminusone(EXPO))
|
|
print_char('(');
|
|
|
|
if (isfraction(BASE) || car(BASE) == symbol(ADD) || car(BASE) == symbol(MULTIPLY) || car(BASE) == symbol(POWER) || lessp(BASE, _zero)) {
|
|
print_char('(');
|
|
print_expr(BASE);
|
|
print_char(')');
|
|
} else
|
|
print_expr(BASE);
|
|
|
|
if (isminusone(EXPO)) {
|
|
restore();
|
|
return;
|
|
}
|
|
|
|
if (test_flag == 0)
|
|
print_str(power_str);
|
|
else
|
|
print_char('^');
|
|
|
|
push(EXPO);
|
|
negate();
|
|
EXPO = pop();
|
|
|
|
if (isfraction(EXPO) || car(EXPO) == symbol(ADD) || car(EXPO) == symbol(MULTIPLY) || car(EXPO) == symbol(POWER)) {
|
|
print_char('(');
|
|
print_expr(EXPO);
|
|
print_char(')');
|
|
} else
|
|
print_expr(EXPO);
|
|
|
|
if (d == 1)
|
|
print_char(')');
|
|
|
|
restore();
|
|
}
|
|
|
|
void
|
|
print_factor(U *p)
|
|
{
|
|
U *q;
|
|
|
|
if (isnum(p)) {
|
|
print_number(p);
|
|
return;
|
|
}
|
|
|
|
if (isstr(p)) {
|
|
//print_str("\"");
|
|
print_str(p->u.str);
|
|
//print_str("\"");
|
|
return;
|
|
}
|
|
|
|
if (istensor(p)) {
|
|
print_tensor(p);
|
|
return;
|
|
}
|
|
|
|
if (isadd(p) || car(p) == symbol(MULTIPLY)) {
|
|
print_str("(");
|
|
print_expr(p);
|
|
print_str(")");
|
|
return;
|
|
}
|
|
|
|
if (car(p) == symbol(POWER)) {
|
|
|
|
if (equal(p, unit_imaginary)) {
|
|
q = symbol(IM)->u.sym.binding;
|
|
if (issymbol(q))
|
|
print_str(get_printname(q));
|
|
else
|
|
print_str("i");
|
|
return;
|
|
}
|
|
|
|
if (cadr(p) == symbol(E)) {
|
|
print_str("exp(");
|
|
print_expr(caddr(p));
|
|
print_str(")");
|
|
return;
|
|
}
|
|
|
|
if (equal(caddr(p), _minus_one)) {
|
|
if (test_flag == 0)
|
|
print_str("1 / ");
|
|
else
|
|
print_str("1/");
|
|
if (iscons(cadr(p))) {
|
|
print_str("(");
|
|
print_expr(cadr(p));
|
|
print_str(")");
|
|
} else
|
|
print_expr(cadr(p));
|
|
return;
|
|
}
|
|
|
|
if (isadd(cadr(p)) || caadr(p) == symbol(MULTIPLY) || caadr(p) == symbol(POWER) || isnegativenumber(cadr(p))) {
|
|
print_str("(");
|
|
print_expr(cadr(p));
|
|
print_str(")");
|
|
} else if (isnum(cadr(p)) && (lessp(cadr(p), _zero) || isfraction(cadr(p)))) {
|
|
print_str("(");
|
|
print_factor(cadr(p));
|
|
print_str(")");
|
|
} else
|
|
print_factor(cadr(p));
|
|
if (test_flag == 0)
|
|
//print_str(" ^ ");
|
|
print_str(power_str);
|
|
else
|
|
print_str("^");
|
|
if (iscons(caddr(p)) || isfraction(caddr(p)) || (isnum(caddr(p)) && lessp(caddr(p), _zero))) {
|
|
print_str("(");
|
|
print_expr(caddr(p));
|
|
print_str(")");
|
|
} else
|
|
print_factor(caddr(p));
|
|
return;
|
|
}
|
|
|
|
// if (car(p) == _list) {
|
|
// print_str("{");
|
|
// p = cdr(p);
|
|
// if (iscons(p)) {
|
|
// print_expr(car(p));
|
|
// p = cdr(p);
|
|
// }
|
|
// while (iscons(p)) {
|
|
// print_str(",");
|
|
// print_expr(car(p));
|
|
// p = cdr(p);
|
|
// }
|
|
// print_str("}");
|
|
// return;
|
|
// }
|
|
|
|
if (car(p) == symbol(INDEX) && cadr(p)->k == SYM) {
|
|
print_index_function(p);
|
|
return;
|
|
}
|
|
|
|
if (car(p) == symbol(FACTORIAL)) {
|
|
print_factorial_function(p);
|
|
return;
|
|
}
|
|
|
|
if (iscons(p)) {
|
|
//if (car(p) == symbol(FORMAL) && cadr(p)->k == SYM) {
|
|
// print_str(((struct symbol *) cadr(p))->name);
|
|
// return;
|
|
//}
|
|
print_factor(car(p));
|
|
p = cdr(p);
|
|
print_str("(");
|
|
if (iscons(p)) {
|
|
print_expr(car(p));
|
|
p = cdr(p);
|
|
while (iscons(p)) {
|
|
if (test_flag == 0)
|
|
print_str(",");
|
|
else
|
|
print_str(",");
|
|
print_expr(car(p));
|
|
p = cdr(p);
|
|
}
|
|
}
|
|
print_str(")");
|
|
return;
|
|
}
|
|
|
|
if (p == symbol(DERIVATIVE))
|
|
print_char('d');
|
|
else if (p == symbol(E))
|
|
print_str("exp(1)");
|
|
else if (p == symbol(PI))
|
|
print_str("pi");
|
|
else
|
|
print_str(get_printname(p));
|
|
}
|
|
|
|
static void
|
|
print_index_function(U *p)
|
|
{
|
|
p = cdr(p);
|
|
if (caar(p) == symbol(ADD) || caar(p) == symbol(MULTIPLY) || caar(p) == symbol(POWER) || caar(p) == symbol(FACTORIAL))
|
|
print_subexpr(car(p));
|
|
else
|
|
print_expr(car(p));
|
|
print_char('[');
|
|
p = cdr(p);
|
|
if (iscons(p)) {
|
|
print_expr(car(p));
|
|
p = cdr(p);
|
|
while(iscons(p)) {
|
|
print_char(',');
|
|
print_expr(car(p));
|
|
p = cdr(p);
|
|
}
|
|
}
|
|
print_char(']');
|
|
}
|
|
|
|
static void
|
|
print_factorial_function(U *p)
|
|
{
|
|
p = cadr(p);
|
|
if (car(p) == symbol(ADD) || car(p) == symbol(MULTIPLY) || car(p) == symbol(POWER) || car(p) == symbol(FACTORIAL))
|
|
print_subexpr(p);
|
|
else
|
|
print_expr(p);
|
|
print_char('!');
|
|
}
|
|
|
|
void
|
|
print_tensor(U *p)
|
|
{
|
|
int k = 0;
|
|
print_tensor_inner(p, 0, &k);
|
|
}
|
|
|
|
void
|
|
print_tensor_inner(U *p, int j, int *k)
|
|
{
|
|
int i;
|
|
print_str("(");
|
|
for (i = 0; i < p->u.tensor->dim[j]; i++) {
|
|
if (j + 1 == p->u.tensor->ndim) {
|
|
print_expr(p->u.tensor->elem[*k]);
|
|
*k = *k + 1;
|
|
} else
|
|
print_tensor_inner(p, j + 1, k);
|
|
if (i + 1 < p->u.tensor->dim[j]) {
|
|
if (test_flag == 0)
|
|
print_str(",");
|
|
else
|
|
print_str(",");
|
|
}
|
|
}
|
|
print_str(")");
|
|
}
|
|
|
|
void
|
|
print_str(char *s)
|
|
{
|
|
while (*s)
|
|
print_char(*s++);
|
|
}
|
|
|
|
void
|
|
print_char(int c)
|
|
{
|
|
last_char = c;
|
|
char_count++;
|
|
// if (display_flag == 1)
|
|
// displaychar(c);
|
|
// else
|
|
printchar(c);
|
|
}
|
|
|
|
void
|
|
print_function_definition(U *p)
|
|
{
|
|
print_str(get_printname(p));
|
|
print_arg_list(cadr(p->u.sym.binding));
|
|
print_str("=");
|
|
print_expr(caddr(p->u.sym.binding));
|
|
print_str("\n");
|
|
}
|
|
|
|
void
|
|
print_arg_list(U *p)
|
|
{
|
|
print_str("(");
|
|
if (iscons(p)) {
|
|
print_str(get_printname(car(p)));
|
|
p = cdr(p);
|
|
while (iscons(p)) {
|
|
print_str(",");
|
|
print_str(get_printname(car(p)));
|
|
p = cdr(p);
|
|
}
|
|
}
|
|
print_str(")");
|
|
}
|
|
|
|
void
|
|
print_lisp(U *p)
|
|
{
|
|
print1(p);
|
|
print_str("\n");
|
|
}
|
|
|
|
void
|
|
print1(U *p)
|
|
{
|
|
switch (p->k) {
|
|
case CONS:
|
|
print_str("(");
|
|
print1(car(p));
|
|
p = cdr(p);
|
|
while (iscons(p)) {
|
|
print_str(" ");
|
|
print1(car(p));
|
|
p = cdr(p);
|
|
}
|
|
if (p != nil) {
|
|
print_str(" . ");
|
|
print1(p);
|
|
}
|
|
print_str(")");
|
|
break;
|
|
case STR:
|
|
//print_str("\"");
|
|
print_str(p->u.str);
|
|
//print_str("\"");
|
|
break;
|
|
#if GMP
|
|
case QNUM:
|
|
case FNUM:
|
|
#else
|
|
case NUM:
|
|
case DOUBLE:
|
|
#endif
|
|
print_number(p);
|
|
break;
|
|
default:
|
|
print_str(get_printname(p));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
print_multiply_sign(void)
|
|
{
|
|
if (test_flag == 0)
|
|
print_str(" ");
|
|
else
|
|
print_str("*");
|
|
}
|
|
|
|
static int
|
|
is_denominator(U *p)
|
|
{
|
|
if (car(p) == symbol(POWER) && cadr(p) != symbol(E) && isnegativeterm(caddr(p)))
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
// don't consider the leading fraction
|
|
|
|
// we want 2/3*a*b*c instead of 2*a*b*c/3
|
|
|
|
static int
|
|
any_denominators(U *p)
|
|
{
|
|
U *q;
|
|
p = cdr(p);
|
|
// if (isfraction(car(p)))
|
|
// return 1;
|
|
while (iscons(p)) {
|
|
q = car(p);
|
|
if (is_denominator(q))
|
|
return 1;
|
|
p = cdr(p);
|
|
}
|
|
return 0;
|
|
}
|