#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; }