summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/generic/apnum
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2015-12-21 23:28:28 +0000
committerKarl Berry <karl@freefriends.org>2015-12-21 23:28:28 +0000
commit338be84a55e6688aefb4e40c24b276f4fa1c08dd (patch)
treeac6d9e772ad272f1329ca38cfb0576c013c442fd /Master/texmf-dist/tex/generic/apnum
parentc50b7eaa45c94a09e1087c6c31f144b497057444 (diff)
apnum (21dec15)
git-svn-id: svn://tug.org/texlive/trunk@39163 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/generic/apnum')
-rw-r--r--Master/texmf-dist/tex/generic/apnum/apnum.tex538
1 files changed, 457 insertions, 81 deletions
diff --git a/Master/texmf-dist/tex/generic/apnum/apnum.tex b/Master/texmf-dist/tex/generic/apnum/apnum.tex
index 72bfceff9cc..d16f159bc9a 100644
--- a/Master/texmf-dist/tex/generic/apnum/apnum.tex
+++ b/Master/texmf-dist/tex/generic/apnum/apnum.tex
@@ -4,47 +4,29 @@
% See the documentation apnum.pdf or apnum.d for more information
-\def\apnumversion{1.2 <May 2015>}
-\message{The Arbitrary Precision Numbers, \apnumversion}
+\def\apVERSION{1.4 <Dec 2015>}
+\message{The Arbitrary Precision Numbers, \apVERSION}
-%%%%%%%%%%%% Internal registers:
+%%%%%%%%%%%% Internal registers, sec. 2.1 in apnum.pdf
\newcount\apnumA \newcount\apnumB \newcount\apnumC \newcount\apnumD
\newcount\apnumE \newcount\apnumF \newcount\apnumG \newcount\apnumH
-\newcount\apnumO \newcount\apnumL
+\newcount\apnumO \newcount\apnumP \newcount\apnumL
\newcount\apnumX \newcount\apnumY \newcount\apnumZ
\newcount\apSIGNa \newcount\apSIGNb \newcount\apEa \newcount\apEb
\newif\ifapX
-\apnumZ=\catcode`\@ \catcode`\@=12
-
-%%%%%%%%%%%% Public macros, sec. 2.1 in apnum.pdf
-
-\def\evaldef{\relax \apEVALa}
-\def\PLUS{\relax \apPPab\apPLUSa}
-\def\MINUS#1#2{\relax \apPPab\apPLUSa{#1}{-#2}}
-\def\MUL{\relax \apPPab\apMULa}
-\def\DIV{\relax \apPPab\apDIVa}
-\def\POW{\relax \apPPab\apPOWa}
-\def\ABS{\relax \apEVALone\apABSa}
-\def\iDIV{\relax \apEVALtwo\apiDIVa}
-\def\iMOD{\relax \apEVALtwo\apiMODa}
-\def\iROUND#1{\relax \evaldef\OUT{#1}\apiROUNDa}
-\def\iFRAC{\relax \apEVALone\apiFRACa}
-\def\FAC{\relax \apEVALone\apFACa}
-\def\ROUND{\apPPs\apROUNDa}
-\def\ROLL{\apPPs\apROLLa}
-\def\NORM{\apPPs\apNORMa}
-\def\addE#1{\edef#1{#1\ifnum\apE=0 \else E\ifnum\apE>0+\fi\the\apE\fi}}
-
-\newcount\apSIGN \let\SIGN=\apSIGN
+\newcount\apSIGN
\newcount\apE
-\newcount\apTOT \apTOT=-30
+\newcount\apTOT \apTOT=0
\newcount\apFRAC \apFRAC=20
+\apnumZ=\catcode`\@ \catcode`\@=12
+
%%%%%%%%%%%% Evaluation of the expression, sec. 2.2 in apnum.pdf
-\def\apEVALa#1#2{{\apnumA=0 \apnumE=1 \apEVALb#2\end\expandafter}\tmpb \let#1=\OUT}
+\def\evaldef{\relax \apEVALa}
+\def\apEVALa#1#2{\begingroup \apnumA=0 \apnumE=1 \apEVALb#2\end \tmpb \apEND \let#1=\OUT}
\def\apEVALb{\def\tmpa{}\apEVALc}
\def\apEVALc#1{%
\ifx+#1\apEVALd \apEVALc \fi
@@ -55,17 +37,19 @@
\apTESTdigit#1\iftrue
\ifx E#1\let\tmpb=\tmpa \expandafter\apEVALd\expandafter\apEVALk
\else \edef\tmpb{\tmpa#1}\expandafter\apEVALd\expandafter\apEVALn\fi\fi
- \edef\tmpb{\tmpa\noexpand#1}\futurelet\apNext\apEVALg
+ \edef\tmpb{\tmpa\noexpand#1}\expandafter
+ \futurelet\expandafter\apNext\expandafter\apEVALg\romannumeral-`\.%
}
-\def\apEVALd#1\fi#2\apNext\apEVALg{\fi#1}
+\def\apEVALd#1\fi#2-`\.{\fi#1}
\def\apEVALe{%
- \ifx\tmpa\empty \else \ifnum\tmpa1<0 \def\tmpb{-1}\apEVALp \MUL 4\fi\fi
+ \ifx\tmpa\empty \else \ifnum\tmpa1<0 \def\tmpb{-1}\apEVALp \apMUL 4\fi\fi
\advance\apnumA by4
\apEVALb
}
\def\apEVALf#1#2{\expandafter\def\expandafter\tmpb\expandafter{\tmpa#1#2}\apEVALo}
\def\apEVALg{\ifx\apNext \bgroup \expandafter\apEVALh \else \expandafter\apEVALo \fi}
-\def\apEVALh#1{\expandafter\def\expandafter\tmpb\expandafter{\tmpb{#1}}\futurelet\apNext\apEVALg}
+\def\apEVALh#1{\expandafter\def\expandafter\tmpb\expandafter{\tmpb{#1}}\expandafter
+ \futurelet\expandafter\apNext\expandafter\apEVALg\romannumeral-`\.}
\def\apEVALk{\afterassignment\apEVALm\apE=}
\def\apEVALm{\edef\tmpb{\tmpb E\the\apE}\apEVALo}
\def\apEVALn#1{\apTESTdigit#1%
@@ -74,18 +58,17 @@
\else \expandafter\apEVALo\expandafter#1\fi
}
\def\apEVALo#1{\let\apNext=\apEVALb
- \ifx+#1\apEVALp \apEPLUS 1\fi
- \ifx-#1\apEVALp \apEMINUS 1\fi
- \ifx*#1\apEVALp \apEMUL 2\fi
- \ifx/#1\apEVALp \apEDIV 2\fi
- \ifx^#1\apEVALp \apEPOW 3\fi
+ \ifx+#1\apEVALp \apPLUS 1\fi
+ \ifx-#1\apEVALp \apMINUS 1\fi
+ \ifx*#1\apEVALp \apMUL 2\fi
+ \ifx/#1\apEVALp \apDIV 2\fi
+ \ifx^#1\apEVALp \apPOWx 3\fi
\ifx)#1\advance\apnumA by-4 \let\apNext=\apEVALo \let\tmpa=\relax
\ifnum\apnumA<0 \apEVALerror{many brackets ")"}\fi
\fi
\ifx\end#1%
- \ifnum\apnumA>0 \apEVALerror{missing bracket ")"}%
- \else \apEVALp\END 0\fi
- \let\apNext=\relax
+ \ifnum\apnumA>0 \apEVALerror{missing bracket ")"}\let\tmpa=\relax
+ \else \apEVALp\END 0\let\apNext=\relax \fi
\fi
\ifx\tmpa\relax \else \apEVALerror{unknown operator "\string#1"}\fi
\apnumE=0 \apNext
@@ -96,7 +79,6 @@
\expandafter\apEVALpush\the\toks0\expandafter{\the\apnumB}% {value}{op}{priority}
\let\tmpa=\relax
}
-\let\apEPLUS=\PLUS \let\apEMINUS=\MINUS \let\apEMUL=\MUL \let\apEDIV=\DIV \let\apEPOW=\POW
\def\apEVALstack{{}{}{0}.}
\def\apEVALpush#1#2#3{% value, operator, priority
\toks0={{#1}{#2}{#3}}%
@@ -104,7 +86,7 @@
\expandafter\apEVALdo\apEVALstack@%
}
\def\apEVALdo#1#2#3#4#5#6#7@{%
- \apnumB=#3 \ifx#2\POW \advance\apnumB by1 \fi
+ \apnumB=#3 \ifx#2\apPOWx \advance\apnumB by1 \fi
\ifnum\apnumB>#6\else
\ifnum#6=0 \def\tmpb{#1}%\toks0={#1}\message{RESULT: \the\toks0}
\ifnum\apnumE=1 \def\tmpb{\apPPn{#1}}\fi
@@ -112,7 +94,7 @@
\fi\fi
}
\def\apEVALerror#1{\message{\noexpand\evaldef ERROR: #1.}%
- \def\tmpb{\def\OUT{??}}\def\apNext##1\end{}%
+ \def\OUT{0}\apE=0\apSIGN=0\def\apNext##1\apEND{\apEND}%
}
\def\apTESTdigit#1#2{%
\ifx E#1\apXtrue \else
@@ -137,8 +119,9 @@
\apPPg#1%
}
\def\apPPd#1\apPPg#2{\fi\expandafter\expandafter\expandafter\apPPc}
-\def\apPPe#1\apPPg#2#3@{\fi\apXtrue{#3% execution of the parameter in the group
- \edef\tmpc{\apE=\the\apE\relax\noexpand\apPPf\OUT@}\expandafter}\tmpc
+\def\apPPe#1\apPPg#2#3@{\fi\apXtrue
+ \begingroup#3% execution of the parameter in the group
+ \edef\tmpb{\apE=\the\apE\relax\noexpand\apPPf\OUT@}\expandafter\endgroup\tmpb
}
\def\apPPf#1{\ifx-#1\apSIGN=-\apSIGN \expandafter\apPPg\else\expandafter\apPPg\expandafter#1\fi}
\def\apPPg#1{%
@@ -146,7 +129,7 @@
\ifx\tmpc\empty\else\edef\tmpc{\tmpc#1}\fi
\ifx0#1\apPPh\fi
\ifx\tmpc\empty\edef\tmpc{#1}\fi
- \ifx@#1\def\tmpc{@}\fi
+ \ifx@#1\def\tmpc{@}\apSIGN=0 \fi
\expandafter\apPPi\tmpc
}
\def\apPPh#1\apPPi\tmpc{\fi\apPPg}
@@ -158,7 +141,10 @@
\ifx@#2@\else \afterassignment\apPPm \apE=#2\fi
}
\def\apPPm E{}
-\def\apPPn#1{\expandafter\apPPb#1@\OUT \edef\OUT{\ifnum\apSIGN<0-\fi\OUT}}
+\def\apPPn#1{\expandafter\apPPb#1@\OUT
+ \ifnum\apSIGN=0 \def\OUT{0}\fi
+ \ifnum\apSIGN<0 \edef\OUT{-\OUT}\fi
+}
\def\apPPab#1#2#3{%
\expandafter\apPPb#2@\tmpa \apSIGNa=\apSIGN \apEa=\apE
\expandafter\apPPb#3@\tmpb \apSIGNb=\apSIGN \apEb=\apE
@@ -173,18 +159,11 @@
\def\apPPu#1#2.@#3{\ifx@#2@\apnumG=0 \ifx#1\apROUNDa\def\XOUT{}\fi
\else\def\apNext{\apPPt#1#2.@#3}\expandafter\apNext\fi
}
-\def\apEVALone#1#2{\evaldef\OUT{#2}\ifnum\apSIGN<0 \expandafter\apNOminus\OUT@\OUT\fi #1}
-\def\apEVALtwo#1#2#3{%
- {\evaldef\OUT{#2}\apOUTtmpb}\tmpb \let\tmpa=\OUT \apSIGNa=\apSIGN \apEa=\apE
- \ifnum\apSIGNa<0 \expandafter\apNOminus\tmpa@\tmpa\fi
- {\evaldef\OUT{#3}\apOUTtmpb}\tmpb \let\tmpb=\OUT \apSIGNb=\apSIGN \apEb=\apE
- \ifnum\apSIGNb<0 \expandafter\apNOminus\tmpb@\tmpb\fi
- #1%
-}
-\def\apNOminus-#1@#2{\def#2{#1}}
%%%%%%%%%%%% Addition and Subtraction, sec. 2.4 in apnum.pdf
+\def\apPLUS{\relax \apPPab\apPLUSa}
+\def\apMINUS#1#2{\relax \apPPab\apPLUSa{#1}{-#2}}
\def\apPLUSa{%
\ifnum\apEa=\apEb \apE=\apEa \else \apPLUSxE \fi
\apDIG\tmpa\relax \apnumA=\apnumD % digits before decimal point
@@ -270,6 +249,7 @@
%%%%%%%%%%%% Multiplication, sec. 2.5 in apnum.pdf
+\def\apMUL{\relax \apPPab\apMULa}
\def\apMULa{%
\apE=\apEa \advance\apE by\apEb
\apSIGN=\apSIGNa \multiply\apSIGN by\apSIGNb
@@ -339,8 +319,9 @@
%%%%%%%%%%%% Division, sec. 2.6 in apnum.pdf
+\def\apDIV{\relax \apPPab\apDIVa}
\def\apDIVa{%
- \ifnum\apSIGNb=0 \errmessage{Dividing by zero}\else
+ \ifnum\apSIGNb=0 \apERR{Dividing by zero}\else
\apSIGN=\apSIGNa \multiply\apSIGN by\apSIGNb
\ifnum\apSIGNa=0 \def\OUT{0}\def\XOUT{0}\apE=0 \apSIGN=0 \else
\apE=\apEa \advance\apE by-\apEb
@@ -377,7 +358,8 @@
\edef\XOUT{\expandafter}\expandafter\apDIVv\XOUT
\def\tmpc{\apnumH}\apnumG=\apSIGNa \expandafter\apROLLa\XOUT.@\XOUT
\fi
- \else \def\OUT{0}\def\XOUT{0}\apE=0 \apSIGN=0
+ \else
+ \def\OUT{0}\def\XOUT{0}\apE=0 \apSIGN=0
\fi\fi\fi
}
\def\apDIVcomp#1#2{%
@@ -483,13 +465,14 @@
%%%%%%%%%%%% Power to the integer, sec. 2.7 in apnum.pdf
+\def\apPOW{\relax \apPPab\apPOWa} \let\apPOWx=\apPOW % for usage as ^ operator
\def\apPOWa{%
\ifnum\apSIGNa=0 \def\OUT{0}\apSIGN=0 \apE=0 \else
\ifnum\apSIGNb=0 \def\OUT{1}\apSIGN=1 \apE=0 \else
\apDIG\tmpb\apnumB
- \ifnum\apnumB>0 \errmessage{POW: non-integer exponent is not implemented yet}\apPOWe\fi
- \ifnum\apEb=0 \else \errmessage{POW: the E notation of exponent isn't allowed}\apPOWe\fi
- \ifnum\apnumD>8 \errmessage{POW: too big exponent.
+ \ifnum\apnumB>0 \apERR{POW: non-integer exponent is not implemented yet}\apPOWe\fi
+ \ifnum\apEb=0 \else \apERR{POW: the E notation of exponent isn't allowed}\apPOWe\fi
+ \ifnum\apnumD>8 \apERR{POW: too big exponent.
Do you really need about 10^\the\apnumD\space digits in output?}\apPOWe\fi
\apE=\apEa \multiply\apE by\tmpb\relax
\apSIGN=\apSIGNa
@@ -549,6 +532,7 @@
%%%%%%%%%%%% ROLL, ROUND and NORM macros, sec. 2.8 in apnum.pdf
+\def\apROLL{\apPPs\apROLLa}
\def\apROLLa{\apnumA=\tmpc\relax \ifnum\apnumA<0 \expandafter\apROLLc\else \expandafter\apROLLg\fi}
\def\apROLLc{\edef\tmpc{}\edef\tmpd{\ifnum\apnumG<0-\fi}\apnumB=0 \apROLLd}
\def\apROLLd#1{%
@@ -590,6 +574,7 @@
}
\def\apROLLo@#1{\let#1=\tmpd}
+\def\apROUND{\apPPs\apROUNDa}
\def\apROUNDa{\apnumD=\tmpc\relax
\ifnum\apnumD<0 \expandafter\apROUNDe
\else \expandafter\apROUNDb
@@ -603,7 +588,7 @@
\fi
\fi \apNext
}
-\def\apROUNDd#1.@#2{\def\XOUT{#1}%
+\def\apROUNDd#1.@#2{\def\XOUT{#1}\edef\XOUT{\apREMzerosR\XOUT}%
\ifnum\apnumX=0 \def\tmpd{}\fi
\ifx\tmpd\empty
\ifx\tmpc\empty \def#2{0}%
@@ -613,6 +598,7 @@
\def\apROUNDe#1.@#2{\apnumC=\apnumD
\apPPs\apROLLa#2{\apnumC}\apPPs\apROUNDa#2{0}\apPPs\apROLLa#2{-\apnumC}%
}
+\def\apNORM{\apPPs\apNORMa}
\def\apNORMa#1.@#2{\ifnum\apnumG<0 \def#2{#1}\fi \expandafter\apNORMb\expandafter#2\tmpc@}
\def\apNORMb#1#2#3@{%
\ifx.#2\apnumC=#3\relax \apDIG#1\apnumA \apNORMc#1%
@@ -625,25 +611,15 @@
\def\apNORMd#1{\advance\apE by\apnumD \advance\apE by-\apnumC
\def\tmpc{\apnumC}\expandafter\apROLLa\expandafter.#1.@#1%
}
+\def\apEadd#1{\ifnum\apE=0 \else\edef#1{#1E\ifnum\apE>0+\fi\the\apE}\apE=0 \fi}
+\def\apEnum#1{\ifnum\apE=0 \else\apROLL#1\apE \apE=0 \fi}
-%%%%%%%%%%%% Function-like macros, sec. 2.9 in apnum.pdf
+%%%%%%%%%%%% Miscelaneous macros, sec. 2.9 in apnum.pdf
-\def\apABSa{\ifnum\apSIGN<0 \apSIGN=1 \fi}
-\def\apiDIVa{{\apFRAC=0 \apTOT=0 \apDIVa \apOUTtmpb}\tmpb}
-\def\apiMODa{{\apFRAC=0 \apTOT=0 \apDIVa \let\OUT=\XOUT \apOUTtmpb}\tmpb}
-\def\apiROUNDa{\apROUNDa\OUT0}
-\def\apiFRACa{\apROUNDa\OUT0\ifx\XOUT\empty\def\OUT{0}\else\edef\OUT{.\XOUT}\fi}
-\def\apFACa{{\apnumC=\OUT\relax
- \loop \ifnum \apnumC>2 \advance\apnumC by-1
- \MUL{\OUT}{\the\apnumC}\repeat
- \global\let\OUT=\OUT}%
+\def\apEND{\global\let\apENDx=\OUT
+ \edef\tmpb{\apSIGN=\the\apSIGN \apE=\the\apE}%
+ \expandafter\endgroup \tmpb \let\OUT=\apENDx
}
-
-%%%%%%%%%%%% Auxiliary macros, sec. 2.10 in apnum.pdf
-
-\def\apREV#1{\expandafter\apREVa#1@!}
-\def\apREVa#1#2!{\ifx@#1\else\apREVa#2!#1\fi}
-
\def\apDIG#1#2{\ifx\relax#2\def\tmpc{}\else #2=0 \def\tmpc{\advance#2 by1 }\fi
\apnumD=0 \expandafter\apDIGa#1..@#1%
}
@@ -699,6 +675,9 @@
\def\apREMdotR#1{\expandafter\apREMdotRa#1@.@!}
\def\apREMdotRa#1.@#2!{\ifx!#2!\apREMzerosRb#1\else#1\fi}
+\def\apREMfirst#1{\expandafter\apREMfirsta#1@#1}
+\def\apREMfirsta#1#2@#3{\def#3{#2}}
+
\def\apOUTx{\apnumO=7
\edef\apOUTn{\the\apnumL}\edef\apOUTl{\apOUTl\apOUTn,}%
\expandafter\def\csname apOUT:\apOUTn\endcsname{}%
@@ -706,17 +685,414 @@
}
\def\apOUTs#1,{\ifx.#1\else\csname apOUT:#1\expandafter\endcsname\expandafter\apOUTs\fi}
-\def\apOUTtmpb{\edef\tmpb{\apSIGN=\the\apSIGN \apE=\the\apE \edef\noexpand\OUT{\OUT}}\expandafter}
+\def\apINIT{\begingroup \let\do=\apEVALxdo \let\localcounts=\apCOUNTS}
+\def\apCOUNTS#1{\ifx;#1\else
+ \advance\count10 by1 \countdef#1=\count10
+ \expandafter\apCOUNTS\fi
+}
+\def\apEVALxdo#1=#2;{#2\let#1=\OUT}
+
+\def\apRETURN#1\apEND{\fi\apEND}
+\def\apERR#1{\errmessage{#1}}
+
+{\lccode`\?=`\p \lccode`\!=`\t \lowercase{\gdef\apNOPT#1?!{#1}}}
+
+\def\loop#1\repeat{\def\body{#1\relax\expandafter\body\fi}\body}
+
+%%%%%%%%%%%% Function-like macros, sec. 2.10 in apnum.pdf
+
+\def\ABS#1{\relax % mandatory \relax for "function-like" macros
+ \evaldef\OUT{#1}% % evaluation of the input parameter
+ \ifnum\apSIGN<0 % if (input < 0)
+ \apSIGN=1 % sign = 1
+ \apREMfirst\OUT % remove first "minus" from OUT
+ \fi % fi
+}
+\def\SGN#1{\relax \evaldef\OUT{#1}\edef\OUT{\the\apSIGN}\apE=0 }
+\def\iDIV#1#2{\relax \apINIT % calculation in group
+ \evaldef\apAparam{#1}\apEadd\apAparam
+ \evaldef\apBparam{#2}\apEadd\apBparam % evaluation of the parameters
+ \apTOT=0 \apFRAC=0 \apDIV\apAparam\apBparam % integer division
+ \apEND % end of group
+}
+\def\iMOD#1#2{\relax \apINIT % calculation in group
+ \evaldef\apAparam{#1}\apEadd\apAparam
+ \evaldef\apBparam{#2}\apEadd\apBparam % evaluation of the parameters
+ \apTOT=0 \apFRAC=0 \apDIV\apAparam\apBparam % integer division
+ \let\OUT=\XOUT % remainder is the output
+ \apEND % end of group
+}
+\def\iROUND#1{\relax \evaldef\OUT{#1}\apEnum\OUT \apROUND\OUT0}
+\def\iFRAC#1{\relax
+ \evaldef\OUT{#1}\apEnum\OUT \apROUND\OUT0% % preparing the parameter
+ \ifx\XOUT\empty \def\OUT{0}\apSIGN=0 % empty fraction part means zero
+ \else \edef\OUT{.\XOUT}\apSIGN=1 % else OUT = dot+fraction part
+ \fi
+}
+
+\def\FAC#1{\relax \apINIT % "function-like" in the group, FAC = factorial
+ \evaldef\OUT{#1}\apEnum\OUT % preparing the parameter
+ \localcounts \N;% % local \newcount
+ \ifnum\apSIGN<0 \apERR{\string\FAC: argument {\OUT} cannot be negative}\apRETURN\fi
+ \let\tmp=\OUT \apROUND\tmp0% % test, if parameter is integer
+ \ifx\XOUT\empty \else \apERR{\string\FAC: argument {\OUT} must be integer}\apRETURN\fi
+ \N=\OUT\relax % N = param (error here if it is an big integer)
+ \ifnum\N=0\def\OUT{1}\apSIGN=1 \fi % special definition for factorial(0)
+ \loop \ifnum \N>2 \advance\N by-1 % loop if (N>2) N--
+ \apMUL{\OUT}{\the\N}\repeat % OUT = OUT * N , repeat
+ \apEND % end of group
+}
+\def\BINOM#1#2{\relax \apINIT % BINOM = {#1 \choose #2} ...
+ \evaldef\apAparam{#1}\apEnum\apAparam
+ \evaldef\apBparam{#2}\apEnum\apBparam % preparation of the parameters
+ \localcounts \A \B \C ;% % local \newcounts
+ \let\OUT=\apBparam \apROUND\OUT0% % test if B is integer
+ \ifx\XOUT\empty\else\apERR{\string\BINOM: second arg. {\apBparam} must be integer}\apRETURN\fi
+ \let\OUT=\apAparam \apROUND\OUT0% % test if A is integer
+ \ifx\XOUT\empty % A is integer:
+ \A=\apAparam \B=\apBparam % A = #1, B = #2
+ \C=\A \advance\C by-\B % C = A - B
+ \ifnum\C>\B \C=\B \fi % if (C > B) C = B fi
+ \ifnum\A<0 \C=\B % if (A < 0) C = B fi
+ \else \ifnum\A<\B \def\OUT{0}\apSIGN=0 % if (0 <= A < B) OUT = 0 return
+ \expandafter\expandafter\expandafter \apRETURN \fi\fi
+ \def\step{\advance\A by-1 \apMUL\OUT{\the\A}}%
+ \else \C=\apBparam % A is not integer
+ \def\step{\let\apBparam\OUT \do\apAparam=\apPLUS\apAparam{-1};%
+ \let\OUT=\apBparam \apMUL\OUT\apAparam}%
+ \fi
+ \ifnum\C=0 \def\OUT{1}\apSIGN=1 \apRETURN\fi
+ \do\D=\FAC{\the\C};% % D = C!
+ \let\OUT=\apAparam % OUT = #1
+ \loop \advance\C by-1 % loop C--
+ \ifnum\C>0 \step \repeat % if (C > 0) A--, OUT = OUT * A, repeat
+ \apDIV{\OUT}{\D}% % OUT = OUT / D
+ \apEND
+}
+\def\SQRT#1{\relax \apINIT % OUT = SQRT(#1) ...
+ \evaldef\A{#1}% % parameter preparation
+ \localcounts \M \E ;% % local counters
+ \E=\apE \apE=0
+ \ifnum\apSIGN=0 \apRETURN\fi % SQRT(0) = 0 (OUT is set to 0 by previous \evaldef)
+ \ifnum\apSIGN<0 \apERR{\string\SQRT: argument {\A} is out of range}\apRETURN\fi
+ \ifodd\E \apROLL\A{-1}\advance\E by1 \fi % we need the E representation with even exponent
+ \let\B=\A \let\C=\A
+ \apDIG\C\relax \M=\apnumD % M is the number of digits before decimal point
+ \advance\M by-2 \ifodd\M \advance\M by1 \fi % M = M - 2 , M must be even
+ \ifx\apSQRTxo\undefined % we need to calculate Xo
+ \ifnum\M=0 \else \apROLL\B{-\M}\divide\M by2 \fi % shift decimal point by -M, M = M / 2
+ \apSQRTr\B \let\Xn=\OUT % Xn = estimate of SQRT
+ \ifnum\M<0 \let\A=\B \fi % if (A < 1) calculate with B where decimal point is shifted
+ \ifnum\M>0 \apROLL\Xn \M \fi % if (A >= 100) shift the decial point of initial guess
+ \else \let\Xn=\apSQRTxo \fi
+ \loop % loop ... Newton's method
+ \apDIV{\apPLUS{\Xn}{\apDIV{\A}{\Xn}}}{2}% % OUT = (Xn + A/Xn) / 2
+ \ifx\OUT\Xn \else % if (OUT != Xn)
+ \let\Xn=\OUT \repeat % Xn = OUT, repeat
+ \ifnum\M<0 \apROLL\OUT\M \fi % shift the decimal point by M back
+ \apE=\E \divide\apE by2 % correct the E exponent
+ \apEND
+}
+\def\apSQRTr#1{\dimen0=#1pt \apnumB=1 \apnumC=1 \apSQRTra}
+\def\apSQRTra{\advance\apnumB by2 \advance\apnumC by\apnumB % B = difference, C = x_i
+ \ifnum\apnumC>100 \def\OUT{10}\else
+ \ifdim\dimen0<\apnumC pt \apSQRTrb \else
+ \expandafter\expandafter\expandafter\apSQRTra\fi\fi
+}
+\def\apSQRTrb{% x = dimen0, B = x_i - x_{i-1}, C = x_i = i
+ \ifdim\dimen0<4pt
+ \ifdim\dimen0>2pt \dimen1=4pt \advance\dimen1 by-\dimen0 \divide\dimen1 by2
+ \else \dimen1=\dimen0 \advance\dimen1 by-1pt \fi
+ \dimen1=.080884\dimen1 % dimen1 = additional linear correction
+ \else \dimen1=0pt \fi
+ \advance\apnumC by-\apnumB % C = x_{i-1}
+ \advance\dimen0 by-\apnumC pt % dimen0 = (x - x_{i-1})
+ \divide\dimen0 by\apnumB % dimen0 = (x - x_{i-1}) / difference
+ \divide\apnumB by2 % B = i-1 = g(x_{i-1})
+ \advance\dimen0 by\apnumB pt % dimen0 = g(x_{i-1}) + (x - x_{i-1} / (x_i-x_{i-1})
+ \advance\dimen0 by\dimen1 % dimen0 += additional linear correction
+ \edef\OUT{\expandafter\apNOPT\the\dimen0}% OUT = dimen0
+}
+\def\EXP#1{\relax\apINIT % OUT = EXP(#1) ...
+ \evaldef\OUT{#1}\apEnum\OUT % OUT = #1
+ \localcounts \N \K ;%
+ \ifnum\apSIGN=0 \def\OUT{1}\apSIGN=1 \apRETURN \fi
+ \edef\digits{\the\apFRAC}\advance\apFRAC by3
+ \edef\signX{\the\apSIGN}%
+ \ifnum\apSIGN<0 \apSIGN=1 \apREMfirst\OUT \fi % remove "minus" sign
+ \K=0 \N=0 % K = 0, N = 0
+ \def\testDot ##1##2\relax##3{\ifx##1.}%
+ \loop \expandafter \testDot\OUT \relax % loop if (OUT >= 1)
+ \iftrue \else % OUT = OUT/2
+ \apDIV\OUT{2}% % K++
+ \advance\K by1 % repeat
+ \repeat % now: #1 = 2^K * OUT, OUT < 1
+ \advance\apFRAC by\K
+ \def\S{1}\def\Sn{1}\N=0 \let\X=\OUT % S = 1, Sn = 1, N = 0, X = OUT
+ \loop \advance\N by1 % loop N++
+ \do\Sn=\apDIV{\apMUL\Sn\X}{\the\N};% % Sn = Sn * X / N
+ \apTAYLOR\iftrue \repeat % S = S + Sn (... Taylor)
+ \N=0
+ \loop \ifnum\N < \K % loop if (N < K)
+ \apPOW\OUT{2}\apROUND\OUT\apFRAC % OUT = OUT^2
+ \advance\N by1 \repeat % N++
+ \ifnum\signX<0 \apDIV 1\OUT \fi % if (signX < 0) OUT = 1 / OUT
+ \apROUND\OUT\digits \apSIGN=1 % EXP is always positive
+ \apEND
+}
+\def\apTAYLOR#1{\ifnum\apSIGN=0 \let\OUT=\S \else \apPLUS\S\Sn \let\S=\OUT }
+
+\def\LN#1{\relax \apINIT % OUT = LN(#1) ...
+ \evaldef\X{#1}% % X = #1
+ \localcounts \M \N \E;%
+ \E=\apE
+ \def\round{\apROUND\OUT\apFRAC}%
+ \edef\digits{\the\apFRAC}\advance\apFRAC by4
+ \ifnum\apSIGN>0 \else \apERR{\string\LN: argument {\X} is out of range}\apRETURN\fi
+ \apDIG\OUT\relax \M=\apnumD % find M: X = mantissa * 10^M
+ \ifnum\M>-\E \def\sgnout{1}\else % if X in (0,1):
+ \def\sgnout{-1}% % sgnout = -1
+ \do\X=\apDIV 1\X;\E=-\E % X = 1/X
+ \apDIG\OUT\relax \M=\apnumD % find M: X = mantissa * 10^M
+ \fi % else sgnout = 1
+ \advance\M by-1 % M = M - 1
+ \ifnum\M=0 \else\apROLL\X{-\M}\fi % X = X * 10^(-M), now X in (1,10)
+ \advance\M by\E % M = M + E (sientific format of numbers)
+ \do\lnX=\apLNr\X;% % lnX = LN(X) ... roughly estimate
+ \do\A=\apDIV\X{\EXP\lnX};% % A = X / EXP(lnX) ... A =approx= 1
+ \apLNtaylor % OUT = LN(A)
+ \do\LNOUT=\apPLUS\OUT\lnX;% % LNOUT = OUT + LNrOUT
+ \ifnum\M>0 % if M > 0
+ \apLNtenexec % LNtenOUT = ln(10)
+ \apPLUS\LNOUT{\apMUL{\the\M}{\apLNten}}% OUT = LNOUT + M * LNten
+ \fi
+ \ifnum\apSIGN=0 \else \apSIGN=\sgnout \fi % if (OUT != 0) apSIGN = saved sign
+ \apROUND\OUT\digits % round result to desired precision
+ \ifnum\apSIGN<0 \xdef\OUT{-\OUT}\else \global\let\OUT=\OUT \fi
+ \apEND
+}
+\def\apLNtaylor{%
+ \apDIV{\apPLUS{\A}{-1}}{\apPLUS{\A}{1}}% % OUT = (A-1) / (A+1)
+ \ifnum\apSIGN=0 \def\OUT{0}\else % ln 1 = 0 else:
+ \let\Sn=\OUT \let\Kn=\OUT \let\S=\OUT % Sn = OUT, Kn = OUT, S = OUT
+ \apPOW\OUT{2}\round \let\XX=\OUT % XX = OUT^2
+ \N=1 % N = 1
+ \loop \advance\N by2 % loop N = N + 2
+ \do\Kn=\apMUL\Kn\XX\round;% % Kn = Kn * XX
+ \do\Sn=\apDIV\Kn{\the\N};% % Sn = Kn / N
+ \apTAYLOR\iftrue \repeat % S = S + Sn (Taylor)
+ \apMUL\S{2}% % OUT = 2 * OUT
+ \fi
+}
+\def\apLNr#1{\dimen0=#1pt \apnumC=1
+ \apLNra {0}{.69}{1.098}{1.386}{1.609}{1.791}{1.9459}{2.079}{2.197}{\apLNrten}{}\relax
+}
+\def\apLNra #1#2{\advance\apnumC by1
+ \ifx\relax#2\relax \let\OUT=\apLNrten \let\apNext=\relax
+ \else
+ \ifdim\dimen0<\apnumC pt % linear interpolation:
+ \advance\dimen0 by-\apnumC pt \advance\dimen0 by1pt % dimen0 = x - x_{i-1}
+ \dimen1=#2pt \advance\dimen1 by-#1pt % dimen1 = f(x_i) - f(x_{i-1})
+ \dimen1=\expandafter\apNOPT\the\dimen0 \dimen1 % dimen1 = (x - x_{i-1}) * dimen1
+ \advance\dimen1 by#1pt % dimen1 = f(x_{i-1}) + dimen1
+ \edef\OUT{\expandafter\apNOPT\the\dimen1}% % OUT = dimen1
+ \def\apNext##1\relax{}%
+ \else \def\apNext{\apLNra{#2}}%
+ \fi\fi \apNext
+}
+\def\apLNrten{2.302585} % apLNrten = ln 10 (roughly)
+\def\apLNtenexec{% % OUT = ln 10 ...
+ \expandafter\ifx\csname LNten:\the\apFRAC\endcsname \relax
+ \begingroup \apTOT=0
+ \do\A=\apDIV{10}{\EXP\apLNrten};% % A = 10 / exp(LNrten)
+ \apLNtaylor % OUT = ln A
+ \apPLUS\OUT\apLNrten % OUT = OUT + LNrten
+ \global\expandafter\let\csname LNten:\the\apFRAC\endcsname=\OUT
+ \endgroup
+ \fi
+ \expandafter\let\expandafter \apLNten \csname LNten:\the\apFRAC\endcsname
+}
+\def\apPIvalue{3.141592653589793238462643383279}
+\def\apPIdigits{30}
+\def\apPIexec{%
+ \expandafter\ifx\csname apPI:\the\apFRAC\endcsname \relax \apPIexecA \else
+ \expandafter\let\expandafter\apPI\csname apPI:\the\apFRAC\endcsname
+ \expandafter\let\expandafter\apPIhalf\csname apPIh:\the\apFRAC\endcsname
+ \fi
+}
+\def\apPIexecA{%
+ \ifnum\apPIdigits<\apFRAC \apPIexecB \fi
+ \let\apPI=\apPIvalue
+ \ifnum\apPIdigits>\apFRAC \apROUND\apPI\apFRAC \fi
+ \apnumP=\apTOT \apTOT=0 \apDIV\apPI2\let\apPIhalf=\OUT \apTOT=\apnumP
+ \global\expandafter\let\csname apPI:\the\apFRAC\endcsname=\apPI
+ \global\expandafter\let\csname apPIh:\the\apFRAC\endcsname=\apPIhalf
+}
+\def\apPIexecB{\apINIT
+ \localcounts \N \a \c;%
+ \apTOT=0 \advance\apFRAC by2
+ \def\apSQRTxo{800.199975006248}% initial value for Newton method for SQRT
+ \SQRT{640320}%
+ \let\sqrtval=\OUT
+ \N=0 \def\An{1}\def\Bn{1}\def\Cn{1}\def\S{13591409}%
+ \loop
+ \advance\N by 1
+ \a=\N \multiply\a by6 \advance\a by-1 \c=\a
+ \advance\a by-2 \multiply\c by\a % An = An * 8 * (6N-5) *
+ \advance\a by-2 \multiply\a by8 % * (6N-3) * (6N-1)
+ \apMUL\An{\apMUL{\the\a}{\the\c}}\let\An=\OUT
+ \c=\N \multiply\c by\N % Bn = Bn * n^3
+ \apMUL\Bn{\apMUL{\the\c}{\the\N}}\let\Bn=\OUT
+ \apMUL\Cn{-262537412640768000}\let\Cn=\OUT % Cn = Cn * K3
+ \apDIV{\apMUL\An{\apPLUS{13591409}{\apMUL{545140134}{\the\N}}}}{\apMUL\Bn\Cn}%
+ \let\Sn=\OUT % Sn = An * (K1 + K2 * N) / (Bn * Cn)
+ \apTAYLOR \iftrue \repeat
+ \advance\apFRAC by-2
+ \apDIV{\apMUL{\sqrtval}{53360}}\S
+ \global\let\apPIvalue=\OUT
+ \xdef\apPIdigits{\the\apFRAC}%
+ \apEND
+}
+\def\PI{\relax \apPIexec \let\OUT=\apPI}
+\def\PIhalf{\relax \apPIexec \let\OUT=\apPIhalf}
+
+\def\SIN{\relax \let\apSINCOSx=\apSINx \apSINCOSa}
+\def\COS{\relax \let\apSINCOSx=\apCOSx \apSINCOSa}
+\def\apSINCOSa#1{\apINIT
+ \advance\apFRAC by3
+ \evaldef\X{#1}\apEnum\X
+ \def\signK{1}\apSINCOSo\apCOSx
+ \ifnum\apSIGN<0 \apREMfirst\X \def\sign{-}\else\def\sign{+}\fi
+ \ifx\apSINCOSx\apCOSx \def\sign{+}\fi
+ \edef\apFRACsave{\the\apFRAC}%
+ \apPIexec
+ \apFRAC=0 \apDIV\X\apPI % OUT = X div PI
+ \ifnum\apSIGN=0 \apSIGN=1 \else
+ \let\K=\OUT
+ \do\X=\apPLUS\X{-\apMUL\K\apPI};% X := X - K * PI
+ \apROLL\K{-1}\apROUND\K{0}%
+ \ifodd 0\XOUT\space \def\signK{-1}\else\def\signK{1}\fi
+ \fi
+ \apSINCOSo\apCOSx
+ \apFRAC=\apFRACsave \relax
+ \do\XmPIh=\apPLUS\X{-\apPIhalf};% XmPIh = | X - PI/2 |
+ \apSINCOSo\apSINx
+ \ifnum\apSIGN<0 \apREMfirst\XmPIh
+ \else % X in (PI/2, PI)
+ \do\X=\apPLUS\apPI{-\X};%
+ \ifx\apSINCOSx\apCOSx \apSIGN=-\signK \edef\signK{\the\apSIGN}\fi
+ \fi % X in (0, PI/2):
+ \apMINUS\X{.78}% % OUT = X - cca PI/4
+ \ifnum\apSIGN<0 \else % if X in (PI/4, PI/2) :
+ \let\X=\XmPIh % X = | X - PI/2 |; SIN <-> COS
+ \ifx\apSINCOSx\apSINx \let\apSINCOSx=\apCOSx \else \let\apSINCOSx=\apSINx \fi
+ \fi
+ \localcounts \N \NN;%
+ \do\XX=\apPOW\X{2}\ROUND\OUT\apFRAC;%
+ \apSINCOSx % X in (0, PI/4), initialize Taylor SIN X or COS X
+ \loop
+ \advance\N by1 \NN=\N
+ \advance\N by1 \multiply\NN by\N
+ \do\Sn=\apDIV{\apMUL\Sn\XX}{-\the\NN};% Sn = - Sn * X^2 / N*(N+1)
+ \apTAYLOR \iftrue\repeat
+ \apSIGN=\sign\signK
+ \ifnum\apTOT=0 \advance\apFRAC by-3 \else \apFRAC=\apTOT \fi
+ \ifnum\apFRAC<0 \apFRAC=-\apFRAC \fi
+ \apROUND\OUT\apFRAC
+ \ifnum\apSIGN<0 \edef\OUT{-\OUT}\fi
+ \apEND
+}
+\def\apSINx{\let\S=\X \N=1 \let\Sn=\X}
+\def\apCOSx{\def\S{1}\N=0 \let\Sn=\S}
+\def\apSINCOSo#1{\ifnum\apSIGN=0 \ifx#1\SCgo \apSIGN=\signK \let\OUT=\signK \fi \apRETURN\fi}
+\def\TAN#1{\relax \apINIT
+ \advance\apFRAC by3
+ \evaldef\X{#1}\apEnum\X
+ \advance\apFRAC by-3
+ \do\denom=\COS\X;%
+ \ifnum\apSIGN=0 \apERR{\string\TAN: argument {\X} is out of range}\apRETURN\fi
+ \SIN\X\message{\OUT/\denom}%
+ \apDIV{\SIN\X}\denom
+ \apEND
+}
+\def\ATAN#1{\relax \apINIT
+ \advance\apFRAC by3
+ \evaldef\X{#1}\apEnum
+ \ifnum\apSIGN=0 \def\OUT{0}\apRETURN\fi
+ \ifnum\apSIGN<0 \def\sign{-}\apREMfirst\X \else\def\sign{}\fi
+ \let\tmp=\X \apDIG\tmp\relax
+ \ifnum\apnumD>0 % if X > 1:
+ \apPIexec % OUT = apPIhalf - apATANox
+ \def\tmp{1}\ifx\tmp\X \apDIV\apPIhalf2\else \apATANox \apPLUS\apPIhalf{-\OUT}\fi
+ \else % else
+ \do\X=\apDIV{1}\X;% X := 1/X
+ \apATANox % OUT = apATANox
+ \fi
+ \ifnum\apTOT=0 \advance\apFRAC by-3 \else \apFRAC=\apTOT \fi
+ \ifnum\apFRAC<0 \apFRAC=-\apFRAC \fi
+ \apROUND\OUT\apFRAC
+ \ifx\sign\empty\apSIGN=1 \else \edef\OUT{-\OUT}\apSIGN=-1 \fi
+ \apEND
+}
+\def\apATANox{%
+ \localcounts \N;%
+ \do\XX=\apPLUS{1}{\apPOW\X{2}}\apROUND\OUT\apFRAC;% XX = 1 + X^2
+ \do\Sn=\apDIV\X\XX \apROUND\OUT\apFRAC;% % Sn = X / (1+X^2)
+ \N=1 \let\S=\Sn
+ \loop
+ \advance\N by1
+ \do\Sn=\apMUL{\the\N}\Sn;%
+ \advance\N by1
+ \do\Sn=\apDIV\Sn{\apMUL{\the\N}\XX};% Sn = Sn * N / ((N+1) * (1+X^2))
+ \apTAYLOR \iftrue \repeat
+}
+\def\ASIN#1{\relax \apINIT
+ \evaldef\X{#1}\apEnum\X \edef\sign{\the\apSIGN}%
+ \apPLUS 1{-\apPOW\X2}% OUT = 1 - X^2
+ \ifnum\apSIGN<0 \apERR{\string\ASIN: argument {\X} is out of range}\apRETURN\fi
+ \do\sqrt=\SQRT\OUT;% sqrt = SRQT {1 - X^1}
+ \ifnum\apSIGN=0 \apPIexec
+ \ifnum\sign<0 \edef\OUT{-\apPIhalf}\apSIGN=-1 % ASIN(-1) = -PI/2
+ \else \let\OUT=\apPIhalf \apSIGN=1 \fi % ASIN(1) = PI/2
+ \apRETURN \fi
+ \ATAN{\X/\sqrt}% OUT = arctan ( X / SQRT {1 - X^2} )
+ \apEND
+}
+\def\ACOS#1{\relax \apPIexec \apPLUS\apPIhalf{-\ASIN{#1}}}
+
%%%%%%%%%%%% Conclusion, sec. 2.11 in apnum.pdf
+\let\PLUS=\apPLUS \let\MINUS=\apMINUS \let\MUL=\apMUL \let\DIV=\apDIV \let\POW=\apPOW
+\let\SIGN=\apSIGN \let\ROUND=\apROUND \let\NORM=\apNORM \let\ROLL=\apROLL
+
\ifx\documentclass\undefined \else % please, don't remove this message
\message{SORRY, you are using LaTeX. I don't recommend this. Petr Olsak}\fi
\catcode`\@=\apnumZ
\endinput
-1.0 <Nov. 2014> - First version released
-1.1 <Jan. 2015>
+1.0 <Nov 2014> - First version released
+1.1 <Jan 2015>
- POW implemented more simple (by base 2 of exponent)
- \next renamed in order to avoid name conflict
1.2 <May 2015> - .5+.5=.1 bug fixed
+1.3 <Dec 2015> -
+ - \apPPn corrected (empty \OUT bug fixed)
+ - \apEVAL: spaces ignored between parameters of function-like macros
+ - \apEVAL: in one group, \apEND introduced, \apOUTtmpb removed
+ - \apPLUS, etc. instead \PLUS introduced
+ - \apSTRIPfirst introduced
+ - \apEVALone, \apEVALtwo removed
+ - \addE renamed to \apEadd
+ - \ROLL, \NORM, \ROUND renamed to \apROLL, \apNORM, \apROUND
+ - \apREV removed
+ - \ABS, \iDIV, \iMOD, \iROUND, \iFRAC, \FAC rewriten
+ - \XOUT is empty, no "0000" after \apROLL\a0 (2.0000 bug fixed)
+ - \def#1{} corrected
+ - \localcount after \evaldef in order to avoid name conflict
+ - \PI added
+ - \apEnorm to \apEnum renamed
+1.4 <Dec 2015>
+ - \ATAN, \ASIN, \ACOS added
+ - \SIN, \COS, \TAN added
+ - \apTOT=0 by default