1493 lines
41 KiB
CoffeeScript
1493 lines
41 KiB
CoffeeScript
power_str = "^"
|
|
codeGen = false
|
|
|
|
# this is only invoked when user invokes
|
|
# "print" explicitly
|
|
Eval_print = ->
|
|
stringsEmittedByUserPrintouts += _print(cdr(p1), printMode)
|
|
push(symbol(NIL));
|
|
|
|
# this is only invoked when user invokes
|
|
# "print2dascii" explicitly
|
|
Eval_print2dascii = ->
|
|
stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_2DASCII)
|
|
push(symbol(NIL));
|
|
|
|
# this is only invoked when user invokes
|
|
# "printcomputer" explicitly
|
|
Eval_printcomputer = ->
|
|
stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_COMPUTER)
|
|
push(symbol(NIL));
|
|
|
|
# this is only invoked when user invokes
|
|
# "printlatex" explicitly
|
|
Eval_printlatex = ->
|
|
stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_LATEX)
|
|
push(symbol(NIL));
|
|
|
|
# this is only invoked when user invokes
|
|
# "printhuman" explicitly
|
|
Eval_printhuman = ->
|
|
# test flag needs to be suspended
|
|
# because otherwise "printcomputer" mode
|
|
# will happen.
|
|
original_test_flag = test_flag
|
|
test_flag = 0
|
|
stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_HUMAN)
|
|
test_flag = original_test_flag
|
|
push(symbol(NIL));
|
|
|
|
# this is only invoked when user invokes
|
|
# "printlist" explicitly
|
|
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();
|
|
|
|
# display single symbol as "symbol = result"
|
|
|
|
# but don't display "symbol = symbol"
|
|
|
|
###
|
|
if (issymbol(car(p)) && car(p) != p2)
|
|
push_symbol(SETQ);
|
|
push(car(p));
|
|
push(p2);
|
|
list(3);
|
|
p2 = pop();
|
|
###
|
|
|
|
origPrintMode = printMode
|
|
if passedPrintMode == PRINTMODE_COMPUTER
|
|
printMode = PRINTMODE_COMPUTER
|
|
accumulator = printline(p2);
|
|
rememberPrint(accumulator, LAST_FULL_PRINT)
|
|
else if passedPrintMode == PRINTMODE_HUMAN
|
|
printMode = PRINTMODE_HUMAN
|
|
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)
|
|
# some variables might contain underscores, escape those
|
|
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)) # p1 is BASE
|
|
accumulator += print_char('(')
|
|
accumulator += print_expr(p1); # p1 is BASE
|
|
accumulator += print_char(')')
|
|
else
|
|
accumulator += print_expr(p1); # p1 is BASE
|
|
return accumulator
|
|
|
|
print_expo_of_denom = (p2) ->
|
|
accumulator = ""
|
|
if (isfraction(p2) || car(p2) == symbol(ADD) || car(p2) == symbol(MULTIPLY) || car(p2) == symbol(POWER)) # p2 is EXPO
|
|
accumulator += print_char('(')
|
|
accumulator += print_expr(p2); # p2 is EXPO
|
|
accumulator += print_char(')')
|
|
else
|
|
accumulator += print_expr(p2); # p2 is EXPO
|
|
return accumulator
|
|
|
|
# prints stuff after the divide symbol "/"
|
|
|
|
# d is the number of denominators
|
|
|
|
#define BASE p1
|
|
#define EXPO p2
|
|
|
|
print_denom = (p, d) ->
|
|
accumulator = ""
|
|
save()
|
|
|
|
p1 = cadr(p); # p1 is BASE
|
|
p2 = caddr(p); # p2 is EXPO
|
|
|
|
# i.e. 1 / (2^(1/3))
|
|
|
|
# get the cases like BASE^(-1) out of
|
|
# the way, they just become 1/BASE
|
|
if (isminusone(p2)) # p2 is EXPO
|
|
accumulator += print_base_of_denom p1
|
|
restore()
|
|
return accumulator
|
|
|
|
if (d == 1) # p2 is EXPO
|
|
accumulator += print_char('(')
|
|
|
|
# prepare the exponent
|
|
# (needs to be negated)
|
|
# before printing it out
|
|
push(p2); # p2 is EXPO
|
|
negate()
|
|
p2 = pop(); # p2 is EXPO
|
|
accumulator += print_power(p1,p2)
|
|
if (d == 1)
|
|
accumulator += print_char(')')
|
|
restore()
|
|
return accumulator
|
|
|
|
|
|
#define A p3
|
|
#define B p4
|
|
|
|
print_a_over_b = (p) ->
|
|
accumulator = ""
|
|
flag = 0
|
|
n = 0
|
|
d = 0
|
|
|
|
save()
|
|
|
|
# count numerators and denominators
|
|
|
|
n = 0
|
|
d = 0
|
|
|
|
p1 = cdr(p)
|
|
p2 = car(p1)
|
|
|
|
if (isrational(p2))
|
|
push(p2)
|
|
mp_numerator()
|
|
absval()
|
|
p3 = pop(); # p3 is A
|
|
push(p2)
|
|
mp_denominator()
|
|
p4 = pop(); # p4 is B
|
|
if (!isplusone(p3)) # p3 is A
|
|
n++
|
|
if (!isplusone(p4)) # p4 is B
|
|
d++
|
|
p1 = cdr(p1)
|
|
else
|
|
p3 = one; # p3 is A
|
|
p4 = one; # p4 is B
|
|
|
|
while (iscons(p1))
|
|
p2 = car(p1)
|
|
if (is_denominator(p2))
|
|
d++
|
|
else
|
|
n++
|
|
p1 = cdr(p1)
|
|
|
|
#debugger
|
|
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)) # p3 is A
|
|
accumulator += print_factor(p3); # p3 is A
|
|
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_HUMAN 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)) # p4 is B
|
|
accumulator += print_factor(p4); # p4 is B
|
|
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_HUMAN and !test_flag
|
|
accumulator += print_str(" + ")
|
|
else
|
|
accumulator += print_str("+")
|
|
else
|
|
if printMode == PRINTMODE_HUMAN 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) && isNumericAtom(cadr(p)) && lessp(cadr(p), zero))
|
|
accumulator += '-'
|
|
else if (isNumericAtom(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)
|
|
|
|
# coeff -1?
|
|
|
|
if (isminusone(car(p)))
|
|
# print_char('-')
|
|
p = cdr(p)
|
|
|
|
|
|
previousFactorWasANumber = false
|
|
|
|
# print the first factor ------------
|
|
if isNumericAtom(car(p))
|
|
previousFactorWasANumber = true
|
|
|
|
# this numberOneOverSomething thing is so that
|
|
# we show things of the form
|
|
# numericFractionOfForm1/something * somethingElse
|
|
# as
|
|
# somethingElse / something
|
|
# so for example 1/2 * sqrt(2) is rendered as
|
|
# sqrt(2)/2
|
|
# rather than the first form, which looks confusing.
|
|
# NOTE that you might want to avoid this
|
|
# when printing polynomials, as it could be nicer
|
|
# to show the numeric coefficients well separated from
|
|
# the variable, but we'll see when we'll
|
|
# come to it if it's an issue.
|
|
numberOneOverSomething = false
|
|
if printMode == PRINTMODE_LATEX and iscons(cdr(p)) and isNumberOneOverSomething(car(p))
|
|
numberOneOverSomething = true
|
|
denom = car(p).q.b.toString()
|
|
|
|
|
|
if numberOneOverSomething
|
|
origAccumulator = accumulator
|
|
accumulator = ""
|
|
else
|
|
accumulator += print_factor(car(p))
|
|
|
|
p = cdr(p)
|
|
|
|
# print all the other factors -------
|
|
while (iscons(p))
|
|
# check if we end up having a case where two numbers
|
|
# are next to each other. In those cases, latex needs
|
|
# to insert a \cdot otherwise they end up
|
|
# right next to each other and read like one big number
|
|
if printMode == PRINTMODE_LATEX
|
|
if previousFactorWasANumber
|
|
# if what comes next is a power and the base
|
|
# is a number, then we are in the case
|
|
# of consecutive numbers.
|
|
# Note that sqrt() i.e when exponent is 1/2
|
|
# doesn't count because the radical gives
|
|
# a nice graphical separation already.
|
|
if caar(p) == symbol(POWER)
|
|
if isNumericAtom(car(cdr(car(p))))
|
|
# rule out square root
|
|
if !isfraction(car(cdr(cdr(car(p)))))
|
|
accumulator += " \\cdot "
|
|
accumulator += print_multiply_sign()
|
|
accumulator += print_factor(car(p),false,true)
|
|
|
|
previousFactorWasANumber = false
|
|
if isNumericAtom(car(p))
|
|
previousFactorWasANumber = true
|
|
|
|
p = cdr(p)
|
|
|
|
if numberOneOverSomething
|
|
accumulator = origAccumulator + "\\frac{" + accumulator + "}{" + denom + "}"
|
|
|
|
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 (isfraction(p) || 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_DOT_codegen = (p) ->
|
|
accumulator = "dot("
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += ", "
|
|
accumulator += print_expr(caddr(p))
|
|
accumulator += ")"
|
|
return accumulator
|
|
|
|
print_SIN_codegen = (p) ->
|
|
accumulator = "Math.sin("
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += ")"
|
|
return accumulator
|
|
|
|
print_COS_codegen = (p) ->
|
|
accumulator = "Math.cos("
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += ")"
|
|
return accumulator
|
|
|
|
print_TAN_codegen = (p) ->
|
|
accumulator = "Math.tan("
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += ")"
|
|
return accumulator
|
|
|
|
print_ARCSIN_codegen = (p) ->
|
|
accumulator = "Math.asin("
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += ")"
|
|
return accumulator
|
|
|
|
print_ARCCOS_codegen = (p) ->
|
|
accumulator = "Math.acos("
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += ")"
|
|
return accumulator
|
|
|
|
print_ARCTAN_codegen = (p) ->
|
|
accumulator = "Math.atan("
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += ")"
|
|
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_TRANSPOSE_codegen = (p) ->
|
|
accumulator = ""
|
|
accumulator += print_str("transpose(")
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += print_str(')')
|
|
return accumulator
|
|
|
|
print_UNIT_codegen = (p) ->
|
|
accumulator = ""
|
|
accumulator += print_str("identity(")
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += print_str(')')
|
|
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_INV_codegen = (p) ->
|
|
accumulator = ""
|
|
accumulator += print_str("inv(")
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += print_str(')')
|
|
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
|
|
|
|
# j scans the dimensions
|
|
# k is an increment for all the printed elements
|
|
# since they are all together in sequence in one array
|
|
print_tensor_inner = (p, j, k) ->
|
|
accumulator = ""
|
|
|
|
accumulator += print_str("[")
|
|
|
|
# only the last dimension prints the actual elements
|
|
# e.g. in a matrix, the first dimension contains
|
|
# vectors, not elements, and the second dimension
|
|
# actually contains the elements
|
|
|
|
# if not the last dimension, we are just printing wrappers
|
|
# and recursing down i.e. we print the next dimension
|
|
if (j < p.tensor.ndim - 1)
|
|
for i in [0...p.tensor.dim[j]]
|
|
[k, retString] = print_tensor_inner(p, j + 1, k)
|
|
accumulator += retString
|
|
# add separator between elements dimensions
|
|
# "above" the inner-most dimension
|
|
if i != p.tensor.dim[j] - 1
|
|
accumulator += print_str(",")
|
|
# if we reached the last dimension, we print the actual
|
|
# elements
|
|
else
|
|
for i in [0...p.tensor.dim[j]]
|
|
accumulator += print_expr(p.tensor.elem[k])
|
|
# add separator between elements in the
|
|
# inner-most dimension
|
|
if i != p.tensor.dim[j] - 1
|
|
accumulator += print_str(",")
|
|
k++
|
|
|
|
accumulator += print_str("]")
|
|
return [k, accumulator]
|
|
|
|
print_tensor_latex = (p) ->
|
|
accumulator = ""
|
|
if p.tensor.ndim <= 2
|
|
accumulator += print_tensor_inner_latex(true, p, 0, 0)[1]
|
|
return accumulator
|
|
|
|
# firstLevel is needed because printing a matrix
|
|
# is not exactly an elegant recursive procedure:
|
|
# the vector on the first level prints the latex
|
|
# "wrap", while the vectors that make up the
|
|
# rows don't. so it's a bit asymmetric and this
|
|
# flag helps.
|
|
# j scans the dimensions
|
|
# k is an increment for all the printed elements
|
|
# since they are all together in sequence in one array
|
|
print_tensor_inner_latex = (firstLevel, p, j, k) ->
|
|
accumulator = ""
|
|
|
|
# open the outer latex wrap
|
|
if firstLevel
|
|
accumulator += "\\begin{bmatrix} "
|
|
|
|
# only the last dimension prints the actual elements
|
|
# e.g. in a matrix, the first dimension contains
|
|
# vectors, not elements, and the second dimension
|
|
# actually contains the elements
|
|
|
|
# if not the last dimension, we are just printing wrappers
|
|
# and recursing down i.e. we print the next dimension
|
|
if (j < p.tensor.ndim - 1)
|
|
for i in [0...p.tensor.dim[j]]
|
|
[k, retString] = print_tensor_inner_latex(0, p, j + 1, k)
|
|
accumulator += retString
|
|
if i != p.tensor.dim[j] - 1
|
|
# add separator between rows
|
|
accumulator += print_str(" \\\\ ")
|
|
# if we reached the last dimension, we print the actual
|
|
# elements
|
|
else
|
|
for i in [0...p.tensor.dim[j]]
|
|
accumulator += print_expr(p.tensor.elem[k])
|
|
# separator between elements in each row
|
|
if i != p.tensor.dim[j] - 1
|
|
accumulator += print_str(" & ")
|
|
k++
|
|
|
|
|
|
# close the outer latex wrap
|
|
if firstLevel
|
|
accumulator += " \\end{bmatrix}"
|
|
|
|
return [k, accumulator]
|
|
|
|
print_SUM_latex = (p) ->
|
|
accumulator = "\\sum_{"
|
|
accumulator += print_expr(caddr(p))
|
|
accumulator += "="
|
|
accumulator += print_expr(cadddr(p))
|
|
accumulator += "}^{"
|
|
accumulator += print_expr(caddddr(p))
|
|
accumulator += "}{"
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += "}"
|
|
return accumulator
|
|
|
|
print_SUM_codegen = (p) ->
|
|
|
|
body = cadr(p)
|
|
variable = caddr(p)
|
|
lowerlimit = cadddr(p)
|
|
upperlimit = caddddr(p)
|
|
|
|
accumulator =
|
|
"(function(){" +
|
|
" var " + variable + "; " +
|
|
" var holderSum = 0; " +
|
|
" var lowerlimit = " + print_expr(lowerlimit) + "; " +
|
|
" var upperlimit = " + print_expr(upperlimit) + "; " +
|
|
" for (" + variable + " = lowerlimit; " + variable + " < upperlimit; " + variable + "++) { " +
|
|
" holderSum += " + print_expr(body) + ";" +
|
|
" } "+
|
|
" return holderSum;" +
|
|
"})()"
|
|
|
|
return accumulator
|
|
|
|
print_TEST_latex = (p) ->
|
|
accumulator = "\\left\\{ \\begin{array}{ll}"
|
|
|
|
p = cdr(p)
|
|
while (iscons(p))
|
|
|
|
# odd number of parameters means that the
|
|
# last argument becomes the default case
|
|
# i.e. the one without a test.
|
|
if (cdr(p) == symbol(NIL))
|
|
accumulator += "{"
|
|
accumulator += print_expr(car(p))
|
|
accumulator += "} & otherwise "
|
|
accumulator += " \\\\\\\\"
|
|
break
|
|
|
|
accumulator += "{"
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += "} & if & "
|
|
accumulator += print_expr(car(p))
|
|
accumulator += " \\\\\\\\"
|
|
|
|
# test unsuccessful, continue to the
|
|
# next pair of test,value
|
|
p = cddr(p)
|
|
accumulator = accumulator.substring(0, accumulator.length - 4);
|
|
accumulator += "\\end{array} \\right."
|
|
|
|
print_TEST_codegen = (p) ->
|
|
|
|
accumulator = "(function(){"
|
|
|
|
p = cdr(p)
|
|
howManyIfs = 0
|
|
while (iscons(p))
|
|
|
|
# odd number of parameters means that the
|
|
# last argument becomes the default case
|
|
# i.e. the one without a test.
|
|
if (cdr(p) == symbol(NIL))
|
|
accumulator += "else {"
|
|
accumulator += "return (" + print_expr(car(p)) + ");"
|
|
accumulator += "}"
|
|
break
|
|
|
|
if howManyIfs
|
|
accumulator += " else "
|
|
|
|
accumulator += "if (" + print_expr(car(p)) + "){"
|
|
accumulator += "return (" + print_expr(cadr(p)) + ");"
|
|
accumulator += "}"
|
|
|
|
# test unsuccessful, continue to the
|
|
# next pair of test,value
|
|
howManyIfs++
|
|
p = cddr(p)
|
|
|
|
accumulator += "})()"
|
|
|
|
return accumulator
|
|
|
|
|
|
print_TESTLT_latex = (p) ->
|
|
accumulator = "{"
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += "}"
|
|
accumulator += " < "
|
|
accumulator += "{"
|
|
accumulator += print_expr(caddr(p))
|
|
accumulator += "}"
|
|
|
|
print_TESTLE_latex = (p) ->
|
|
accumulator = "{"
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += "}"
|
|
accumulator += " \\leq "
|
|
accumulator += "{"
|
|
accumulator += print_expr(caddr(p))
|
|
accumulator += "}"
|
|
|
|
print_TESTGT_latex = (p) ->
|
|
accumulator = "{"
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += "}"
|
|
accumulator += " > "
|
|
accumulator += "{"
|
|
accumulator += print_expr(caddr(p))
|
|
accumulator += "}"
|
|
|
|
print_TESTGE_latex = (p) ->
|
|
accumulator = "{"
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += "}"
|
|
accumulator += " \\geq "
|
|
accumulator += "{"
|
|
accumulator += print_expr(caddr(p))
|
|
accumulator += "}"
|
|
|
|
print_TESTEQ_latex = (p) ->
|
|
accumulator = "{"
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += "}"
|
|
accumulator += " = "
|
|
accumulator += "{"
|
|
accumulator += print_expr(caddr(p))
|
|
accumulator += "}"
|
|
|
|
print_FOR_codegen = (p) ->
|
|
body = cadr(p)
|
|
variable = caddr(p)
|
|
lowerlimit = cadddr(p)
|
|
upperlimit = caddddr(p)
|
|
|
|
accumulator =
|
|
"(function(){" +
|
|
" var " + variable + "; " +
|
|
" var lowerlimit = " + print_expr(lowerlimit) + "; " +
|
|
" var upperlimit = " + print_expr(upperlimit) + "; " +
|
|
" for (" + variable + " = lowerlimit; " + variable + " < upperlimit; " + variable + "++) { " +
|
|
" " + print_expr(body) +
|
|
" } "+
|
|
"})()"
|
|
|
|
return accumulator
|
|
|
|
print_DO_codegen = (p) ->
|
|
accumulator = ""
|
|
|
|
p = cdr(p)
|
|
while iscons(p)
|
|
accumulator += print_expr(car(p))
|
|
p = cdr(p)
|
|
|
|
return accumulator
|
|
|
|
print_SETQ_codegen = (p) ->
|
|
accumulator = ""
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += " = "
|
|
accumulator += print_expr(caddr(p))
|
|
accumulator += "; "
|
|
return accumulator
|
|
|
|
|
|
print_PRODUCT_latex = (p) ->
|
|
accumulator = "\\prod_{"
|
|
accumulator += print_expr(caddr(p))
|
|
accumulator += "="
|
|
accumulator += print_expr(cadddr(p))
|
|
accumulator += "}^{"
|
|
accumulator += print_expr(caddddr(p))
|
|
accumulator += "}{"
|
|
accumulator += print_expr(cadr(p))
|
|
accumulator += "}"
|
|
return accumulator
|
|
|
|
print_PRODUCT_codegen = (p) ->
|
|
|
|
body = cadr(p)
|
|
variable = caddr(p)
|
|
lowerlimit = cadddr(p)
|
|
upperlimit = caddddr(p)
|
|
|
|
accumulator =
|
|
"(function(){" +
|
|
" var " + variable + "; " +
|
|
" var holderProduct = 1; " +
|
|
" var lowerlimit = " + print_expr(lowerlimit) + "; " +
|
|
" var upperlimit = " + print_expr(upperlimit) + "; " +
|
|
" for (" + variable + " = lowerlimit; " + variable + " < upperlimit; " + variable + "++) { " +
|
|
" holderProduct *= " + print_expr(body) + ";" +
|
|
" } "+
|
|
" return holderProduct;" +
|
|
"})()"
|
|
|
|
return 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 (isNumericAtom(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)) || (isNumericAtom(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 = ""
|
|
|
|
#debugger
|
|
if DEBUG then console.log "power base: " + base + " " + " exponent: " + exponent
|
|
|
|
# quick check is this is actually a square root.
|
|
if isoneovertwo(exponent)
|
|
if equaln(base, 2)
|
|
if codeGen
|
|
accumulator += print_str("Math.SQRT2")
|
|
return accumulator
|
|
else
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_str("\\sqrt{")
|
|
accumulator += print_expr(base)
|
|
accumulator += print_str("}")
|
|
return accumulator
|
|
else if codeGen
|
|
accumulator += print_str("Math.sqrt(")
|
|
accumulator += print_expr(base)
|
|
accumulator += print_str(')')
|
|
return accumulator
|
|
|
|
|
|
if ((equaln(get_binding(symbol(PRINT_LEAVE_E_ALONE)), 1)) and base == symbol(E))
|
|
if codeGen
|
|
accumulator += print_str("Math.exp(")
|
|
accumulator += print_expo_of_denom exponent
|
|
accumulator += print_str(')')
|
|
return accumulator
|
|
|
|
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 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_X_ALONE)), 0)) or base.printname != "x")
|
|
# if the exponent is negative then
|
|
# we invert the base BUT we don't do
|
|
# that if the base is "e", because for
|
|
# example when trigonometric functions are
|
|
# expressed in terms of exponential functions
|
|
# that would be really confusing, one wants to
|
|
# keep "e" as the base and the negative exponent
|
|
if (base != symbol(E))
|
|
if (isminusone(exponent))
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_str("\\frac{1}{")
|
|
else if printMode == PRINTMODE_HUMAN 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_HUMAN 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()
|
|
# we omit the "2" on the radical
|
|
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
|
|
# print the base,
|
|
# determining if it needs to be
|
|
# wrapped in parentheses or not
|
|
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 (isNumericAtom(base) && (lessp(base, zero) || isfraction(base)))
|
|
accumulator += print_str('(')
|
|
accumulator += print_factor(base)
|
|
accumulator += print_str(')')
|
|
else
|
|
accumulator += print_factor(base)
|
|
|
|
# print the power symbol
|
|
#debugger
|
|
if printMode == PRINTMODE_HUMAN and !test_flag
|
|
#print_str(" ^ ")
|
|
accumulator += print_str(power_str)
|
|
else
|
|
accumulator += print_str("^")
|
|
|
|
# print the exponent
|
|
if printMode == PRINTMODE_LATEX
|
|
# in latex mode, one can omit the curly braces
|
|
# wrapping the exponent if the exponent is only
|
|
# one character long
|
|
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) || (isNumericAtom(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, pastFirstFactor) ->
|
|
# debugger
|
|
accumulator = ""
|
|
if (isNumericAtom(p))
|
|
# in an evaluated term, all the numeric parts
|
|
# are at the beginning of the term.
|
|
# When printing the EXPRESSION,
|
|
# we peek into the first factor of the term and we
|
|
# look at whether it's a number less then zero.
|
|
# if it is, we print the "-" as the "leading" part of the
|
|
# print of the EXPRESSION, and then we proceed printint the factors
|
|
# of the term. This means that when we come here, we must
|
|
# skip printing the minus if the number is negative,
|
|
# because it's already been printed.
|
|
if pastFirstFactor and lessp(p, zero)
|
|
accumulator += '('
|
|
accumulator += print_number(p, pastFirstFactor)
|
|
if pastFirstFactor and lessp(p, zero)
|
|
accumulator += ')'
|
|
return accumulator
|
|
|
|
if (isstr(p))
|
|
accumulator += print_str("\"")
|
|
accumulator += print_str(p.str)
|
|
accumulator += print_str("\"")
|
|
return accumulator
|
|
|
|
if (istensor(p))
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_tensor_latex(p)
|
|
else
|
|
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) == _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(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_HUMAN 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)
|
|
#debugger
|
|
accumulator += print_SQRT_latex(p)
|
|
return accumulator
|
|
else if car(p) == symbol(TRANSPOSE)
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_TRANSPOSE_latex(p)
|
|
return accumulator
|
|
else if codeGen
|
|
accumulator += print_TRANSPOSE_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(UNIT)
|
|
if codeGen
|
|
accumulator += print_UNIT_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(INV)
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_INV_latex(p)
|
|
return accumulator
|
|
else if codeGen
|
|
accumulator += print_INV_codegen(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)
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_DOT_latex(p)
|
|
return accumulator
|
|
else if codeGen
|
|
accumulator += print_DOT_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(SIN)
|
|
if codeGen
|
|
accumulator += print_SIN_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(COS)
|
|
if codeGen
|
|
accumulator += print_COS_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(TAN)
|
|
if codeGen
|
|
accumulator += print_TAN_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(ARCSIN)
|
|
if codeGen
|
|
accumulator += print_ARCSIN_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(ARCCOS)
|
|
if codeGen
|
|
accumulator += print_ARCCOS_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(ARCTAN)
|
|
if codeGen
|
|
accumulator += print_ARCTAN_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(SUM)
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_SUM_latex(p)
|
|
return accumulator
|
|
else if codeGen
|
|
accumulator += print_SUM_codegen(p)
|
|
return accumulator
|
|
#else if car(p) == symbol(QUOTE)
|
|
# if printMode == PRINTMODE_LATEX
|
|
# print_expr(cadr(p))
|
|
# return accumulator
|
|
else if car(p) == symbol(PRODUCT)
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_PRODUCT_latex(p)
|
|
return accumulator
|
|
else if codeGen
|
|
accumulator += print_PRODUCT_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(FOR)
|
|
if codeGen
|
|
accumulator += print_FOR_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(DO)
|
|
if codeGen
|
|
accumulator += print_DO_codegen(p)
|
|
return accumulator
|
|
else if car(p) == symbol(TEST)
|
|
if codeGen
|
|
accumulator += print_TEST_codegen(p)
|
|
return accumulator
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_TEST_latex(p)
|
|
return accumulator
|
|
else if car(p) == symbol(TESTLT)
|
|
if codeGen
|
|
accumulator += "(("+print_expr(cadr(p))+") < ("+print_expr(caddr(p))+"))"
|
|
return accumulator
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_TESTLT_latex(p)
|
|
return accumulator
|
|
else if car(p) == symbol(TESTLE)
|
|
if codeGen
|
|
accumulator += "(("+print_expr(cadr(p))+") <= ("+print_expr(caddr(p))+"))"
|
|
return accumulator
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_TESTLE_latex(p)
|
|
return accumulator
|
|
else if car(p) == symbol(TESTGT)
|
|
if codeGen
|
|
accumulator += "(("+print_expr(cadr(p))+") > ("+print_expr(caddr(p))+"))"
|
|
return accumulator
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_TESTGT_latex(p)
|
|
return accumulator
|
|
else if car(p) == symbol(TESTGE)
|
|
if codeGen
|
|
accumulator += "(("+print_expr(cadr(p))+") >= ("+print_expr(caddr(p))+"))"
|
|
return accumulator
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_TESTGE_latex(p)
|
|
return accumulator
|
|
else if car(p) == symbol(TESTEQ)
|
|
if codeGen
|
|
accumulator += "(("+print_expr(cadr(p))+") === ("+print_expr(caddr(p))+"))"
|
|
return accumulator
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += print_TESTEQ_latex(p)
|
|
return accumulator
|
|
else if car(p) == symbol(FLOOR)
|
|
if codeGen
|
|
accumulator += "Math.floor("+print_expr(cadr(p))+")"
|
|
return accumulator
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += " \\lfloor {" + print_expr(cadr(p)) + "} \\rfloor "
|
|
return accumulator
|
|
else if car(p) == symbol(CEILING)
|
|
if codeGen
|
|
accumulator += "Math.ceiling("+print_expr(cadr(p))+")"
|
|
return accumulator
|
|
if printMode == PRINTMODE_LATEX
|
|
accumulator += " \\lceil {" + print_expr(cadr(p)) + "} \\rceil "
|
|
return accumulator
|
|
else if car(p) == symbol(ROUND)
|
|
if codeGen
|
|
accumulator += "Math.round("+print_expr(cadr(p))+")"
|
|
return accumulator
|
|
else if car(p) == symbol(SETQ)
|
|
if codeGen
|
|
accumulator += print_SETQ_codegen(p)
|
|
return accumulator
|
|
else
|
|
accumulator += print_expr cadr p
|
|
accumulator += print_str("=")
|
|
accumulator += print_expr caddr p
|
|
return accumulator
|
|
|
|
|
|
if (iscons(p))
|
|
#if (car(p) == symbol(FORMAL) && cadr(p)->k == SYM) {
|
|
# print_str(((struct symbol *) cadr(p))->name)
|
|
# return
|
|
#}
|
|
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 codeGen
|
|
accumulator += print_str("Math.E")
|
|
else
|
|
accumulator += print_str("e")
|
|
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
|
|
#print_str("\"")
|
|
accumulator += (p.str)
|
|
#print_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_HUMAN and !test_flag
|
|
accumulator += print_str(" ")
|
|
else
|
|
return accumulator
|
|
|
|
if printMode == PRINTMODE_HUMAN 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
|
|
|
|
# don't consider the leading fraction
|
|
# we want 2/3*a*b*c instead of 2*a*b*c/3
|
|
|
|
any_denominators = (p) ->
|
|
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
|
|
|