1 | #!/usr/bin/sed -f |
---|
2 | # dc.sed - an arbitrary precision RPN calculator |
---|
3 | # Created by Greg Ubben <gsu@romulus.ncsc.mil> early 1995, late 1996 |
---|
4 | # |
---|
5 | # Dedicated to MAC's memory of the IBM 1620 ("CADET") computer. |
---|
6 | # @(#)GSU dc.sed 1.0 27-Feb-1997 [non-explanatory] |
---|
7 | # |
---|
8 | # Examples: |
---|
9 | # sqrt(2) to 10 digits: echo "10k 2vp" | dc.sed |
---|
10 | # 20 factorial: echo "[d1-d1<!*]s! 20l!xp" | dc.sed |
---|
11 | # sin(ln(7)): echo "s(l(7))" | bc -c /usr/lib/lib.b | dc.sed |
---|
12 | # hex to base 60: echo "60o16i 6B407.CAFE p" | dc.sed |
---|
13 | # |
---|
14 | # To debug or analyze, give the dc Y command as input or add it to |
---|
15 | # embedded dc routines, or add the sed p command to the beginning of |
---|
16 | # the main loop or at various points in the low-level sed routines. |
---|
17 | # If you need to allow [|~] characters in the input, filter this |
---|
18 | # script through "tr '|~' '\36\37'" first. |
---|
19 | # |
---|
20 | # Not implemented: ! \ |
---|
21 | # But implemented: K Y t # !< !> != fractional-bases |
---|
22 | # SunOS limits: 199/199 commands (though could pack in 10-20 more) |
---|
23 | # Limitations: scale <= 999; |obase| >= 1; input digits in [0..F] |
---|
24 | # Completed: 1am Feb 4, 1997 |
---|
25 | |
---|
26 | s/^/|P|K0|I10|O10|?~/ |
---|
27 | |
---|
28 | : next |
---|
29 | s/|?./|?/ |
---|
30 | s/|?#[ -}]*/|?/ |
---|
31 | /|?!*[lLsS;:<>=]\{0,1\}$/N |
---|
32 | /|?!*[-+*/%^<>=]/b binop |
---|
33 | /^|.*|?[dpPfQXZvxkiosStT;:]/b binop |
---|
34 | /|?[_0-9A-F.]/b number |
---|
35 | /|?\[/b string |
---|
36 | /|?l/b load |
---|
37 | /|?L/b Load |
---|
38 | /|?[sS]/b save |
---|
39 | /|?c/ s/[^|]*// |
---|
40 | /|?d/ s/[^~]*~/&&/ |
---|
41 | /|?f/ s//&[pSbz0<aLb]dSaxsaLa/ |
---|
42 | /|?x/ s/\([^~]*~\)\(.*|?x\)~*/\2\1/ |
---|
43 | /|?[KIO]/ s/.*|\([KIO]\)\([^|]*\).*|?\1/\2~&/ |
---|
44 | /|?T/ s/\.*0*~/~/ |
---|
45 | # a slow, non-stackable array implementation in dc, just for completeness |
---|
46 | # A fast, stackable, associative array implementation could be done in sed |
---|
47 | # (format: {key}value{key}value...), but would be longer, like load & save. |
---|
48 | /|?;/ s/|?;\([^{}]\)/|?~[s}s{L{s}q]S}[S}l\1L}1-d0>}s\1L\1l{xS\1]dS{xL}/ |
---|
49 | /|?:/ s/|?:\([^{}]\)/|?~[s}L{s}L{s}L}s\1q]S}S}S{[L}1-d0>}S}l\1s\1L\1l{xS\1]dS{x/ |
---|
50 | /|?[ ~ cdfxKIOT]/b next |
---|
51 | /|?\n/b next |
---|
52 | /|?[pP]/b print |
---|
53 | /|?k/ s/^\([0-9]\{1,3\}\)\([.~].*|K\)[^|]*/\2\1/ |
---|
54 | /|?i/ s/^\(-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}\)\(~.*|I\)[^|]*/\2\1/ |
---|
55 | /|?o/ s/^\(-\{0,1\}[1-9][0-9]*\.\{0,1\}[0-9]*\)\(~.*|O\)[^|]*/\2\1/ |
---|
56 | /|?[kio]/b pop |
---|
57 | /|?t/b trunc |
---|
58 | /|??/b input |
---|
59 | /|?Q/b break |
---|
60 | /|?q/b quit |
---|
61 | h |
---|
62 | /|?[XZz]/b count |
---|
63 | /|?v/b sqrt |
---|
64 | s/.*|?\([^Y]\).*/\1 is unimplemented/ |
---|
65 | s/\n/\\n/g |
---|
66 | l |
---|
67 | g |
---|
68 | b next |
---|
69 | |
---|
70 | : print |
---|
71 | /^-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}~.*|?p/!b Print |
---|
72 | /|O10|/b Print |
---|
73 | |
---|
74 | # Print a number in a non-decimal output base. Uses registers a,b,c,d. |
---|
75 | # Handles fractional output bases (O<-1 or O>=1), unlike other dc's. |
---|
76 | # Converts the fraction correctly on negative output bases, unlike |
---|
77 | # UNIX dc. Also scales the fraction more accurately than UNIX dc. |
---|
78 | # |
---|
79 | s,|?p,&KSa0kd[[-]Psa0la-]Sad0>a[0P]sad0=a[A*2+]saOtd0>a1-ZSd[[[[ ]P]sclb1\ |
---|
80 | !=cSbLdlbtZ[[[-]P0lb-sb]sclb0>c1+]sclb0!<c[0P1+dld>c]scdld>cscSdLbP]q]Sb\ |
---|
81 | [t[1P1-d0<c]scd0<c]ScO_1>bO1!<cO[16]<bOX0<b[[q]sc[dSbdA>c[A]sbdA=c[B]sbd\ |
---|
82 | B=c[C]sbdC=c[D]sbdD=c[E]sbdE=c[F]sb]xscLbP]~Sd[dtdZOZ+k1O/Tdsb[.5]*[.1]O\ |
---|
83 | X^*dZkdXK-1+ktsc0kdSb-[Lbdlb*lc+tdSbO*-lb0!=aldx]dsaxLbsb]sad1!>a[[.]POX\ |
---|
84 | +sb1[SbO*dtdldx-LbO*dZlb!<a]dsax]sadXd0<asbsasaLasbLbscLcsdLdsdLdLak[]pP, |
---|
85 | b next |
---|
86 | |
---|
87 | : Print |
---|
88 | /|?p/s/[^~]*/&\ |
---|
89 | ~&/ |
---|
90 | s/\(.*|P\)\([^|]*\)/\ |
---|
91 | \2\1/ |
---|
92 | s/\([^~]*\)\n\([^~]*\)\(.*|P\)/\1\3\2/ |
---|
93 | h |
---|
94 | s/~.*// |
---|
95 | /./{ s/.//; p; } |
---|
96 | # Just s/.//p would work if we knew we were running under the -n option. |
---|
97 | # Using l vs p would kind of do \ continuations, but would break strings. |
---|
98 | g |
---|
99 | |
---|
100 | : pop |
---|
101 | s/[^~]*~// |
---|
102 | b next |
---|
103 | |
---|
104 | : load |
---|
105 | s/\(.*|?.\)\(.\)/\20~\1/ |
---|
106 | s/^\(.\)0\(.*|r\1\([^~|]*\)~\)/\1\3\2/ |
---|
107 | s/.// |
---|
108 | b next |
---|
109 | |
---|
110 | : Load |
---|
111 | s/\(.*|?.\)\(.\)/\2\1/ |
---|
112 | s/^\(.\)\(.*|r\1\)\([^~|]*~\)/|\3\2/ |
---|
113 | /^|/!i\ |
---|
114 | register empty |
---|
115 | s/.// |
---|
116 | b next |
---|
117 | |
---|
118 | : save |
---|
119 | s/\(.*|?.\)\(.\)/\2\1/ |
---|
120 | /^\(.\).*|r\1/ !s/\(.\).*|/&r\1|/ |
---|
121 | /|?S/ s/\(.\).*|r\1/&~/ |
---|
122 | s/\(.\)\([^~]*~\)\(.*|r\1\)[^~|]*~\{0,1\}/\3\2/ |
---|
123 | b next |
---|
124 | |
---|
125 | : quit |
---|
126 | t quit |
---|
127 | s/|?[^~]*~[^~]*~/|?q/ |
---|
128 | t next |
---|
129 | # Really should be using the -n option to avoid printing a final newline. |
---|
130 | s/.*|P\([^|]*\).*/\1/ |
---|
131 | q |
---|
132 | |
---|
133 | : break |
---|
134 | s/[0-9]*/&;987654321009;/ |
---|
135 | : break1 |
---|
136 | s/^\([^;]*\)\([1-9]\)\(0*\)\([^1]*\2\(.\)[^;]*\3\(9*\).*|?.\)[^~]*~/\1\5\6\4/ |
---|
137 | t break1 |
---|
138 | b pop |
---|
139 | |
---|
140 | : input |
---|
141 | N |
---|
142 | s/|??\(.*\)\(\n.*\)/|?\2~\1/ |
---|
143 | b next |
---|
144 | |
---|
145 | : count |
---|
146 | /|?Z/ s/~.*// |
---|
147 | /^-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}$/ s/[-.0]*\([^.]*\)\.*/\1/ |
---|
148 | /|?X/ s/-*[0-9A-F]*\.*\([0-9A-F]*\).*/\1/ |
---|
149 | s/|.*// |
---|
150 | /~/ s/[^~]//g |
---|
151 | |
---|
152 | s/./a/g |
---|
153 | : count1 |
---|
154 | s/a\{10\}/b/g |
---|
155 | s/b*a*/&a9876543210;/ |
---|
156 | s/a.\{9\}\(.\).*;/\1/ |
---|
157 | y/b/a/ |
---|
158 | /a/b count1 |
---|
159 | G |
---|
160 | /|?z/ s/\n/&~/ |
---|
161 | s/\n[^~]*// |
---|
162 | b next |
---|
163 | |
---|
164 | : trunc |
---|
165 | # for efficiency, doesn't pad with 0s, so 10k 2 5/ returns just .40 |
---|
166 | # The X* here and in a couple other places works around a SunOS 4.x sed bug. |
---|
167 | s/\([^.~]*\.*\)\(.*|K\([^|]*\)\)/\3;9876543210009909:\1,\2/ |
---|
168 | : trunc1 |
---|
169 | s/^\([^;]*\)\([1-9]\)\(0*\)\([^1]*\2\(.\)[^:]*X*\3\(9*\)[^,]*\),\([0-9]\)/\1\5\6\4\7,/ |
---|
170 | t trunc1 |
---|
171 | s/[^:]*:\([^,]*\)[^~]*/\1/ |
---|
172 | b normal |
---|
173 | |
---|
174 | : number |
---|
175 | s/\(.*|?\)\(_\{0,1\}[0-9A-F]*\.\{0,1\}[0-9A-F]*\)/\2~\1~/ |
---|
176 | s/^_/-/ |
---|
177 | /^[^A-F~]*~.*|I10|/b normal |
---|
178 | /^[-0.]*~/b normal |
---|
179 | s:\([^.~]*\)\.*\([^~]*\):[Ilb^lbk/,\1\2~0A1B2C3D4E5F1=11223344556677889900;.\2: |
---|
180 | : digit |
---|
181 | s/^\([^,]*\),\(-*\)\([0-F]\)\([^;]*\(.\)\3[^1;]*\(1*\)\)/I*+\1\2\6\5~,\2\4/ |
---|
182 | t digit |
---|
183 | s:...\([^/]*.\)\([^,]*\)[^.]*\(.*|?.\):\2\3KSb[99]k\1]SaSaXSbLalb0<aLakLbktLbk: |
---|
184 | b next |
---|
185 | |
---|
186 | : string |
---|
187 | /|?[^]]*$/N |
---|
188 | s/\(|?[^]]*\)\[\([^]]*\)]/\1|{\2|}/ |
---|
189 | /|?\[/b string |
---|
190 | s/\(.*|?\)|{\(.*\)|}/\2~\1[/ |
---|
191 | s/|{/[/g |
---|
192 | s/|}/]/g |
---|
193 | b next |
---|
194 | |
---|
195 | : binop |
---|
196 | /^[^~|]*~[^|]/ !i\ |
---|
197 | stack empty |
---|
198 | //!b next |
---|
199 | /^-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}~/ !s/[^~]*\(.*|?!*[^!=<>]\)/0\1/ |
---|
200 | /^[^~]*~-\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}~/ !s/~[^~]*\(.*|?!*[^!=<>]\)/~0\1/ |
---|
201 | h |
---|
202 | /|?\*/b mul |
---|
203 | /|?\//b div |
---|
204 | /|?%/b rem |
---|
205 | /|?^/b exp |
---|
206 | |
---|
207 | /|?[+-]/ s/^\(-*\)\([^~]*~\)\(-*\)\([^~]*~\).*|?\(-\{0,1\}\).*/\2\4s\3o\1\3\5/ |
---|
208 | s/\([^.~]*\)\([^~]*~[^.~]*\)\(.*\)/<\1,\2,\3|=-~.0,123456789<></ |
---|
209 | /^<\([^,]*,[^~]*\)\.*0*~\1\.*0*~/ s/</=/ |
---|
210 | : cmp1 |
---|
211 | s/^\(<[^,]*\)\([0-9]\),\([^,]*\)\([0-9]\),/\1,\2\3,\4/ |
---|
212 | t cmp1 |
---|
213 | /^<\([^~]*\)\([^~]\)[^~]*~\1\(.\).*|=.*\3.*\2/ s/</>/ |
---|
214 | /|?/{ |
---|
215 | s/^\([<>]\)\(-[^~]*~-.*\1\)\(.\)/\3\2/ |
---|
216 | s/^\(.\)\(.*|?!*\)\1/\2!\1/ |
---|
217 | s/|?![^!]\(.\)/&l\1x/ |
---|
218 | s/[^~]*~[^~]*~\(.*|?\)!*.\(.*\)|=.*/\1\2/ |
---|
219 | b next |
---|
220 | } |
---|
221 | s/\(-*\)\1|=.*/;9876543210;9876543210/ |
---|
222 | /o-/ s/;9876543210/;0123456789/ |
---|
223 | s/^>\([^~]*~\)\([^~]*~\)s\(-*\)\(-*o\3\(-*\)\)/>\2\1s\5\4/ |
---|
224 | |
---|
225 | s/,\([0-9]*\)\.*\([^,]*\),\([0-9]*\)\.*\([0-9]*\)/\1,\2\3.,\4;0/ |
---|
226 | : right1 |
---|
227 | s/,\([0-9]\)\([^,]*\),;*\([0-9]\)\([0-9]*\);*0*/\1,\2\3,\4;0/ |
---|
228 | t right1 |
---|
229 | s/.\([^,]*\),~\(.*\);0~s\(-*\)o-*/\1~\30\2~/ |
---|
230 | |
---|
231 | : addsub1 |
---|
232 | s/\(.\{0,1\}\)\(~[^,]*\)\([0-9]\)\(\.*\),\([^;]*\)\(;\([^;]*\(\3[^;]*\)\).*X*\1\(.*\)\)/\2,\4\5\9\8\7\6/ |
---|
233 | s/,\([^~]*~\).\{10\}\(.\)[^;]\{0,9\}\([^;]\{0,1\}\)[^;]*/,\2\1\3/ |
---|
234 | # could be done in one s/// if we could have >9 back-refs... |
---|
235 | /^~.*~;/!b addsub1 |
---|
236 | |
---|
237 | : endbin |
---|
238 | s/.\([^,]*\),\([0-9.]*\).*/\1\2/ |
---|
239 | G |
---|
240 | s/\n[^~]*~[^~]*// |
---|
241 | |
---|
242 | : normal |
---|
243 | s/^\(-*\)0*\([0-9.]*[0-9]\)[^~]*/\1\2/ |
---|
244 | s/^[^1-9~]*~/0~/ |
---|
245 | b next |
---|
246 | |
---|
247 | : mul |
---|
248 | s/\(-*\)\([0-9]*\)\.*\([0-9]*\)~\(-*\)\([0-9]*\)\.*\([0-9]*\).*|K\([^|]*\).*/\1\4\2\5.!\3\6,|\2<\3~\5>\6:\7;9876543210009909/ |
---|
249 | |
---|
250 | : mul1 |
---|
251 | s/![0-9]\([^<]*\)<\([0-9]\{0,1\}\)\([^>]*\)>\([0-9]\{0,1\}\)/0!\1\2<\3\4>/ |
---|
252 | /![0-9]/ s/\(:[^;]*\)\([1-9]\)\(0*\)\([^0]*\2\(.\).*X*\3\(9*\)\)/\1\5\6\4/ |
---|
253 | /<~[^>]*>:0*;/!t mul1 |
---|
254 | |
---|
255 | s/\(-*\)\1\([^>]*\).*/;\2^>:9876543210aaaaaaaaa/ |
---|
256 | |
---|
257 | : mul2 |
---|
258 | s/\([0-9]~*\)^/^\1/ |
---|
259 | s/<\([0-9]*\)\(.*[~^]\)\([0-9]*\)>/\1<\2>\3/ |
---|
260 | |
---|
261 | : mul3 |
---|
262 | s/>\([0-9]\)\(.*\1.\{9\}\(a*\)\)/\1>\2;9\38\37\36\35\34\33\32\31\30/ |
---|
263 | s/\(;[^<]*\)\([0-9]\)<\([^;]*\).*\2[0-9]*\(.*\)/\4\1<\2\3/ |
---|
264 | s/a[0-9]/a/g |
---|
265 | s/a\{10\}/b/g |
---|
266 | s/b\{10\}/c/g |
---|
267 | /|0*[1-9][^>]*>0*[1-9]/b mul3 |
---|
268 | |
---|
269 | s/;/a9876543210;/ |
---|
270 | s/a.\{9\}\(.\)[^;]*\([^,]*\)[0-9]\([.!]*\),/\2,\1\3/ |
---|
271 | y/cb/ba/ |
---|
272 | /|<^/!b mul2 |
---|
273 | b endbin |
---|
274 | |
---|
275 | : div |
---|
276 | # CDDET |
---|
277 | /^[-.0]*[1-9]/ !i\ |
---|
278 | divide by 0 |
---|
279 | //!b pop |
---|
280 | s/\(-*\)\([0-9]*\)\.*\([^~]*~-*\)\([0-9]*\)\.*\([^~]*\)/\2.\3\1;0\4.\5;0/ |
---|
281 | : div1 |
---|
282 | s/^\.0\([^.]*\)\.;*\([0-9]\)\([0-9]*\);*0*/.\1\2.\3;0/ |
---|
283 | s/^\([^.]*\)\([0-9]\)\.\([^;]*;\)0*\([0-9]*\)\([0-9]\)\./\1.\2\30\4.\5/ |
---|
284 | t div1 |
---|
285 | s/~\(-*\)\1\(-*\);0*\([^;]*[0-9]\)[^~]*/~123456789743222111~\2\3/ |
---|
286 | s/\(.\(.\)[^~]*\)[^9]*\2.\{8\}\(.\)[^~]*/\3~\1/ |
---|
287 | s,|?.,&SaSadSaKdlaZ+LaX-1+[sb1]Sbd1>bkLatsbLa[dSa2lbla*-*dLa!=a]dSaxsakLasbLb*t, |
---|
288 | b next |
---|
289 | |
---|
290 | : rem |
---|
291 | s,|?%,&Sadla/LaKSa[999]k*Lak-, |
---|
292 | b next |
---|
293 | |
---|
294 | : exp |
---|
295 | # This decimal method is just a little faster than the binary method done |
---|
296 | # totally in dc: 1LaKLb [kdSb*LbK]Sb [[.5]*d0ktdSa<bkd*KLad1<a]Sa d1<a kk* |
---|
297 | /^[^~]*\./i\ |
---|
298 | fraction in exponent ignored |
---|
299 | s,[^-0-9].*,;9d**dd*8*d*d7dd**d*6d**d5d*d*4*d3d*2lbd**1lb*0, |
---|
300 | : exp1 |
---|
301 | s/\([0-9]\);\(.*\1\([d*]*\)[^l]*\([^*]*\)\(\**\)\)/;dd*d**d*\4\3\5\2/ |
---|
302 | t exp1 |
---|
303 | G |
---|
304 | s,-*.\{9\}\([^9]*\)[^0]*0.\(.*|?.\),\2~saSaKdsaLb0kLbkK*+k1\1LaktsbkLax, |
---|
305 | s,|?.,&SadSbdXSaZla-SbKLaLadSb[0Lb-d1lb-*d+K+0kkSb[1Lb/]q]Sa0>a[dk]sadK<a[Lb], |
---|
306 | b next |
---|
307 | |
---|
308 | : sqrt |
---|
309 | # first square root using sed: 8k2v at 1:30am Dec 17, 1996 |
---|
310 | /^-/i\ |
---|
311 | square root of negative number |
---|
312 | /^[-0]/b next |
---|
313 | s/~.*// |
---|
314 | /^\./ s/0\([0-9]\)/\1/g |
---|
315 | /^\./ !s/[0-9][0-9]/7/g |
---|
316 | G |
---|
317 | s/\n/~/ |
---|
318 | s,|?.,&KSbSb[dk]SadXdK<asadlb/lb+[.5]*[sbdlb/lb+[.5]*dlb>a]dsaxsasaLbsaLatLbk, |
---|
319 | b next |
---|
320 | |
---|
321 | # END OF GSU dc.sed |
---|