-
Notifications
You must be signed in to change notification settings - Fork 23
/
SSS32.ps
2516 lines (2320 loc) · 65.3 KB
/
SSS32.ps
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
%!PS-Adobe-3.0
%%Orientation: Portrait
%%Pages: 21
%%EndComments
%%BeginSetup
[(Shamir's Secret) (Sharing Codex)]
(revision alpha-4.6)
[
(MIT License)
()
(Copyright (c) 2020 Blockstream)
()
(Permission is hereby granted, free of charge, to any person obtaining a copy)
(of this software and associated documentation files (the "Software"), to deal)
(in the Software without restriction, including without limitation the rights)
(to use, copy, modify, merge, publish, distribute, sublicense, and/or sell)
(copies of the Software, and to permit persons to whom the Software is)
(furnished to do so, subject to the following conditions:)
()
(The above copyright notice and this permission notice shall be included in all)
(copies or substantial portions of the Software.)
()
(THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR)
(IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,)
(FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE)
(AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER)
(LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,)
(OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE)
(SOFTWARE.)
]
[
(WARNING: Seriously, this is a work in progress, and it is only a concept right now.)
(If you try to use this for your valuable data, I promise you will lose your data.)
(You will lose this document and come back here only to find that I have made incompatible changes,)
(and your data is lost forever. Even if you don't lose this document, there is no warranty or)
(guarantee of any kind that you will be able to recover successfully recover your data.)
]
%************************************************************************
%************************************************************************
%*
%* Section One: Preamble
%*
%************************************************************************
%************************************************************************
%******************
%* Front matter
%*
%* Define variables for the preceeding front matter text.
%*
/warning exch def
/MIT exch def
/ver exch def
/title exch def
/README [
(MATERIALS: Scissors, X-Acto knife, brass fasteners)
()
(CONSTRUCTION:)
(The bottom discs are the discs with a small circle in the center of them.)
(The top discs are the discs with a small cross in the centre. All the top discs are identical. Cut out each disc.)
(Cut out the small centre circle in each the bottom discs. Cut out each of the 32 squares of each top disc.)
(Cut a slit along one one of the small lines of the cross in each of the top discs.)
(Pass the brass fastener through a top disc and bottom disc.)
(Fold the legs of the fastener apart to secure the top and bottom discs together.)
(The two discs should now be able to rotate about their common centre.)
()
(SECRET RECOVERY:)
(Find 2 of your secured shares.)
(Make sure all your shares have the same identifier and a valid checksum (see checksum worksheet).)
(Dial the recover share disc to the share index of the first secured share (the 5th character).)
(Look up the symbol associated with the share index of the other share.)
(Set your translation disc to that symbol and translate the first secured share by looking up every charater in turn.)
(Dial the recover share disc to the share index of the second secured share (the 5th character).)
(Look up the symbol associated with the share index of the first share.)
(Set your translation disc to that symbol and translate the second secured share by looking up every charater in turn.)
(Add the two translated shares, character by character, using the Addition disc.)
(The result is your secret share and will have share index S and a valid checksum.)
] def
%******************
%* Helper Functions and Utilities
%*
% determinant : matrix -- det(matrix)
/determinant {
1 0 2 index dtransform
0 1 5 4 roll dtransform
3 1 roll mul
3 1 roll mul
exch sub
} bind def
% tan : angle -- tan(angle)
/tan {
dup sin exch cos div
} bind def
% arcsin: y h -- arcsin(y/h)
/arcsin {
dup mul 1 index dup mul sub sqrt
atan
} bind def
% arccos: x h -- arccos(x/h)
/arccos {
dup mul 1 index dup mul sub sqrt
exch atan
} bind def
% Given a rod of length 2r, what angle does it fit inside a w by h sized box so that
% the ends of the rod are equaldistant from the two sides making a corner with the box.
/angleinbox {
10 dict begin
{ /r /h /w } {exch def} forall
h w sub
2 2 sqrt r mul mul
arcsin 45 sub
end
} bind def
% Constructs a coordinate transformation used for the illustration of folding volvelles.
/foldprojection {
10 dict begin
/foldangle exch def
/squish 0.25 def
/squash 1 squish dup mul sub sqrt def % sqrt (1 - squish^2)
/rollangle squish neg 1 atan def
[rollangle cos squish mul
rollangle sin
dup neg squish mul foldangle cos mul foldangle sin squash mul add
rollangle cos foldangle cos mul
0 0 ]
end
} bind def
/concatstrings % (a) (b) -> (ab)
{ exch dup length
2 index length add string
dup dup 4 2 roll copy length
4 -1 roll putinterval
} bind def
%******************
%* Field Arthmetic
%*
%* Calculations within GF(32), extended with the "null element", represented by
%* numberic 32, which is displayed as a blank, and on which every operation
%* returns null again. Used to represent incomplete/unknown data.
%*
%* Our generator for GF(32) has minimum polynomial x^5 + x^3 + 1.
%*
/gf32add % x y -> x [+] y where [+] is addition in GF32.
% returns 32 if x or y is out of range.
% Note that x [+] y = x [-] y in GF32.
{ % x y
2 copy 32 ge % x y x (y >= 32)
exch 32 ge or % x y (y >= 32 || x >= 32)
{pop pop 32} % 32
{xor} % x [+] y
ifelse % if (y >= 32 || x >= 32) then 32 else (x [+] y)
} bind def
/gf32mulalpha % x -> x [*] alpha where [*] is multiplicaiton in GF32 and alpha is represted by 0b00010.
{ % x
2 mul % 2*x
dup 32 ge % 2*x (2*x >= 0b100000)
{ 41 xor } % 2*x `xor` 0b101001
if % if (2*x >= 0xb100000) then 2*x `xor` 0x0b101001 else 2*x
} bind def
/gf32mul % x y -> x [*] y where [*] is multiplication in GF32.
% returns 32 if x or y is out of range.
{ % x y
10 dict begin
{ /y /x } {exch def} forall
x 32 ge y 32 ge or % (y >= 32 || x >= 32)
{32} % 32
{
/xShift x def
/yAlpha y def
0 % 0
5 { % ((x & 0b001..1) [*] y) (x >> i) (y [*] alpha[^i])
xShift 1 and yAlpha mul xor % ((x & 0b001..1) [*] y [+] ((x >> i) & 1) * (y [*] alpha [^i]))
/xShift xShift -1 bitshift def
/yAlpha yAlpha gf32mulalpha def
} repeat % ((x & 0b11111) [*] y)
} ifelse % if (y >= 32 || x >= 32) then 32 else (x [*] y)
end
} bind def
/gf32inv % x -> x [^-1] where [^-1] is the inverse operation in GF32.
% returns 0 when given 0.
% returns 32 if x is out of range.
{ % x
dup dup gf32mul % x x[^2]
dup gf32mul gf32mul % x[^5]
dup dup gf32mul gf32mul % x[^15]
dup gf32mul % x[^30]
% x[^-1]
} bind def
/lagrange % x xj [x[0] .. x[k]] -> l[j](x)
% returns the lagrange basis polynomial l[j] evaluated at x for interpolation of coordinates [x[0] .. x[k]].
% Requires xj `elem` [x[0] ... x[k]]
{ % x xj [x[0] .. x[k]]
10 dict begin
{ /xs /xj /x } {exch def} forall
1 xs % 1 [x[0] .. x[k]]
{ % let P = product [(x [-] x[m]) [/] (xj [-] x[m]) | m <- [0..i-1], x[m] /= xj]
% P x[i]
/xi exch def % P
xi xj gf32add % P (xj [-] x[i])
dup 0 eq % P (xj [-] x[i]) (xj [-] x[i] == 0)
{ pop } % P
{ gf32inv gf32mul % (P [/] (xj [-] x[i])
xi x gf32add gf32mul % (P [*] (x [-] x[i]) [/] (xj [-] x[i]))
}
ifelse % (if xj == x[i] then P else (P [*] (x [-] x[i]) [/] (xj [-] x[i]))
} forall % x xj (product [(x [-] x[m]) [/] (xj [-] x[m]) | m <- [0..k], x[m] /= xj])
end
} bind def
/makeShare % sS sA i -> si
{ 3 2 roll 1 index permS 0 get permS 0 2 getinterval lagrange gf32mul
3 1 roll permS 1 get permS 0 2 getinterval lagrange gf32mul
xor
} bind def
/gf32mularray % x b -> x * b
{ [ 3 1 roll { 1 index gf32mul exch } forall pop ]
} bind def
/gf32addarray % a b -> a + b pointwise
{ [ 3 1 roll 0 1 2 index length 1 sub { 2 index 1 index get 2 index 2 index get gf32add exch pop 3 1 roll } for pop pop ]
} bind def
%******************
%* Code Parameters
%*
%* Data related to the representation of GF(32) elements
%*
/perm [29 24 13 25 9 8 23 18 22 31 27 19 1 0 3 16 11 28 12 14 6 4 2 15 10 17 21 20 26 30 7 5 ] def
/permS [16 29 24 13 25 9 8 23 18 22 31 27 19 1 0 3 11 28 12 14 6 4 2 15 10 17 21 20 26 30 7 5 ] def
/permV [22 11 10 29 31 28 17 24 27 12 21 13 19 14 20 25 1 6 26 9 0 4 30 8 3 2 7 23 16 15 5 18 ] def
/permId [ 0 1 31 {} for ] def
/code [/Q /P /Z /R /Y /nine /X /eight /G /F /two /T /V /D /W /zero /S /three /J /N /five /four /K /H /C /E /six /M /U /A /seven /L /space] def
/code2 [/multiply /aleph /alpha /beta /Gamma /Delta /epsilon /eta /Theta /Lambda /mu /Xi /Pi /rho /Sigma /Phi /Psi /Omega /at /numbersign /percent /cent /yen /Euro /currency /circleplus /dagger /daggerdbl /section /paragraph /diamond /heart /space ] def
/decode {
[ exch { <<
113 0
81 0
112 1
80 1
122 2
90 2
114 3
82 3
121 4
89 4
57 5
120 6
88 6
56 7
103 8
71 8
102 9
70 9
50 10
116 11
84 11
118 12
86 12
100 13
68 13
119 14
87 14
48 15
115 16
83 16
51 17
106 18
74 18
110 19
78 19
53 20
52 21
107 22
75 22
104 23
72 23
99 24
67 24
101 25
69 25
54 26
109 27
77 27
117 28
85 28
97 29
65 29
55 30
108 31
76 31
32 32
>> exch get } forall ]
} bind def
%******************
%* BCH
%*
%* Data and functions related to the error-correcting code.
%*
/polymodulus [25 27 17 8 0 25 25 25 31 27 24 16 16] def % coefficents from c12 to c0
/checksum [16 25 24 3 25 11 16 23 29 3 25 17 10] def
/checksumstring { polymodulus length array checksum 0 1 polymodulus length 1 sub {3 copy exch 1 index get code exch 1 getinterval putinterval pop } for pop } bind def
/polymod0 % array -> [ c5 c4 c3 c2 c1 c0 ]
{ [ polymodulus length {0} repeat ]
exch
{ [ exch 2 index 1 polymodulus length 1 sub getinterval aload pop polymodulus length dup 1 sub roll ] exch 0 get polymodulus gf32mularray gf32addarray } forall
} bind def
/polymodshift2 % c7 c6 -> [ c5 c4 c3 c2 c1 c0 ]
{ [ 3 1 roll polymodulus length {0} repeat ] polymod0
} bind def
/polymodhrp % string -> [ c5 c4 c3 c2 c1 c0 ]
{
[ exch 1 exch dup { dup dup 65 ge exch 90 le exch and { 32 add } if 32 idiv exch } forall 0 exch { 31 and } forall ] polymod0
} bind def
%************************************************************************
%************************************************************************
%*
%* Section Two: Graphics
%*
%************************************************************************
%************************************************************************
%******************
%* Helper Functions and Utilities
%*
/pgsize currentpagedevice /PageSize known
{ currentpagedevice /PageSize get
} {
[611.842163 791.842163] % letter size
} ifelse
def
20 dict dup /portraitPage exch def begin
pgsize aload pop [ /pageH /pageW ] { exch def } forall
/centerX pageW 2 div def
/centerY pageH 2 div def
/marginX1 36 def
/marginX2 pageW 36 sub def
/marginY1 pageH 48 sub def
/marginY2 48 def
/marginW marginX2 marginX1 sub def
/marginH marginY2 marginY1 sub def
% Draw a line indicating where the margins of the page are; can be used
% for debugging graphical output
/drawMargin {
gsave
0 setgray thin line
marginX1 marginY1 marginW marginH rectstroke
grestore
} bind def
% Draw the page number and any (TODO) content in the page content array
% Takes the pagenum as a numeric value
/drawPageContent {
10 dict begin
/pagenum exch def
gsave
/Times-Roman findfont 12 scalefont setfont
centerX marginY2 moveto
pagenum pagenum 10 lt { 1 } { 2 } ifelse string cvs show
grestore
end
} bind def
end
% landscapePage is a modified copy of portraitPage
portraitPage dup 20 dict copy dup /landscapePage exch def begin
pgsize aload pop exch [ /pageH /pageW ] { exch def } forall
/centerX pageW 2 div def
/centerY pageH 2 div def
/marginX1 36 def
/marginX2 pageW 36 sub def
/marginY1 pageH 48 sub def
/marginY2 48 def
/marginW marginX2 marginX1 sub def
/marginH marginY2 marginY1 sub def
/pageW portraitPage /pageH get def
/pageH portraitPage /pageW get def
/drawPageContent {
90 rotate
0 pageH neg translate
portraitPage /drawPageContent get exec
} bind def
end
% line : width --
/line {
setlinewidth
1 setlinecap
1 setlinejoin
[] 0 setdash
} bind def
/verythin 0.2 def
/thin 0.4 def
/thick 0.8 def
/verythick 1.2 def
/pen {
50 setlinewidth
1 setlinecap
1 setlinejoin
[] 0 setdash
} bind def
% Runs stroke under a uniformly scaled matrix.
% ps2pdf doesn't seem to handle strokes under a non-uniformly scaled matrix properly.
/resetstroke {
matrix currentmatrix
dup determinant abs
initmatrix
matrix currentmatrix determinant abs div
sqrt dup scale
stroke
setmatrix
} bind def
/brass { 0.7098 0.651 0.2588 } def
/pink { 1 0.9 0.9 } def
/substitute <<
/Omega /uni03A9
/circleplus /uni2295
>> def
% codexshow : /glyph size --
/codexshow {
10 dict begin
/sz exch def
/charname exch def
/basefont /Courier findfont def
/basechars basefont /CharStrings get def
/backupfont /Symbol findfont def
substitute charname known basechars charname known not and
{ basechars substitute charname get known { /charname substitute charname get def } if } if
basechars charname known
{ basefont sz scalefont setfont charname glyphshow }
{ backupfont sz scalefont setfont charname glyphshow } ifelse
end
} bind def
/withcrosses true def
% draftingshow : /glyph size --
/draftingshow {
gsave
10 dict begin
currentpoint translate
1000 div dup scale
[1 0 10 tan 1 -100 -100] concat
<<
/space { }
/A { newpath
100 100 moveto
400 700 lineto
700 100 lineto
200 300 moveto
600 300 lineto
pen stroke }
/C { newpath
400 400 300 2 3 arccos -2 3 arccos 180 add arc
pen stroke }
/D { newpath
100 100 moveto
300 400 300 270 90 arc
100 700 lineto
closepath
pen stroke }
/E { newpath
600 700 moveto
100 700 lineto
100 100 lineto
600 100 lineto
100 400 moveto
400 400 lineto
pen stroke }
/F { newpath
600 700 moveto
100 700 lineto
100 100 lineto
100 400 moveto
400 400 lineto
pen stroke }
/G { newpath
400 400 300 2 3 arccos -2 3 arccos 180 add arc
600 400 lineto
400 400 lineto
pen stroke }
/H { newpath
600 700 moveto
600 100 lineto
100 700 moveto
100 100 lineto
100 400 moveto
600 400 lineto
pen stroke }
/J { newpath
600 700 moveto
matrix currentmatrix
100 100 translate
1 4 5 div scale
250 250 250 0 180 arcn
setmatrix
pen stroke }
/L { newpath
100 700 moveto
100 100 lineto
600 100 lineto
pen stroke }
/K { newpath
600 700 moveto
100 300 lineto
100 700 moveto
100 100 lineto
300 460 moveto
600 100 lineto
pen stroke }
/M { newpath
100 100 moveto
100 700 lineto
400 100 lineto
700 700 lineto
700 100 lineto
pen stroke }
/N { newpath
600 700 moveto
600 100 lineto
100 700 lineto
100 100 lineto
pen stroke }
/P { newpath
100 400 moveto
450 550 150 270 90 arc
100 700 lineto
100 100 lineto
pen stroke }
/Q { newpath
400 400 300 0 360 arc
500 250 moveto
600 100 lineto
pen stroke }
/R { newpath
100 400 moveto
450 550 150 270 90 arc
100 700 lineto
100 100 lineto
400 400 moveto
600 100 lineto
pen stroke }
/S { newpath
matrix currentmatrix
100 100 translate
5 3 div 1 scale
150 150 150 -90 1 3 arccos sub 90 arc
setmatrix
matrix currentmatrix
150 400 translate
4 3 div 1 scale
150 150 150 270 90 1 3 arccos sub arcn
setmatrix
withcrosses {
350 50 moveto
350 750 lineto
} if
pen stroke }
/T { newpath
100 700 moveto
700 700 lineto
400 700 moveto
400 100 lineto
pen stroke }
/U { newpath
600 700 moveto
matrix currentmatrix
100 100 translate
1 4 5 div scale
250 250 250 0 180 arcn
setmatrix
100 700 lineto
pen stroke }
/V { newpath
100 700 moveto
400 100 lineto
700 700 lineto
pen stroke }
/W { newpath
100 700 moveto
300 100 lineto
500 700 lineto
700 100 lineto
900 700 lineto
pen stroke }
/X { newpath
100 100 moveto
650 700 lineto
150 700 moveto
700 100 lineto
pen stroke }
/Y { newpath
100 700 moveto
400 400 lineto
700 700 lineto
400 400 moveto
400 100 lineto
pen stroke }
/Z { newpath
100 700 moveto
600 700 lineto
100 100 lineto
600 100 lineto
withcrosses {
200 400 moveto
500 400 lineto
} if
pen stroke }
/zero { newpath
matrix currentmatrix
100 100 translate
5 6 div 1 scale
300 300 300 0 360 arc
setmatrix
withcrosses {
100 100 moveto
600 700 lineto
} if
pen stroke }
/two { newpath
matrix currentmatrix
150 400 translate
4 3 div 1 scale
150 150 150 90 1 3 arccos add -90 arcn
setmatrix
matrix currentmatrix
100 -200 translate
5 6 div 1 scale
300 300 300 90 180 arc
setmatrix
600 100 lineto
pen stroke }
/three { newpath
matrix currentmatrix
100 100 translate
5 3 div 1 scale
150 150 150 -90 1 3 arccos sub 90 arc
setmatrix
matrix currentmatrix
150 400 translate
4 3 div 1 scale
150 150 150 -90 90 1 3 arccos add arc
setmatrix
pen stroke }
/four { newpath
500 100 moveto
500 700 lineto
100 250 lineto
600 250 lineto
pen stroke }
/five { newpath
matrix currentmatrix
100 100 translate
5 4 div 1 scale
200 200 200 -90 1 2 arccos sub 180 4 5 arccos sub arc
setmatrix
150 700 lineto
550 700 lineto
pen stroke }
/six { newpath
matrix currentmatrix
100 100 translate
5 6 div 1 scale
300 300 300 90 2 3 arccos sub 270 arc
setmatrix
matrix currentmatrix
100 100 translate
5 4 div 1 scale
200 200 200 -90 90 arc
setmatrix
pen stroke
newpath
matrix currentmatrix
100 100 translate
5 6 div 1 scale
300 300 300 0 360 arc
setmatrix
clip
newpath
matrix currentmatrix
100 100 translate
5 4 div 1 scale
200 200 200 90 180 arc
setmatrix
stroke }
/seven { newpath
100 700 moveto
600 700 lineto
400 400 300 300 300 100 curveto
withcrosses {
300 400 moveto
500 400 lineto
} if
pen stroke }
/eight { newpath
matrix currentmatrix
100 100 translate
5 3 div 1 scale
150 150 150 90 450 arc
setmatrix
matrix currentmatrix
150 400 translate
4 3 div 1 scale
150 150 150 -90 270 arc
setmatrix
pen stroke }
/nine { newpath
matrix currentmatrix
100 100 translate
5 6 div 1 scale
300 300 300 -90 2 3 arccos sub 90 arc
setmatrix
matrix currentmatrix
100 300 translate
5 4 div 1 scale
200 200 200 90 -90 arc
setmatrix
pen stroke
newpath
matrix currentmatrix
100 100 translate
5 6 div 1 scale
300 300 300 0 360 arc
setmatrix
clip
newpath
matrix currentmatrix
100 300 translate
5 4 div 1 scale
200 200 200 -90 0 arc
setmatrix
stroke }
>>
exch get exec
end
grestore
} bind def
/glyphwidth {
gsave
nulldevice newpath 0 0 moveto glyphshow currentpoint
grestore
} bind def
/codexwidth {
gsave
nulldevice newpath 0 0 moveto codexshow currentpoint
grestore
} bind def
/draftingwidth {
exch
32 dict begin
/M 800 def
/N 700 def
/W 1000 def
/A M def
/C N def
/D N def
/E N def
/F N def
/G N def
/H N def
/J N def
/K N def
/L N def
/P N def
/Q M def
/R N def
/S N def
/T M def
/U N def
/V M def
/X M def
/Y M def
/Z N def
/zero N def
/two N def
/three N def
/four N def
/five N def
/six N def
/seven N def
/eight N def
/nine N def
/space N def
load
end
mul 1000 div
0
} bind def
/centreshow {dup stringwidth pop 2 div neg 0 rmoveto show} bind def
/centrecodexshow {2 copy codexwidth pop 2 div neg 0 rmoveto codexshow} bind def
/centresquare {dup neg 2 div dup rmoveto dup 0 rlineto dup 0 exch rlineto neg 0 rlineto closepath stroke} bind def
/centredraftingshow {2 copy draftingwidth pop 2 div neg 0 rmoveto draftingshow} bind def
% From BLUEBOOK Program #10
/outsidecircletext
{ circtextdict begin
/radius exch def
/centerangle exch def
/ptsize exch def
/str exch def
/xradius radius ptsize 4 div add def
gsave
centerangle str findhalfangle add rotate
str
{ /charcode exch def
( ) dup 0 charcode put outsideplacechar
} forall
grestore
end
} def
/insidecircletext
{ circtextdict begin
/radius exch def /centerangle exch def
/ptsize exch def /str exch def
/xradius radius ptsize 3 div sub def
gsave
centerangle str findhalfangle sub rotate
str
{ /charcode exch def
( ) dup 0 charcode put insideplacechar
} forall
grestore
end
} def
/circtextdict 16 dict def
circtextdict begin
/findhalfangle
{ stringwidth pop 2 div
2 xradius mul pi mul div 360 mul
} def
/outsideplacechar
{ /char exch def
/halfangle char findhalfangle def
gsave
halfangle neg rotate
radius 0 translate
-90 rotate
char stringwidth pop 2 div neg 0 moveto
char show
grestore
halfangle 2 mul neg rotate
} def
/insideplacechar
{ /char exch def
/halfangle char findhalfangle def
gsave
halfangle rotate
radius 0 translate
90 rotate
char stringwidth pop 2 div neg 0 moveto
char show
grestore
halfangle 2 mul rotate
} def
/pi 3.1415923 def
end
%******************
%* Volvelle and Slide Charts
%*
/magic 94 def % a magic angle for making nice looking spirals.
/drawBottomWheelPage
{ 10 dict begin
/outerperm exch def
/outercode exch def
/innercode exch def
/title exch def
/binop exch def
/angle 360 outerperm length div neg def
% Move cursor to center of page
pgsize aload pop 2 div exch 2 div exch translate
% Draw white interior circle
newpath 0 0 6 40 mul 0 360 arc stroke
gsave verythin line
newpath 0 0 6 40 mul 28 add 0 360 arc stroke
newpath 0 0 6 0 360 arc stroke
grestore
% Draw title (small text, repeated)
/Helvetica findfont 12 scalefont setfont
title 12 270 30 insidecircletext
% Draw letters (using human-centric ABCD... permutation)
/Helvetica findfont 6 scalefont setfont
gsave
360 16 div 360 64 div sub rotate
0 360 8 div 360 {title 6 3 -1 roll 262 outsidecircletext} for
grestore
outerperm {0 38 sqrt 40 mul moveto outercode exch get 18 centrecodexshow angle rotate} forall
% Draw inside contents
0 1 31 { % Draw 32 circles of increasing radius
dup 1 add magic mul 24 add
/theta exch def
outerperm {
1 index 2 add sqrt 40 mul 2 sub
/lam exch def
lam theta sin mul
lam theta cos mul neg
moveto
0 -3 rmoveto
1 index 31 exch sub % 31 - inner index
permV exch get binop % apply binary operation to the permuted letter and the inner index
innercode exch get 12 centrecodexshow % display the result
angle rotate % rotate one entry
} forall pop
} for
end
} bind def
/showTopWheelPage
{
% Move cursor to center of page
pgsize aload pop 2 div exch 2 div exch translate
gsave verythin line
newpath 0 0 6 40 mul 0 360 arc stroke
grestore
% Draw gray "handle" and white interior circle
gsave
0.8 setgray
newpath 0 0 7.25 40 mul 140 40 arc clip fill
1 setgray
newpath 0 0 6 40 mul 0 360 arc fill
0 setgray
newpath 0 0 6 40 mul 0 360 arc stroke
grestore
% Draw centre cross
gsave verythin line
newpath 0 6 moveto 0 -6 lineto stroke
newpath 6 0 moveto -6 0 lineto stroke
grestore
% Draw indicator arrow
newpath 0 6 40 mul moveto 10 -20 rlineto -20 0 rlineto closepath fill
% Draw text
0 1 31 {
dup 1 add magic mul 24 add
/theta exch def
dup 2 add sqrt 40 mul 2 sub % lam = 40*sqrt(idx + 0.5) - 2
/lam exch def
newpath
lam theta sin mul
lam theta cos mul neg
2 copy moveto
12 centresquare % draw square
moveto % return to midpoint
-26 -3 rmoveto % Move to the left
31 exch sub % 31 - loop index
permV exch get code exch get % Permute index and extract 1-char substring of alphabet
12 codexshow % ...and draw it
/Symbol findfont 12 scalefont setfont /arrowright glyphshow % Draw a right arrow
} for
} bind def
% drawPointer : sz --
% draws a fillied triangle of sz pointing up (or down if sz is negative).
/drawPointer {
/sz exch def
0 sz eq not {