1 # This is ksb's infamous sed calculator. (ksb@sa.fedex.com)
4 # $Id: math.sed,v 2.5 1998/08/02 13:23:34 ksb Exp ksb $
5 # expr ::= (expr) | expr! |
7 # -expr | expr * expr | expr / expr | expr % expr |
8 # expr + expr | expr - expr |
10 # Bugs: some sign combinations don't work, and I got sick of added cases
11 # for unary +. Don't depend on signed math working all the time. -- ksb
13 # $Compile: echo "4+7*3+2^7/3" | sed -f %f
15 # make sure the expression is well formed
19 poorly formed expression, dyadic operator on the end
24 poorly formed expression, leading dyadic operator
28 # fill hold space with done token
33 # main loop, process operators ((), !, *, /, %, +, and -)
35 # uncomment the print below to follow the "logic" -- ksb
45 # eval parenthesised sub expressions first
46 /^\(.*\)(\([^)]*\))\(.*\)$/{
50 s/^\(.*\)\n\(.*\)(\([^()]*\))\(.*\)$/()\2@\4@\1/
54 # reduce a^b^c -> a^(b^c)
55 /\([0-9][0-9]*^\)\([0-9][0-9]*^[0-9][0-9^]*\)/{
59 # pull any buried exponents
60 /^\(.*[^0-9]\)\([0-9][0-9]*^[0-9][0-9]*\)$/{
64 /^\(.*[^0-9]\)\([0-9][0-9]*^[0-9][0-9]*\)\([^0-9].*\)$/{
68 /^\([0-9][0-9]*^[0-9][0-9]*\)\([^0-9].*\)$/{
72 /^\([-]*[0-9]*\)^0*$/{
76 /^\([-]*[0-9]*\)^0*1$/{
80 /^\([-]*[0-9]*\)^-[0-9]*$/{
84 /^\([-]*\)\([0-9]*\)^\([0-9][0-9]*[13579]\)$/{
85 s//\1\2*((\2*\2)^(\3\/2))/
88 /^[-]*\([0-9]*\)^\([0-9][0-9]*[02468]\)$/{
92 # single digit powers (2 3,9 4,6,8 5,7
93 /^[-]*\([0-9]*\)^0*2$/{
97 /^\([-]*\)\([0-9]*\)^0*\([39]\)$/{
98 s//\1(\2*(\2*\2))^(\3\/3)/
101 /^[-]*\([0-9]*\)^0*\([468]\)$/{
106 /^\([-]*[0-9]*\)^\([0-9]*\)$/{
110 # reduce all number factorials
115 /\([*+-/%^]\)0*[01]!/{
123 # sign simplifications
124 /^-\([0-9]*\)\([*/%]\)-\([0-9]*\)$/{
128 /^\([0-9]*\)\([*/%]\)-\([0-9]*\)$/{
132 /^-\([0-9][0-9]*\)[+]*-\([0-9][0-9]*\)$/{
139 /^-\([0-9]*\)[+]\([0-9]\)*$/{
147 s/^\(.*\)\n-.*$/()-@@\1/
151 # can we simplify multiplications
152 /^\([0-9]*\)\([*][0-9]*[1-9]\)00*$/{
156 s/^\(.*\)\n[0-9]*[*][0-9]*[1-9]\(00*\)$/()@\2@\1/
160 /^\([0-9][1-9]*\)00*\([*][0-9]*\)$/{
164 s/^\(.*\)\n[0-9][1-9]*\(00*\)[*][0-9]*$/()@\2@\1/
168 # can we simplify division (20/30 -> 2/3)
169 /^\([0-9][0-9]*\)0\([/%]\)\([0-9][0-9]*\)0$/{
174 /^0*\([0-9][0-9]*\)0[/]0*1$/{
178 # n%2 -> last_digit(n)%2 (same for 1, BTW) N.B. NO LOOP
179 /^[0-9]*\([0-9]\)%0*\([12]\)$/{
182 # move any mul/divs to the front via parans
183 /^\([0-9+]*\)\([-+]\)\([0-9]*[*/][0-9*/]*\)/{
196 /^[0-9]*[/%][0-9]*$/{
198 s/\([0-9]\).*[/%]/\1-/
200 s/^\(.*\)\n\([0-9]\)\([0-9]*\)\([/%]\)\([0-9]*\).*$/.\4\3q0r\2-\5@\1/
204 /^\([0-9]*[*/%][0-9]*\)\(.*\)/{
208 s/^\(.*\)\n\([0-9]*[*/][0-9]*\)\(.*\)$/()@\3@\1/
212 # can we add or subtract -- note subtract hold expression for underflow
217 /^[0-9][0-9]*-[0-9]*$/{
222 /^\([0-9][0-9]*[-+][0-9]*\)\(.*\)/{
226 s/^\(.*\)\n\([0-9]*[-+][0-9]*\)\(.*\)$/()@\3@\1/
230 # look in hold space for stack to reduce
234 s/^0*\([0-9][0-9]*\)/\1/
238 # .[/%] numerator q quotient r remainder-divisor @stack
244 s/.\(.\)\([0-9]*\)q\([^r]*\)r\([0-9]*\)-\([0-9]*\)@\(.*\)\n\(.*\)/.\1\2q\3+1r\7-\5@\6/
246 s/..[0-9]*q[^r]*r\([0-9]*-[0-9]*\)@.*/\1/
251 /.\(.\)\([0-9]\)\([0-9]*\)q\([^r]*\)r0*\([0-9]*\)-\([^@]*\)@.*/{
254 s/.\(.\)\([0-9]\)\([0-9]*\)q\([^r]*\)r0*\([0-9]*\)-\([0-9]*\)@\(.*\)/.\1\3q(\4)*10r\5\2-\6@\7/
258 # no digits to shift on
259 s/^\.[/]q\([^r]*\)r[^@]*@.*/\1/
260 s/^\.[%]q[^r]*r0*\([0-9][0-9]*\)-[^@]*@.*/\1/
267 s/^\.[/%]q[^r]*r[^@]*@\(.*\)/\1/
276 s/\(.*\)\n\([^@]*\)@\([^@]*\)@\(.*\)/\2\1\3/
278 s/[^@]*@[^@]*@\(.*\)/\1/
283 help, stack problem - the hold space
293 # turn mul into add until 1*x -> x, 0*x -> 0
302 s/^0*\([0-9][0-9]*\)/\1/
305 s/^\([0-9]*\)0\*\([0-9]*\)/\1*\20/
306 s/^\([0-9]*\)1\*\([0-9]*\)/\1*\20+\2/
307 s/^\([0-9]*\)2\*\([0-9]*\)/\1*\20+(\2+\2)/
308 s/^\([0-9]*\)3\*\([0-9]*\)/\1*\20+(\2+\2+\2)/
309 s/^\([0-9]*\)4\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2)/
310 s/^\([0-9]*\)5\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2)/
311 s/^\([0-9]*\)6\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2)/
312 s/^\([0-9]*\)7\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2+\2)/
313 s/^\([0-9]*\)8\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2+\2+\2)/
314 s/^\([0-9]*\)9\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2+\2+\2+\2)/
315 /^0*\*[0-9]*[+]*\(.*\)/{
321 # get rid of a plus term until 0+x -> x
331 /^\([0-9]*\)0[+]\([0-9]*\)\([0-9]\)=/{
335 /^\([0-9]*\)\([0-9]\)[+]\([0-9]*\)0=/{
339 s/^\([0-9]*\)1[+]/\10+/
340 s/^\([0-9]*\)2[+]/\11+/
341 s/^\([0-9]*\)3[+]/\12+/
342 s/^\([0-9]*\)4[+]/\13+/
343 s/^\([0-9]*\)5[+]/\14+/
344 s/^\([0-9]*\)6[+]/\15+/
345 s/^\([0-9]*\)7[+]/\16+/
346 s/^\([0-9]*\)8[+]/\17+/
347 s/^\([0-9]*\)9[+]/\18+/
349 s/9=\([0-9]*\)$/_=\1/
350 s/8=\([0-9]*\)$/9=\1/
351 s/7=\([0-9]*\)$/8=\1/
352 s/6=\([0-9]*\)$/7=\1/
353 s/5=\([0-9]*\)$/6=\1/
354 s/4=\([0-9]*\)$/5=\1/
355 s/3=\([0-9]*\)$/4=\1/
356 s/2=\([0-9]*\)$/3=\1/
357 s/1=\([0-9]*\)$/2=\1/
376 # get rid of a sub term until /-0*=/ or underflow
388 s/.*\n\([0-9]*\)-\([0-9]*\).*/-(\2-\1)/
394 /^\([0-9]*\)\([0-9]\)-\([0-9]*\)0=/{
408 s/^\([0-9]*\)1-/\1_-/
409 s/^\([0-9]*\)2-/\11-/
410 s/^\([0-9]*\)3-/\12-/
411 s/^\([0-9]*\)4-/\13-/
412 s/^\([0-9]*\)5-/\14-/
413 s/^\([0-9]*\)6-/\15-/
414 s/^\([0-9]*\)7-/\16-/
415 s/^\([0-9]*\)8-/\17-/
416 s/^\([0-9]*\)9-/\18-/
417 s/^\([0-9]*\)0-/\1'9-/