1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22\starttext
23
24\dontcomplain
25
26\setuppapersize
27 [S6][S6]
28
29\setupwhitespace
30 [medium]
31
32\setupbodyfont
33 [dejavu,9pt]
34
35\setuptyping
36 [margin=standard]
37
38\setuplayout
39 [backspace=1cm,
40 topspace=1cm,
41 header=0pt,
42 footer=0pt,
43 width=middle,
44 height=middle]
45
46\setupinteraction
47 [page=yes,
48 state=start,
49 author=Hans Hagen,
50 title=The Calculator,
51 color=keyboard]
52
53\setupinteractionscreen
54 [option=max]
55
56\definecolor [action] [r= 1, g=.9, b=.5]
57\definecolor [keyboard] [r= 0, g=.7, b=.7]
58\definecolor [stack] [r=.7, g=.6, b=.8]
59
60\useURL[pragmamail][mailto:pragma@xs4all.nl][][pragma@xs4all.nl]
61
62
63
64
65\def\MinLevel{50}
66\def\MaxLevel {8}
67
68\startJSpreamble {variables} used now
69
70 var Growing = false ;
71 var MinLevel = 50 ;
72 var MaxLevel = 8 ;
73 var Level = 1 ;
74 var NoErrorFound = ">ok" ;
75 var NoValueError = ">invalid" ;
76 var WhateverError = ">error" ;
77 var OverflowError = ">overflow" ;
78 var ExhaustedError = ">exhausted" ;
79
80 var Stack = new Array() ;
81 var Stats = new Array() ;
82
83 console.clear() ;
84
85 console.println("preamble loaded: variables") ;
86
87\stopJSpreamble
88
89\startJSpreamble {housekeeping} used now
90
91 function doresetall () {
92 if (Growing) {
93 Level = 1 ;
94 } else {
95 Level = MaxLevel ;
96 }
97 for (var i=MinLevel ; i<=MaxLevel ; i) {
98 Stack[i] = "" ;
99 }
100 domark (NoErrorFound) ;
101 }
102
103 function dorefresh (i) {
104 var vv = this.getField("Stack." String(i)) ;
105 if (vv) {
106 vv.value = Stack[i] ;
107 vv.readonly = (i != Level) ;
108 this.dirty = false ;
109 }
110 }
111
112 function dorefreshall () {
113 for (var i=1 ; i<=MaxLevel ; i) {
114 dorefresh(i) ;
115 }
116 }
117
118 function doupdateA () {
119 if (Stack[1] == "") {
120 for (var i=1 ; i<=MaxLevel ; i) {
121 vv = this.getField("Stack." String(i)) ;
122 if (vv) {
123 Level = i ;
124 if (validnumber(vv.value)) {
125 Stack[Level] = String(vv.value)
126 } else {
127 vv.value = "" ;
128 this.dirty = false ;
129 return ;
130 }
131 }
132 }
133 }
134 }
135
136 function doupdateB () {
137 if (String(Stack[MaxLevel1]) == "") {
138 for (var i=1 ; i<=MaxLevel ; i) {
139 vv = this.getField("Stack." String(i)) ;
140 if (vv) {
141 if (validnumber(vv.value)) {
142 Stack[Level] = String(vv.value) ;
143 } else {
144 vv.value = "" ;
145 this.dirty = false ;
146 return ;
147 }
148 }
149 }
150 }
151 }
152
153 function doupdate () {
154 if (Growing) {
155 doupdateA() ;
156 } else {
157 doupdateB() ;
158 }
159 }
160
161 function domark (s) {
162 var vv = this.getField("Stack." String(Level)) ;
163 if (vv) {
164 vv.value = s ;
165 this.dirty = false ;
166 }
167 }
168
169 console.println("preamble loaded: housekeeping") ;
170\stopJSpreamble
171
172\startJSpreamble {handling} used now
173
174 function doenter () {
175 doupdate() ;
176 var vv = this.getField("Stack." String(Level)) ;
177 if ((vv.value!=Stack[Level]) (String(vv.value).search(>)==1)) {
178 dopush (vv.value) ;
179 } else {
180 dopush (Stack[Level]) ;
181 }
182 }
183
184 function dopushA (Value) {
185 doupdate() ;
186 Stack[Level] = String(Value) ;
187 doparse(Level) ;
188 if (String(Stack[Level])!="") {
189 if (Level<MaxLevel) {
190 Level ;
191 domark (ErrorString) ;
192 } else {
193 for (var i=MinLevel ; i<MaxLevel ; i) {
194 Stack[i] = Stack[i1] ;
195 }
196 Stack[MaxLevel] = "" ;
197 dorefreshall() ;
198 if (String(Stack[MinLevel])!="") {
199 ErrorString = ExhaustedError ;
200 }
201 domark (ErrorString) ;
202 }
203 }
204 }
205
206 function dopushB (Value) {
207 doupdate() ;
208 Stack[MaxLevel] = String(Value) ;
209 doparse(MaxLevel) ;
210 if (String(Stack[MaxLevel])!="") {
211 for (var i=MinLevel ; i<MaxLevel ; i) {
212 Stack[i] = Stack[i1] ;
213 }
214 Stack[MaxLevel] = "" ;
215 dorefreshall() ;
216 if (Stack[MinLevel]!="") {
217 ErrorString = ExhaustedError ;
218 }
219 domark (ErrorString) ;
220 }
221 }
222
223 function dopush (Value) {
224 if (Growing) {
225 dopushA (Value) ;
226 } else {
227 dopushB (Value) ;
228 }
229 }
230
231 function dopopA () {
232 doupdate() ;
233 if (String(Stack[0])!="") {
234 for (var i=MaxLevel ; i>MinLevel ; i) {
235 Stack[i] = Stack[i1] ;
236 }
237 Stack[MinLevel] = "" ;
238 dorefreshall() ;
239 Level = MaxLevel ;
240 } else {
241 while ((Level>1) (String(Stack[Level])=="")) {
242 dorefresh(Level) ;
243 Level ;
244 }
245 }
246 if (String(Stack[Level])=="") {
247 return("") ;
248 } else {
249 Value = Number(Stack[Level]) ;
250 Stack[Level] = "" ;
251 dorefresh(Level) ;
252 return(Value) ;
253 }
254 }
255
256 function dopopB () {
257 doupdate() ;
258 if (String(Stack[MaxLevel])=="") {
259 for (var i=MaxLevel ; i>MinLevel ; i) {
260 Stack[i] = Stack[i1] ;
261 }
262 Stack[MinLevel] = "" ;
263 dorefreshall() ;
264 }
265 if (String(Stack[MaxLevel])=="") {
266 return("") ;
267 } else {
268 Value = Number(Stack[MaxLevel]) ;
269 Stack[MaxLevel] = "" ;
270 return(Value) ;
271 }
272 }
273
274 function dopop () {
275 if (Growing) {
276 return(dopopA()) ;
277 } else {
278 return(dopopB()) ;
279 }
280 }
281
282 function dodup () {
283 var X = dopop() ;
284 if (validnumber(X)) {
285 dopush(X) ;
286 dopush(X) ;
287 } else {
288 domark (ErrorString) ;
289 }
290 }
291
292 function doparse ( i ) {
293 if (validnumber(Stack[i])) {
294 Stack[i] = parseFloat(Stack[i]) ;
295 dorefresh(i) ;
296 } else {
297 Stack[i] = "" ;
298 dorefresh(i) ;
299 domark (ErrorString) ;
300 }
301 }
302
303 function dodigit ( d ) {
304 Stack[Level] = String(d) ;
305 dorefresh(Level) ;
306 }
307
308 function validnumber ( x ) {
309 if (String(x) == "") {
310 ErrorString = NoValueError ;
311 return(false) ;
312 } else if (isNaN(x)) {
313 ErrorString = NoValueError ;
314 return(false) ;
315 } else if (isFinite(x)) {
316 ErrorString = NoErrorFound ;
317 return(true) ;
318 } else {
319 ErrorString = OverflowError ;
320 return(false) ;
321 }
322 }
323
324 console.println("preamble loaded: handling") ;
325
326\stopJSpreamble
327
328\startJSpreamble {operations} used now
329
330 function docalculate (Operator) {
331 doenter() ;
332 var Y = dopop() ;
333 var X = 0 ;
334 if (validnumber(Y)) {
335 X = dopop() ;
336 if (validnumber(X)) {
337 switch (Number(Operator)) {
338 case 1 :
339 if (Y) {
340 X = Y ;
341 }
342 break ;
343 case 2 :
344 X *= Y ;
345 break ;
346 case 3 :
347 X = Y ;
348 break ;
349 case 4 :
350 X = Y ;
351 break ;
352 case 5 :
353 X = Math.max(X,Y) ;
354 break ;
355 case 6 :
356 X = Math.min(X,Y) ;
357 break ;
358 case 7 :
359 X = Math.pow(X,Y) ;
360 break
361 }
362 dopush(X) ;
363 } else {
364 dopush(Y) ;
365 ErrorString = NoValueError ;
366 }
367 }
368 domark(ErrorString) ;
369 }
370
371 console.println("preamble loaded: operations") ;
372\stopJSpreamble
373
374\startJSpreamble {functions} used now
375
376 function dofacultate (Value) {
377 var n = Math.min(Math.round(Value),500) ;
378 if (n <= 1) {
379 return(1) ;
380 } else {
381 var m = 1 ;
382 for (m=1, i=1 ; i<=n ; i) {
383 m = m * i ;
384 }
385 return(m) ;
386 }
387 }
388
389 function doconstant (Operation) {
390 doupdate() ;
391 switch (Number(Operation)) {
392 case 1 :
393 dopush(Math.PI) ;
394 break ;
395 case 2 :
396 dopush(Math.E) ;
397 break ;
398 case 3 :
399 dopush(Math.random(1)) ;
400 break ;
401 case 4 :
402 dodup() ;
403 break ;
404 }
405 }
406
407 function dodomemory (mv, Sign) {
408 var X = dopop() ;
409 if (validnumber(X)) {
410 mv.value = Sign*X ;
411 if (!validnumber(mv.value)) {
412 mv.value = "" ;
413 }
414 this.dirty = false ;
415 }
416 domark(ErrorString) ;
417 }
418
419 function domemory (Operation) {
420 var mv = this.getField("Stats.mem") ;
421 if (mv) {
422 switch (Number(Operation)) {
423 case 1 :
424 mv.value = "" ;
425 break ;
426 case 2 :
427 dodomemory(mv, 1) ;
428 break ;
429 case 3 :
430 dodomemory(mv, 1) ;
431 break ;
432 case 4 :
433 if (mv.value == "") {
434 ErrorString = NoValueError ;
435 domark(ErrorString) ;
436 } else {
437 dopush(mv.value) ;
438 }
439 break ;
440 }
441 this.dirty = false ;
442 }
443 }
444
445 function dooperation (Operator) {
446 doenter() ;
447 var X = dopop() ;
448 if (validnumber(X)) {
449 switch (Number(Operator)) {
450 case 1 :
451 dopush(Math.sin(X)) ;
452 break ;
453 case 2 :
454 dopush(Math.cos(X)) ;
455 break ;
456 case 3 :
457 dopush(Math.tan(X)) ;
458 break ;
459 case 4 :
460 dopush(Math.exp(X)) ;
461 break ;
462 case 5 :
463 dopush(Math.ceil(X)) ;
464 break ;
465 case 6 :
466 dopush(Math.pow(X,2)) ;
467 break ;
468 case 7 :
469 dopush(dofacultate(X)) ;
470 break ;
471 case 8 :
472 dopush(Math.asin(X)) ;
473 break ;
474 case 9 :
475 dopush(Math.acos(X)) ;
476 break ;
477 case 10 :
478 dopush(Math.atan(X)) ;
479 break ;
480 case 11 :
481 dopush(Math.log(X)) ;
482 break ;
483 case 12 :
484 dopush(Math.floor(X)) ;
485 break ;
486 case 13 :
487 dopush(Math.sqrt(X)) ;
488 break ;
489 case 14 :
490 dopush(Math.round(X)) ;
491 break ;
492 case 15 :
493 dopush(Math.pow(X,1)) ;
494 break ;
495 case 16 :
496 dopush(X*(2*Math.PI360)) ;
497 break ;
498 case 17 :
499 dopush(X(2*Math.PI360)) ;
500 break ;
501 case 18 :
502 dopush(X) ;
503 break ;
504 }
505 }
506 domark(ErrorString) ;
507 }
508
509 console.println("preamble loaded: functions") ;
510\stopJSpreamble
511
512\startJSpreamble {statistics} used now
513
514 var sminmax = 1 ;
515 var ssqrt = 0 ;
516
517 function dostatcalcs (Sign, X) {
518 sn.value = Sign ;
519 ssqrt = Sign*X*X ;
520 stotal.value = Sign*X ;
521 smean.value = stotal.value sn.value ;
522 stemp = Math.max(ssqrt 2*stotal.value*smean.value
523 sn.value*smean.value*smean.value, 0) ;
524 ssdev.value = Math.sqrt(stempsn.value) ;
525 if (!(validnumber(X) validnumber(ssqrt)
526 validnumber(ssdev.value) validnumber(stotal.value)
527 validnumber(smean.value))) {
528 dostatistics(1) ;
529 }
530 this.dirty = false ;
531 }
532
533 function dostatistics(Operator) {
534 var sn = this.getField("Stats.n") ;
535 var smin = this.getField("Stats.min") ;
536 var smax = this.getField("Stats.max") ;
537 var stotal = this.getField("Stats.total") ;
538 var smean = this.getField("Stats.mean") ;
539 var ssdev = this.getField("Stats.sdev") ;
540 if ((ssqrt==0) (sn.value!="") (sn.value>0)) {
541 sminmax = 1 ;
542 ssqrt = sn.value*ssdev.value*ssdev.value
543 2*stotal.value*smean.value
544 sn.value*smean.value*smean.value ;
545 }
546 switch (Number(Operator)) {
547 case 1 :
548 sminmax = 1 ;
549 sn.value = "" ;
550 smin.value = "" ;
551 smax.value = "" ;
552 stotal.value = "" ;
553 smean.value = "" ;
554 ssdev.value = "" ;
555 ssqrt = 0 ;
556 break ;
557 case 2 :
558 doenter() ;
559 var X = dopop() ;
560 if (validnumber(X)) {
561 if (sn.value=="") {
562 sn.value = 0 ;
563 stotal.value = 0 ;
564 smean.value = 0 ;
565 if (sminmax) {
566 smin.value = X ;
567 smax.value = X ;
568 }
569 } else {
570 if ((sminmax) (X<smin.value)) {
571 smin.value = X ;
572 }
573 if ((sminmax) (X>smax.value)) {
574 smax.value = X ;
575 }
576 }
577 dostatcalcs(1,X) ;
578 }
579 break ;
580 case 3 :
581 doenter() ;
582 var X = dopop() ;
583 if (validnumber(X)) {
584 smin.value = "" ;
585 smax.value = "" ;
586 sminmax = 0 ;
587 if (sn.value>0) {
588 dostatcalcs(1,X) ;
589 } else {
590 dostatistics(1) ;
591 }
592 }
593 break ;
594 }
595 domark(ErrorString) ;
596 this.dirty = false ;
597 }
598
599 function docopystat (Field) {
600 var sv = this.getField("Stats.".concat(Field)) ;
601 dopush(sv.value) ;
602 }
603
604 console.println("preamble loaded: statistics") ;
605\stopJSpreamble
606
607\startJSpreamble {initialization} used now
608 doresetall() ;
609 doupdate() ;
610 dorefreshall() ;
611 domark (NoErrorFound) ;
612
613 console.println("preamble loaded: initialization") ;
614\stopJSpreamble
615
616
617
618
619\startJScode{period}
620 if (Stack[Level].search([.e])==1) {
621 dodigit(".") ;
622 }
623\stopJScode
624
625\startJScode{sign}
626 L = Stack[Level].length ;
627 if ((L==0) (Stack[Level].charAt(L1)=="e")) {
628 dodigit("") ;
629 }
630\stopJScode
631
632\startJScode{exponent}
633 L = Stack[Level].length ;
634 if ((L>0) validnumber(Stack[Level]) (Stack[Level].search([e])==1)) {
635 dodigit("e") ;
636 }
637\stopJScode
638
639\startJScode{reset}
640 doresetall() ;
641 dorefreshall() ;
642 domark (NoErrorFound) ;
643\stopJScode
644
645\startJScode{clear}
646 doupdate() ;
647 Stack[Level] = String(Stack[Level]).substring(0,String(Stack[Level]).length1) ;
648 dorefresh(Level) ;
649\stopJScode
650
651\startJScode{pop}
652 X = dopop() ;
653 domark(NoErrorFound) ;
654\stopJScode
655
656\startJScode{push}
657 doenter() ;
658\stopJScode
659
660\startJScode{grow}
661 Growing = !Growing ;
662 doresetall() ;
663 dorefreshall() ;
664 domark (NoErrorFound) ;
665\stopJScode
666
667
668
669\startuniqueMPgraphic{page}
670 fill OverlayBox
671 withcolor .4white ;
672 draw OverlayBox enlarged -10pt
673 withpen pencircle scaled 5pt
674 withcolor .8white ;
675\stopuniqueMPgraphic
676
677\startuniqueMPgraphic{shape}
678 path p ; color c ;
679 p := OverlayBox ;
680 c := \overlaycolor ;
681 fill p withcolor c ;
682 draw p withpen pencircle scaled 1.5pt withcolor .8c ;
683\stopuniqueMPgraphic
684
685\defineoverlay [page] [\uniqueMPgraphic{page}]
686\defineoverlay [shape] [\uniqueMPgraphic{shape}]
687
688\setupbackgrounds
689 [page]
690 [background=page]
691
692\definemeasure[ButtonWidth][\makeupwidth15]
693
694\setupbuttons
695 [width=\measured{ButtonWidth},
696 height=\measured{ButtonWidth},
697 background=shape,
698 backgroundcolor=\MPcolor{keyboard},
699 frame=off,
700 style=,
701 color=]
702
703\setupfield
704 [Results]
705 [horizontal,frame]
706 [width=fit,
707 align={lohi},
708 height=.5\measured{ButtonWidth},
709 background=shape,
710 backgroundcolor=\MPcolor{stack},
711 frame=off]
712 [width=3.5\measured{ButtonWidth},
713 frame=off]
714 [width=3.5\measured{ButtonWidth},
715 height=.45\measured{ButtonWidth},
716 option=readonly,
717 frame=off]
718
719\starttexdefinition unexpanded Star
720 \lower.65ex\hbox {
721 *
722 }
723\stoptexdefinition
724
725\starttexdefinition unexpanded InfoButton #1
726 \setbox\scratchbox\hbox {
727 \lower .5cm \hbox {
728 \button [
729 width=\dimexpr\overlaywidth .5cm\relax,
730 height=\dimexpr\overlayheight .5cm\relax,
731 strut=no,
732 frame=off,
733 background=
734 ] {
735 } [
736 info:#1
737 ]
738 }
739 }
740 \wd\scratchbox\overlaywidth
741 \ht\scratchbox\overlayheight
742 \box\scratchbox
743\stoptexdefinition
744
745\starttexdefinition unexpanded SomeKey #1#2#3
746
747 \bgroup
748
749 \doifelsenothing {#2} {
750 \button[background=]{#2}[#3]
751 } {
752 \defineoverlay
753 [infobutton]
754 [\InfoButton{#1}]
755
756
757
758
759 \framed
760 [offset=overlay,
761 frame=off,
762 background=infobutton,
763 backgroundcolor=red]
764 {\button{#2}[#3]}
765 }
766
767 \egroup
768
769 \ignorespaces
770
771\stoptexdefinition
772
773\starttexdefinition unexpanded StatField #1
774 \hbox \bgroup
775 \doifelsenothing {#1} {
776 \framed [
777 height=.5\measured{ButtonWidth},
778 width=3.5\measured{ButtonWidth},
779 frame=off
780 ] {
781 }
782 } {
783 \definefield[Stats.#1][line][Results]
784 \field[Stats.#1][option=readonly]
785 }
786 \egroup
787 \ignorespaces
788\stoptexdefinition
789
790\setbox\scratchboxone=\hbox to .4\makeupwidth \bgroup
791 \ss
792 \SomeKey {7} {\ssb 7} {JS(dodigit{7})} \hss
793 \SomeKey {8} {\ssb 8} {JS(dodigit{8})} \hss
794 \SomeKey {9} {\ssb 9} {JS(dodigit{9})} \hss
795 \SomeKey {div} {\ssb } {JS(docalculate{1})} \hss
796 \SomeKey {del} {del} {JS(clear)}
797\egroup
798
799\setbox\scratchboxtwo=\hbox to \wd\scratchboxone \bgroup
800 \ss
801 \SomeKey {4} {\ssb 4} {JS(dodigit{4})} \hss
802 \SomeKey {5} {\ssb 5} {JS(dodigit{5})} \hss
803 \SomeKey {6} {\ssb 6} {JS(dodigit{6})} \hss
804 \SomeKey {mul} {\ssb \Star} {JS(docalculate{2})} \hss
805 \SomeKey {E} {E} {JS(exponent)}
806\egroup
807
808\setbox\scratchboxthree=\hbox to \wd\scratchboxone \bgroup
809 \ss
810 \SomeKey {1} {\ssb 1} {JS(dodigit{1})} \hss
811 \SomeKey {2} {\ssb 2} {JS(dodigit{2})} \hss
812 \SomeKey {3} {\ssb 3} {JS(dodigit{3})} \hss
813 \SomeKey {sub} {\ssb } {JS(docalculate{3})} \hss
814 \SomeKey {pop} {pop} {JS(pop)}
815\egroup
816
817\setbox\scratchboxfour=\hbox to \wd\scratchboxone \bgroup
818 \ss
819 \SomeKey {0} {\ssb 0} {JS(dodigit{0})} \hss
820 \SomeKey {period} {\ssb .} {JS(period)} \hss
821 \SomeKey {sign} {\ssb } {JS(sign)} \hss
822 \SomeKey {add} {\ssb } {JS(docalculate{4})} \hss
823 \SomeKey {push} {push} {JS(push)}
824\egroup
825
826\setbox\scratchboxone=\vbox to .8\wd\scratchboxone \bgroup
827 \box\scratchboxone \vss
828 \box\scratchboxtwo \vss
829 \box\scratchboxthree\vss
830 \box\scratchboxfour
831\egroup
832
833\setbox\scratchboxtwo=\vbox to \ht\scratchboxone \bgroup
834 \dostepwiserecurse {\MaxLevel} {1} {1} {
835 \definefield[Stack.\recurselevel][line][Results]
836 \hbox \bgroup
837 \field[Stack.\recurselevel][option=readonly]
838 \egroup
839 \vfill
840 }
841 \unskip
842\egroup
843
844\setbox\scratchboxthree=\vbox to \ht\scratchboxone \bgroup
845 \StatField {n} \vfill
846 \StatField {min} \vfill
847 \StatField {max} \vfill
848 \StatField {total} \vfill
849 \StatField {mean} \vfill
850 \StatField {sdev} \vfill
851 \StatField {} \vfill
852 \StatField {}
853\egroup
854
855\setbox\scratchboxfour=\vbox to \ht\scratchboxone \bgroup
856 \ss\setstrut
857 \setupbuttons
858 [width=\measured{ButtonWidth},
859 height=.5\measured{ButtonWidth},
860 backgroundcolor=\MPcolor{action}]
861 \SomeKey {sn} {n} {JS(docopystat{n})} \vfill
862 \SomeKey {smin} {min} {JS(docopystat{min})} \vfill
863 \SomeKey {smax} {max} {JS(docopystat{max})} \vfill
864 \SomeKey {stotal} {total} {JS(docopystat{total})} \vfill
865 \SomeKey {smean} {mean} {JS(docopystat{mean})} \vfill
866 \SomeKey {ssdev} {sdev} {JS(docopystat{sdev})} \vfill
867 \SomeKey {} {} {} \vfill
868 \SomeKey {} {} {}
869\egroup
870
871\setbox\scratchboxone=\hbox to \hsize \bgroup
872 \box\scratchboxone \hss
873 \box\scratchboxtwo \hss
874 \box\scratchboxthree\hss
875 \box\scratchboxfour
876\egroup
877
878\setupbuttons
879 [width=1.5cm,
880 height=1cm,
881 backgroundcolor=\MPcolor{action}]
882
883\setbox\scratchboxtwo=\hbox to \wd\scratchboxone \bgroup
884 \ss\setstrut
885 \SomeKey {sin} {sin} {JS(dooperation{1})} \hss
886 \SomeKey {cos} {cos} {JS(dooperation{2})} \hss
887 \SomeKey {tan} {tan} {JS(dooperation{3})} \hss
888 \SomeKey {max} {max} {JS(docalculate{5})} \hss
889 \SomeKey {exp} {exp} {JS(dooperation{4})} \hss
890 \SomeKey {ceil} {ceil} {JS(dooperation{5})} \hss
891 \SomeKey {sqr} {x\high{2}} {JS(dooperation{6})} \hss
892 \SomeKey {fac} {x!} {JS(dooperation{7})} \hss
893 \SomeKey {pow} {x\high{y}} {JS(docalculate{7})} \hss
894 \SomeKey {rad} {rad} {JS(dooperation{16})}
895\egroup
896
897\setbox\scratchboxthree=\hbox to \wd\scratchboxone \bgroup
898 \ss\setstrut
899 \SomeKey {asin} {asin} {JS(dooperation{8})} \hss
900 \SomeKey {acos} {acos} {JS(dooperation{9})} \hss
901 \SomeKey {atan} {atan} {JS(dooperation{10})} \hss
902 \SomeKey {min} {min} {JS(docalculate{6})} \hss
903 \SomeKey {ln} {ln} {JS(dooperation{11})} \hss
904 \SomeKey {floor}{floor} {JS(dooperation{12})} \hss
905 \SomeKey {sqrt} {sqrt} {JS(dooperation{13})} \hss
906 \SomeKey {round}{round} {JS(dooperation{14})} \hss
907 \SomeKey {inv} {1x} {JS(dooperation{15})} \hss
908 \SomeKey {deg} {deg} {JS(dooperation{17})}
909\egroup
910
911\setbox\scratchboxfour=\hbox to \wd\scratchboxone \bgroup
912 \ss\setstrut
913 \SomeKey {} {} {} \hss
914 \SomeKey {} {} {} \hss
915 \setupbuttons
916 [backgroundcolor=\MPcolor{keyboard}]
917 \SomeKey {new} {new} {JS(reset)} \hss
918 \SomeKey {} {} {} \hss
919 \SomeKey {} {} {} \hss
920 \SomeKey {} {} {} \hss
921 \SomeKey {} {} {} \hss
922 \SomeKey {newn} {new} {JS(dostatistics{1})} \hss
923 \SomeKey {addn} {n} {JS(dostatistics{2})} \hss
924 \SomeKey {subn} {n} {JS(dostatistics{3})}
925\egroup
926
927\setbox\scratchboxfive=\hbox to \wd\scratchboxone \bgroup
928 \ss\setstrut
929 \SomeKey {neg} {x} {JS(dooperation{18})} \hss
930 \SomeKey {random}{random} {JS(doconstant{3})} \hss
931 \SomeKey {pi} {pi} {JS(doconstant{1})} \hss
932 \SomeKey {e} {e} {JS(doconstant{2})} \hss
933 \SomeKey {dup} {dup} {JS(doconstant{4})} \hss
934 \SomeKey {} {} {} \hss
935 \SomeKey {} {} {} \hss
936 \setupbuttons
937 [backgroundcolor=\MPcolor{keyboard}]
938 \SomeKey {} {} {} \hss
939 \SomeKey {exit} {exit} {CloseDocument} \hss
940 \SomeKey {help} {info} {info:help}
941\egroup
942
943\setbox\scratchboxsix=\hbox to \wd\scratchboxone \bgroup
944 \ss\setstrut
945 \setupbuttons
946 [width=\measured{ButtonWidth},
947 height=.5\measured{ButtonWidth},
948 backgroundcolor=\MPcolor{keyboard}]
949 \SomeKey {newmem} {new} {JS(domemory{1})} \hss
950 \SomeKey {addmem} {m} {JS(domemory{2})} \hss
951 \SomeKey {submem} {m} {JS(domemory{3})} \hss
952 \StatField {mem} \hss
953 \setupbuttons
954 [backgroundcolor=\MPcolor{action}]
955 \SomeKey {copmem} {mem} {JS(domemory{4})} \hss
956 \SomeKey {} {} {} \hss
957 \setupbuttons
958 [backgroundcolor=\MPcolor{stack}]
959 \SomeKey {grow} {grow} {JS(grow)} \hss
960 \StatField {}
961\egroup
962
963\startstandardmakeup
964
965 \pagereference[calculator]
966
967 \vfill
968
969 \hbox to \hsize \bgroup
970 \hss
971 \vbox to \vsize \bgroup
972 \box\scratchboxtwo \vss
973 \box\scratchboxthree\vss
974 \box\scratchboxone \vss
975 \box\scratchboxfour \vss
976 \box\scratchboxfive \vss
977 \box\scratchboxsix
978 \egroup
979 \hss
980 \egroup
981
982 \vfill
983
984\stopstandardmakeup
985
986\starttexdefinition unexpanded BackgroundButton
987 \button [
988 background=screen,
989 backgroundscreen=.8,
990 backgroundoffset=5pt,
991 height=\vsize,
992 width=\hsize
993 ] {
994 } [
995 calculator
996 ]
997\stoptexdefinition
998
999\setuptexttexts
1000 [\BackgroundButton]
1001 []
1002
1003\starttexdefinition unexpanded Key #1#2
1004 \goto {
1005 \ss#1
1006 } [
1007 info:#2
1008 ]
1009\stoptexdefinition
1010
1011\startstandardmakeup[top=,bottom=]
1012
1013 \switchtobodyfont[8pt]
1014
1015 \start
1016
1017 \setupwhitespace[big]
1018
1019 \midaligned{\ssd The Calculator}
1020
1021 \blank[2*big]
1022
1023 \pagereference[info:help]
1024 This calculator is stack based, which means that one enters values and
1025 invokes an action that acts on the value(s) last entered. Subtracting 10 from
1026 20 using (\Key {} {sub}) for instance comes down to clicking:
1027
1028 \startnarrower\ss
1029 10\quad in\quad 20\quad
1030 \stopnarrower
1031
1032 while calculating a sinus (\Key {sin} {sin}) results from entering:
1033
1034 \startnarrower\ss
1035 .89\quad sin
1036 \stopnarrower
1037
1038 The left column of fields (numbers) shows the Stack. One uses \Key {push}
1039 {push} to push a value on the stack and \Key {pop} {pop} to remove a value.
1040 Clicking \Key {new} {new} removes them all and the \Key {del} {del} button
1041 can be used to undo the last entered digit. When a dyadic operation is
1042 applied, the top value is used asy. The \Key {grow} {grow} key toggles
1043 between two different visualizations of the stack.
1044
1045 The stack is considerably larger than the screen representation suggests. In
1046 the rare occasion that one encounters the message {\ss exhausted}, the amount
1047 of stack entries already has totaled far beyond \MinLevel\ and one probably
1048 already has forgotten what the values first entered represent.
1049
1050 The right column of fields reports the statistic calculations. By clicking on
1051 the tag, one pushes the value on the Stack. The lower buttons are used to
1052 reset(\Key {new} {newn}), enter(\Key {} {addn}) and remove(\Key {}
1053 {subn}) values to be taken into account when calculating those statistics.
1054
1055 This document is produced by \ConTeXt, a macro package written in \TeX. The
1056 graphics are METAPOST graphics. The graphics, the PDF objects and the form
1057 fields as well as JavaScript code were generated and inserted at run time.
1058 Originally we used PDF\TeX\ and \MKII\ to process this document but this one
1059 is done by \LUATEX\ and \MKIV. We kept the design and code original so that
1060 it reflects how things were done (for readability we updated some \TEX\
1061 definitions).
1062
1063 \stop
1064
1065 \vfilll
1066
1067 \startMPrun
1068 logotype := 302 ;
1069 mpgraph := 302 ;
1070 input mpprag ;
1071 \stopMPrun
1072
1073 \startlinecorrection
1074 \midaligned{\externalfigure[mprun.302][height=1.5cm]}
1075 \stoplinecorrection
1076
1077 \midaligned{\strut Hans Hagen, PRAGMA ADE, \ConTeXt\ 18219982592018}
1078
1079 \blank
1080
1081 \midaligned{\strut\url[pragmamail]}
1082
1083\stopstandardmakeup
1084
1085\starttexdefinition unexpanded BackgroundButton
1086 \button [
1087 background=screen,
1088 backgroundscreen=.8,
1089 backgroundoffset=5pt,
1090 height=\vsize,
1091 width=\hsize
1092 ] {
1093 } [
1094 firstpage
1095 ]
1096\stoptexdefinition
1097
1098\starttexdefinition unexpanded ShowInfo #1#2
1099 \startstandardmakeup
1100 \pagereference[info:#1]
1101 \vfill
1102 \hbox to \hsize \bgroup
1103 \hss
1104 \useMPgraphic{#1}
1105 \hss
1106 \egroup
1107 \blank[2*big]
1108 \midaligned{#2}
1109 \vfill
1110 \stopstandardmakeup
1111\stoptexdefinition
1112
1113\startMPinclusions
1114
1115 path ax, ay, p[] ;
1116 color c ; c := \MPcolor{action} ;
1117 pmax := 0 ;
1118
1119 let normalpow = pow ;
1120
1121 def draw_function (text fun) (expr xmin, xmax, xstep) =
1122 pmax := pmax+1 ;
1123 p[pmax] := for x=xmin step xstep until xmax:
1124 (x,fun(x)) ..
1125 endfor (xmax,fun(xmax)) ;
1126 enddef ;
1127
1128 def draw_axis =
1129 pickup pencircle scaled 0 ;
1130 for i=1 upto pmax:
1131 draw p[i] ;
1132 endfor ;
1133 xmin := xpart llcorner currentpicture ;
1134 xmax := xpart urcorner currentpicture ;
1135 ymin := ypart llcorner currentpicture ;
1136 ymax := ypart urcorner currentpicture ;
1137 ax := (xmin,0)--(0,0)--(xmax,0) ;
1138 ay := (0,ymin)--(0,0)--(0,ymax) ;
1139 currentpicture := nullpicture ;
1140 sx := 400(xmaxxmin) ;
1141 sy := 250(ymaxymin) ;
1142 pickup pencircle xscaled (10sx) yscaled (10sy) ;
1143 draw ax withcolor .4white ;
1144 draw ay withcolor .4white ;
1145 for i=1 upto pmax:
1146 draw p[i] withcolor c ;
1147 endfor ;
1148 currentpicture := currentpicture xscaled sx yscaled sy ;
1149 pmax := 0 ;
1150 enddef ;
1151
1152\stopMPinclusions
1153
1154\startuseMPgraphic{sin}
1155 draw_function(sind)(-360,360,60) ; draw_axis ;
1156\stopuseMPgraphic
1157
1158\ShowInfo{sin}{Calculate the sine of the topmost stack entry.}
1159
1160\startuseMPgraphic{cos}
1161 draw_function(cosd)(-360,360,60) ; draw_axis ;
1162\stopuseMPgraphic
1163
1164\ShowInfo{cos}{Calculate the cosine of the topmost stack entry.}
1165
1166\startuseMPgraphic{tan}
1167 draw_function(tand)(-240,-120,30) ;
1168 draw_function(tand)( -60, 60,30) ;
1169 draw_function(tand)( 120, 240,30) ;
1170 draw_axis ;
1171\stopuseMPgraphic
1172
1173\ShowInfo{tan}{Calculate the tangent of the topmost stack entry.}
1174
1175\startuseMPgraphic{asin}
1176 draw_function(asin)(-1,1,.2) ; draw_axis ;
1177\stopuseMPgraphic
1178
1179\ShowInfo{asin}{Calculate the arcsine of the topmost stack entry.}
1180
1181\startuseMPgraphic{acos}
1182 draw_function(acos)(-1,1,.2) ; draw_axis ;
1183\stopuseMPgraphic
1184
1185\ShowInfo{acos}{Calculate the arccosine of the topmost stack entry.}
1186
1187\startuseMPgraphic{atan}
1188 draw_function(atan)(-1,1,.2) ; draw_axis ;
1189\stopuseMPgraphic
1190
1191\ShowInfo{atan}{Calculate the arctangent of the topmost stack entry.}
1192
1193\startuseMPgraphic{sqr}
1194 draw_function(sqr)(-3,3,1) ; draw_axis ;
1195\stopuseMPgraphic
1196
1197\ShowInfo{sqr}{Calculate the square of the topmost stack entry.}
1198
1199\startuseMPgraphic{sqrt}
1200 draw_function(sqrt)(0,5,1) ; draw_axis ;
1201\stopuseMPgraphic
1202
1203\ShowInfo{sqrt}{Calculate the square root of the topmost stack entry.}
1204
1205\startuseMPgraphic{exp}
1206 draw_function(exp)(0,5,1) ; draw_axis ;
1207\stopuseMPgraphic
1208
1209\ShowInfo{exp}{Calculate the exponential function of the topmost stack entry.}
1210
1211\startuseMPgraphic{ln}
1212 draw_function(ln)(0,50,5) ; draw_axis ;
1213\stopuseMPgraphic
1214
1215\ShowInfo{ln}{Calculate the natural logaritm of the topmost stack entry.}
1216
1217\startuseMPgraphic{pow}
1218 vardef mypow(expr n) = 3n enddef ;
1219 draw_function(mypow)(-3,3,.5) ; draw_axis ;
1220\stopuseMPgraphic
1221
1222\ShowInfo{pow}{Calculate x\high{y} where y is the topmost stack entry.}
1223
1224\startuseMPgraphic{inv}
1225 draw_function(inv)(-10,10,1) ; draw_axis ;
1226\stopuseMPgraphic
1227
1228\ShowInfo{inv}{Calculate 1x using the topmost stack entry.}
1229
1230\startMPinclusions
1231
1232 def draw_statistics (expr ShowNew, ShowAdd, ShowSubtract, ShowN, ShowSum, ShowMin, ShowMax, ShowMean, ShowSdev) =
1233 color c ; c := \MPcolor{action} ;
1234 Delta := 20 ;
1235 Total := 100 ;
1236 Range := 24 ;
1237 Sum := 0 ;
1238 Sqr := 0 ;
1239 randomseed := .5 ;
1240 pickup pencircle scaled .5Delta ;
1241 for r := 0 upto Range:
1242 Value[r] := 0 ;
1243 endfor ;
1244 for i=1 upto Total:
1245 r := uniformdeviate 1 ;
1246 Sum := Sum r ;
1247 Sqr := Sqr rr ;
1248 r := round(rRange) ;
1249 Value[r] := Value[r]+1 ;
1250 endfor ;
1251 Mean := SumTotal ;
1252 Sdev := sqrt((Sqr-2SumMeanTotalMeanMean)Total) ;
1253 Mean := MeanRange ;
1254 Sdev := SdevRange ;
1255 SdevMin := MeanSdev ;
1256 SdevMax := MeanSdev ;
1257 for r := 0 upto Range:
1258 draw (rDelta,0)--(rDelta,Value[r]Delta)
1259 withcolor
1260 if (ShowSdev and (r>SdevMin) and (r<SdevMax)) or ShowSum or
1261 (ShowMin and (r=0)) or (ShowMax and (r=Range)) or
1262 (ShowMean and (r=round(Mean)) or ShowSubtract) :
1263 c
1264 else :
1265 .4white
1266 fi ;
1267 if ShowN:
1268 draw (rDelta,0) withcolor c
1269 fi ;
1270 endfor ;
1271 if ShowAdd or ShowNew:
1272 pushboundingbox currentpicture ;
1273 currentpicture := nullpicture ;
1274 for r := 0 upto Range:
1275 draw (rDelta,0) withcolor .4white ;
1276 endfor ;
1277 if ShowAdd:
1278 draw (5Delta,0) withcolor c ;
1279 fi ;
1280 popboundingbox currentpicture ;
1281 elseif ShowSubtract:
1282 draw (5Delta,0) withcolor .4white ;
1283 fi ;
1284 enddef ;
1285
1286\stopMPinclusions
1287
1288\startuseMPgraphic{addn}
1289 draw_statistics (false, true, false, false, false, false, false, false, false) ;
1290\stopuseMPgraphic
1291
1292\ShowInfo{addn}{Add an observation to the statistics.}
1293
1294\startuseMPgraphic{subn}
1295 draw_statistics (false, false, true, false, false, false, false, false, false) ;
1296\stopuseMPgraphic
1297
1298\ShowInfo{subn}{Remove an observation from the statistics.}
1299
1300\startuseMPgraphic{newn}
1301 draw_statistics (true, false, false, false, false, false, false, false, false) ;
1302\stopuseMPgraphic
1303
1304\ShowInfo{newn}{Reset the statistics.}
1305
1306\startuseMPgraphic{sn}
1307 draw_statistics (false, false, false, true, false, false, false, false, false) ;
1308\stopuseMPgraphic
1309
1310\ShowInfo{sn}{Push the number of observations to the stack.}
1311
1312\startuseMPgraphic{stotal}
1313 draw_statistics (false, false, false, false, true, false, false, false, false) ;
1314\stopuseMPgraphic
1315
1316\ShowInfo{stotal}{Push the sum of encountered values to the stack.}
1317
1318\startuseMPgraphic{smin}
1319 draw_statistics (false, false, false, false, false, true, false, false, false) ;
1320\stopuseMPgraphic
1321
1322\ShowInfo{smin}{Push the lowest encountered value to the stack.}
1323
1324\startuseMPgraphic{smax}
1325 draw_statistics (false, false, false, false, false, false, true, false, false) ;
1326\stopuseMPgraphic
1327
1328\ShowInfo{smax}{Push the highest encountered value to the stack.}
1329
1330\startuseMPgraphic{smean}
1331 draw_statistics (false, false, false, false, false, false, false, true, false) ;
1332\stopuseMPgraphic
1333
1334\ShowInfo{smean}{Push the mean value to the stack.}
1335
1336\startuseMPgraphic{ssdev}
1337 draw_statistics (false, false, false, false, false, false, false, false, true) ;
1338\stopuseMPgraphic
1339
1340\ShowInfo{ssdev}{Push the standard deviation to the stack.}
1341
1342\startMPinclusions
1343
1344 def draw_ranges (expr ShowNegate, ShowCeiling, ShowFloor, ShowRound, ShowMin, ShowMax, ShowE) =
1345
1346 color c ; c := \MPcolor{action} ;
1347
1348 Tics := 5 ;
1349 Gap := 5Tics ;
1350 Height := .5Gap ;
1351 Place := 3 ;
1352
1353 pickup pencircle scaled 10 ;
1354
1355 for i=Tics upto Tics:
1356 draw (iGap,Height)--(iGap,Height) withcolor .4white ;
1357 endfor ;
1358
1359 draw (TicsGap,0)--(TicsGap,0) withcolor .4white ;
1360 draw (0,-2Height)--(0,2Height) withcolor .4white ;
1361
1362 z1 = (PlaceGap,0) ;
1363 z2 = ((Place+1)Gap,0) ;
1364
1365 if ShowNegate:
1366 draw (x1,Height)--(x1,Height) withcolor c ;
1367 draw (x1,-0)--(x1,0) withcolor c ;
1368 elseif ShowCeiling:
1369 draw (x2,Height)--(x2,Height) withcolor c ;
1370 linecap := butt ;
1371 draw z1z2 withcolor c ;
1372 elseif ShowFloor:
1373 draw (x1,Height)--(x1,Height) withcolor c ;
1374 linecap := butt ;
1375 draw z1z2 withcolor c ;
1376 elseif ShowRound:
1377 draw (x2,Height)--(x2,Height) withcolor c ;
1378 linecap := butt ;
1379 draw .5[z1,z2]z2 withcolor c ;
1380 elseif ShowMin:
1381 draw (x1,Height)--(x1,Height) withcolor c ;
1382 draw (x2,0)--(x2,0) withcolor c ;
1383 elseif ShowMax:
1384 draw (x2,Height)--(x2,Height) withcolor c ;
1385 draw (x1,0)--(x1,0) withcolor c ;
1386 elseif ShowE:
1387 e := Gapmexp256 ;
1388 draw (e,-3Height)--(e,3Height) withcolor c ;
1389 fi ;
1390
1391enddef ;
1392
1393\stopMPinclusions
1394
1395\startuseMPgraphic{neg}
1396 draw_ranges (true, false, false, false, false, false, false) ;
1397\stopuseMPgraphic
1398
1399\ShowInfo{neg}{Negate the topmost stack entry.}
1400
1401\startuseMPgraphic{ceil}
1402 draw_ranges (false, true, false, false, false, false, false) ;
1403\stopuseMPgraphic
1404
1405\ShowInfo{ceil}{Set the topmost stack entry to the next integer.}
1406
1407\startuseMPgraphic{floor}
1408 draw_ranges (false, false, true, false, false, false, false) ;
1409\stopuseMPgraphic
1410
1411\ShowInfo{floor}{Set the topmost stack entry to the previous integer.}
1412
1413\startuseMPgraphic{round}
1414 draw_ranges (false, false, false, true, false, false, false) ;
1415\stopuseMPgraphic
1416
1417\ShowInfo{round}{Set the topmost stack entry to the nearest integer.}
1418
1419\startuseMPgraphic{min}
1420 draw_ranges (false, false, false, false, true, false, false) ;
1421\stopuseMPgraphic
1422
1423\ShowInfo{min}{Take the minumum of the two topmost stack entries.}
1424
1425\startuseMPgraphic{max}
1426 draw_ranges (false, false, false, false, false, true, false) ;
1427\stopuseMPgraphic
1428
1429\ShowInfo{max}{Take the maximum of the two topmost stack entries.}
1430
1431\startuseMPgraphic{e}
1432 draw_ranges (false, false, false, false, false, false, true) ;
1433\stopuseMPgraphic
1434
1435\ShowInfo{e}{Push 2.71828182845905 onto the stack.}
1436
1437\startuseMPgraphic{pi}
1438 pickup pencircle scaled 10 ;
1439 draw fullcircle scaled 150 withcolor .4white ;
1440 linecap := butt ;
1441 ahlength := 25 ;
1442 drawarrow halfcircle scaled 150 withcolor \MPcolor{action} ;
1443\stopuseMPgraphic
1444
1445\ShowInfo{pi}{Push 3.14159265358979 onto the stack.}
1446
1447\startMPinclusions
1448
1449 def draw_degrees(expr DrawInner, DrawOuter) =
1450 pickup pencircle scaled .02 ;
1451 path p ; p := fullcircle ;
1452 path q ; q := subpath(0,1) of fullcircle ;
1453 path r ; r := (0,0)q--(0,0)cycle ;
1454 filldraw p withcolor .4white ;
1455 filldraw r withcolor \MPcolor{action} ;
1456 ahlength := .04 ;
1457 if DrawInner:
1458 drawarrow q scaled .30 withcolor .4white ;
1459 elseif DrawOuter:
1460 drawarrow q scaled .90 withcolor .4white ;
1461 fi ;
1462 currentpicture := currentpicture scaled 200 ;
1463 enddef ;
1464
1465\stopMPinclusions
1466
1467\startuseMPgraphic{deg}
1468 draw_degrees (true, false)
1469\stopuseMPgraphic
1470
1471\ShowInfo{deg}{Convert radians into degrees.}
1472
1473\startuseMPgraphic{rad}
1474 draw_degrees (false, true)
1475\stopuseMPgraphic
1476
1477\ShowInfo{rad}{Convert degrees into radians.}
1478
1479\startuseMPgraphic{random}
1480
1481 pickup pencircle scaled 5 ;
1482 color c ; c := \MPcolor{action} ;
1483 draw unitsquare scaled 100 withcolor .4white ;
1484 for i=1 upto 250:
1485 draw (uniformdeviate 90, uniformdeviate 90)
1486 shifted (5,5) withcolor (.4uniformdeviate .6)c ;
1487 endfor ;
1488 currentpicture := currentpicture scaled 2 ;
1489
1490\stopuseMPgraphic
1491
1492\ShowInfo{random}{Generate a random number in the range 01.}
1493
1494\startMPinclusions
1495
1496 def do_draw_number (expr n, drift, s, c) =
1497 numeric Height, Delta, Drift, x_max, y_max, x_pos, y_pos ;
1498 Height := 11 ;
1499 Delta := 5 ;
1500 Drift := if drift: 1.5 else: 0 fi ;
1501 x_max := 8 ;
1502 def d = (uniformdeviate Drift) enddef ;
1503 if n=0:
1504 draw ((d-4.5Delta,d)--(d-0.5Delta,Heightd))
1505 withpen pencircle scaled 2
1506 withcolor c ;
1507 else:
1508 for i := 1 upto n :
1509 x_pos := ((i-1) mod (5x_max))Delta ;
1510 y_pos := ((i-1) div (5x_max))(HeightDelta) ;
1511 draw
1512 if (i mod 5)=0 :
1513 ((d-4.5Delta,d)--(d-0.5Delta,Heightd))
1514 else :
1515 ((d,d)--(d,Heightd))
1516 fi
1517 shifted (x_pos,y_pos)
1518 withpen pencircle scaled 2
1519 withcolor c ;
1520 endfor ;
1521 fi ;
1522 currentpicture := currentpicture scaled s ;
1523 enddef ;
1524
1525 def draw_number (expr n, s) =
1526 do_draw_number(n,false,s,\MPcolor{keyboard}) ;
1527 push_boundingbox currentpicture ;
1528 currentpicture := nullpicture ;
1529 do_draw_number(n,true,s,\MPcolor{keyboard}) ;
1530 pop_boundingbox currentpicture ;
1531 enddef ;
1532
1533\stopMPinclusions
1534
1535\dostepwiserecurse {0}{9}{1} {
1536 \startuseMPgraphic{\recurselevel}
1537 draw_number(\recurselevel,10)
1538 \stopuseMPgraphic
1539 \expanded {
1540 \ShowInfo
1541 {\recurselevel}
1542 {Add a digit \recurselevel\ to the current stack entry.}
1543 }
1544}
1545
1546\startuseMPgraphic{fac}
1547
1548 def facultate (expr n) =
1549 if n=1: 1 else: nfacultate(n-1) fi
1550 enddef ;
1551 picture pic[] ;
1552 for m := 1 upto 5:
1553 do_draw_number(facultate(m),true,1,\MPcolor{action}) ;
1554 pic[m] := currentpicture ;
1555 currentpicture := nullpicture ;
1556 endfor ;
1557 xmax := xpart urcorner pic[5] xpart llcorner pic[5] ;
1558 for m = 1 upto 5:
1559 xmin := xpart urcorner pic[m] xpart llcorner pic[m] ;
1560 addto currentpicture also pic[m] shifted (.5(xmaxxmin),m25) ;
1561 endfor ;
1562 currentpicture := currentpicture scaled 2 ;
1563
1564\stopuseMPgraphic
1565
1566\ShowInfo{fac}{Calculate the recursive multiplication of n, n1, n2, etc.}
1567
1568\startMPinclusions
1569
1570 def draw_template (expr ShowSign, ShowPeriod, ShowExponent, ShowDel) =
1571 pickup pencircle scaled 10 ;
1572 color ca ; ca := if (ShowDel): .4white else: \MPcolor{stack} fi ;
1573 color cb ; cb := \MPcolor{keyboard} ;
1574 Delta := 20 ;
1575 Width := 10 ;
1576 Position := 6 ;
1577 Max := 15 ;
1578 path p ; p := (0,0)--(Width,0) ;
1579 draw (-2Width,0)--(0,0) withcolor if ShowSign: cb else: ca fi ;
1580 for i=1 upto Position-1:
1581 draw p shifted (iDelta,0) withcolor ca ;
1582 endfor ;
1583 draw (PositionDelta+.5Width,0)
1584 withcolor if ShowPeriod: cb else: ca fi ;
1585 for i=Position+1 upto Max:
1586 if i=Max-3:
1587 draw ((Width,0)--(0,0)--(0,2Width)--(Width,2Width))
1588 shifted (iDelta,-2.5)
1589 withpen pencircle scaled 5
1590 withcolor if ShowExponent: cb else: ca fi ;
1591 draw ((0,Width)--(Width,Width))
1592 shifted (iDelta,-2.5)
1593 withpen pencircle scaled 5
1594 withcolor if ShowExponent: cb else: ca fi ;
1595 else:
1596 draw p shifted (iDelta,0) withcolor ca ;
1597 fi ;
1598 endfor ;
1599 enddef ;
1600
1601\stopMPinclusions
1602
1603\startuseMPgraphic{sign}
1604 draw_template(true, false, false, false) ;
1605\stopuseMPgraphic
1606
1607\ShowInfo{sign}{Add a sign to the current stack entry.}
1608
1609\startuseMPgraphic{period}
1610 draw_template(false, true, false, false) ;
1611\stopuseMPgraphic
1612
1613\ShowInfo{period}{Add a period to the current stack entry.}
1614
1615\startuseMPgraphic{E}
1616 draw_template(false, false, true, false) ;
1617\stopuseMPgraphic
1618
1619\ShowInfo{E}{Start setting the exponent part of the current stack entry.}
1620
1621\startuseMPgraphic{del}
1622 draw_template(false, false, false, true) ;
1623\stopuseMPgraphic
1624
1625\ShowInfo{del}{Delete the last entered digit of the current stack entry.}
1626
1627\startMPinclusions
1628
1629 u := 50 ;
1630 logo_type := 0 ;
1631 input mpprag ;
1632 set_phead(u) ;
1633
1634 def draw_memory (expr DrawErase, DrawAdd, DrawSubtract, DrawCopy) =
1635 pickup pencircle scaled .1u ;
1636 color ca ; ca := \MPcolor{stack} ;
1637 color cb ; cb := \MPcolor{keyboard} ;
1638 draw phead withcolor .4white ;
1639 if DrawErase:
1640 stripe_path_n
1641 (withcolor .4white)
1642 (fill) pbrain scaled .8 shifted (.5u,.5u) withcolor .8cb ;
1643 else:
1644 fill pbrain scaled .8 shifted (.5u,.5u)
1645 if DrawCopy: withcolor .8ca else: withcolor .8cb fi ;
1646 fi ;
1647 draw pbrain scaled .8 shifted (.5u,.5u) withcolor cb ;
1648 push_boundingbox currentpicture ;
1649 ahlength:=.2u ;
1650 path drain ; drain := (4.5u,2u){dir 120}..(2.25u,2.75u) ;
1651 if DrawAdd:
1652 drawarrow drain withcolor ca ;
1653 elseif DrawSubtract or DrawCopy:
1654 drawarrow reverse drain withcolor ca ;
1655 fi ;
1656 pop_boundingbox currentpicture ;
1657 enddef ;
1658
1659\stopMPinclusions
1660
1661\startuseMPgraphic{newmem}
1662 draw_memory (true,false,false,false) ;
1663\stopuseMPgraphic
1664
1665\ShowInfo{newmem}{Erase the memory buffer.}
1666
1667\startuseMPgraphic{addmem}
1668 draw_memory (false,true,false,false) ;
1669\stopuseMPgraphic
1670
1671\ShowInfo{addmem}{Add to the memory buffer.}
1672
1673\startuseMPgraphic{submem}
1674 draw_memory (false,false,true,false) ;
1675\stopuseMPgraphic
1676
1677\ShowInfo{submem}{Substract from the memory buffer.}
1678
1679\startuseMPgraphic{copmem}
1680 draw_memory (false,false,false,true) ;
1681\stopuseMPgraphic
1682
1683\ShowInfo{copmem}{Copy the memory buffer to the stack.}
1684
1685\startMPinclusions
1686
1687 def erase_stack =
1688 stripe_path_n
1689 (withcolor .4white)
1690 (fill) p withcolor .8cb ;
1691 enddef ;
1692
1693 def draw_stack (expr ShowNew, ShowPush, ShowPop, ShowDup) =
1694 path p ;
1695 color ca ; ca := \MPcolor{stack} ;
1696 color cb ; cb := \MPcolor{keyboard} ;
1697 for i=8 downto 1:
1698 j := i-1 ;
1699 pickup pencircle scaled 1.5 ;
1700 p := unitsquare
1701 shifted(-.5,-.5)
1702 xscaled 100 yscaled 40
1703 shifted(20j,j15)
1704 scaled (1j.04) ;
1705 if i<3:
1706 fill p withcolor .4white ;
1707 elseif ShowPush:
1708 fill p withcolor if i=3: .8cb else : .8ca fi ;
1709 elseif ShowPop:
1710 if i=3: erase_stack else: fill p withcolor .8ca fi ;
1711 elseif ShowNew:
1712 erase_stack ;
1713 elseif ShowDup:
1714 fill p withcolor if i>4: .8ca else: .8cb fi ;
1715 else:
1716 fill p withcolor .4white ;
1717 fi ;
1718 draw p withcolor ca ;
1719 endfor ;
1720 currentpicture := currentpicture scaled 1.5 ;
1721 enddef ;
1722
1723\stopMPinclusions
1724
1725\startuseMPgraphic{push}
1726 draw_stack (false, true, false, false)
1727\stopuseMPgraphic
1728
1729\ShowInfo{push}{Push a new entry to the stack.}
1730
1731\startuseMPgraphic{pop}
1732 draw_stack (false, false, true, false)
1733\stopuseMPgraphic
1734
1735\ShowInfo{pop}{Remove the topmost entry from the stack.}
1736
1737\startuseMPgraphic{new}
1738 draw_stack (true, false, false, false)
1739\stopuseMPgraphic
1740
1741\ShowInfo{new}{Erase the whole stack.}
1742
1743\startuseMPgraphic{dup}
1744 draw_stack (false, false, false, true)
1745\stopuseMPgraphic
1746
1747\ShowInfo{dup}{Duplicate the topmost stack entry.}
1748
1749\startMPinclusions
1750
1751 def draw_funcalc (expr p, q, r, action) =
1752
1753 color b ; b := \MPcolor{keyboard} ;
1754 color c ; c := \MPcolor{stack} ;
1755
1756 draw ((-2.25max(p,q,r))-1,0)--(-1,0) withcolor .4white ;
1757
1758 pickup pencircle scaled 2 ;
1759 for i=1 upto p: draw (i2.25, 3.75) withcolor c ; endfor ;
1760 for i=1 upto q: draw (i2.25, 1.50) withcolor c ; endfor ;
1761 for i=1 upto r: draw (i2.25,-1.50) withcolor c ; endfor ;
1762 pickup pencircle scaled .5 ;
1763
1764 push_boundingbox currentpicture ;
1765
1766 pair w ; w := (1.125,0) ;
1767 path ww ; ww := w -- w ;
1768
1769 if action=1:
1770 draw ww shifted w withcolor b ;
1771 draw ww rotated 90 shifted w withcolor b ;
1772 elseif action=2:
1773 draw ww shifted w withcolor b ;
1774 elseif action=3:
1775 draw ww rotated 45 shifted w withcolor b ;
1776 draw ww rotated 135 shifted w withcolor b ;
1777 elseif action=4:
1778 draw ww rotated 45 shifted w withcolor b ;
1779 fi ;
1780
1781 pop_boundingbox currentpicture ;
1782
1783 currentpicture := currentpicture scaled 15 ;
1784
1785 enddef ;
1786
1787\stopMPinclusions
1788
1789\startuseMPgraphic{add}
1790 draw_funcalc (6, 6, 7, 1)
1791\stopuseMPgraphic
1792
1793\ShowInfo{add}{Add the two topmost stack entries.}
1794
1795\startuseMPgraphic{sub}
1796 draw_funcalc (5, 4, 5, 2)
1797\stopuseMPgraphic
1798
1799\ShowInfo{sub}{Subtract the topmost stack entry from the one below.}
1800
1801\startuseMPgraphic{mul}
1802 draw_funcalc (3, 4, 7, 3)
1803\stopuseMPgraphic
1804
1805\ShowInfo{mul}{Multiply the two topmost stack entries.}
1806
1807\startuseMPgraphic{div}
1808 draw_funcalc (5, 2, 4, 4)
1809\stopuseMPgraphic
1810
1811\ShowInfo{div}{Divide the prelast stack entry by the topmost one.}
1812
1813\startuseMPgraphic{grow}
1814
1815 pickup pencircle scaled 5 ;
1816 ahlength := 10 ;
1817
1818 path p ; p := (0,0)--(60,0) ;
1819 path q ; q := (30,215)--(30,715) ;
1820 path r ; r := (30,0)--(30,715) ;
1821
1822 for i=0 upto 7:
1823 draw p shifted (0,i15) withcolor
1824 if i<3: \MPcolor{stack} else: .4white fi ;
1825 endfor ;
1826
1827 addto currentpicture also currentpicture
1828 rotatedaround (center currentpicture, 180)
1829 shifted (90, 0) ;
1830
1831 drawarrow q withcolor \MPcolor{keyboard} ;
1832 drawarrow reverse r shifted (90, 0) withcolor \MPcolor{keyboard} ;
1833
1834 currentpicture := currentpicture scaled 2 ;
1835
1836\stopuseMPgraphic
1837
1838\ShowInfo{grow}{Toggle grow mode, another way of stacking.}
1839
1840\startuseMPgraphic{exit}
1841
1842 path p ; p := (100,30)--(100,0)--(0,0)--(0,100)--(100,100)--(100,70) ;
1843 pickup pencircle scaled 10 ;
1844 linecap := butt ;
1845 ahlength := 60 ;
1846 ahangle := 75 ;
1847 filldraw
1848 pcycle
1849 withcolor \MPcolor{action} ;
1850 draw
1851 p
1852 withcolor \MPcolor{stack} ;
1853 push_boundingbox currentpicture ;
1854 pickup pencircle scaled 30 ;
1855 draw
1856 center currentpicture --
1857 (xpart lrcorner currentpicture+.75ahlength, ypart center currentpicture)
1858 withcolor \MPcolor{keyboard} ;
1859 pickup pencircle scaled 5 ;
1860 drawarrow
1861 center currentpicture --
1862 (xpart lrcorner currentpicture, ypart center currentpicture)
1863 withcolor \MPcolor{keyboard} ;
1864 pop_boundingbox currentpicture ;
1865 currentpicture := currentpicture scaled 1.75 ;
1866
1867\stopuseMPgraphic
1868
1869\ShowInfo{exit}{Close this document.}
1870
1871\stoptext
1872 |