UNPKG

17.4 kBtext/coffeescriptView Raw
1###
2
3Prints in "2d", e.g. instead of 1/(x+1)^2 :
4
5 1
6 ----------
7 2
8 (1 + x)
9
10 Note that although this looks more natural, a) it's not parsable and
11 b) it can be occasionally be ambiguous, such as:
12
13 1
14 ----
15 2
16 x
17
18is 1/x^2 but it also looks a little like x^(1/2)
19
20###
21
22#-----------------------------------------------------------------------------
23#
24# Examples:
25#
26# 012345678
27# -2 .........
28# -1 .........
29# 0 ..hello.. x=2, y=0, h=1, w=5
30# 1 .........
31# 2 .........
32#
33# 012345678
34# -2 .........
35# -1 ..355....
36# 0 ..---.... x=2, y=-1, h=3, w=3
37# 1 ..113....
38# 2 .........
39#
40#-----------------------------------------------------------------------------
41
42
43
44YMAX = 10000
45class glyph
46 c: 0
47 x: 0
48 y: 0
49
50# will contain glyphs
51chartab = []
52for charTabIndex in [0...YMAX]
53 chartab[charTabIndex] = new glyph()
54
55
56yindex = 0
57level = 0
58emit_x = 0
59expr_level = 0
60display_flag = 0
61
62
63# this is not really the translated version,
64# the original is in window.cpp and is
65# rather more complex
66printchar_nowrap = (character) ->
67 accumulator = ""
68 accumulator += character
69 return accumulator
70
71printchar = (character) ->
72 return printchar_nowrap character
73
74print2dascii = (p) ->
75 h = 0
76 w = 0
77 y = 0
78
79 save()
80
81 yindex = 0
82 level = 0
83 emit_x = 0
84 emit_top_expr(p)
85
86 # if too wide then print flat
87
88 [h,w,y] = get_size(0, yindex)
89
90 if (w > 100)
91 printline(p)
92 restore()
93 return
94
95 beenPrinted = print_glyphs()
96
97 restore()
98 return beenPrinted
99
100emit_top_expr = (p) ->
101 if (car(p) == symbol(SETQ))
102 emit_expr(cadr(p))
103 __emit_str(" = ")
104 emit_expr(caddr(p))
105 return
106
107 if (istensor(p))
108 emit_tensor(p)
109 else
110 emit_expr(p)
111
112will_be_displayed_as_fraction = (p) ->
113 if (level > 0)
114 return 0
115 if (isfraction(p))
116 return 1
117 if (car(p) != symbol(MULTIPLY))
118 return 0
119 if (isfraction(cadr(p)))
120 return 1
121 while (iscons(p))
122 if (isdenominator(car(p)))
123 return 1
124 p = cdr(p)
125 return 0
126
127emit_expr = (p) ->
128 # if (level > 0) {
129 # printexpr(p)
130 # return
131 # }
132 expr_level++
133 if (car(p) == symbol(ADD))
134 p = cdr(p)
135 if (__is_negative(car(p)))
136 __emit_char('-')
137 if (will_be_displayed_as_fraction(car(p)))
138 __emit_char(' ')
139 emit_term(car(p))
140 p = cdr(p)
141 while (iscons(p))
142 if (__is_negative(car(p)))
143 __emit_char(' ')
144 __emit_char('-')
145 __emit_char(' ')
146 else
147 __emit_char(' ')
148 __emit_char('+')
149 __emit_char(' ')
150
151 emit_term(car(p))
152 p = cdr(p)
153 else
154 if (__is_negative(p))
155 __emit_char('-')
156 if (will_be_displayed_as_fraction(p))
157 __emit_char(' ')
158 emit_term(p)
159 expr_level--
160
161emit_unsigned_expr = (p) ->
162 if (car(p) == symbol(ADD))
163 p = cdr(p)
164 # if (__is_negative(car(p)))
165 # __emit_char('-')
166 emit_term(car(p))
167 p = cdr(p)
168 while (iscons(p))
169 if (__is_negative(car(p)))
170 __emit_char(' ')
171 __emit_char('-')
172 __emit_char(' ')
173 else
174 __emit_char(' ')
175 __emit_char('+')
176 __emit_char(' ')
177 emit_term(car(p))
178 p = cdr(p)
179 else
180 # if (__is_negative(p))
181 # __emit_char('-')
182 emit_term(p)
183
184__is_negative = (p) ->
185 if (isnegativenumber(p))
186 return 1
187 if (car(p) == symbol(MULTIPLY) && isnegativenumber(cadr(p)))
188 return 1
189 return 0
190
191emit_term = (p) ->
192 if (car(p) == symbol(MULTIPLY))
193 n = count_denominators(p)
194 if (n && level == 0)
195 emit_fraction(p, n)
196 else
197 emit_multiply(p, n)
198 else
199 emit_factor(p)
200
201isdenominator = (p) ->
202 if (car(p) == symbol(POWER) && cadr(p) != symbol(E) && __is_negative(caddr(p)))
203 return 1
204 else
205 return 0
206
207count_denominators = (p) ->
208 count = 0
209 p = cdr(p)
210 # if (isfraction(car(p))) {
211 # count++
212 # p = cdr(p)
213 # }
214 while (iscons(p))
215 q = car(p)
216 if (isdenominator(q))
217 count++
218 p = cdr(p)
219 return count
220
221# n is the number of denominators, not counting a fraction like 1/2
222emit_multiply = (p, n) ->
223 if (n == 0)
224 p = cdr(p)
225 if (isplusone(car(p)) || isminusone(car(p)))
226 p = cdr(p)
227 emit_factor(car(p))
228 p = cdr(p)
229 while (iscons(p))
230 __emit_char(' ')
231 emit_factor(car(p))
232 p = cdr(p)
233 else
234 emit_numerators(p)
235 __emit_char('/')
236 # need grouping if more than one denominator
237 if (n > 1 || isfraction(cadr(p)))
238 __emit_char('(')
239 emit_denominators(p)
240 __emit_char(')')
241 else
242 emit_denominators(p)
243
244#define A p3
245#define B p4
246
247# sign of term has already been emitted
248
249emit_fraction = (p, d) ->
250 count = 0
251 k1 = 0
252 k2 = 0
253 n = 0
254 x = 0
255
256 save()
257
258 p3 = one; # p3 is A
259 p4 = one; # p4 is B
260
261 # handle numerical coefficient
262
263 if (isrational(cadr(p)))
264 push(cadr(p))
265 mp_numerator()
266 absval()
267 p3 = pop(); # p3 is A
268 push(cadr(p))
269 mp_denominator()
270 p4 = pop(); # p4 is B
271
272 if (isdouble(cadr(p)))
273 push(cadr(p))
274 absval()
275 p3 = pop(); # p3 is A
276
277 # count numerators
278
279 if (isplusone(p3)) # p3 is A
280 n = 0
281 else
282 n = 1
283 p1 = cdr(p)
284 if (isnum(car(p1)))
285 p1 = cdr(p1)
286 while (iscons(p1))
287 p2 = car(p1)
288 if (isdenominator(p2))
289 doNothing = 1
290 else
291 n++
292 p1 = cdr(p1)
293
294 # emit numerators
295
296 x = emit_x
297
298 k1 = yindex
299
300 count = 0
301
302 # emit numerical coefficient
303
304 if (!isplusone(p3)) # p3 is A
305 emit_number(p3, 0); # p3 is A
306 count++
307
308 # skip over "multiply"
309
310 p1 = cdr(p)
311
312 # skip over numerical coefficient, already handled
313
314 if (isnum(car(p1)))
315 p1 = cdr(p1)
316
317 while (iscons(p1))
318 p2 = car(p1)
319 if (isdenominator(p2))
320 doNothing = 1
321 else
322 if (count > 0)
323 __emit_char(' ')
324 if (n == 1)
325 emit_expr(p2)
326 else
327 emit_factor(p2)
328 count++
329 p1 = cdr(p1)
330
331 if (count == 0)
332 __emit_char('1')
333
334 # emit denominators
335
336 k2 = yindex
337
338 count = 0
339
340 if (!isplusone(p4)) # p4 is B
341 emit_number(p4, 0); # p4 is B
342 count++
343 d++
344
345 p1 = cdr(p)
346
347 if (isrational(car(p1)))
348 p1 = cdr(p1)
349
350 while (iscons(p1))
351 p2 = car(p1)
352 if (isdenominator(p2))
353 if (count > 0)
354 __emit_char(' ')
355 emit_denominator(p2, d)
356 count++
357 p1 = cdr(p1)
358
359 fixup_fraction(x, k1, k2)
360
361 restore()
362
363# p points to a multiply
364
365emit_numerators = (p) ->
366 save()
367
368 n = 0
369
370 p1 = one
371
372 p = cdr(p)
373
374 if (isrational(car(p)))
375 push(car(p))
376 mp_numerator()
377 absval()
378 p1 = pop()
379 p = cdr(p)
380 else if (isdouble(car(p)))
381 push(car(p))
382 absval()
383 p1 = pop()
384 p = cdr(p)
385
386 n = 0
387
388 if (!isplusone(p1))
389 emit_number(p1, 0)
390 n++
391
392 while (iscons(p))
393 if (isdenominator(car(p)))
394 doNothing = 1
395 else
396 if (n > 0)
397 __emit_char(' ')
398 emit_factor(car(p))
399 n++
400 p = cdr(p)
401
402 if (n == 0)
403 __emit_char('1')
404
405 restore()
406
407# p points to a multiply
408
409emit_denominators = (p) ->
410
411 save()
412
413 n = 0
414
415 p = cdr(p)
416
417 if (isfraction(car(p)))
418 push(car(p))
419 mp_denominator()
420 p1 = pop()
421 emit_number(p1, 0)
422 n++
423 p = cdr(p)
424
425 while (iscons(p))
426 if (isdenominator(car(p)))
427 if (n > 0)
428 __emit_char(' ')
429 emit_denominator(car(p), 0)
430 n++
431 p = cdr(p)
432
433 restore()
434
435emit_factor = (p) ->
436 if (istensor(p))
437 if (level == 0)
438 #emit_tensor(p)
439 emit_flat_tensor(p)
440 else
441 emit_flat_tensor(p)
442 return
443
444 if (isdouble(p))
445 emit_number(p, 0)
446 return
447
448 if (car(p) == symbol(ADD) || car(p) == symbol(MULTIPLY))
449 emit_subexpr(p)
450 return
451
452 if (car(p) == symbol(POWER))
453 emit_power(p)
454 return
455
456 if (iscons(p))
457 #if (car(p) == symbol(FORMAL) && cadr(p).k == SYM)
458 # emit_symbol(cadr(p))
459 #else
460 emit_function(p)
461 return
462
463 if (isnum(p))
464 if (level == 0)
465 emit_numerical_fraction(p)
466 else
467 emit_number(p, 0)
468 return
469
470 if (issymbol(p))
471 emit_symbol(p)
472 return
473
474 if (isstr(p))
475 emit_string(p)
476 return
477
478emit_numerical_fraction = (p) ->
479 k1 = 0
480 k2 = 0
481 x = 0
482
483 save()
484
485 push(p)
486 mp_numerator()
487 absval()
488 p3 = pop(); # p3 is A
489
490 push(p)
491 mp_denominator()
492 p4 = pop(); # p4 is B
493
494 if (isplusone(p4)) # p4 is B
495 emit_number(p3, 0); # p3 is A
496 restore()
497 return
498
499 x = emit_x
500
501 k1 = yindex
502
503 emit_number(p3, 0); # p3 is A
504
505 k2 = yindex
506
507 emit_number(p4, 0) # p4 is B
508
509 fixup_fraction(x, k1, k2)
510
511 restore()
512
513# if it's a factor then it doesn't need parens around it, i.e. 1/sin(theta)^2
514
515isfactor = (p) ->
516 if (iscons(p) && car(p) != symbol(ADD) && car(p) != symbol(MULTIPLY) && car(p) != symbol(POWER))
517 return 1
518 if (issymbol(p))
519 return 1
520 if (isfraction(p))
521 return 0
522 if (isnegativenumber(p))
523 return 0
524 if (isnum(p))
525 return 1
526 return 0
527
528emit_power = (p) ->
529 k1 = 0
530 k2 = 0
531 x = 0
532
533 if (cadr(p) == symbol(E))
534 __emit_str("exp(")
535 emit_expr(caddr(p))
536 __emit_char(')')
537 return
538
539 if (level > 0)
540 if (isminusone(caddr(p)))
541 __emit_char('1')
542 __emit_char('/')
543 if (isfactor(cadr(p)))
544 emit_factor(cadr(p))
545 else
546 emit_subexpr(cadr(p))
547 else
548 if (isfactor(cadr(p)))
549 emit_factor(cadr(p))
550 else
551 emit_subexpr(cadr(p))
552 __emit_char('^')
553 if (isfactor(caddr(p)))
554 emit_factor(caddr(p))
555 else
556 emit_subexpr(caddr(p))
557 return
558
559 # special case: 1 over something
560
561 if (__is_negative(caddr(p)))
562 x = emit_x
563 k1 = yindex
564 __emit_char('1')
565 k2 = yindex
566 #level++
567 emit_denominator(p, 1)
568 #level--
569 fixup_fraction(x, k1, k2)
570 return
571
572 k1 = yindex
573 if (isfactor(cadr(p)))
574 emit_factor(cadr(p))
575 else
576 emit_subexpr(cadr(p))
577 k2 = yindex
578 level++
579 emit_expr(caddr(p))
580 level--
581 fixup_power(k1, k2)
582
583# if n == 1 then emit as expr (no parens)
584
585# p is a power
586
587emit_denominator = (p, n) ->
588 k1 = 0
589 k2 = 0
590
591 # special case: 1 over something
592
593 if (isminusone(caddr(p)))
594 if (n == 1)
595 emit_expr(cadr(p))
596 else
597 emit_factor(cadr(p))
598 return
599
600 k1 = yindex
601
602 # emit base
603
604 if (isfactor(cadr(p)))
605 emit_factor(cadr(p))
606 else
607 emit_subexpr(cadr(p))
608
609 k2 = yindex
610
611 # emit exponent, don't emit minus sign
612
613 level++
614
615 emit_unsigned_expr(caddr(p))
616
617 level--
618
619 fixup_power(k1, k2)
620
621emit_function = (p) ->
622 if (car(p) == symbol(INDEX) && issymbol(cadr(p)))
623 emit_index_function(p)
624 return
625
626 if (car(p) == symbol(FACTORIAL))
627 emit_factorial_function(p)
628 return
629
630 if (car(p) == symbol(DERIVATIVE))
631 __emit_char('d')
632 else
633 emit_symbol(car(p))
634 __emit_char('(')
635 p = cdr(p)
636 if (iscons(p))
637 emit_expr(car(p))
638 p = cdr(p)
639 while (iscons(p))
640 __emit_char(',')
641 #__emit_char(' ')
642 emit_expr(car(p))
643 p = cdr(p)
644 __emit_char(')')
645
646emit_index_function = (p) ->
647 p = cdr(p)
648 if (caar(p) == symbol(ADD) || caar(p) == symbol(MULTIPLY) || caar(p) == symbol(POWER) || caar(p) == symbol(FACTORIAL))
649 emit_subexpr(car(p))
650 else
651 emit_expr(car(p))
652 __emit_char('[')
653 p = cdr(p)
654 if (iscons(p))
655 emit_expr(car(p))
656 p = cdr(p)
657 while(iscons(p))
658 __emit_char(',')
659 emit_expr(car(p))
660 p = cdr(p)
661 __emit_char(']')
662
663emit_factorial_function = (p) ->
664 p = cadr(p)
665 if (car(p) == symbol(ADD) || car(p) == symbol(MULTIPLY) || car(p) == symbol(POWER) || car(p) == symbol(FACTORIAL))
666 emit_subexpr(p)
667 else
668 emit_expr(p)
669 __emit_char('!')
670
671emit_subexpr = (p) ->
672 __emit_char('(')
673 emit_expr(p)
674 __emit_char(')')
675
676emit_symbol = (p) ->
677
678 i = 0
679 if (p == symbol(E))
680 __emit_str("exp(1)")
681 return
682
683 pPrintName = get_printname(p)
684 for i in [0...pPrintName.length]
685 __emit_char(pPrintName[i])
686
687emit_string = (p) ->
688 i = 0
689 pString = p.str
690 __emit_char('"')
691 for i in [0...pString.length]
692 __emit_char(pString[i])
693 __emit_char('"')
694
695fixup_fraction = (x, k1, k2) ->
696 dx = 0
697 dy = 0
698 i = 0
699 w = 0
700 y = 0
701 h1 = 0
702 w1 = 0
703 y1 = 0
704 h2 = 0
705 w2 = 0
706 y2 = 0
707
708 [h1,w1,y1] = get_size(k1, k2)
709 [h2,w2,y2] = get_size(k2, yindex)
710
711 if (w2 > w1)
712 dx = (w2 - w1) / 2; # shift numerator right
713 else
714 dx = 0
715
716 dx++
717 # this is how much is below the baseline
718
719 y = y1 + h1 - 1
720
721 dy = -y - 1
722
723 move(k1, k2, dx, dy)
724
725 if (w2 > w1)
726 dx = -w1
727 else
728 dx = -w1 + (w1 - w2) / 2
729
730 dx++
731 dy = -y2 + 1
732
733 move(k2, yindex, dx, dy)
734
735 if (w2 > w1)
736 w = w2
737 else
738 w = w1
739
740 w+=2
741 emit_x = x
742
743 for i in [0...w]
744 __emit_char('-')
745
746fixup_power = (k1, k2) ->
747 dy = 0
748 h1 = 0
749 w1 = 0
750 y1 = 0
751 h2 = 0
752 w2 = 0
753 y2 = 0
754
755 [h1,w1,y1] = get_size(k1, k2)
756 [h2,w2,y2] = get_size(k2, yindex)
757
758 # move superscript to baseline
759
760 dy = -y2 - h2 + 1
761
762 # now move above base
763
764 dy += y1 - 1
765
766 move(k2, yindex, 0, dy)
767
768move = (j, k, dx, dy) ->
769 i = 0
770 for i in [j...k]
771 chartab[i].x += dx
772 chartab[i].y += dy
773
774# finds the bounding rectangle and vertical position
775
776get_size = (j, k)->
777 i = 0
778 min_x = chartab[j].x
779 max_x = chartab[j].x
780 min_y = chartab[j].y
781 max_y = chartab[j].y
782 for i in [(j + 1)...k]
783 if (chartab[i].x < min_x)
784 min_x = chartab[i].x
785 if (chartab[i].x > max_x)
786 max_x = chartab[i].x
787 if (chartab[i].y < min_y)
788 min_y = chartab[i].y
789 if (chartab[i].y > max_y)
790 max_y = chartab[i].y
791 h = max_y - min_y + 1
792 w = max_x - min_x + 1
793 y = min_y
794 return [h,w,y]
795
796displaychar = (c) ->
797 __emit_char(c)
798
799__emit_char = (c) ->
800 if (yindex == YMAX)
801 return
802 if !chartab[yindex]?
803 debugger
804 chartab[yindex].c = c
805 chartab[yindex].x = emit_x
806 chartab[yindex].y = 0
807 yindex++
808 emit_x++
809
810__emit_str = (s) ->
811 i = 0
812 for i in [0...s.length]
813 __emit_char(s[i])
814
815emit_number = (p, emit_sign) ->
816 tmpString = ""
817 i = 0
818 switch (p.k)
819 when NUM
820 tmpString = p.q.a.toString()
821 if (tmpString[0] == '-' && emit_sign == 0)
822 tmpString = tmpString.substring(1)
823 for i in [0...tmpString.length]
824 __emit_char(tmpString[i])
825 tmpString = p.q.b.toString()
826 if (tmpString == "1")
827 break
828 __emit_char('/')
829 for i in [0...tmpString.length]
830 __emit_char(tmpString[i])
831
832 when DOUBLE
833 tmpString = doubleToReasonableString(p.d)
834 if (tmpString[0] == '-' && emit_sign == 0)
835 tmpString = tmpString.substring(1)
836 for i in [0...tmpString.length]
837 __emit_char(tmpString[i])
838
839# a and b are glyphs
840cmpGlyphs = (a, b) ->
841
842 if (a.y < b.y)
843 return -1
844
845 if (a.y > b.y)
846 return 1
847
848 if (a.x < b.x)
849 return -1
850
851 if (a.x > b.x)
852 return 1
853
854 return 0
855
856print_glyphs = ->
857
858 i = 0
859 accumulator = ""
860
861 # now sort the glyphs by their vertical positions,
862 # since we are going to build a string where obviously the
863 # "upper" line has to printed out first, followed by
864 # a new line, followed by the other lines.
865 #qsort(chartab, yindex, sizeof (struct glyph), __cmp)
866 subsetOfStack = chartab.slice(0,yindex)
867 subsetOfStack.sort(cmpGlyphs)
868 chartab = [].concat(subsetOfStack).concat(chartab.slice(yindex))
869
870 x = 0
871
872 y = chartab[0].y
873
874 for i in [0...yindex]
875
876 while (chartab[i].y > y)
877 accumulator += printchar('\n')
878 x = 0
879 y++
880
881 while (chartab[i].x > x)
882 accumulator += printchar_nowrap(' ')
883 x++
884
885 accumulator += printchar_nowrap(chartab[i].c)
886
887 x++
888
889 return accumulator
890
891buffer = ""
892
893getdisplaystr = ->
894 yindex = 0
895 level = 0
896 emit_x = 0
897 emit_expr(pop())
898 fill_buf()
899 return buffer
900
901fill_buf = ->
902 tmpBuffer = buffer
903 sIndex = 0
904 i = 0
905
906 #qsort(chartab, yindex, sizeof (struct glyph), __cmp)
907 subsetOfStack = chartab.slice(0,yindex)
908 subsetOfStack.sort(cmpGlyphs)
909 chartab = [].concat(subsetOfStack).concat(chartab.slice(yindex))
910
911 x = 0
912
913 y = chartab[0].y
914
915 for i in [0...yindex]
916
917 while (chartab[i].y > y)
918 tmpBuffer[sIndex++] = '\n'
919 x = 0
920 y++
921
922 while (chartab[i].x > x)
923 tmpBuffer[sIndex++] = ' '
924 x++
925
926 tmpBuffer[sIndex++] = chartab[i].c
927
928 x++
929
930 tmpBuffer[sIndex++] = '\n'
931
932
933N = 100
934
935class oneElement
936 x: 0
937 y: 0
938 h: 0
939 w: 0
940 index: 0
941 count: 0
942
943elem = []
944for elelmIndex in [0...10000]
945 elem[elelmIndex] = new oneElement
946
947SPACE_BETWEEN_COLUMNS = 3
948SPACE_BETWEEN_ROWS = 1
949
950emit_tensor = (p) ->
951 i = 0
952 n = 0
953 nrow = 0
954 ncol = 0
955 x = 0
956 y = 0
957 h = 0
958 w = 0
959 dx = 0
960 dy = 0
961 eh = 0
962 ew = 0
963 row = 0
964 col = 0
965
966 if (p.tensor.ndim > 2)
967 emit_flat_tensor(p)
968 return
969
970 nrow = p.tensor.dim[0]
971
972 if (p.tensor.ndim == 2)
973 ncol = p.tensor.dim[1]
974 else
975 ncol = 1
976
977 n = nrow * ncol
978
979 if (n > N)
980 emit_flat_tensor(p)
981 return
982
983 # horizontal coordinate of the matrix
984
985 #if 0
986 #emit_x += 2; # make space for left paren
987 #endif
988
989 x = emit_x
990
991 # emit each element
992
993 for i in [0...n]
994 elem[i].index = yindex
995 elem[i].x = emit_x
996 emit_expr(p.tensor.elem[i])
997 elem[i].count = yindex - elem[i].index
998 [elem[i].h, elem[i].w, elem[i].y] = get_size(elem[i].index, yindex)
999
1000 # find element height and width
1001
1002 eh = 0
1003 ew = 0
1004
1005 for i in [0...n]
1006 if (elem[i].h > eh)
1007 eh = elem[i].h
1008 if (elem[i].w > ew)
1009 ew = elem[i].w
1010
1011 # this is the overall height of the matrix
1012
1013 h = nrow * eh + (nrow - 1) * SPACE_BETWEEN_ROWS
1014
1015 # this is the overall width of the matrix
1016
1017 w = ncol * ew + (ncol - 1) * SPACE_BETWEEN_COLUMNS
1018
1019 # this is the vertical coordinate of the matrix
1020
1021 y = -(h / 2)
1022
1023 # move elements around
1024
1025 for row in [0...nrow]
1026 for col in [0...ncol]
1027
1028 i = row * ncol + col
1029
1030 # first move to upper left corner of matrix
1031
1032 dx = x - elem[i].x
1033 dy = y - elem[i].y
1034
1035 move(elem[i].index, elem[i].index + elem[i].count, dx, dy)
1036
1037 # now move to official position
1038
1039 dx = 0
1040
1041 if (col > 0)
1042 dx = col * (ew + SPACE_BETWEEN_COLUMNS)
1043
1044 dy = 0
1045
1046 if (row > 0)
1047 dy = row * (eh + SPACE_BETWEEN_ROWS)
1048
1049 # small correction for horizontal centering
1050
1051 dx += (ew - elem[i].w) / 2
1052
1053 # small correction for vertical centering
1054
1055 dy += (eh - elem[i].h) / 2
1056
1057 move(elem[i].index, elem[i].index + elem[i].count, dx, dy)
1058
1059 emit_x = x + w
1060
1061 ###
1062 if 0
1063
1064 # left brace
1065
1066 for (i = 0; i < h; i++) {
1067 if (yindex == YMAX)
1068 break
1069 chartab[yindex].c = '|'
1070 chartab[yindex].x = x - 2
1071 chartab[yindex].y = y + i
1072 yindex++
1073 }
1074
1075 # right brace
1076
1077 emit_x++
1078
1079 for (i = 0; i < h; i++) {
1080 if (yindex == YMAX)
1081 break
1082 chartab[yindex].c = '|'
1083 chartab[yindex].x = emit_x
1084 chartab[yindex].y = y + i
1085 yindex++
1086 }
1087
1088 emit_x++
1089
1090 endif
1091 ###
1092
1093
1094emit_flat_tensor = (p) ->
1095 emit_tensor_inner(p, 0, 0)
1096
1097emit_tensor_inner = (p, j, k) ->
1098 i = 0
1099 __emit_char('(')
1100 for i in [0...p.tensor.dim[j]]
1101 if (j + 1 == p.tensor.ndim)
1102 emit_expr(p.tensor.elem[k])
1103 k = k + 1
1104 else
1105 k = emit_tensor_inner(p, j + 1, k)
1106 if (i + 1 < p.tensor.dim[j])
1107 __emit_char(',')
1108 __emit_char(')')
1109 return k
1110
1111