#!/usr/bin/perl
my
(
$hold
,
$line
);
@ARGV
= (
'-'
)
unless
@ARGV
;
$_
=
"|P|K0|I10|O10|?"
;
for
(;;) {
s/\|\?./|?/s;
if
(/\|\?!*[lLsS;:<>=]?$/) {
$line
= <>;
last
unless
defined
$line
;
$line
=~
tr
/|~/\36\37/;
$_
.=
$line
;
}
if
(/\|\?(
s/\|\?(.)([^\n~]*)/|?/;
(
$line
= $2) =~
tr
/\36\37/|~/;
warn
(
"! command is deprecated\n"
)
if
$1 eq
'!'
;
}
goto
Binop
if
/\|\?!*[-+*\/%^<>=]/;
goto
Binop
if
/^\|.*\|\?[dpPfQXZvxkiosStT;:]/s;
goto
Number
if
/\|\?[_0-9A-F.]/;
goto
String
if
/\|\?\[/;
goto
Load
if
/\|\?l/;
goto
Load1
if
/\|\?L/;
goto
Save
if
/\|\?[sS]/;
/\|\?c/ && s/[^|]*//;
/\|\?d/ && s/([^~]*~)/$1$1/;
/\|\?f/ && s//|?f[pSbz0<aLb]dSaxsaLa/;
/\|\?x/ && s/([^~]*~)(.*\|\?x)~*/$2$1/s;
/\|\?[KIO]/ && s/(.*\|([KIO])([^|]*).*\|\?\2)/$3~$1/s;
/\|\?T/ && s/\.*0*~/~/;
/\|\?;/ &&
s/\|\?;([^{}])/|?~[s}s{L{s}
q]S}[S}l$1L}1-d0>}s$1L$1l{xS$1]
dS{xL}/;
/\|\?:/ &&
s/\|\?:([^{}])/|?~[s}L{s}L{s}L}s$1q]S}S}S{[L}1-d0>}S}l$1s$1L$1l{xS$1]dS{x/;
next
if
/\|\?[\s~cdfxKIOT]/;
goto
Print
if
/\|\?[pP]/;
/\|\?k/ && s/^(\d{1,3})([.~].*\|K)[^|]*/$2$1/s;
/\|\?i/ && s/^(-?\d*\.?\d+)(~.*\|I)[^|]*/$2$1/s;
/\|\?o/ && s/^(-?[1-9]\d*\.?\d*)(~.*\|O)[^|]*/$2$1/s;
goto
Pop
if
/\|\?[kio]/;
goto
Trunc
if
/\|\?t/;
goto
Input
if
/\|\?\?/;
goto
Break
if
/\|\?Q/;
goto
Quit
if
/\|\?
q/;
$hold = $_;
goto Count if /
\|\?[XZz]/;
goto
Sqrt
if
/\|\?v/;
s/.*\|\?([^Y]).*/$1 is unimplemented/s;
s/([^\n -[\]-~])/
sprintf
'\%03o'
,
ord
$1/eg;
s/\n/\\n/g;
print
$_
,
"\n"
;
$_
=
$hold
;
next
;
Print:
if
(/^-?\d*\.?\d+~.*\|\?p/s and not /\|O10\|/) {
s{\|\?p}
{|?pKSa0kd[[-]Psa0la-]Sad0>a[0P]sad0=a[A*2+]saOtd0>a1-ZSd[[[[ ]P]sclb
1!=cSbLdlbtZ[[[-]P0lb-sb]sclb0>c1+]sclb0!<c[0P1+dld>c]scdld>cscSdLbP]
q]Sb
[t[1P1-d0<c]
scd0<c]ScO_1>bO1!<cO[16]<bOX0<b[[
q]sc[dSbdA>c[A]
sbdA=c[B]sbd
B=c[C]sbdC=c[D]sbdD=c[E]sbdE=c[F]sb]xscLbP]~Sd[dtdZOZ+k1O/Tdsb[.5]*[.1]O
X^
*dZkdXK
-1+ktsc0kdSb-[Lbdlb
*lc
+tdSbO*-lb0!=aldx]dsaxLbsb]sad1!>a[[.]POX
+sb1[SbO
*dtdldx
-LbO
*dZlb
!<a]dsax]sadXd0<asbsasaLasbLbscLcsdLdsdLdLak[]pP};
next
;
}
/\|\?p/ && s/([^~]*)/$1\n~$1/;
$hold
=
$_
;
s/~.*//s;
tr
/\36\37/|~/;
print
;
$_
=
$hold
;
Pop:
s/[^~]*~//;
next
;
Load:
s/(.*\|\?.)(.)/${2}0~$1/s;
s/^(.)0(.*\|r\1([^~|]*)~)/$1$3$2/s;
s/.//s;
next
;
Load1:
s/(.*\|\?.)(.)/$2$1/s;
s/^(.)(.*\|r\1)([^~|]*~)/|$3$2/s;
warn
"register empty\n"
unless
/^\|/;
s/.//s;
next
;
Save:
s/(.*\|\?.)(.)/$2$1/s;
/^(.).*\|r\1/s || s/((.).*\|)/$1r$2|/s;
/\|\?S/ && s/((.).*\|r\2)/$1~/s;
s/(.)([^~]*~)(.*\|r\1)[^~|]*~?/$3$2/s;
next
;
Quit:
last
unless
s/\|\?[^~]*~[^~]*~/|?
q/;
next;
Break:
s/
(\d*)/$1;987654321009;/;
1
while
s/^([^;]*)([1-9])(0*)([^1]*\2(.)[^;]*\3(9*).*\|\?.)[^~]*~/$1$5$6$4/s;
goto
Pop;
Input:
$line
= <STDIN>;
last
unless
defined
$line
;
$line
=~
tr
/|~/\36\37/;
$_
.=
"\n"
.
$line
;
s/\|\?\?(.*)(\n.*)\n/|?$2~$1/s;
next
;
Count:
/\|\?Z/ && s/~.*//s;
/^-?\d*\.?\d+$/ && s/[-.0]*([^.]*)\.*/$1/;
/\|\?X/ && s/-*[0-9A-F]*\.*([0-9A-F]*).*/$1/s;
s/\|.*//s;
/~/ && s/[^~]//g;
s/./a/gs;
do
{
s/a{10}/b/g;
s/(b
*a
*)/$1a9876543210;/;
s/a.{9}(.).*;/$1/;
y/b/a/;
}
while
/a/;
$_
.=
"\n"
;
$_
.=
$hold
;
/\|\?z/ && s/\n/\n~/;
s/\n[^~]*//;
next
;
Trunc:
s/([^.~]*\.*)(.*\|K([^|]*))/$3;9876543210009909:$1,$2/s;
1
while
s/^([^;]*)([1-9])(0*)([^1]*\2(.)[^:]*\3(9*)[^,]*),(\d)/$1$5$6$4$7,/;
s/[^:]*:([^,]*)[^~]*/$1/;
goto
Normal;
Number:
s/(.*\|\?)(_?[0-9A-F]*\.?[0-9A-F]*)/$2~$1~/s;
s/^_/-/;
goto
Normal
if
/^[^A-F~]*~.*\|I10\|/s or /^[-0.]*~/;
s {([^.~]*)\.*([^~]*)}
{[Ilb^lbk/,$1$2~0A1B2C3D4E5F1=11223344556677889900;.$2};
1
while
s/^([^,]*),(-*)([0-F])([^;]*(.)\3[^1;]*(1*))/I*+$1$2$6$5~,$2$4/;
s {...([^/]*.)([^,]*)[^.]*(.*\|\?.)}
{$2$3KSb[99]k$1]SaSaXSbLalb0<aLakLbktLbk}s;
next
;
String:
do
{
if
(/\|\?[^]]*$/) {
$line
= <>;
last
unless
defined
$line
;
$line
=~
tr
/|~/\36\37/;
$_
.=
$line
;
}
s/(\|\?[^]]*)\[([^]]*)]/$1|{$2|}/;
}
while
/\|\?\[/;
s/(.*\|\?)\|\{(.*)\|}/$2~${1}[/s;
s/\|\{/[/g;
s/\|\}/]/g;
next
;
Binop:
unless
(/^[^~|]*~[^|]/) {
warn
"stack empty\n"
;
next
;
}
/^-?\d*\.?\d+~/ || s/[^~]*(.*\|\?!*[^!=<>])/0$1/s;
/^[^~]*~-?\d*\.?\d+~/ || s/~[^~]*(.*\|\?!*[^!=<>])/~0$1/s;
$hold
=
$_
;
goto
Mul
if
/\|\?\*/;
goto
Div
if
/\|\?\//;
goto
Rem
if
/\|\?\%/;
goto
Exp
if
/\|\?\^/;
/\|\?[+-]/ && s/^(-*)([^~]*~)(-*)([^~]*~).*\|\?(-?).*/$2$4s$3o$1$3$5/s;
s/([^.~]*)([^~]*~[^.~]*)(.*)/<$1,$2,$3|=-~.0,123456789<></s;
/^<([^,]*,[^~]*)\.*0*~\1\.*0*~/ && s/</=/;
1
while
s/^(<[^,]*)(\d),([^,]*)(\d),/$1,$2$3,$4/;
/^<([^~]*)([^~])[^~]*~\1(.).*\|=.*\3.*\2/s && s/</>/;
if
(/\|\?/) {
s/^([<>])(-[^~]*~-.*\1)(.)/$3$2/s;
s/^(.)(.*\|\?!*)\1/$2!$1/s;
s/(\|\?)/$1l$2x/s;
s/[^~]*~[^~]*~(.*\|\?)!*.(.*)\|=.*/$1$2/s;
next
;
}
s/(-*)\1\|=.*/;9876543210;9876543210/;
/o-/ && s/;9876543210/;0123456789/;
s/^>([^~]*~)([^~]*~)s(-*)(-
*o
\3(-*))/>$2$1s$5$4/;
s/,(\d*)\.*([^,]*),(\d*)\.*(\d*)/$1,$2$3.,$4;0/;
1
while
s/,(\d)([^,]*),;*(\d)(\d*);*0*/$1,$2$3,$4;0/;
s/.([^,]*),~(.*);0~s(-*)o-*/$1~${3}0$2~/;
do
{
s {(.?)(~[^,]*)(\d)(\.*),([^;]*)(;([^;]*(\3[^;]*)).*\1(.*))}
{$2,$4$5$9$8$7$6};
s/,([^~]*~).{10}(.)[^;]{0,9}([^;]?)[^;]*/,$2$1$3/;
}
until
/^~.*~;/;
Endbin:
s/.([^,]*),([\d.]*).*/$1$2/;
$_
.=
"\n"
;
$_
.=
$hold
;
s/\n[^~]*~[^~]*//;
Normal:
s/^(-*)0*([\d.]*\d)[^~]*/$1$2/;
s/^[^1-9~]*~/0~/;
next
;
Mul:
s {(-*)(\d*)\.*(\d*)~(-*)(\d*)\.*(\d*).*\|K([^|]*).*}
{$1$4$2$5.!$3$6,|$2<$3~$5>$6:$7;9876543210009909}s;
1
while
s/!\d([^<]*)<(\d?)([^>]*)>(\d?)/0!$1$2<$3$4>/ +
(/!\d/ && s/(:[^;]*)([1-9])(0*)([^0]*\2(.).*\3(9*))/$1$5$6$4/)
and not /<~[^>]*>:0*;/;
s/(-*)\1([^>]*).*/;$2^>:9876543210aaaaaaaaa/;
do
{
s/(\d~*)\^/^$1/;
s/<(\d*)(.*[~^])(\d*)>/$1<$2>$3/;
do
{
s{>(\d)(.*\1.{9}(a*))}
{$1>$2;9${3}8${3}7${3}6${3}5${3}4${3}3${3}2${3}1${3}0};
s/(;[^<]*)(\d)<([^;]*).*\2\d*(.*)/$4$1<$2$3/;
s/a\d/a/g;
s/a{10}/b/g;
s/b{10}/c/g;
}
while
/\|0*[1-9][^>]*>0*[1-9]/;
s/;/a9876543210;/;
s/a.{9}(.)[^;]*([^,]*)\d([.!]*),/$2,$1$3/;
y/cb/ba/;
}
until
/\|<\^/;
goto
Endbin;
Div:
unless
(/^[-.0]*[1-9]/) {
warn
"divide by 0\n"
;
goto
Pop;
}
s/(-*)(\d*)\.*([^~]*~-*)(\d*)\.*([^~]*)/$2.$3$1;0$4.$5;0/;
1
while
s/^\.0([^.]*)\.;*(\d)(\d*);*0*/.$1$2.$3;0/ or
s/^([^.]*)(\d)\.([^;]*;)0*(\d*)(\d)\./$1.$2${3}0$4.$5/;
s/~(-*)\1(-*);0*([^;]*\d)[^~]*/~123456789743222111~$2$3/;
s/(.(.)[^~]*)[^9]*\2.{8}(.)[^~]*/$3~$1/s;
s {(\|\?.)}
{$1SaSadSaKdlaZ+LaX-1+[sb1]Sbd1>bkLatsbLa[dSa2lbla*-
*dLa
!=a]dSaxsakLasbLb
*t
};
next
;
Rem:
s,\|\?%,|?
%Sadla
/LaKSa[999]k
*Lak
-,;
next
;
Exp:
warn
"fraction in exponent ignored\n"
if
/^[^~]*\./;
s,[^-\d].*,;9d*
*dd
*8
*d
*d7dd
*
*d
*6d*
*d5d
*d
*4
*d3d
*2lbd**1lb*0,s;
1
while
s/(\d);(.*\1([d*]*)[^l]*([^*]*)(\**))/;dd
*d
*
*d
*$4$3$5$2/;
$_
.=
"\n"
;
$_
.=
$hold
;
s,-*.{9}([^9]*)[^0]*0.(.*\|\?.),$2~saSaKdsaLb0kLbkK*+k1$1LaktsbkLax,s;
s{(\|\?.)}
{$1SadSbdXSaZla-SbKLaLadSb[0Lb-d1lb-
*d
+K+0kkSb[1Lb/]
q]Sa0>a[dk]
sadK<a[Lb]};
next
;
Sqrt:
warn
"square root of negative number\n"
if
/^-/;
next
if
/^[-0]/;
s/~.*//s;
/^\./ ? s/0(\d)/$1/g : s/\d\d/7/g;
$_
.=
"~"
;
$_
.=
$hold
;
s{(\|\?.)}
{$1KSbSb[dk]SadXdK<asadlb/lb+[.5]*[sbdlb/lb+[.5]
*dlb
>a]dsaxsasaLbsaLatLbk};
/^\d*~.*\|K0/s && s/(\|\?.KSb)([^t]*)/${1}1k${2}0k/;
next
;
}
=encoding utf8
=head1 NAME
dc - an arbitrary precision calculator