UNPKG

38.7 kBtext/coffeescriptView Raw
1power_str = "^"
2codeGen = false
3
4# this is only invoked when user invokes
5# "print" explicitly
6Eval_print = ->
7 stringsEmittedByUserPrintouts += _print(cdr(p1),environment_printmode)
8 push(symbol(NIL));
9
10# this is only invoked when user invokes
11# "print2dascii" explicitly
12Eval_print2dascii = ->
13 stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_2DASCII)
14 push(symbol(NIL));
15
16# this is only invoked when user invokes
17# "printfull" explicitly
18Eval_printfull = ->
19 stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_FULL)
20 push(symbol(NIL));
21
22# this is only invoked when user invokes
23# "printlatex" explicitly
24Eval_printlatex = ->
25 stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_LATEX)
26 push(symbol(NIL));
27
28# this is only invoked when user invokes
29# "printplain" explicitly
30Eval_printplain = ->
31 # test flag needs to be suspended
32 # because otherwise "printfull" mode
33 # will happen.
34 original_test_flag = test_flag
35 test_flag = 0
36 stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_PLAIN)
37 test_flag = original_test_flag
38 push(symbol(NIL));
39
40# this is only invoked when user invokes
41# "printlist" explicitly
42Eval_printlist = ->
43 beenPrinted = _print(cdr(p1),PRINTMODE_LIST)
44 stringsEmittedByUserPrintouts += beenPrinted
45 push(symbol(NIL))
46
47
48_print = (p, passedPrintMode) ->
49 accumulator = ""
50
51 while (iscons(p))
52
53 push(car(p));
54 Eval();
55 p2 = pop();
56
57 # display single symbol as "symbol = result"
58
59 # but don't display "symbol = symbol"
60
61 ###
62 if (issymbol(car(p)) && car(p) != p2)
63 push_symbol(SETQ);
64 push(car(p));
65 push(p2);
66 list(3);
67 p2 = pop();
68 ###
69
70 origPrintMode = printMode
71 if passedPrintMode == PRINTMODE_FULL
72 printMode = PRINTMODE_FULL
73 accumulator = printline(p2);
74 rememberPrint(accumulator, LAST_FULL_PRINT)
75 else if passedPrintMode == PRINTMODE_PLAIN
76 printMode = PRINTMODE_PLAIN
77 accumulator = printline(p2);
78 rememberPrint(accumulator, LAST_PLAIN_PRINT)
79 else if passedPrintMode == PRINTMODE_2DASCII
80 printMode = PRINTMODE_2DASCII
81 accumulator = print2dascii(p2);
82 rememberPrint(accumulator, LAST_2DASCII_PRINT)
83 else if passedPrintMode == PRINTMODE_LATEX
84 printMode = PRINTMODE_LATEX
85 accumulator = printline(p2);
86 rememberPrint(accumulator, LAST_LATEX_PRINT)
87 else if passedPrintMode == PRINTMODE_LIST
88 printMode = PRINTMODE_LIST
89 accumulator = print_list(p2);
90 rememberPrint(accumulator, LAST_LIST_PRINT)
91 printMode = origPrintMode
92
93
94 p = cdr(p);
95
96 if DEBUG then console.log "emttedString from display: " + stringsEmittedByUserPrintouts
97 return accumulator
98
99rememberPrint = (theString, theTypeOfPrint) ->
100 scan('"' + theString + '"')
101 parsedString = pop()
102 set_binding(symbol(theTypeOfPrint), parsedString)
103
104print_str = (s) ->
105 if DEBUG then console.log "emttedString from print_str: " + stringsEmittedByUserPrintouts
106 return s
107
108print_char = (c) ->
109 return c
110
111collectLatexStringFromReturnValue = (p) ->
112 origPrintMode = printMode
113 printMode = PRINTMODE_LATEX
114 originalCodeGen = codeGen
115 codeGen = false
116 returnedString = print_expr(p)
117 # some variables might contain underscores, escape those
118 returnedString = returnedString.replace(/_/g, "\\_");
119 printMode = origPrintMode
120 codeGen = originalCodeGen
121 if DEBUG then console.log "emttedString from collectLatexStringFromReturnValue: " + stringsEmittedByUserPrintouts
122 return returnedString
123
124printline = (p) ->
125 accumulator = ""
126 accumulator += print_expr(p)
127 return accumulator
128
129
130print_base_of_denom = (p1) ->
131 accumulator = ""
132 if (isfraction(p1) || car(p1) == symbol(ADD) || car(p1) == symbol(MULTIPLY) || car(p1) == symbol(POWER) || lessp(p1, zero)) # p1 is BASE
133 accumulator += print_char('(')
134 accumulator += print_expr(p1); # p1 is BASE
135 accumulator += print_char(')')
136 else
137 accumulator += print_expr(p1); # p1 is BASE
138 return accumulator
139
140print_expo_of_denom = (p2) ->
141 accumulator = ""
142 if (isfraction(p2) || car(p2) == symbol(ADD) || car(p2) == symbol(MULTIPLY) || car(p2) == symbol(POWER)) # p2 is EXPO
143 accumulator += print_char('(')
144 accumulator += print_expr(p2); # p2 is EXPO
145 accumulator += print_char(')')
146 else
147 accumulator += print_expr(p2); # p2 is EXPO
148 return accumulator
149
150# prints stuff after the divide symbol "/"
151
152# d is the number of denominators
153
154#define BASE p1
155#define EXPO p2
156
157print_denom = (p, d) ->
158 accumulator = ""
159 save()
160
161 p1 = cadr(p); # p1 is BASE
162 p2 = caddr(p); # p2 is EXPO
163
164 # i.e. 1 / (2^(1/3))
165
166 # get the cases like BASE^(-1) out of
167 # the way, they just become 1/BASE
168 if (isminusone(p2)) # p2 is EXPO
169 accumulator += print_base_of_denom p1
170 restore()
171 return accumulator
172
173 if (d == 1) # p2 is EXPO
174 accumulator += print_char('(')
175
176 # prepare the exponent
177 # (needs to be negated)
178 # before printing it out
179 push(p2); # p2 is EXPO
180 negate()
181 p2 = pop(); # p2 is EXPO
182 accumulator += print_power(p1,p2)
183 if (d == 1)
184 accumulator += print_char(')')
185 restore()
186 return accumulator
187
188
189#define A p3
190#define B p4
191
192print_a_over_b = (p) ->
193 accumulator = ""
194 flag = 0
195 n = 0
196 d = 0
197
198 save()
199
200 # count numerators and denominators
201
202 n = 0
203 d = 0
204
205 p1 = cdr(p)
206 p2 = car(p1)
207
208 if (isrational(p2))
209 push(p2)
210 mp_numerator()
211 absval()
212 p3 = pop(); # p3 is A
213 push(p2)
214 mp_denominator()
215 p4 = pop(); # p4 is B
216 if (!isplusone(p3)) # p3 is A
217 n++
218 if (!isplusone(p4)) # p4 is B
219 d++
220 p1 = cdr(p1)
221 else
222 p3 = one; # p3 is A
223 p4 = one; # p4 is B
224
225 while (iscons(p1))
226 p2 = car(p1)
227 if (is_denominator(p2))
228 d++
229 else
230 n++
231 p1 = cdr(p1)
232
233 #debugger
234 if printMode == PRINTMODE_LATEX
235 accumulator += print_str('\\frac{')
236
237 if (n == 0)
238 accumulator += print_char('1')
239 else
240 flag = 0
241 p1 = cdr(p)
242 if (isrational(car(p1)))
243 p1 = cdr(p1)
244 if (!isplusone(p3)) # p3 is A
245 accumulator += print_factor(p3); # p3 is A
246 flag = 1
247 while (iscons(p1))
248 p2 = car(p1)
249 if (is_denominator(p2))
250 doNothing = 1
251 else
252 if (flag)
253 accumulator += print_multiply_sign()
254 accumulator += print_factor(p2)
255 flag = 1
256 p1 = cdr(p1)
257
258 if printMode == PRINTMODE_LATEX
259 accumulator += print_str('}{')
260 else if printMode == PRINTMODE_PLAIN and !test_flag
261 accumulator += print_str(" / ")
262 else
263 accumulator += print_str("/")
264
265 if (d > 1 and printMode != PRINTMODE_LATEX)
266 accumulator += print_char('(')
267
268
269 flag = 0
270 p1 = cdr(p)
271
272 if (isrational(car(p1)))
273 p1 = cdr(p1)
274
275 if (!isplusone(p4)) # p4 is B
276 accumulator += print_factor(p4); # p4 is B
277 flag = 1
278
279 while (iscons(p1))
280 p2 = car(p1)
281 if (is_denominator(p2))
282 if (flag)
283 accumulator += print_multiply_sign()
284 accumulator += print_denom(p2, d)
285 flag = 1
286 p1 = cdr(p1)
287
288 if (d > 1 and printMode != PRINTMODE_LATEX)
289 accumulator += print_char(')')
290
291 if printMode == PRINTMODE_LATEX
292 accumulator += print_str('}')
293
294 restore()
295 return accumulator
296
297
298print_expr = (p) ->
299 accumulator = ""
300 if (isadd(p))
301 p = cdr(p)
302 if (sign_of_term(car(p)) == '-')
303 accumulator += print_str("-")
304 accumulator += print_term(car(p))
305 p = cdr(p)
306 while (iscons(p))
307 if (sign_of_term(car(p)) == '+')
308 if printMode == PRINTMODE_PLAIN and !test_flag
309 accumulator += print_str(" + ")
310 else
311 accumulator += print_str("+")
312 else
313 if printMode == PRINTMODE_PLAIN and !test_flag
314 accumulator += print_str(" - ")
315 else
316 accumulator += print_str("-")
317 accumulator += print_term(car(p))
318 p = cdr(p)
319 else
320 if (sign_of_term(p) == '-')
321 accumulator += print_str("-")
322 accumulator += print_term(p)
323 return accumulator
324
325sign_of_term = (p) ->
326 accumulator = ""
327 if (car(p) == symbol(MULTIPLY) && isnum(cadr(p)) && lessp(cadr(p), zero))
328 accumulator += '-'
329 else if (isnum(p) && lessp(p, zero))
330 accumulator += '-'
331 else
332 accumulator += '+'
333 return accumulator
334
335print_term = (p) ->
336 accumulator = ""
337 if (car(p) == symbol(MULTIPLY) && any_denominators(p))
338 accumulator += print_a_over_b(p)
339 return accumulator
340
341 if (car(p) == symbol(MULTIPLY))
342 p = cdr(p)
343
344 # coeff -1?
345
346 if (isminusone(car(p)))
347 # print_char('-')
348 p = cdr(p)
349
350
351 previousFactorWasANumber = false
352
353 # print the first factor ------------
354 if isnum(car(p))
355 previousFactorWasANumber = true
356
357 # this numberOneOverSomething thing is so that
358 # we show things of the form
359 # numericFractionOfForm1/something * somethingElse
360 # as
361 # somethingElse / something
362 # so for example 1/2 * sqrt(2) is rendered as
363 # sqrt(2)/2
364 # rather than the first form, which looks confusing.
365 # NOTE that you might want to avoid this
366 # when printing polynomials, as it could be nicer
367 # to show the numeric coefficients well separated from
368 # the variable, but we'll see when we'll
369 # come to it if it's an issue.
370 numberOneOverSomething = false
371 if printMode == PRINTMODE_LATEX and iscons(cdr(p)) and isnumberoneoversomething(car(p))
372 numberOneOverSomething = true
373 denom = car(p).q.b.toString()
374
375
376 if numberOneOverSomething
377 origAccumulator = accumulator
378 accumulator = ""
379 else
380 accumulator += print_factor(car(p))
381
382 p = cdr(p)
383
384 # print all the other factors -------
385 while (iscons(p))
386 # check if we end up having a case where two numbers
387 # are next to each other. In those cases, latex needs
388 # to insert a \cdot otherwise they end up
389 # right next to each other and read like one big number
390 if printMode == PRINTMODE_LATEX
391 if previousFactorWasANumber
392 # if what comes next is a power and the base
393 # is a number, then we are in the case
394 # of consecutive numbers.
395 # Note that sqrt() i.e when exponent is 1/2
396 # doesn't count because the radical gives
397 # a nice graphical separation already.
398 if caar(p) == symbol(POWER)
399 if isnum(car(cdr(car(p))))
400 # rule out square root
401 if !isfraction(car(cdr(cdr(car(p)))))
402 accumulator += " \\cdot "
403 accumulator += print_multiply_sign()
404 accumulator += print_factor(car(p))
405
406 previousFactorWasANumber = false
407 if isnum(car(p))
408 previousFactorWasANumber = true
409
410 p = cdr(p)
411
412 if numberOneOverSomething
413 accumulator = origAccumulator + "\\frac{" + accumulator + "}{" + denom + "}"
414
415 else
416 accumulator += print_factor(p)
417 return accumulator
418
419print_subexpr = (p) ->
420 accumulator = ""
421 accumulator += print_char('(')
422 accumulator += print_expr(p)
423 accumulator += print_char(')')
424 return accumulator
425
426print_factorial_function = (p) ->
427 accumulator = ""
428 p = cadr(p)
429 if (car(p) == symbol(ADD) || car(p) == symbol(MULTIPLY) || car(p) == symbol(POWER) || car(p) == symbol(FACTORIAL))
430 accumulator += print_subexpr(p)
431 else
432 accumulator += print_expr(p)
433 accumulator += print_char('!')
434 return accumulator
435
436print_ABS_latex = (p) ->
437 accumulator = ""
438 accumulator += print_str("\\left |")
439 accumulator += print_expr(cadr(p))
440 accumulator += print_str(" \\right |")
441 return accumulator
442
443print_BINOMIAL_latex = (p) ->
444 accumulator = ""
445 accumulator += print_str("\\binom{")
446 accumulator += print_expr(cadr(p))
447 accumulator += print_str("}{")
448 accumulator += print_expr(caddr(p))
449 accumulator += print_str("} ")
450 return accumulator
451
452print_DOT_latex = (p) ->
453 accumulator = ""
454 accumulator += print_expr(cadr(p))
455 accumulator += print_str(" \\cdot ")
456 accumulator += print_expr(caddr(p))
457 return accumulator
458
459print_DOT_codegen = (p) ->
460 accumulator = "dot("
461 accumulator += print_expr(cadr(p))
462 accumulator += ", "
463 accumulator += print_expr(caddr(p))
464 accumulator += ")"
465 return accumulator
466
467print_SIN_codegen = (p) ->
468 accumulator = "Math.sin("
469 accumulator += print_expr(cadr(p))
470 accumulator += ")"
471 return accumulator
472
473print_COS_codegen = (p) ->
474 accumulator = "Math.cos("
475 accumulator += print_expr(cadr(p))
476 accumulator += ")"
477 return accumulator
478
479print_TAN_codegen = (p) ->
480 accumulator = "Math.tan("
481 accumulator += print_expr(cadr(p))
482 accumulator += ")"
483 return accumulator
484
485print_ARCSIN_codegen = (p) ->
486 accumulator = "Math.asin("
487 accumulator += print_expr(cadr(p))
488 accumulator += ")"
489 return accumulator
490
491print_ARCCOS_codegen = (p) ->
492 accumulator = "Math.acos("
493 accumulator += print_expr(cadr(p))
494 accumulator += ")"
495 return accumulator
496
497print_ARCTAN_codegen = (p) ->
498 accumulator = "Math.atan("
499 accumulator += print_expr(cadr(p))
500 accumulator += ")"
501 return accumulator
502
503print_SQRT_latex = (p) ->
504 accumulator = ""
505 accumulator += print_str("\\sqrt{")
506 accumulator += print_expr(cadr(p))
507 accumulator += print_str("} ")
508 return accumulator
509
510print_TRANSPOSE_latex = (p) ->
511 accumulator = ""
512 accumulator += print_str("{")
513 if iscons(cadr(p))
514 accumulator += print_str('(')
515 accumulator += print_expr(cadr(p))
516 if iscons(cadr(p))
517 accumulator += print_str(')')
518 accumulator += print_str("}")
519 accumulator += print_str("^T")
520 return accumulator
521
522print_TRANSPOSE_codegen = (p) ->
523 accumulator = ""
524 accumulator += print_str("transpose(")
525 accumulator += print_expr(cadr(p))
526 accumulator += print_str(')')
527 return accumulator
528
529print_UNIT_codegen = (p) ->
530 accumulator = ""
531 accumulator += print_str("identity(")
532 accumulator += print_expr(cadr(p))
533 accumulator += print_str(')')
534 return accumulator
535
536print_INV_latex = (p) ->
537 accumulator = ""
538 accumulator += print_str("{")
539 if iscons(cadr(p))
540 accumulator += print_str('(')
541 accumulator += print_expr(cadr(p))
542 if iscons(cadr(p))
543 accumulator += print_str(')')
544 accumulator += print_str("}")
545 accumulator += print_str("^{-1}")
546 return accumulator
547
548print_INV_codegen = (p) ->
549 accumulator = ""
550 accumulator += print_str("inv(")
551 accumulator += print_expr(cadr(p))
552 accumulator += print_str(')')
553 return accumulator
554
555print_DEFINT_latex = (p) ->
556 accumulator = ""
557 functionBody = car(cdr(p))
558
559 p = cdr(p)
560 originalIntegral = p
561 numberOfIntegrals = 0
562
563 while iscons(cdr(cdr(p)))
564 numberOfIntegrals++
565 theIntegral = cdr(cdr(p))
566
567 accumulator += print_str("\\int^{")
568 accumulator += print_expr(car(cdr(theIntegral)))
569 accumulator += print_str("}_{")
570 accumulator += print_expr(car(theIntegral))
571 accumulator += print_str("} \\! ")
572 p = cdr(theIntegral)
573
574 accumulator += print_expr(functionBody)
575 accumulator += print_str(" \\,")
576
577 p = originalIntegral
578
579 for i in [1..numberOfIntegrals]
580 theVariable = cdr(p)
581 accumulator += print_str(" \\mathrm{d} ")
582 accumulator += print_expr(car(theVariable))
583 if i < numberOfIntegrals
584 accumulator += print_str(" \\, ")
585 p = cdr(cdr(theVariable))
586 return accumulator
587
588
589
590print_tensor = (p) ->
591 accumulator = ""
592 accumulator += print_tensor_inner(p, 0, 0)[1]
593 return accumulator
594
595# j scans the dimensions
596# k is an increment for all the printed elements
597# since they are all together in sequence in one array
598print_tensor_inner = (p, j, k) ->
599 accumulator = ""
600
601 accumulator += print_str("[")
602
603 # only the last dimension prints the actual elements
604 # e.g. in a matrix, the first dimension contains
605 # vectors, not elements, and the second dimension
606 # actually contains the elements
607
608 # if not the last dimension, we are just printing wrappers
609 # and recursing down i.e. we print the next dimension
610 if (j < p.tensor.ndim - 1)
611 for i in [0...p.tensor.dim[j]]
612 [k, retString] = print_tensor_inner(p, j + 1, k)
613 accumulator += retString
614 # add separator between elements dimensions
615 # "above" the inner-most dimension
616 if i != p.tensor.dim[j] - 1
617 accumulator += print_str(",")
618 # if we reached the last dimension, we print the actual
619 # elements
620 else
621 for i in [0...p.tensor.dim[j]]
622 accumulator += print_expr(p.tensor.elem[k])
623 # add separator between elements in the
624 # inner-most dimension
625 if i != p.tensor.dim[j] - 1
626 accumulator += print_str(",")
627 k++
628
629 accumulator += print_str("]")
630 return [k, accumulator]
631
632print_tensor_latex = (p) ->
633 accumulator = ""
634 if p.tensor.ndim <= 2
635 accumulator += print_tensor_inner_latex(true, p, 0, 0)[1]
636 return accumulator
637
638# firstLevel is needed because printing a matrix
639# is not exactly an elegant recursive procedure:
640# the vector on the first level prints the latex
641# "wrap", while the vectors that make up the
642# rows don't. so it's a bit asymmetric and this
643# flag helps.
644# j scans the dimensions
645# k is an increment for all the printed elements
646# since they are all together in sequence in one array
647print_tensor_inner_latex = (firstLevel, p, j, k) ->
648 accumulator = ""
649
650 # open the outer latex wrap
651 if firstLevel
652 accumulator += "\\begin{bmatrix} "
653
654 # only the last dimension prints the actual elements
655 # e.g. in a matrix, the first dimension contains
656 # vectors, not elements, and the second dimension
657 # actually contains the elements
658
659 # if not the last dimension, we are just printing wrappers
660 # and recursing down i.e. we print the next dimension
661 if (j < p.tensor.ndim - 1)
662 for i in [0...p.tensor.dim[j]]
663 [k, retString] = print_tensor_inner_latex(0, p, j + 1, k)
664 accumulator += retString
665 if i != p.tensor.dim[j] - 1
666 # add separator between rows
667 accumulator += print_str(" \\\\ ")
668 # if we reached the last dimension, we print the actual
669 # elements
670 else
671 for i in [0...p.tensor.dim[j]]
672 accumulator += print_expr(p.tensor.elem[k])
673 # separator between elements in each row
674 if i != p.tensor.dim[j] - 1
675 accumulator += print_str(" & ")
676 k++
677
678
679 # close the outer latex wrap
680 if firstLevel
681 accumulator += " \\end{bmatrix}"
682
683 return [k, accumulator]
684
685print_SUM_latex = (p) ->
686 accumulator = "\\sum_{"
687 accumulator += print_expr(caddr(p))
688 accumulator += "="
689 accumulator += print_expr(cadddr(p))
690 accumulator += "}^{"
691 accumulator += print_expr(caddddr(p))
692 accumulator += "}{"
693 accumulator += print_expr(cadr(p))
694 accumulator += "}"
695 return accumulator
696
697print_SUM_codegen = (p) ->
698
699 body = cadr(p)
700 variable = caddr(p)
701 lowerlimit = cadddr(p)
702 upperlimit = caddddr(p)
703
704 accumulator =
705 "(function(){" +
706 " var " + variable + "; " +
707 " var holderSum = 0; " +
708 " var lowerlimit = " + print_expr(lowerlimit) + "; " +
709 " var upperlimit = " + print_expr(upperlimit) + "; " +
710 " for (" + variable + " = lowerlimit; " + variable + " < upperlimit; " + variable + "++) { " +
711 " holderSum += " + print_expr(body) + ";" +
712 " } "+
713 " return holderSum;" +
714 "})()"
715
716 return accumulator
717
718print_TEST_latex = (p) ->
719 accumulator = "\\left\\{ \\begin{array}{ll}"
720
721 p = cdr(p)
722 while (iscons(p))
723
724 # odd number of parameters means that the
725 # last argument becomes the default case
726 # i.e. the one without a test.
727 if (cdr(p) == symbol(NIL))
728 accumulator += "{"
729 accumulator += print_expr(car(p))
730 accumulator += "} & otherwise "
731 accumulator += " \\\\\\\\"
732 break
733
734 accumulator += "{"
735 accumulator += print_expr(cadr(p))
736 accumulator += "} & if & "
737 accumulator += print_expr(car(p))
738 accumulator += " \\\\\\\\"
739
740 # test unsuccessful, continue to the
741 # next pair of test,value
742 p = cddr(p)
743 accumulator = accumulator.substring(0, accumulator.length - 4);
744 accumulator += "\\end{array} \\right."
745
746print_TEST_codegen = (p) ->
747
748 accumulator = "(function(){"
749
750 p = cdr(p)
751 howManyIfs = 0
752 while (iscons(p))
753
754 # odd number of parameters means that the
755 # last argument becomes the default case
756 # i.e. the one without a test.
757 if (cdr(p) == symbol(NIL))
758 accumulator += "else {"
759 accumulator += "return (" + print_expr(car(p)) + ");"
760 accumulator += "}"
761 break
762
763 if howManyIfs
764 accumulator += " else "
765
766 accumulator += "if (" + print_expr(car(p)) + "){"
767 accumulator += "return (" + print_expr(cadr(p)) + ");"
768 accumulator += "}"
769
770 # test unsuccessful, continue to the
771 # next pair of test,value
772 howManyIfs++
773 p = cddr(p)
774
775 accumulator += "})()"
776
777 return accumulator
778
779
780print_TESTLT_latex = (p) ->
781 accumulator = "{"
782 accumulator += print_expr(cadr(p))
783 accumulator += "}"
784 accumulator += " < "
785 accumulator += "{"
786 accumulator += print_expr(caddr(p))
787 accumulator += "}"
788
789print_TESTLE_latex = (p) ->
790 accumulator = "{"
791 accumulator += print_expr(cadr(p))
792 accumulator += "}"
793 accumulator += " \\leq "
794 accumulator += "{"
795 accumulator += print_expr(caddr(p))
796 accumulator += "}"
797
798print_TESTGT_latex = (p) ->
799 accumulator = "{"
800 accumulator += print_expr(cadr(p))
801 accumulator += "}"
802 accumulator += " > "
803 accumulator += "{"
804 accumulator += print_expr(caddr(p))
805 accumulator += "}"
806
807print_TESTGE_latex = (p) ->
808 accumulator = "{"
809 accumulator += print_expr(cadr(p))
810 accumulator += "}"
811 accumulator += " \\geq "
812 accumulator += "{"
813 accumulator += print_expr(caddr(p))
814 accumulator += "}"
815
816print_TESTEQ_latex = (p) ->
817 accumulator = "{"
818 accumulator += print_expr(cadr(p))
819 accumulator += "}"
820 accumulator += " = "
821 accumulator += "{"
822 accumulator += print_expr(caddr(p))
823 accumulator += "}"
824
825print_FOR_codegen = (p) ->
826 body = cadr(p)
827 variable = caddr(p)
828 lowerlimit = cadddr(p)
829 upperlimit = caddddr(p)
830
831 accumulator =
832 "(function(){" +
833 " var " + variable + "; " +
834 " var lowerlimit = " + print_expr(lowerlimit) + "; " +
835 " var upperlimit = " + print_expr(upperlimit) + "; " +
836 " for (" + variable + " = lowerlimit; " + variable + " < upperlimit; " + variable + "++) { " +
837 " " + print_expr(body) +
838 " } "+
839 "})()"
840
841 return accumulator
842
843print_DO_codegen = (p) ->
844 accumulator = ""
845
846 p = cdr(p)
847 while iscons(p)
848 accumulator += print_expr(car(p))
849 p = cdr(p)
850
851 return accumulator
852
853print_SETQ_codegen = (p) ->
854 accumulator = ""
855 accumulator += print_expr(cadr(p))
856 accumulator += " = "
857 accumulator += print_expr(caddr(p))
858 accumulator += "; "
859 return accumulator
860
861
862print_PRODUCT_latex = (p) ->
863 accumulator = "\\prod_{"
864 accumulator += print_expr(caddr(p))
865 accumulator += "="
866 accumulator += print_expr(cadddr(p))
867 accumulator += "}^{"
868 accumulator += print_expr(caddddr(p))
869 accumulator += "}{"
870 accumulator += print_expr(cadr(p))
871 accumulator += "}"
872 return accumulator
873
874print_PRODUCT_codegen = (p) ->
875
876 body = cadr(p)
877 variable = caddr(p)
878 lowerlimit = cadddr(p)
879 upperlimit = caddddr(p)
880
881 accumulator =
882 "(function(){" +
883 " var " + variable + "; " +
884 " var holderProduct = 1; " +
885 " var lowerlimit = " + print_expr(lowerlimit) + "; " +
886 " var upperlimit = " + print_expr(upperlimit) + "; " +
887 " for (" + variable + " = lowerlimit; " + variable + " < upperlimit; " + variable + "++) { " +
888 " holderProduct *= " + print_expr(body) + ";" +
889 " } "+
890 " return holderProduct;" +
891 "})()"
892
893 return accumulator
894
895
896print_base = (p) ->
897 accumulator = ""
898 if (isadd(cadr(p)) || caadr(p) == symbol(MULTIPLY) || caadr(p) == symbol(POWER) || isnegativenumber(cadr(p)))
899 accumulator += print_str('(')
900 accumulator += print_expr(cadr(p))
901 accumulator += print_str(')')
902 else if (isnum(cadr(p)) && (lessp(cadr(p), zero) || isfraction(cadr(p))))
903 accumulator += print_str('(')
904 accumulator += print_factor(cadr(p))
905 accumulator += print_str(')')
906 else
907 accumulator += print_factor(cadr(p))
908 return accumulator
909
910print_exponent = (p) ->
911 accumulator = ""
912 if (iscons(caddr(p)) || isfraction(caddr(p)) || (isnum(caddr(p)) && lessp(caddr(p), zero)))
913 accumulator += print_str('(')
914 accumulator += print_expr(caddr(p))
915 accumulator += print_str(')')
916 else
917 accumulator += print_factor(caddr(p))
918 return accumulator
919
920print_power = (base, exponent) ->
921 accumulator = ""
922
923 #debugger
924 if DEBUG then console.log "power base: " + base + " " + " exponent: " + exponent
925
926 # quick check is this is actually a square root.
927 if isoneovertwo(exponent)
928 if equaln(base, 2)
929 if codeGen
930 accumulator += print_str("Math.SQRT2")
931 return accumulator
932 else
933 if printMode == PRINTMODE_LATEX
934 accumulator += print_str("\\sqrt{")
935 accumulator += print_expr(base)
936 accumulator += print_str("}")
937 return accumulator
938 else if codeGen
939 accumulator += print_str("Math.sqrt(")
940 accumulator += print_expr(base)
941 accumulator += print_str(')')
942 return accumulator
943
944
945 if ((equaln(get_binding(symbol(PRINT_LEAVE_E_ALONE)), 1)) and base == symbol(E))
946 if codeGen
947 accumulator += print_str("Math.exp(")
948 accumulator += print_expo_of_denom exponent
949 accumulator += print_str(')')
950 return accumulator
951
952 if printMode == PRINTMODE_LATEX
953 accumulator += print_str("e^{")
954 accumulator += print_expr(exponent)
955 accumulator += print_str("}")
956 else
957 accumulator += print_str("exp(")
958 accumulator += print_expr(exponent)
959 accumulator += print_str(')')
960 return accumulator
961
962 if codeGen
963 accumulator += print_str("Math.pow(")
964 accumulator += print_base_of_denom base
965 accumulator += print_str(", ")
966 accumulator += print_expo_of_denom exponent
967 accumulator += print_str(')')
968 return accumulator
969
970
971 if ((equaln(get_binding(symbol(PRINT_LEAVE_X_ALONE)), 0)) or base.printname != "x")
972 # if the exponent is negative then
973 # we invert the base BUT we don't do
974 # that if the base is "e", because for
975 # example when trigonometric functions are
976 # expressed in terms of exponential functions
977 # that would be really confusing, one wants to
978 # keep "e" as the base and the negative exponent
979 if (base != symbol(E))
980 if (isminusone(exponent))
981 if printMode == PRINTMODE_LATEX
982 accumulator += print_str("\\frac{1}{")
983 else if printMode == PRINTMODE_PLAIN and !test_flag
984 accumulator += print_str("1 / ")
985 else
986 accumulator += print_str("1/")
987
988 if (iscons(base) and printMode != PRINTMODE_LATEX)
989 accumulator += print_str('(')
990 accumulator += print_expr(base)
991 accumulator += print_str(')')
992 else
993 accumulator += print_expr(base)
994
995 if printMode == PRINTMODE_LATEX
996 accumulator += print_str("}")
997
998 return accumulator
999
1000 if (isnegativeterm(exponent))
1001 if printMode == PRINTMODE_LATEX
1002 accumulator += print_str("\\frac{1}{")
1003 else if printMode == PRINTMODE_PLAIN and !test_flag
1004 accumulator += print_str("1 / ")
1005 else
1006 accumulator += print_str("1/")
1007
1008 push(exponent)
1009 push_integer(-1)
1010 multiply()
1011 newExponent = pop()
1012
1013 if (iscons(base) and printMode != PRINTMODE_LATEX)
1014 accumulator += print_str('(')
1015 accumulator += print_power(base, newExponent)
1016 accumulator += print_str(')')
1017 else
1018 accumulator += print_power(base, newExponent)
1019
1020
1021 if printMode == PRINTMODE_LATEX
1022 accumulator += print_str("}")
1023
1024 return accumulator
1025
1026
1027 if (isfraction(exponent) and printMode == PRINTMODE_LATEX)
1028 accumulator += print_str("\\sqrt")
1029 push(exponent)
1030 denominator()
1031 denomExponent = pop()
1032 # we omit the "2" on the radical
1033 if !isplustwo(denomExponent)
1034 accumulator += print_str("[")
1035 accumulator += print_expr(denomExponent)
1036 accumulator += print_str("]")
1037 accumulator += print_str("{")
1038 push(exponent)
1039 numerator()
1040 numExponent = pop()
1041 exponent = numExponent
1042 accumulator += print_power(base, exponent)
1043 accumulator += print_str("}")
1044 return accumulator
1045
1046 if printMode == PRINTMODE_LATEX and isplusone(exponent)
1047 # if we are in latex mode we turn many
1048 # radicals into a radix sign with a power
1049 # underneath, and the power is often one
1050 # (e.g. square root turns into a radical
1051 # with a power one underneath) so handle
1052 # this case simply here, just print the base
1053 accumulator += print_expr(base)
1054 else
1055 # print the base,
1056 # determining if it needs to be
1057 # wrapped in parentheses or not
1058 if (isadd(base) || isnegativenumber(base))
1059 accumulator += print_str('(')
1060 accumulator += print_expr(base)
1061 accumulator += print_str(')')
1062 else if ( car(base) == symbol(MULTIPLY) || car(base) == symbol(POWER))
1063 if printMode != PRINTMODE_LATEX then accumulator += print_str('(')
1064 accumulator += print_factor(base, true)
1065 if printMode != PRINTMODE_LATEX then accumulator += print_str(')')
1066 else if (isnum(base) && (lessp(base, zero) || isfraction(base)))
1067 accumulator += print_str('(')
1068 accumulator += print_factor(base)
1069 accumulator += print_str(')')
1070 else
1071 accumulator += print_factor(base)
1072
1073 # print the power symbol
1074 #debugger
1075 if printMode == PRINTMODE_PLAIN and !test_flag
1076 #print_str(" ^ ")
1077 accumulator += print_str(power_str)
1078 else
1079 accumulator += print_str("^")
1080
1081 # print the exponent
1082 if printMode == PRINTMODE_LATEX
1083 # in latex mode, one can omit the curly braces
1084 # wrapping the exponent if the exponent is only
1085 # one character long
1086 if print_expr(exponent).length > 1
1087 accumulator += print_str("{")
1088 accumulator += print_expr(exponent)
1089 accumulator += print_str("}")
1090 else
1091 accumulator += print_expr(exponent)
1092 else if (iscons(exponent) || isfraction(exponent) || (isnum(exponent) && lessp(exponent, zero)))
1093 accumulator += print_str('(')
1094 accumulator += print_expr(exponent)
1095 accumulator += print_str(')')
1096 else
1097 accumulator += print_factor(exponent)
1098 return accumulator
1099
1100print_index_function = (p) ->
1101 accumulator = ""
1102 p = cdr(p);
1103 if (caar(p) == symbol(ADD) || caar(p) == symbol(MULTIPLY) || caar(p) == symbol(POWER) || caar(p) == symbol(FACTORIAL))
1104 accumulator += print_subexpr(car(p));
1105 else
1106 accumulator += print_expr(car(p));
1107 accumulator += print_str('[');
1108 p = cdr(p);
1109 if (iscons(p))
1110 accumulator += print_expr(car(p));
1111 p = cdr(p);
1112 while(iscons(p))
1113 accumulator += print_str(',');
1114 accumulator += print_expr(car(p));
1115 p = cdr(p);
1116 accumulator += print_str(']');
1117 return accumulator
1118
1119
1120print_factor = (p, omitParens) ->
1121 # debugger
1122 accumulator = ""
1123 if (isnum(p))
1124 accumulator += print_number(p, false)
1125 return accumulator
1126
1127 if (isstr(p))
1128 accumulator += print_str("\"")
1129 accumulator += print_str(p.str)
1130 accumulator += print_str("\"")
1131 return accumulator
1132
1133 if (istensor(p))
1134 if printMode == PRINTMODE_LATEX
1135 accumulator += print_tensor_latex(p)
1136 else
1137 accumulator += print_tensor(p)
1138 return accumulator
1139
1140 if (car(p) == symbol(MULTIPLY))
1141 if !omitParens
1142 if (sign_of_term(p) == '-' or printMode != PRINTMODE_LATEX)
1143 if printMode == PRINTMODE_LATEX
1144 accumulator += print_str(" \\left (")
1145 else
1146 accumulator += print_str('(')
1147 accumulator += print_expr(p)
1148 if !omitParens
1149 if (sign_of_term(p) == '-' or printMode != PRINTMODE_LATEX)
1150 if printMode == PRINTMODE_LATEX
1151 accumulator += print_str(" \\right ) ")
1152 else
1153 accumulator += print_str(')')
1154 return accumulator
1155 else if (isadd(p))
1156 if !omitParens then accumulator += print_str('(')
1157 accumulator += print_expr(p)
1158 if !omitParens then accumulator += print_str(')')
1159 return accumulator
1160
1161 if (car(p) == symbol(POWER))
1162 base = cadr(p)
1163 exponent = caddr(p)
1164 accumulator += print_power(base, exponent)
1165 return accumulator
1166
1167 # if (car(p) == _list) {
1168 # print_str("{")
1169 # p = cdr(p)
1170 # if (iscons(p)) {
1171 # print_expr(car(p))
1172 # p = cdr(p)
1173 # }
1174 # while (iscons(p)) {
1175 # print_str(",")
1176 # print_expr(car(p))
1177 # p = cdr(p)
1178 # }
1179 # print_str("}")
1180 # return
1181 # }
1182
1183 if (car(p) == symbol(FUNCTION))
1184 fbody = cadr(p)
1185
1186 if !codeGen
1187 parameters = caddr(p)
1188 accumulator += print_str "function "
1189 if DEBUG then console.log "emittedString from print_factor " + stringsEmittedByUserPrintouts
1190 returned = print_list parameters
1191 accumulator += returned
1192 accumulator += print_str " -> "
1193 accumulator += print_expr fbody
1194 return accumulator
1195
1196 if (car(p) == symbol(PATTERN))
1197
1198 accumulator += print_expr(caadr(p))
1199 if printMode == PRINTMODE_LATEX
1200 accumulator += print_str(" \\rightarrow ")
1201 else
1202 if printMode == PRINTMODE_PLAIN and !test_flag
1203 accumulator += print_str(" -> ")
1204 else
1205 accumulator += print_str("->")
1206
1207 accumulator += print_expr car(cdr(cadr(p)))
1208 return accumulator
1209
1210
1211 if (car(p) == symbol(INDEX) && issymbol(cadr(p)))
1212 accumulator += print_index_function(p)
1213 return accumulator
1214
1215 if (car(p) == symbol(FACTORIAL))
1216 accumulator += print_factorial_function(p)
1217 return accumulator
1218 else if (car(p) == symbol(ABS) && printMode == PRINTMODE_LATEX)
1219 accumulator += print_ABS_latex(p)
1220 return accumulator
1221 else if (car(p) == symbol(SQRT) && printMode == PRINTMODE_LATEX)
1222 #debugger
1223 accumulator += print_SQRT_latex(p)
1224 return accumulator
1225 else if car(p) == symbol(TRANSPOSE)
1226 if printMode == PRINTMODE_LATEX
1227 accumulator += print_TRANSPOSE_latex(p)
1228 return accumulator
1229 else if codeGen
1230 accumulator += print_TRANSPOSE_codegen(p)
1231 return accumulator
1232 else if car(p) == symbol(UNIT)
1233 if codeGen
1234 accumulator += print_UNIT_codegen(p)
1235 return accumulator
1236 else if car(p) == symbol(INV)
1237 if printMode == PRINTMODE_LATEX
1238 accumulator += print_INV_latex(p)
1239 return accumulator
1240 else if codeGen
1241 accumulator += print_INV_codegen(p)
1242 return accumulator
1243 else if (car(p) == symbol(BINOMIAL) && printMode == PRINTMODE_LATEX)
1244 accumulator += print_BINOMIAL_latex(p)
1245 return accumulator
1246 else if (car(p) == symbol(DEFINT) && printMode == PRINTMODE_LATEX)
1247 accumulator += print_DEFINT_latex(p)
1248 return accumulator
1249 else if isinnerordot(p)
1250 if printMode == PRINTMODE_LATEX
1251 accumulator += print_DOT_latex(p)
1252 return accumulator
1253 else if codeGen
1254 accumulator += print_DOT_codegen(p)
1255 return accumulator
1256 else if car(p) == symbol(SIN)
1257 if codeGen
1258 accumulator += print_SIN_codegen(p)
1259 return accumulator
1260 else if car(p) == symbol(COS)
1261 if codeGen
1262 accumulator += print_COS_codegen(p)
1263 return accumulator
1264 else if car(p) == symbol(TAN)
1265 if codeGen
1266 accumulator += print_TAN_codegen(p)
1267 return accumulator
1268 else if car(p) == symbol(ARCSIN)
1269 if codeGen
1270 accumulator += print_ARCSIN_codegen(p)
1271 return accumulator
1272 else if car(p) == symbol(ARCCOS)
1273 if codeGen
1274 accumulator += print_ARCCOS_codegen(p)
1275 return accumulator
1276 else if car(p) == symbol(ARCTAN)
1277 if codeGen
1278 accumulator += print_ARCTAN_codegen(p)
1279 return accumulator
1280 else if car(p) == symbol(SUM)
1281 if printMode == PRINTMODE_LATEX
1282 accumulator += print_SUM_latex(p)
1283 return accumulator
1284 else if codeGen
1285 accumulator += print_SUM_codegen(p)
1286 return accumulator
1287 #else if car(p) == symbol(QUOTE)
1288 # if printMode == PRINTMODE_LATEX
1289 # print_expr(cadr(p))
1290 # return accumulator
1291 else if car(p) == symbol(PRODUCT)
1292 if printMode == PRINTMODE_LATEX
1293 accumulator += print_PRODUCT_latex(p)
1294 return accumulator
1295 else if codeGen
1296 accumulator += print_PRODUCT_codegen(p)
1297 return accumulator
1298 else if car(p) == symbol(FOR)
1299 if codeGen
1300 accumulator += print_FOR_codegen(p)
1301 return accumulator
1302 else if car(p) == symbol(DO)
1303 if codeGen
1304 accumulator += print_DO_codegen(p)
1305 return accumulator
1306 else if car(p) == symbol(TEST)
1307 if codeGen
1308 accumulator += print_TEST_codegen(p)
1309 return accumulator
1310 if printMode == PRINTMODE_LATEX
1311 accumulator += print_TEST_latex(p)
1312 return accumulator
1313 else if car(p) == symbol(TESTLT)
1314 if codeGen
1315 accumulator += "(("+print_expr(cadr(p))+") < ("+print_expr(caddr(p))+"))"
1316 return accumulator
1317 if printMode == PRINTMODE_LATEX
1318 accumulator += print_TESTLT_latex(p)
1319 return accumulator
1320 else if car(p) == symbol(TESTLE)
1321 if codeGen
1322 accumulator += "(("+print_expr(cadr(p))+") <= ("+print_expr(caddr(p))+"))"
1323 return accumulator
1324 if printMode == PRINTMODE_LATEX
1325 accumulator += print_TESTLE_latex(p)
1326 return accumulator
1327 else if car(p) == symbol(TESTGT)
1328 if codeGen
1329 accumulator += "(("+print_expr(cadr(p))+") > ("+print_expr(caddr(p))+"))"
1330 return accumulator
1331 if printMode == PRINTMODE_LATEX
1332 accumulator += print_TESTGT_latex(p)
1333 return accumulator
1334 else if car(p) == symbol(TESTGE)
1335 if codeGen
1336 accumulator += "(("+print_expr(cadr(p))+") >= ("+print_expr(caddr(p))+"))"
1337 return accumulator
1338 if printMode == PRINTMODE_LATEX
1339 accumulator += print_TESTGE_latex(p)
1340 return accumulator
1341 else if car(p) == symbol(TESTEQ)
1342 if codeGen
1343 accumulator += "(("+print_expr(cadr(p))+") === ("+print_expr(caddr(p))+"))"
1344 return accumulator
1345 if printMode == PRINTMODE_LATEX
1346 accumulator += print_TESTEQ_latex(p)
1347 return accumulator
1348 else if car(p) == symbol(FLOOR)
1349 if codeGen
1350 accumulator += "Math.floor("+print_expr(cadr(p))+")"
1351 return accumulator
1352 if printMode == PRINTMODE_LATEX
1353 accumulator += " \\lfloor {" + print_expr(cadr(p)) + "} \\rfloor "
1354 return accumulator
1355 else if car(p) == symbol(CEILING)
1356 debugger
1357 if codeGen
1358 accumulator += "Math.ceiling("+print_expr(cadr(p))+")"
1359 return accumulator
1360 if printMode == PRINTMODE_LATEX
1361 accumulator += " \\lceil {" + print_expr(cadr(p)) + "} \\rceil "
1362 return accumulator
1363 else if car(p) == symbol(ROUND)
1364 if codeGen
1365 accumulator += "Math.round("+print_expr(cadr(p))+")"
1366 return accumulator
1367 else if car(p) == symbol(SETQ)
1368 if codeGen
1369 accumulator += print_SETQ_codegen(p)
1370 return accumulator
1371 else
1372 accumulator += print_expr cadr p
1373 accumulator += print_str("=")
1374 accumulator += print_expr caddr p
1375 return accumulator
1376
1377
1378 if (iscons(p))
1379 #if (car(p) == symbol(FORMAL) && cadr(p)->k == SYM) {
1380 # print_str(((struct symbol *) cadr(p))->name)
1381 # return
1382 #}
1383 accumulator += print_factor(car(p))
1384 p = cdr(p)
1385 if !omitParens then accumulator += print_str('(')
1386 if (iscons(p))
1387 accumulator += print_expr(car(p))
1388 p = cdr(p)
1389 while (iscons(p))
1390 accumulator += print_str(",")
1391 accumulator += print_expr(car(p))
1392 p = cdr(p)
1393 if !omitParens then accumulator += print_str(')')
1394 return accumulator
1395
1396 if (p == symbol(DERIVATIVE))
1397 accumulator += print_char('d')
1398 else if (p == symbol(E))
1399 if codeGen
1400 accumulator += print_str("Math.E")
1401 else
1402 accumulator += print_str("e")
1403 else if (p == symbol(PI))
1404 if printMode == PRINTMODE_LATEX
1405 accumulator += print_str("\\pi")
1406 else
1407 accumulator += print_str("pi")
1408 else
1409 accumulator += print_str(get_printname(p))
1410 return accumulator
1411
1412
1413print_list = (p) ->
1414 accumulator = ""
1415 switch (p.k)
1416 when CONS
1417 accumulator += ('(')
1418 accumulator += print_list(car(p))
1419 if p == cdr(p) and p != symbol(NIL)
1420 console.log "oh no recursive!"
1421 debugger
1422 p = cdr(p)
1423 while (iscons(p))
1424 accumulator += (" ")
1425 accumulator += print_list(car(p))
1426 p = cdr(p)
1427 if p == cdr(p) and p != symbol(NIL)
1428 console.log "oh no recursive!"
1429 debugger
1430 if (p != symbol(NIL))
1431 accumulator += (" . ")
1432 accumulator += print_list(p)
1433 accumulator += (')')
1434 when STR
1435 #print_str("\"")
1436 accumulator += (p.str)
1437 #print_str("\"")
1438 when NUM, DOUBLE
1439 accumulator += print_number(p, true)
1440 when SYM
1441 accumulator += get_printname(p)
1442 else
1443 accumulator += ("<tensor>")
1444 return accumulator
1445
1446print_multiply_sign = ->
1447 accumulator = ""
1448 if printMode == PRINTMODE_LATEX
1449 if printMode == PRINTMODE_PLAIN and !test_flag
1450 accumulator += print_str(" ")
1451 else
1452 return accumulator
1453
1454 if printMode == PRINTMODE_PLAIN and !test_flag and !codeGen
1455 accumulator += print_str(" ")
1456 else
1457 accumulator += print_str("*")
1458 return accumulator
1459
1460is_denominator = (p) ->
1461 if (car(p) == symbol(POWER) && cadr(p) != symbol(E) && isnegativeterm(caddr(p)))
1462 return 1
1463 else
1464 return 0
1465
1466# don't consider the leading fraction
1467# we want 2/3*a*b*c instead of 2*a*b*c/3
1468
1469any_denominators = (p) ->
1470 p = cdr(p)
1471 # if (isfraction(car(p)))
1472 # return 1
1473 while (iscons(p))
1474 q = car(p)
1475 if (is_denominator(q))
1476 return 1
1477 p = cdr(p)
1478 return 0
1479