1 # This is ksb's infamous sed calculator. (ksb@sa.fedex.com)
3 # $FreeBSD: src/usr.bin/sed/TEST/math.sed,v 1.2 2004/05/01 02:15:58 smkelly Exp $
5 # $Id: math.sed,v 2.5 1998/08/02 13:23:34 ksb Exp ksb $
6 # expr ::= (expr) | expr! |
8 # -expr | expr * expr | expr / expr | expr % expr |
9 # expr + expr | expr - expr |
11 # Bugs: some sign combinations don't work, and I got sick of added cases
12 # for unary +. Don't depend on signed math working all the time. -- ksb
14 # $Compile: echo "4+7*3+2^7/3" | sed -f %f
16 # make sure the expression is well formed
20 poorly formed expression, dyadic operator on the end
25 poorly formed expression, leading dyadic operator
29 # fill hold space with done token
34 # main loop, process operators ((), !, *, /, %, +, and -)
36 # uncomment the print below to follow the "logic" -- ksb
46 # eval parenthesised sub expressions first
47 /^\(.*\)(\([^)]*\))\(.*\)$/{
51 s/^\(.*\)\n\(.*\)(\([^()]*\))\(.*\)$/()\2@\4@\1/
55 # reduce a^b^c -> a^(b^c)
56 /\([0-9][0-9]*^\)\([0-9][0-9]*^[0-9][0-9^]*\)/{
60 # pull any burried exponents
61 /^\(.*[^0-9]\)\([0-9][0-9]*^[0-9][0-9]*\)$/{
65 /^\(.*[^0-9]\)\([0-9][0-9]*^[0-9][0-9]*\)\([^0-9].*\)$/{
69 /^\([0-9][0-9]*^[0-9][0-9]*\)\([^0-9].*\)$/{
73 /^\([-]*[0-9]*\)^0*$/{
77 /^\([-]*[0-9]*\)^0*1$/{
81 /^\([-]*[0-9]*\)^-[0-9]*$/{
85 /^\([-]*\)\([0-9]*\)^\([0-9][0-9]*[13579]\)$/{
86 s//\1\2*((\2*\2)^(\3\/2))/
89 /^[-]*\([0-9]*\)^\([0-9][0-9]*[02468]\)$/{
93 # single digit powers (2 3,9 4,6,8 5,7
94 /^[-]*\([0-9]*\)^0*2$/{
98 /^\([-]*\)\([0-9]*\)^0*\([39]\)$/{
99 s//\1(\2*(\2*\2))^(\3\/3)/
102 /^[-]*\([0-9]*\)^0*\([468]\)$/{
107 /^\([-]*[0-9]*\)^\([0-9]*\)$/{
111 # reduce all number factorials
116 /\([*+-/%^]\)0*[01]!/{
124 # sign simplifications
125 /^-\([0-9]*\)\([*/%]\)-\([0-9]*\)$/{
129 /^\([0-9]*\)\([*/%]\)-\([0-9]*\)$/{
133 /^-\([0-9][0-9]*\)[+]*-\([0-9][0-9]*\)$/{
140 /^-\([0-9]*\)[+]\([0-9]\)*$/{
148 s/^\(.*\)\n-.*$/()-@@\1/
152 # can we simplify multiplications
153 /^\([0-9]*\)\([*][0-9]*[1-9]\)00*$/{
157 s/^\(.*\)\n[0-9]*[*][0-9]*[1-9]\(00*\)$/()@\2@\1/
161 /^\([0-9][1-9]*\)00*\([*][0-9]*\)$/{
165 s/^\(.*\)\n[0-9][1-9]*\(00*\)[*][0-9]*$/()@\2@\1/
169 # can we simplify division (20/30 -> 2/3)
170 /^\([0-9][0-9]*\)0\([/%]\)\([0-9][0-9]*\)0$/{
175 /^0*\([0-9][0-9]*\)0[/]0*1$/{
179 # n%2 -> last_digit(n)%2 (same for 1, BTW) N.B. NO LOOP
180 /^[0-9]*\([0-9]\)%0*\([12]\)$/{
183 # move any mul/divs to the front via parans
184 /^\([0-9+]*\)\([-+]\)\([0-9]*[*/][0-9*/]*\)/{
197 /^[0-9]*[/%][0-9]*$/{
199 s/\([0-9]\).*[/%]/\1-/
201 s/^\(.*\)\n\([0-9]\)\([0-9]*\)\([/%]\)\([0-9]*\).*$/.\4\3q0r\2-\5@\1/
205 /^\([0-9]*[*/%][0-9]*\)\(.*\)/{
209 s/^\(.*\)\n\([0-9]*[*/][0-9]*\)\(.*\)$/()@\3@\1/
213 # can we add or subtract -- note subtract hold expression for underflow
218 /^[0-9][0-9]*-[0-9]*$/{
223 /^\([0-9][0-9]*[-+][0-9]*\)\(.*\)/{
227 s/^\(.*\)\n\([0-9]*[-+][0-9]*\)\(.*\)$/()@\3@\1/
231 # look in hold space for stack to reduce
235 s/^0*\([0-9][0-9]*\)/\1/
239 # .[/%] numerator q quotient r remainder-divisor @stack
245 s/.\(.\)\([0-9]*\)q\([^r]*\)r\([0-9]*\)-\([0-9]*\)@\(.*\)\n\(.*\)/.\1\2q\3+1r\7-\5@\6/
247 s/..[0-9]*q[^r]*r\([0-9]*-[0-9]*\)@.*/\1/
252 /.\(.\)\([0-9]\)\([0-9]*\)q\([^r]*\)r0*\([0-9]*\)-\([^@]*\)@.*/{
255 s/.\(.\)\([0-9]\)\([0-9]*\)q\([^r]*\)r0*\([0-9]*\)-\([0-9]*\)@\(.*\)/.\1\3q(\4)*10r\5\2-\6@\7/
259 # no digits to shift on
260 s/^\.[/]q\([^r]*\)r[^@]*@.*/\1/
261 s/^\.[%]q[^r]*r0*\([0-9][0-9]*\)-[^@]*@.*/\1/
268 s/^\.[/%]q[^r]*r[^@]*@\(.*\)/\1/
277 s/\(.*\)\n\([^@]*\)@\([^@]*\)@\(.*\)/\2\1\3/
279 s/[^@]*@[^@]*@\(.*\)/\1/
284 help, stack problem - the hold space
294 # turn mul into add until 1*x -> x, 0*x -> 0
303 s/^0*\([0-9][0-9]*\)/\1/
306 s/^\([0-9]*\)0\*\([0-9]*\)/\1*\20/
307 s/^\([0-9]*\)1\*\([0-9]*\)/\1*\20+\2/
308 s/^\([0-9]*\)2\*\([0-9]*\)/\1*\20+(\2+\2)/
309 s/^\([0-9]*\)3\*\([0-9]*\)/\1*\20+(\2+\2+\2)/
310 s/^\([0-9]*\)4\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2)/
311 s/^\([0-9]*\)5\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2)/
312 s/^\([0-9]*\)6\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2)/
313 s/^\([0-9]*\)7\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2+\2)/
314 s/^\([0-9]*\)8\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2+\2+\2)/
315 s/^\([0-9]*\)9\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2+\2+\2+\2)/
316 /^0*\*[0-9]*[+]*\(.*\)/{
322 # get rid of a plus term until 0+x -> x
332 /^\([0-9]*\)0[+]\([0-9]*\)\([0-9]\)=/{
336 /^\([0-9]*\)\([0-9]\)[+]\([0-9]*\)0=/{
340 s/^\([0-9]*\)1[+]/\10+/
341 s/^\([0-9]*\)2[+]/\11+/
342 s/^\([0-9]*\)3[+]/\12+/
343 s/^\([0-9]*\)4[+]/\13+/
344 s/^\([0-9]*\)5[+]/\14+/
345 s/^\([0-9]*\)6[+]/\15+/
346 s/^\([0-9]*\)7[+]/\16+/
347 s/^\([0-9]*\)8[+]/\17+/
348 s/^\([0-9]*\)9[+]/\18+/
350 s/9=\([0-9]*\)$/_=\1/
351 s/8=\([0-9]*\)$/9=\1/
352 s/7=\([0-9]*\)$/8=\1/
353 s/6=\([0-9]*\)$/7=\1/
354 s/5=\([0-9]*\)$/6=\1/
355 s/4=\([0-9]*\)$/5=\1/
356 s/3=\([0-9]*\)$/4=\1/
357 s/2=\([0-9]*\)$/3=\1/
358 s/1=\([0-9]*\)$/2=\1/
377 # get rid of a sub term until /-0*=/ or underflow
389 s/.*\n\([0-9]*\)-\([0-9]*\).*/-(\2-\1)/
395 /^\([0-9]*\)\([0-9]\)-\([0-9]*\)0=/{
409 s/^\([0-9]*\)1-/\1_-/
410 s/^\([0-9]*\)2-/\11-/
411 s/^\([0-9]*\)3-/\12-/
412 s/^\([0-9]*\)4-/\13-/
413 s/^\([0-9]*\)5-/\14-/
414 s/^\([0-9]*\)6-/\15-/
415 s/^\([0-9]*\)7-/\16-/
416 s/^\([0-9]*\)8-/\17-/
417 s/^\([0-9]*\)9-/\18-/
418 s/^\([0-9]*\)0-/\1'9-/