Eigenmath/print.cpp

757 lines
12 KiB
C++

// tty style printing
#include "stdafx.h"
#include "defs.h"
#include "console.h"
#include "tex/TeX.h"
#define TEX 1
#define MAX_TEX_WIDTH 110
#define MAX_TEX_HEIGHT 50
//char* get_tex_flag_address();
int tex_flag = 1;
int out_index, out_length;
char *out_str;
static int char_count, last_char;
char *power_str = "^";
extern "C"{
int* get_tex_flag_address()
{
return &tex_flag;
}
}
void
print(U *p)
{
print_expr(p);
}
void
printline(U *p)
{
int old_tex_flag = tex_flag;
#ifdef TEX
int width, height, baseline;
char* edit_line = (char*)Console_GetEditLine();
//tex_flag = 1;
#endif
print_expr(p);
#ifdef TEX
TeX_sizeComplex(edit_line, &width, &height, &baseline);
/*if(width > MAX_TEX_WIDTH || height > MAX_TEX_HEIGHT) {
tex_flag = 0;
Console_Clear_EditLine();
print_expr(p);
}*/
tex_flag = old_tex_flag;
#endif
}
void
print_subexpr(U *p)
{
print_char('(');
print_expr(p);
print_char(')');
}
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);
}
}
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
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 (isrational(p2)) {
push(p2);
mp_numerator();
absval();
A = pop();
push(p2);
mp_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);
}
//#ifdef TEX
if(tex_flag) print_str("\\frac{");
//#endif
if (n == 0)
print_char('1');
else {
flag = 0;
p1 = cdr(p);
if (isrational(car(p1)))
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);
}
}
//#ifdef TEX
if(tex_flag) print_str("}{");
else {
//#else
if (test_flag == 0)
print_str(" / ");
else
print_str("/");
if (d > 1)
print_char('(');
}
//#endif
flag = 0;
p1 = cdr(p);
if (isrational(car(p1)))
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);
}
//#ifdef TEX
//#else
if(!tex_flag && d > 1) //if (d > 1)
print_char(')');
if(tex_flag) print_str("}");
//#endif
restore();
}
void
print_term(U *p)
{
U* p_sqrt = NULL;
int sqrt_factor_number = 0, non_sqrt_factor_number = 0, i = 0;
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 (isminusone(car(p))) {
// print_char('-');
p = cdr(p);
}
#if 0
#ifdef TEX
p_sqrt = p; //temp buffer
sqrt_factor_number = 0;
non_sqrt_factor_number = 0;
//Get the number of factor which are square root of something
while(iscons(p_sqrt) || isnum(p_sqrt)){
if(caar(p_sqrt) == symbol(POWER) && equalq(caddar(p), 1, 2)) sqrt_factor_number++;
else non_sqrt_factor_number++;
p_sqrt = cdr(p_sqrt);
}
p_sqrt = p;
if(sqrt_factor_number > 1) {
//First, print the factor wich are not square root of something
if(non_sqrt_factor_number) {
//Print the first wich is not square root of something
while (iscons(p_sqrt) || isnum(p_sqrt)) {
if(!(caar(p_sqrt) == symbol(POWER) && equalq(caddar(p), 1, 2))) {
print_factor(cdar(p_sqrt));
break;
}
else p_sqrt = cdr(p_sqrt);
}
p_sqrt = cdr(p_sqrt);
i++;
//Print the other ones
while ((iscons(p_sqrt) || isnum(p_sqrt)) && i < non_sqrt_factor_number) {
if(!(caar(p_sqrt) == symbol(POWER) && equalq(caddar(p), 1, 2))){
print_multiply_sign();
print_factor(cdar(p_sqrt));
p_sqrt = cdr(p_sqrt);
i++;
}
}
}
p_sqrt = p;
i = 0;
print_str("\\sqrt{");
while (iscons(p_sqrt) || isnum(p_sqrt)) {
if(caar(p_sqrt) == symbol(POWER) && equalq(caddar(p), 1, 2)) {
print_expr(cadar(p_sqrt));
i++;
break;
}
p_sqrt = cdr(p_sqrt);
}
p_sqrt = cdr(p_sqrt);
while ((iscons(p_sqrt) || isnum(p_sqrt)) && i < sqrt_factor_number) {
if(caar(p_sqrt) == symbol(POWER) && equalq(caddar(p), 1, 2)) {
print_multiply_sign();
print_expr(cadar(p_sqrt));
i++;
p_sqrt = cdr(p_sqrt);
}
}
print_str("}");
return;
}
#endif // TeX
#endif // 0
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
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('(');
#ifdef TEX
if (tex_flag && equalq(EXPO, -1, 2)) {
print_str("\\sqrt{");
print_expr(BASE);
print_str("}");
restore();
return;
}
#endif
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)
{
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 (cadr(p) == symbol(E)) {
#ifdef ARM9
print_str("\235(");
#else
print_str("e^(");
#endif
print_expr(caddr(p));
print_str(")");
return;
}
if (isminusone(caddr(p))) {
if (test_flag == 0)
if(tex_flag) print_str("\\frac{1}{");
else print_str("1 / ");
else {
print_str("1/");
}
if (iscons(cadr(p))) {
print_str("(");
print_expr(cadr(p));
print_str(")");
} else
print_expr(cadr(p));
if(tex_flag) print_str("}");
return;
}
#ifdef TEX
if (tex_flag && equalq(caddr(p), 1, 2)) {
print_str("\\sqrt{");
print_expr(cadr(p));
print_str("}");
return;
}
if (tex_flag && equalq(caddr(p), -1, 2)) {
print_str("\\frac{1}{\\sqrt{");
print_expr(cadr(p));
//if(caddr)
print_str("}}");
return;
}
#endif
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("^");
{
int a,b,c;
a = iscons(caddr(p));
b = isfraction(caddr(p));
c = (isnum(caddr(p)) && lessp(caddr(p), zero));
if ( a|| b || c) {
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) && issymbol(cadr(p))) {
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))
#ifdef ARM9
print_str("\235(1)");
#else
print_str("e");
#endif
else if (p == symbol(PI))
#ifdef ARM9
print_str("\233");
#else
Console_Output((const unsigned char *)"pi");
#endif
else
print_str(get_printname(p));
}
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(']');
}
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(get_binding(p)));
print_str("=");
print_expr(caddr(get_binding(p)));
}
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);
}
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 != symbol(NIL)) {
print_str(" . ");
print1(p);
}
print_str(")");
break;
case STR:
//print_str("\"");
print_str(p->u.str);
//print_str("\"");
break;
case NUM:
case DOUBLE:
print_number(p);
break;
case SYM:
print_str(get_printname(p));
break;
default:
print_str("<tensor>");
break;
}
}
void
print_multiply_sign(void)
{
if (test_flag == 0)
Console_Output("*");
else
Console_Output(" ");
}
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
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;
}