algebrite
Version:
Computer Algebra System in Coffeescript
905 lines (773 loc) • 23.2 kB
text/coffeescript
power_str = "^"
codeGen = false
Eval_print = ->
stringsEmittedByUserPrintouts += _print(cdr(p1),environment_printmode)
push(symbol(NIL));
Eval_print2dascii = ->
stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_2DASCII)
push(symbol(NIL));
Eval_printfull = ->
stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_FULL)
push(symbol(NIL));
Eval_printlatex = ->
stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_LATEX)
push(symbol(NIL));
Eval_printplain = ->
original_test_flag = test_flag
test_flag = 0
stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_PLAIN)
test_flag = original_test_flag
push(symbol(NIL));
Eval_printlist = ->
beenPrinted = _print(cdr(p1),PRINTMODE_LIST)
stringsEmittedByUserPrintouts += beenPrinted
push(symbol(NIL))
_print = (p, passedPrintMode) ->
accumulator = ""
while (iscons(p))
push(car(p));
Eval();
p2 = pop();
if (issymbol(car(p)) && car(p) != p2)
push_symbol(SETQ);
push(car(p));
push(p2);
list(3);
p2 = pop();
origPrintMode = printMode
if passedPrintMode == PRINTMODE_FULL
printMode = PRINTMODE_FULL
accumulator = printline(p2);
rememberPrint(accumulator, LAST_FULL_PRINT)
else if passedPrintMode == PRINTMODE_PLAIN
printMode = PRINTMODE_PLAIN
accumulator = printline(p2);
rememberPrint(accumulator, LAST_PLAIN_PRINT)
else if passedPrintMode == PRINTMODE_2DASCII
printMode = PRINTMODE_2DASCII
accumulator = print2dascii(p2);
rememberPrint(accumulator, LAST_2DASCII_PRINT)
else if passedPrintMode == PRINTMODE_LATEX
printMode = PRINTMODE_LATEX
accumulator = printline(p2);
rememberPrint(accumulator, LAST_LATEX_PRINT)
else if passedPrintMode == PRINTMODE_LIST
printMode = PRINTMODE_LIST
accumulator = print_list(p2);
rememberPrint(accumulator, LAST_LIST_PRINT)
printMode = origPrintMode
p = cdr(p);
if DEBUG then console.log "emttedString from display: " + stringsEmittedByUserPrintouts
return accumulator
rememberPrint = (theString, theTypeOfPrint) ->
scan('"' + theString + '"')
parsedString = pop()
set_binding(symbol(theTypeOfPrint), parsedString)
print_str = (s) ->
if DEBUG then console.log "emttedString from print_str: " + stringsEmittedByUserPrintouts
return s
print_char = (c) ->
return c
collectLatexStringFromReturnValue = (p) ->
origPrintMode = printMode
printMode = PRINTMODE_LATEX
originalCodeGen = codeGen
codeGen = false
returnedString = print_expr(p)
returnedString = returnedString.replace(/_/g, "\\\\_");
printMode = origPrintMode
codeGen = originalCodeGen
if DEBUG then console.log "emttedString from collectLatexStringFromReturnValue: " + stringsEmittedByUserPrintouts
return returnedString
printline = (p) ->
accumulator = ""
accumulator += print_expr(p)
return accumulator
print_base_of_denom = (p1) ->
accumulator = ""
if (isfraction(p1) || car(p1) == symbol(ADD) || car(p1) == symbol(MULTIPLY) || car(p1) == symbol(POWER) || lessp(p1, zero))
accumulator += print_char('(')
accumulator += print_expr(p1);
accumulator += print_char(')')
else
accumulator += print_expr(p1);
return accumulator
print_expo_of_denom = (p2) ->
accumulator = ""
if (isfraction(p2) || car(p2) == symbol(ADD) || car(p2) == symbol(MULTIPLY) || car(p2) == symbol(POWER))
accumulator += print_char('(')
accumulator += print_expr(p2);
accumulator += print_char(')')
else
accumulator += print_expr(p2);
return accumulator
print_denom = (p, d) ->
accumulator = ""
save()
p1 = cadr(p);
p2 = caddr(p);
if (isminusone(p2))
accumulator += print_base_of_denom p1
restore()
return accumulator
if (d == 1) # p2 is EXPO
accumulator += print_char('(')
push(p2);
negate()
p2 = pop();
accumulator += print_power(p1,p2)
if (d == 1)
accumulator += print_char(')')
restore()
return accumulator
print_a_over_b = (p) ->
accumulator = ""
flag = 0
n = 0
d = 0
save()
n = 0
d = 0
p1 = cdr(p)
p2 = car(p1)
if (isrational(p2))
push(p2)
mp_numerator()
absval()
p3 = pop();
push(p2)
mp_denominator()
p4 = pop();
if (!isplusone(p3))
n++
if (!isplusone(p4))
d++
p1 = cdr(p1)
else
p3 = one;
p4 = one;
while (iscons(p1))
p2 = car(p1)
if (is_denominator(p2))
d++
else
n++
p1 = cdr(p1)
if printMode == PRINTMODE_LATEX
accumulator += print_str('\\frac{')
if (n == 0)
accumulator += print_char('1')
else
flag = 0
p1 = cdr(p)
if (isrational(car(p1)))
p1 = cdr(p1)
if (!isplusone(p3))
accumulator += print_factor(p3);
flag = 1
while (iscons(p1))
p2 = car(p1)
if (is_denominator(p2))
doNothing = 1
else
if (flag)
accumulator += print_multiply_sign()
accumulator += print_factor(p2)
flag = 1
p1 = cdr(p1)
if printMode == PRINTMODE_LATEX
accumulator += print_str('}{')
else if printMode == PRINTMODE_PLAIN and !test_flag
accumulator += print_str(" / ")
else
accumulator += print_str("/")
if (d > 1 and printMode != PRINTMODE_LATEX)
accumulator += print_char('(')
flag = 0
p1 = cdr(p)
if (isrational(car(p1)))
p1 = cdr(p1)
if (!isplusone(p4))
accumulator += print_factor(p4);
flag = 1
while (iscons(p1))
p2 = car(p1)
if (is_denominator(p2))
if (flag)
accumulator += print_multiply_sign()
accumulator += print_denom(p2, d)
flag = 1
p1 = cdr(p1)
if (d > 1 and printMode != PRINTMODE_LATEX)
accumulator += print_char(')')
if printMode == PRINTMODE_LATEX
accumulator += print_str('}')
restore()
return accumulator
print_expr = (p) ->
accumulator = ""
if (isadd(p))
p = cdr(p)
if (sign_of_term(car(p)) == '-')
accumulator += print_str("-")
accumulator += print_term(car(p))
p = cdr(p)
while (iscons(p))
if (sign_of_term(car(p)) == '+')
if printMode == PRINTMODE_PLAIN and !test_flag
accumulator += print_str(" + ")
else
accumulator += print_str("+")
else
if printMode == PRINTMODE_PLAIN and !test_flag
accumulator += print_str(" - ")
else
accumulator += print_str("-")
accumulator += print_term(car(p))
p = cdr(p)
else
if (sign_of_term(p) == '-')
accumulator += print_str("-")
accumulator += print_term(p)
return accumulator
sign_of_term = (p) ->
accumulator = ""
if (car(p) == symbol(MULTIPLY) && isnum(cadr(p)) && lessp(cadr(p), zero))
accumulator += '-'
else if (isnum(p) && lessp(p, zero))
accumulator += '-'
else
accumulator += '+'
return accumulator
print_term = (p) ->
accumulator = ""
if (car(p) == symbol(MULTIPLY) && any_denominators(p))
accumulator += print_a_over_b(p)
return accumulator
if (car(p) == symbol(MULTIPLY))
p = cdr(p)
if (isminusone(car(p)))
p = cdr(p)
accumulator += print_factor(car(p))
p = cdr(p)
while (iscons(p))
accumulator += print_multiply_sign()
accumulator += print_factor(car(p))
p = cdr(p)
else
accumulator += print_factor(p)
return accumulator
print_subexpr = (p) ->
accumulator = ""
accumulator += print_char('(')
accumulator += print_expr(p)
accumulator += print_char(')')
return accumulator
print_factorial_function = (p) ->
accumulator = ""
p = cadr(p)
if (car(p) == symbol(ADD) || car(p) == symbol(MULTIPLY) || car(p) == symbol(POWER) || car(p) == symbol(FACTORIAL))
accumulator += print_subexpr(p)
else
accumulator += print_expr(p)
accumulator += print_char('!')
return accumulator
print_ABS_latex = (p) ->
accumulator = ""
accumulator += print_str("\\left |")
accumulator += print_expr(cadr(p))
accumulator += print_str(" \\right |")
return accumulator
print_BINOMIAL_latex = (p) ->
accumulator = ""
accumulator += print_str("\\binom{")
accumulator += print_expr(cadr(p))
accumulator += print_str("}{")
accumulator += print_expr(caddr(p))
accumulator += print_str("} ")
return accumulator
print_DOT_latex = (p) ->
accumulator = ""
accumulator += print_expr(cadr(p))
accumulator += print_str(" \\cdot ")
accumulator += print_expr(caddr(p))
return accumulator
print_SQRT_latex = (p) ->
accumulator = ""
accumulator += print_str("\\sqrt{")
accumulator += print_expr(cadr(p))
accumulator += print_str("} ")
return accumulator
print_TRANSPOSE_latex = (p) ->
accumulator = ""
accumulator += print_str("{")
if iscons(cadr(p))
accumulator += print_str('(')
accumulator += print_expr(cadr(p))
if iscons(cadr(p))
accumulator += print_str(')')
accumulator += print_str("}")
accumulator += print_str("^T")
return accumulator
print_INV_latex = (p) ->
accumulator = ""
accumulator += print_str("{")
if iscons(cadr(p))
accumulator += print_str('(')
accumulator += print_expr(cadr(p))
if iscons(cadr(p))
accumulator += print_str(')')
accumulator += print_str("}")
accumulator += print_str("^{-1}")
return accumulator
print_DEFINT_latex = (p) ->
accumulator = ""
functionBody = car(cdr(p))
p = cdr(p)
originalIntegral = p
numberOfIntegrals = 0
while iscons(cdr(cdr(p)))
numberOfIntegrals++
theIntegral = cdr(cdr(p))
accumulator += print_str("\\int^{")
accumulator += print_expr(car(cdr(theIntegral)))
accumulator += print_str("}_{")
accumulator += print_expr(car(theIntegral))
accumulator += print_str("} \\! ")
p = cdr(theIntegral)
accumulator += print_expr(functionBody)
accumulator += print_str(" \\,")
p = originalIntegral
for i in [1..numberOfIntegrals]
theVariable = cdr(p)
accumulator += print_str(" \\mathrm{d} ")
accumulator += print_expr(car(theVariable))
if i < numberOfIntegrals
accumulator += print_str(" \\, ")
p = cdr(cdr(theVariable))
return accumulator
print_tensor = (p) ->
accumulator = ""
accumulator += print_tensor_inner(p, 0, 0)[1]
return accumulator
print_tensor_inner = (p, j, k) ->
accumulator = ""
i = 0
if codeGen then accumulator += print_str("[") else accumulator += print_str('(')
for i in [0...p.tensor.dim[j]]
if (j + 1 == p.tensor.ndim)
accumulator += print_expr(p.tensor.elem[k])
k++
else
[] = print_tensor_inner(p, j + 1, k)
accumulator += retString
if (i + 1 < p.tensor.dim[j])
accumulator += print_str(",")
if codeGen then accumulator += print_str("]") else accumulator += print_str(')')
return [k, accumulator]
print_base = (p) ->
accumulator = ""
if (isadd(cadr(p)) || caadr(p) == symbol(MULTIPLY) || caadr(p) == symbol(POWER) || isnegativenumber(cadr(p)))
accumulator += print_str('(')
accumulator += print_expr(cadr(p))
accumulator += print_str(')')
else if (isnum(cadr(p)) && (lessp(cadr(p), zero) || isfraction(cadr(p))))
accumulator += print_str('(')
accumulator += print_factor(cadr(p))
accumulator += print_str(')')
else
accumulator += print_factor(cadr(p))
return accumulator
print_exponent = (p) ->
accumulator = ""
if (iscons(caddr(p)) || isfraction(caddr(p)) || (isnum(caddr(p)) && lessp(caddr(p), zero)))
accumulator += print_str('(')
accumulator += print_expr(caddr(p))
accumulator += print_str(')')
else
accumulator += print_factor(caddr(p))
return accumulator
print_power = (base, exponent) ->
accumulator = ""
if codeGen
accumulator += print_str("Math.pow(")
accumulator += print_base_of_denom base
accumulator += print_str(", ")
accumulator += print_expo_of_denom exponent
accumulator += print_str(')')
return accumulator
if ((equaln(get_binding(symbol(PRINT_LEAVE_E_ALONE)), 1)) and base == symbol(E))
if printMode == PRINTMODE_LATEX
accumulator += print_str("e^{")
accumulator += print_expr(exponent)
accumulator += print_str("}")
else
accumulator += print_str("exp(")
accumulator += print_expr(exponent)
accumulator += print_str(')')
return accumulator
if ((equaln(get_binding(symbol(PRINT_LEAVE_X_ALONE)), 0)) or base.printname != "x")
if (base != symbol(E))
if (isminusone(exponent))
if printMode == PRINTMODE_LATEX
accumulator += print_str("\\frac{1}{")
else if printMode == PRINTMODE_PLAIN and !test_flag
accumulator += print_str("1 / ")
else
accumulator += print_str("1/")
if (iscons(base) and printMode != PRINTMODE_LATEX)
accumulator += print_str('(')
accumulator += print_expr(base)
accumulator += print_str(')')
else
accumulator += print_expr(base)
if printMode == PRINTMODE_LATEX
accumulator += print_str("}")
return accumulator
if (isnegativeterm(exponent))
if printMode == PRINTMODE_LATEX
accumulator += print_str("\\frac{1}{")
else if printMode == PRINTMODE_PLAIN and !test_flag
accumulator += print_str("1 / ")
else
accumulator += print_str("1/")
push(exponent)
push_integer(-1)
multiply()
newExponent = pop()
if (iscons(base) and printMode != PRINTMODE_LATEX)
accumulator += print_str('(')
accumulator += print_power(base, newExponent)
accumulator += print_str(')')
else
accumulator += print_power(base, newExponent)
if printMode == PRINTMODE_LATEX
accumulator += print_str("}")
return accumulator
if (isfraction(exponent) and printMode == PRINTMODE_LATEX)
accumulator += print_str("\\sqrt")
push(exponent)
denominator()
denomExponent = pop()
if !isplustwo(denomExponent)
accumulator += print_str("[")
accumulator += print_expr(denomExponent)
accumulator += print_str("]")
accumulator += print_str("{")
push(exponent)
numerator()
numExponent = pop()
exponent = numExponent
accumulator += print_power(base, exponent)
accumulator += print_str("}")
return accumulator
if printMode == PRINTMODE_LATEX and isplusone(exponent)
# if we are in latex mode we turn many
# radicals into a radix sign with a power
# underneath, and the power is often one
# (e.g. square root turns into a radical
# with a power one underneath) so handle
# this case simply here, just print the base
accumulator += print_expr(base)
else
if (isadd(base) || isnegativenumber(base))
accumulator += print_str('(')
accumulator += print_expr(base)
accumulator += print_str(')')
else if ( car(base) == symbol(MULTIPLY) || car(base) == symbol(POWER))
if printMode != PRINTMODE_LATEX then accumulator += print_str('(')
accumulator += print_factor(base, true)
if printMode != PRINTMODE_LATEX then accumulator += print_str(')')
else if (isnum(base) && (lessp(base, zero) || isfraction(base)))
accumulator += print_str('(')
accumulator += print_factor(base)
accumulator += print_str(')')
else
accumulator += print_factor(base)
if printMode == PRINTMODE_PLAIN and !test_flag
accumulator += print_str(power_str)
else
accumulator += print_str("^")
if printMode == PRINTMODE_LATEX
if print_expr(exponent).length > 1
accumulator += print_str("{")
accumulator += print_expr(exponent)
accumulator += print_str("}")
else
accumulator += print_expr(exponent)
else if (iscons(exponent) || isfraction(exponent) || (isnum(exponent) && lessp(exponent, zero)))
accumulator += print_str('(')
accumulator += print_expr(exponent)
accumulator += print_str(')')
else
accumulator += print_factor(exponent)
return accumulator
print_index_function = (p) ->
accumulator = ""
p = cdr(p);
if (caar(p) == symbol(ADD) || caar(p) == symbol(MULTIPLY) || caar(p) == symbol(POWER) || caar(p) == symbol(FACTORIAL))
accumulator += print_subexpr(car(p));
else
accumulator += print_expr(car(p));
accumulator += print_str('[');
p = cdr(p);
if (iscons(p))
accumulator += print_expr(car(p));
p = cdr(p);
while(iscons(p))
accumulator += print_str(',');
accumulator += print_expr(car(p));
p = cdr(p);
accumulator += print_str(']');
return accumulator
print_factor = (p, omitParens) ->
accumulator = ""
if (isnum(p))
accumulator += print_number(p, false)
return accumulator
if (isstr(p))
accumulator += print_str("\"")
accumulator += print_str(p.str)
accumulator += print_str("\"")
return accumulator
if (istensor(p))
accumulator += print_tensor(p)
return accumulator
if (car(p) == symbol(MULTIPLY))
if !omitParens
if (sign_of_term(p) == '-' or printMode != PRINTMODE_LATEX)
if printMode == PRINTMODE_LATEX
accumulator += print_str(" \\left (")
else
accumulator += print_str('(')
accumulator += print_expr(p)
if !omitParens
if (sign_of_term(p) == '-' or printMode != PRINTMODE_LATEX)
if printMode == PRINTMODE_LATEX
accumulator += print_str(" \\right ) ")
else
accumulator += print_str(')')
return accumulator
else if (isadd(p))
if !omitParens then accumulator += print_str('(')
accumulator += print_expr(p)
if !omitParens then accumulator += print_str(')')
return accumulator
if (car(p) == symbol(POWER))
base = cadr(p)
exponent = caddr(p)
accumulator += print_power(base, exponent)
return accumulator
if (car(p) == symbol(FUNCTION))
fbody = cadr(p)
if !codeGen
parameters = caddr(p)
accumulator += print_str "function "
if DEBUG then console.log "emittedString from print_factor " + stringsEmittedByUserPrintouts
returned = print_list parameters
accumulator += returned
accumulator += print_str " -> "
accumulator += print_expr fbody
return accumulator
if (car(p) == symbol(PATTERN))
accumulator += print_expr(caadr(p))
if printMode == PRINTMODE_LATEX
accumulator += print_str(" \\rightarrow ")
else
if printMode == PRINTMODE_PLAIN and !test_flag
accumulator += print_str(" -> ")
else
accumulator += print_str("->")
accumulator += print_expr car(cdr(cadr(p)))
return accumulator
if (car(p) == symbol(INDEX) && issymbol(cadr(p)))
accumulator += print_index_function(p)
return accumulator
if (car(p) == symbol(FACTORIAL))
accumulator += print_factorial_function(p)
return accumulator
else if (car(p) == symbol(ABS) && printMode == PRINTMODE_LATEX)
accumulator += print_ABS_latex(p)
return accumulator
else if (car(p) == symbol(SQRT) && printMode == PRINTMODE_LATEX)
accumulator += print_SQRT_latex(p)
return accumulator
else if (car(p) == symbol(TRANSPOSE) && printMode == PRINTMODE_LATEX)
accumulator += print_TRANSPOSE_latex(p)
return accumulator
else if (car(p) == symbol(INV) && printMode == PRINTMODE_LATEX)
accumulator += print_INV_latex(p)
return accumulator
else if (car(p) == symbol(BINOMIAL) && printMode == PRINTMODE_LATEX)
accumulator += print_BINOMIAL_latex(p)
return accumulator
else if (car(p) == symbol(DEFINT) && printMode == PRINTMODE_LATEX)
accumulator += print_DEFINT_latex(p)
return accumulator
else if (isinnerordot(p) && printMode == PRINTMODE_LATEX)
accumulator += print_DOT_latex(p)
return accumulator
if (iscons(p))
#if (car(p) == symbol(FORMAL) && cadr(p)->k == SYM) {
accumulator += print_factor(car(p))
p = cdr(p)
if !omitParens then accumulator += print_str('(')
if (iscons(p))
accumulator += print_expr(car(p))
p = cdr(p)
while (iscons(p))
accumulator += print_str(",")
accumulator += print_expr(car(p))
p = cdr(p)
if !omitParens then accumulator += print_str(')')
return accumulator
if (p == symbol(DERIVATIVE))
accumulator += print_char('d')
else if (p == symbol(E))
if printMode == PRINTMODE_LATEX
accumulator += print_str("e")
else
accumulator += print_str("exp(1)")
else if (p == symbol(PI))
if printMode == PRINTMODE_LATEX
accumulator += print_str("\\pi")
else
accumulator += print_str("pi")
else
accumulator += print_str(get_printname(p))
return accumulator
print_list = (p) ->
accumulator = ""
switch (p.k)
when CONS
accumulator += ('(')
accumulator += print_list(car(p))
if p == cdr(p) and p != symbol(NIL)
console.log "oh no recursive!"
debugger
p = cdr(p)
while (iscons(p))
accumulator += (" ")
accumulator += print_list(car(p))
p = cdr(p)
if p == cdr(p) and p != symbol(NIL)
console.log "oh no recursive!"
debugger
if (p != symbol(NIL))
accumulator += (" . ")
accumulator += print_list(p)
accumulator += (')')
when STR
accumulator += (p.str)
when NUM, DOUBLE
accumulator += print_number(p, true)
when SYM
accumulator += get_printname(p)
else
accumulator += ("<tensor>")
return accumulator
print_multiply_sign = ->
accumulator = ""
if printMode == PRINTMODE_LATEX
if printMode == PRINTMODE_PLAIN and !test_flag
accumulator += print_str(" ")
else
return accumulator
if printMode == PRINTMODE_PLAIN and !test_flag and !codeGen
accumulator += print_str(" ")
else
accumulator += print_str("*")
return accumulator
is_denominator = (p) ->
if (car(p) == symbol(POWER) && cadr(p) != symbol(E) && isnegativeterm(caddr(p)))
return 1
else
return 0
any_denominators = (p) ->
p = cdr(p)
while (iscons(p))
q = car(p)
if (is_denominator(q))
return 1
p = cdr(p)
return 0