summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Master/texmf-dist/doc/generic/minifp/README102
-rw-r--r--Master/texmf-dist/doc/generic/minifp/minifp.pdfbin0 -> 418427 bytes
-rw-r--r--Master/texmf-dist/doc/generic/minifp/test1.tex480
-rw-r--r--Master/texmf-dist/doc/generic/minifp/test2.tex376
-rw-r--r--Master/texmf-dist/source/generic/minifp/minifp.dtx3937
-rw-r--r--Master/texmf-dist/source/generic/minifp/minifp.ins51
-rw-r--r--Master/texmf-dist/tex/generic/minifp/mfpextra.tex638
-rw-r--r--Master/texmf-dist/tex/generic/minifp/minifp.sty806
-rwxr-xr-xMaster/tlpkg/bin/tlpkg-ctan-check2
-rw-r--r--Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc1
-rw-r--r--Master/tlpkg/tlpsrc/minifp.tlpsrc0
11 files changed, 6392 insertions, 1 deletions
diff --git a/Master/texmf-dist/doc/generic/minifp/README b/Master/texmf-dist/doc/generic/minifp/README
new file mode 100644
index 00000000000..f6b413bf9ee
--- /dev/null
+++ b/Master/texmf-dist/doc/generic/minifp/README
@@ -0,0 +1,102 @@
+The MiniFP package
+
+Purpose:
+
+ minifp.sty defines macros for calculating with decimal real numbers.
+ It provides 8 decimal digits before and after the decimal point.
+ Minifp also provides a stack-based "assembly" language for writing
+ "programs".
+
+ In its basic form, minifp makes only simple operations available. To
+ get additional operations (sine, cosine, angle, square root, log and
+ exp), the file mfpextra.tex is provided.
+
+ Minifp should work in both latex and plaintex.
+
+ This is version 0.9. It should work reasonably well, barring any bugs,
+ but I expect to spend some time fine-tuning it for version 1.0.
+
+License:
+
+ All files of the minifp distribution (listed below) may be distributed
+ and/or modified under the conditions of the LaTeX Project Public
+ License, either version 1.3c of this license or (at your option) any
+ later version. The latest version of this license is in
+ http://www.latex-project.org/lppl.txt
+ and version 1.3c or later is part of all distributions of LaTeX
+ version 2008/12/01 or later.
+
+ While every effort has been made to make minifp useful, it comes with
+ no warranty, expressed or implied.
+
+Usage:
+
+ You can use minifp as a LaTeX package with
+ \usepackage{minifp}
+ or use it in plain TeX with
+ \input minifp.sty
+
+ You can access the extra commands from mfpextra.tex by issuing the
+ command
+ \MFPloadextra
+ after minifp.sty has been loaded.
+
+Installation:
+
+ To install minifp, obtain minifp.tds.zip from CTAN and unzip it in any
+ TDS-compliant texmf tree.
+
+ Or, in the presence of minifp.dtx, run tex or latex on minifp.ins to
+ unpack the files minifp.sty and mfpextra.tex. Copy those files to some
+ place where both tex and latex can find them. For example, in a TDS
+ compliant system, the directory /tex/generic/minifp/ under one of your
+ TEXMF root directories.
+
+ The documentation is provided in minifp.pdf. Put minifp.pdf (and this
+ README and the files test*.tex, if you wish) wherever documentation of
+ packages is kept. For example, in the directory /doc/generic/minifp/
+ under one of your TEXMF root directories.
+
+ If you wish to regenerate the documentation, run latex (or pdflatex)
+ on minifp.dtx three times and then
+ makeindex -s gind.ist -o minifp.ind minifp.idx
+ and then (pdf)latex again on minifp.dtx.
+
+Manifest:
+
+ These, together with the files minifp.sty and mfpextra.tex (generated
+ by tex-ing minifp.ins), constitute the minifp distribution to which the
+ license applies:
+
+ minifp.dtx Contains minifp.sty and mfpextra.tex
+ minifp.ins The unpacking script: run tex or latex on it.
+ It reads in minifp.dtx and produces the files
+ minifp.sty and mfpextra.tex
+ minifp.pdf Documentation
+ test1.tex A suite of tests, including error messages (plain TeX)
+ test2.tex More tests, including long tests of speed (plain TeX)
+ README This file.
+
+ This distribution, the latest updates, and possibly some past
+ versions, should also be available at my web site:
+ <http://comp.uark.edu/~luecking/tex/>.
+
+History:
+
+ Version 0.9 : maximum possible accuracy achieved for angle, at some
+ cost to speed.
+ Version 0.8 : exp: now more accurate for many cases.
+ Version 0.7 : sqrt: now exact when possible and much more accurate.
+ Version 0.6 : Added angle to mfpextra. Changed package name to minifp.
+ Version 0.5 : Added sqrt, deg, rad to mfpextra.
+ Version 0.4 : Added log, exp, pow to mfpextra.
+ Version 0.3 : Added mfpextra.tex, defines sin and cos.
+ Version 0.2 : Added macros for printing, formatting the results.
+ Version 0.1 : First working set of macros. Package named mfp.sty.
+
+--
+Dan Luecking <luecking (at) uark (dot) edu>
+Department of Mathematical Sciences
+1 University of Arkansas
+Fayetteville, Arkansas 72701-1201
+U.S.A.
diff --git a/Master/texmf-dist/doc/generic/minifp/minifp.pdf b/Master/texmf-dist/doc/generic/minifp/minifp.pdf
new file mode 100644
index 00000000000..94d43d6488f
--- /dev/null
+++ b/Master/texmf-dist/doc/generic/minifp/minifp.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/generic/minifp/test1.tex b/Master/texmf-dist/doc/generic/minifp/test1.tex
new file mode 100644
index 00000000000..024e5c5a44d
--- /dev/null
+++ b/Master/texmf-dist/doc/generic/minifp/test1.tex
@@ -0,0 +1,480 @@
+\errorcontextlines999\relax
+%\def\MFPextra{}
+X\input minifp.sty\relax X
+X\MFPloadextra X
+
+\def\filbreak{\vskip 12pt plus 100pt\penalty 0 \vskip 0pt plus -100pt\relax}
+\def\meaningless#1>{}
+\def\verbprint#1{%
+\begingroup
+ \toks0=\expandafter{#1}\edef\x{\the\toks0}%
+ \edef\x{\expandafter\meaningless\meaning\x}%
+ \tt "\x"%
+\endgroup}
+{\catcode`\@=11
+ \gdef\y{\Y\\}
+ \gdef\Y{\space\verbprint\MFP@Rstack}% adds its own space
+}
+\def\\{\hfill\break\ignorespaces}
+\def\U{\X}
+\baselineskip 12.1pt plus .2pt minus 2pt
+
+\filbreak
+\startMFPprogram
+{\bf Stack-only operations:}\\
+Stack is empty, test the error message for popping an empty
+stack:\immediate\write16{^^J*** The following tests the error for popping an
+empty stack:^^J}\Rpop\X\y
+Push 0.000 001:\Rpush{0.000 001}\y
+Pop into {\tt\string\X}:\Rpop\X\\
+\indent {\tt \string\X:}\verbprint\X\\
+\indent {\tt stack:}\y
+Push 1.2 then -2.3:\Rpush{1.2}\Rpush{-2.3}\y
+Exchange them:\Rexch\y
+Duplicate the last:\Rdup\Y
+
+\filbreak
+{\bf Unary operations:}\\
+First a new stack with only one value
+$21.34$:\Rpop\X\Rpop\X\Rpop\X\Rpush{21.34}\y
+Unless otherwise noted, the stack will always be restored to this value
+between operations.
+
+\medskip
+\noindent
+Change sign:\Rchs\y
+ \Rpop\X\Rpush{21.34}%
+Absolute value:\Rabs\y
+ \Rpop\X\Rpush{21.34}%
+Integer part:\Rint\y
+ \Rpop\X\Rpush{21.34}%
+Fractional part:\Rfrac\y
+ \Rpop\X\Rpush{21.34}%
+Double:\Rdbl\y
+ \Rpop\X\Rpush{21.34}%
+Halve:\Rhalve\y
+ \Rpop\X\Rpush{21.34}%
+Signum:\Rsgn\y
+ \Rpop\X\Rpush{-21.34}%
+Signum of negative:\Rsgn\y
+ \Rpop\X\Rpush{21.34}%
+Increment:\Rincr\y
+ \Rpop\X\Rpush{21.34}%
+Decrement:\Rdecr\y
+ \Rpop\X\Rpush{21.34}%
+Sine:\Rsin\y
+ \Rpop\X\Rpush{21.34}%
+Cosine:\Rcos\y
+ \Rpop\X\Rpush{21.34}%
+Radians to degrees:\Rdeg\y
+ \Rpop\X\Rpush{21.34}%
+Degrees to radians :\Rrad\y
+ \Rpop\X\Rpush{21.34}%
+Common logarithm:\Rlog\y
+ \Rpop\X\Rpush{21.34}%
+Natural logarithm:\Rln\y
+Put $-1.34$ on the stack:\Rpop\X\Rpush{-1.34}\y
+Exponential:\Rexp\y
+Put $3.3$ on the stack:\Rpop\X\Rpush{3.3}\y
+Exponential:\Rexp\y
+Back to $21.34$:\Rpop\X\Rpush{21.34}\y
+Square:\Rsq\y
+ \Rpop\X\Rpush{21.34}%
+\tracingmacros1
+Inversion:\Rinv\y
+\tracingmacros0
+ \Rpop\X\Rpush{21.34}%
+Floor:\Rfloor\y
+ \Rpop\X\Rpush{21.34}%
+Ceiling:\Rceil\y
+ \Rpop\X\Rpush{21.34}%
+Square root:\Rsqrt\y
+Now put $21.34$ and $12.34$ in that order:\Rpop\X\Rpush{21.34}\Rpush{12.34}\y
+Compare: \Rcmp
+ 21.34 is\IFlt{}{ not} less than 12.34.
+ 21.34 is\IFgt{}{ not} more than 12.34.
+ 21.34 is\IFeq{}{ not} equal to 12.34.\\
+Take difference and check:\Rsub\Rchk\y
+ 21.34-12.34 is\IFneg {}{ not} negative.
+ 21.34-12.34 is\IFpos {}{ not} positive.
+ 21.34-12.34 is\IFzero{}{ not} zero.
+
+\Rpop\X
+
+\filbreak
+{\bf Binary operations:}\\
+({\it After each operation we restore the original stack.})\\
+Start with empty stack and\\
+push 1.2 then -2.3:\Rpush{1.2}\Rpush{-2.3}\y
+Angle:\Rangle\y\Rpop\X\Rpush{1.2}\Rpush{-2.3}%
+Add:\Radd\y\Rpop\X\Rpush{1.2}\Rpush{-2.3}%
+Subtract:\Rsub\y\Rpop\X\Rpush{1.2}\Rpush{-2.3}%
+Multiply:\Rmul\y\Rpop\X\Rpush{1.2}\Rpush{-2.3}%
+Divide:\Rdiv\y
+New stack:\Rpop\X\Rpush{2.3}\Rpush{0}\y
+\immediate\write16{^^J*** The following tests the error for dividing by 0:^^J}
+Divide by zero:\Rdiv\y
+Reset stack:\Rpop\X\Rpush{2.3}\Rpush{17}\y
+Raise to a power ($(2.3)^{17}$):\Rpow\y
+Reset stack:\Rpop\X\Rpush{2.3}\Rpush{-17}\y
+Raise to a power ($(2.3)^{-17}$):\Rpow\y
+Back to $1.2$ and $-2.3$:\Rpop\X\Rpush{1.2}\Rpush{-2.3}\y
+Find max:\Rmax\y
+ \Rpop\X\Rpush{1.2}\Rpush{-2.3}%
+Find min:\Rmin\y
+Exporting stack (value above).\\
+Exporting \verbprint\U: \verbprint\X
+\ExportStack
+\Export\X
+% change \X
+\def\X{0}
+\stopMFPprogram
+
+\medskip
+\noindent
+Exported value of \verbprint\U: \verbprint\X\\
+Exported value of stack:\Y
+
+\def\w{\W\\}
+\def\W{ \verbprint\Z}% adds its own space
+
+\filbreak
+{\bf Operand forms}\\
+{\it All results go to {\tt\string\Z}. All operate on {\tt\string\X}
+and/or {\tt\string\Y}}\\
+Define ${\tt X}=1.2$ and ${\tt Y}=-2.3$:\def\X{1.2}\def\Y{-2.3}\\
+\indent {\tt X}:=\verbprint\X\\
+\indent {\tt Y}:=\verbprint\Y
+
+\filbreak
+{\bf Unary operations:}\\
+ Change sign of {\tt X}:\MFPchs\X\Z\w
+ Change sign of {\tt Y}:\MFPchs\Y\Z\w
+ Absolute value of {\tt X}:\MFPabs\X\Z\w
+ Absolute value of {\tt Y}:\MFPabs\Y\Z\w
+ Double value of {\tt X}:\MFPdbl\X\Z\w
+ Double value of {\tt Y}:\MFPdbl\Y\Z\w
+ Half of {\tt X}:\MFPhalve\X\Z\w
+ Half of {\tt Y}:\MFPhalve\Y\Z\w
+ Integer part of {\tt X}:\MFPint\X\Z\w
+ Integer part of {\tt Y}:\MFPint\Y\Z\w
+ Signum of {\tt X}:\MFPsgn\X\Z\w
+ Signum of {\tt Y}:\MFPsgn\Y\Z\w
+ Increment of {\tt X}:\MFPincr\X\Z\w
+ Increment of {\tt Y}:\MFPincr\Y\Z\w
+ Decrement of {\tt X}:\MFPdecr\X\Z\w
+ Decrement of {\tt Y}:\MFPdecr\Y\Z\w
+ Square of {\tt X}:\MFPsq\X\Z\w
+ Square of {\tt Y}:\MFPsq\Y\Z\w
+ Inverse of {\tt X}:\MFPinv\X\Z\w
+ Inverse of {\tt Y}:\MFPinv\Y\Z\w
+ Fractional part of {\tt X}:\MFPfrac\X\Z\w
+ Fractional part of {\tt Y}:\MFPfrac\Y\Z\w
+ Floor of {\tt X}:\MFPfloor\X\Z\w
+ Floor of {\tt Y}:\MFPfloor\Y\Z\w
+ Ceiling of {\tt X}:\MFPceil\X\Z\w
+ Ceiling of {\tt Y}:\MFPceil\Y\Z\w
+ Sine of {\tt 30}:\MFPsin{30}\Z\w
+ Sine of {\tt 420}:\MFPsin{420}\Z\w
+ Cosine of {\tt 60}:\MFPcos{60}\Z\w
+ Cosine of {\tt 390}:\MFPcos{390}\Z\w
+ Common logarithm of {\tt X}:\MFPlog\X\Z\w
+\immediate\write16{^^J*** The following tests the warning for log of a negative
+number:^^J}%
+ Common logarithm of {\tt Y}:\MFPlog\Y\Z\w
+Natural logarithm of {\tt X}:\MFPln\X\Z\w
+\immediate\write16{^^J*** The following tests the warning for ln of a negative
+number:^^J}%
+Natural Logarithm of {\tt Y}:\MFPln\Y\Z\w
+ Exponential of {\tt X}:\MFPexp\X\Z\w
+ Exponential of {\tt Y}:\MFPexp\Y\Z\W
+
+\filbreak
+{\bf Extra tests of sine}\\
+Sine of 1:\MFPsin{1}\Z\w
+Cosine of 1:\MFPcos{1}\Z\w
+Sine of $-2$:\MFPsin{-2}\Z\w
+Cosine of 3:\MFPcos{3}\Z\w
+Sine of $-4$:\MFPsin{-4}\Z\w
+Cosine of 5:\MFPcos{5}\Z\w
+Sine of $-6$:\MFPsin{-6}\Z\w
+Cosine of 7:\MFPcos{7}\Z\w
+Sine of $-8$:\MFPsin{-8}\Z\w
+Cosine of 9:\MFPcos{9}\Z\w
+Sine of $-10$:\MFPsin{-10}\Z\w
+Cosine of 20:\MFPcos{20}\Z\w
+Sine of $-30$:\MFPsin{-30}\Z\w
+Cosine of 40:\MFPcos{40}\Z\w
+Sine of $-50$:\MFPsin{-50}\Z\w
+Cosine of 60:\MFPcos{60}\Z\w
+Sine of $-70$:\MFPsin{-70}\Z\w
+Cosine of 80:\MFPcos{80}\Z\w
+Sine of $-90$:\MFPsin{-90}\Z\w
+Sine of $135$:\MFPsin{135}\Z\w
+Sine of $180$:\MFPsin{180}\Z\w
+Sine of $225$:\MFPsin{225}\Z\w
+Sine of $270$:\MFPsin{270}\Z\w
+Sine of $315$:\MFPsin{315}\Z\W
+
+\medskip
+\noindent
+Angle of $(10,.1)$:\MFPangle{10}{.1}\Z\w
+Angle of $(-11.5,.1)$:\MFPangle{-11.5}{.1}\Z\w
+Angle of $(11.5,-.2)$:\MFPangle{11.5}{-.2}\Z\w
+Angle of $(-11.5,.3)$:\MFPangle{-11.5}{.3}\Z\w
+Angle of $(11.5,-.4)$:\MFPangle{11.5}{-.4}\Z\w
+Angle of $(-11.5,.5)$:\MFPangle{-11.5}{.5}\Z\w
+Angle of $(11.5,-.6)$:\MFPangle{11.5}{-.6}\Z\w
+Angle of $(-11.5,.7)$:\MFPangle{-11.5}{.7}\Z\w
+Angle of $(11.5,-.8)$:\MFPangle{11.5}{-.8}\Z\w
+Angle of $(-11.5,.9)$:\MFPangle{-11.5}{.9}\Z\w
+ Angle of $(11.5,-1)$:\MFPangle{11.5}{-1}\Z\w
+ Angle of $(-11.5,2)$:\MFPangle{-11.5}{2}\Z\w
+ Angle of $(11.5,-3)$:\MFPangle{11.5}{-3}\Z\w
+ Angle of $(-11.5,4)$:\MFPangle{-11.5}{4}\Z\w
+ Angle of $(11.5,-5)$:\MFPangle{11.5}{-5}\Z\w
+ Angle of $(-11.5,6)$:\MFPangle{-11.5}{6}\Z\w
+ Angle of $(11.5,-7)$:\MFPangle{11.5}{-7}\Z\w
+ Angle of $(-11.5,8)$:\MFPangle{-11.5}{8}\Z\w
+ Angle of $(11.5,-9)$:\MFPangle{11.5}{-9}\Z\w
+Angle of $(-11.5,10)$:\MFPangle{-11.5}{10}\Z\w
+Angle of $(11.5,-20)$:\MFPangle{11.5}{-20}\Z\w
+Angle of $(-11.5,30)$:\MFPangle{-11.5}{30}\Z\w
+Angle of $(11.5,-40)$:\MFPangle{11.5}{-40}\Z\w
+Angle of $(-11.5,50)$:\MFPangle{-11.5}{50}\Z\w
+Angle of $(11.5,-60)$:\MFPangle{11.5}{-60}\Z\w
+Angle of $(-11.5,70)$:\MFPangle{-11.5}{70}\Z\w
+Angle of $(11.5,-80)$:\MFPangle{11.5}{-80}\Z\w
+Angle of $(-11.5,90)$:\MFPangle{-11.5}{90}\Z\w
+Angle of $(11.5,-100)$:\MFPangle{11.5}{-100}\Z\w
+Angle of $(0,10)$:\MFPangle{0}{10}\Z\w
+Angle of $(0,-10)$:\MFPangle{0}{-10}\Z\w
+\immediate\write16{^^J*** The following tests the warning for angle of
+(0,0):^^J}
+Angle of $(0,0)$:\MFPangle{0}{0}\Z\W
+
+\noindent
+Testing large arguments:\\
+Angle of $(85 713 000, 99 999 999)$:\MFPangle{8571 3000}{9999 9999}\Z\W
+
+
+\filbreak
+{\bf Extra tests of log}\\
+ Log of $.1$:\MFPlog{.1}\Z\w
+ Log of $.2$:\MFPlog{.2}\Z\w
+ Log of $.3$:\MFPlog{.3}\Z\w
+ Log of $.4$:\MFPlog{.4}\Z\w
+ Log of $.5$:\MFPlog{.5}\Z\w
+ Log of $.6$:\MFPlog{.6}\Z\w
+ Log of $.7$:\MFPlog{.7}\Z\w
+ Log of $.8$:\MFPlog{.8}\Z\w
+ Log of $.9$:\MFPlog{.9}\Z\w
+ Log of $1$:\MFPlog{1}\Z\w
+Log of $1.01$:\MFPlog{1.01}\Z\w
+Log of $1.02$:\MFPlog{1.02}\Z\w
+Log of $1.03$:\MFPlog{1.03}\Z\w
+Log of $1.04$:\MFPlog{1.04}\Z\w
+Log of $1.05$:\MFPlog{1.05}\Z\w
+Log of $1.06$:\MFPlog{1.06}\Z\w
+Log of $1.07$:\MFPlog{1.07}\Z\w
+Log of $1.08$:\MFPlog{1.08}\Z\w
+Log of $1.09$:\MFPlog{1.09}\Z\w
+\immediate\write16{^^J*** The following tests the error for log of 0:^^J}
+Log of $0$:\MFPlog{0}\Z\W
+
+\filbreak
+{\bf Extra tests of exp}\\
+ Exp of $.00009990$:\MFPexp{.00009990}\Z
+\w
+ Exp of $.00009999$:\MFPexp{.00009999}\Z\w
+ Exp of $.0001$:\MFPexp{.0001}\Z\w
+ Exp of $.0002$:\MFPexp{.0002}\Z\w
+ Exp of $.0003$:\MFPexp{.0003}\Z\w
+ Exp of $.0004$:\MFPexp{.0004}\Z\w
+ Exp of $.0005$:\MFPexp{.0005}\Z\w
+ Exp of $.0006$:\MFPexp{.0006}\Z\w
+ Exp of $.0007$:\MFPexp{.0007}\Z\w
+ Exp of $.0008$:\MFPexp{.0008}\Z\w
+ Exp of $.0009$:\MFPexp{.0009}\Z\w
+ Exp of $.001$:\MFPexp{.001}\Z\w
+ Exp of $.002$:\MFPexp{.002}\Z\w
+ Exp of $.003$:\MFPexp{.003}\Z\w
+ Exp of $.004$:\MFPexp{.004}\Z\w
+ Exp of $.005$:\MFPexp{.005}\Z\w
+ Exp of $.006$:\MFPexp{.006}\Z\w
+ Exp of $.007$:\MFPexp{.007}\Z\w
+ Exp of $.008$:\MFPexp{.008}\Z\w
+ Exp of $.009$:\MFPexp{.009}\Z\w
+ Exp of $.01$:\MFPexp{.01}\Z\w
+ Exp of $.02$:\MFPexp{.02}\Z\w
+ Exp of $.03$:\MFPexp{.03}\Z\w
+ Exp of $.04$:\MFPexp{.04}\Z\w
+ Exp of $.05$:\MFPexp{.05}\Z\w
+ Exp of $.06$:\MFPexp{.06}\Z\w
+ Exp of $.07$:\MFPexp{.07}\Z\w
+ Exp of $.08$:\MFPexp{.08}\Z\w
+ Exp of $.09$:\MFPexp{.09}\Z\w
+ Exp of $.1$:\MFPexp{.1}\Z\w
+ Exp of $.2$:\MFPexp{.2}\Z\w
+ Exp of $.3$:\MFPexp{.3}\Z\w
+ Exp of $.4$:\MFPexp{.4}\Z\w
+ Exp of $.5$:\MFPexp{.5}\Z\w
+ Exp of $.6$:\MFPexp{.6}\Z\w
+ Exp of $.7$:\MFPexp{.7}\Z\w
+ Exp of $.8$:\MFPexp{.8}\Z\w
+ Exp of $.9$:\MFPexp{.9}\Z\w
+ Exp of $1$:\MFPexp{1}\Z\w
+ Exp of $2$:\MFPexp{2}\Z\w
+ Exp of $3$:\MFPexp{3}\Z\w
+ Exp of $4$:\MFPexp{4}\Z\w
+ Exp of $5$:\MFPexp{5}\Z\w
+ Exp of $6$:\MFPexp{6}\Z\w
+ Exp of $7$:\MFPexp{7}\Z\w
+ Exp of $8$:\MFPexp{8}\Z\w
+ Exp of $9$:\MFPexp{9}\Z\w
+ Exp of $10$:\MFPexp{10}\Z\w
+ Exp of $-8.3254$:\MFPexp{-8.3254}\Z\w
+ Exp of $18.42068073$:\MFPexp{18.42068073}\Z\w
+ Exp of $18.42068074$:\MFPexp{18.42068074}\Z\w
+\immediate\write16{^^J*** The following tests the error for a power too
+large:^^J}
+ Exp of $18.42068075$:\MFPexp{18.42068075}\Z\W
+
+\filbreak
+{\bf Extra tests of pow}\\
+ $-10$ power of $3$:\MFPpow{3}{-10}\Z\w
+ $-9$ power of $3$:\MFPpow{3}{-9}\Z\w
+ $-8$ power of $3$:\MFPpow{3}{-8}\Z\w
+ $-7$ power of $3$:\MFPpow{3}{-7}\Z\w
+ $-6$ power of $3$:\MFPpow{3}{-6}\Z\w
+ $-5$ power of $3$:\MFPpow{3}{-5}\Z\w
+ $-4$ power of $3$:\MFPpow{3}{-4}\Z\w
+ $-3$ power of $3$:\MFPpow{3}{-3}\Z\w
+ $-2$ power of $3$:\MFPpow{3}{-2}\Z\w
+ $-1$ power of $3$:\MFPpow{3}{-1}\Z\w
+ $0$ power of $3$:\MFPpow{3}{0}\Z\w
+ $1$ power of $3$:\MFPpow{3}{1}\Z\w
+ $2$ power of $3$:\MFPpow{3}{2}\Z\w
+ $3$ power of $3$:\MFPpow{3}{3}\Z\w
+ $4$ power of $3$:\MFPpow{3}{4}\Z\w
+ $5$ power of $3$:\MFPpow{3}{5}\Z\w
+ $6$ power of $3$:\MFPpow{3}{6}\Z\w
+ $7$ power of $3$:\MFPpow{3}{7}\Z\w
+ $8$ power of $3$:\MFPpow{3}{8}\Z\w
+ $9$ power of $3$:\MFPpow{3}{9}\Z\w
+ $10$ power of $3$:\MFPpow{3}{10}\Z\w
+\immediate\write16{^^J*** The following tests the error for a power too
+large:^^J}
+ $10$ power of $9$:\MFPpow{9}{10}\Z\w
+\immediate\write16{^^J*** The following also tests the error for a power too
+large:^^J}
+ $10$ power of $-9$:\MFPpow{-9}{10}\Z\w
+\immediate\write16{^^J*** The following also tests the error for a power too
+large:^^J}
+ $11$ power of $-9$:\MFPpow{-9}{11}\Z\w
+\immediate\write16{^^J*** The following tests the error for a negative power of
+0:^^J}
+ $-10$ power of $0$:\MFPpow{0}{-10}\Z\w
+\immediate\write16{^^J*** The following also tests the error for a power too
+large:^^J}
+ $-10$ power of $0.1$:\MFPpow{0.1}{-10}\Z\W
+
+\filbreak
+{\bf Extra tests of sqrt}\\
+\immediate\write16{^^J*** The following tests the error for a square root of a
+negative:^^J}
+ Square root of $-1$:\MFPsqrt{-1}\Z\w
+ Square root of $0$:\MFPsqrt{0}\Z\w
+ Square root of $.0001$:\MFPsqrt{.0001}\Z\w
+ Square root of $.002$:\MFPsqrt{.002}\Z\w
+ Square root of $.03$:\MFPsqrt{.03}\Z\w
+ Square root of $.4$:\MFPsqrt{.4}\Z\w
+ Square root of $.5$:\MFPsqrt{.5}\Z\w
+ Square root of $.6$:\MFPsqrt{.6}\Z\w
+ Square root of $.7$:\MFPsqrt{.7}\Z\w
+ Square root of $.8$:\MFPsqrt{.8}\Z\w
+ Square root of $.9$:\MFPsqrt{.9}\Z\w
+ Square root of $1$:\MFPsqrt{1}\Z\w
+ Square root of $2$:\MFPsqrt{2}\Z\w
+ Square root of $3$:\MFPsqrt{3}\Z\w
+ Square root of $4$:\MFPsqrt{4}\Z\w
+ Square root of $5$:\MFPsqrt{5}\Z\w
+ Square root of $6$:\MFPsqrt{6}\Z\w
+ Square root of $7$:\MFPsqrt{7}\Z\w
+ Square root of $8$:\MFPsqrt{8}\Z\w
+ Square root of $9$:\MFPsqrt{9}\Z\w
+ Square root of $10$:\MFPsqrt{10}\Z\w
+ Square root of $1524157.65279684$ (should be exact):\MFPsqrt{1524157.65279684}\Z\w
+Square root of $99999998.00000001$ (should be exact):\MFPsqrt{99999998.00000001}\Z\w
+ Square root of $9999.99$:\MFPsqrt{9999.99}\Z\w
+ Square root of $9999.999 999$:\MFPsqrt{9999.999999}\Z\W
+
+\filbreak
+{\bf Binary operations:}\\
+Add $X+Y$:\MFPadd\X\Y\Z\w
+Add $\infty+\infty$:\MFPadd{99999999.99999999}{99999999.99999999}\Z\w
+Subtract $X-Y$:\MFPsub\X\Y\Z\w
+Subtract $Y-X$:\MFPsub\Y\X\Z\w
+Subtract $X-X$:\MFPsub\X\X\Z\w
+Subtract $Y-Y$:\MFPsub\Y\Y\Z\w
+Multiply:\MFPmul\X\Y\Z\w
+Multiply $10^4\times10^4$:\MFPmul{10000}{10000}\Z\w
+Divide $X/Y$:\MFPdiv\X\Y\Z\w
+Divide $Y/X$:\MFPdiv\Y\X\Z\w
+Max:\MFPmax\X\Y\Z\w
+Min:\MFPmin\X\Y\Z\w
+Angle $(X,Y)$:\MFPangle\X\Y\Z\w
+Angle $(Y,X)$:\MFPangle\Y\X\Z\w
+Power $X^5$:\MFPpow\X{5}\Z\w
+Power $X^{-5}$:\MFPpow\X{-5}\Z\w
+Power $Y^{5}$:\MFPpow\Y{5}\Z\w
+Power $Y^{-5}$:\MFPpow\Y{-5}\Z\w
+Compare: \MFPcmp\X\Y
+ \X\ is\IFlt{}{ not} less than \Y.
+ \X\ is\IFgt{}{ not} more than \Y.
+ \X\ is\IFeq{}{ not} equal to \Y.\\
+Take difference and check:\MFPsub\X\Y\Z\w
+ $\X-\Y$ is\IFneg{}{ not} negative.
+ $\X-\Y$ is\IFpos{}{ not} positive.
+ $\X-\Y$ is\IFzero{}{ not} zero.
+
+\filbreak
+{\bf Print-related formating}
+
+\def\T{333.00000000}
+\def\S{1357.12345678}
+
+\noindent This is original: $T ={}${\tt"\T"}\\
+Truncate to 4 digits right of decimal:\MFPtruncate{4}\T\Z\w
+Truncate to the decimal:\MFPtruncate{0}\T\Z\w
+Truncate to 2 digits left of decimal:\MFPtruncate{-2}\T\Z\w
+Strip trailing zeros:\MFPstrip\T\Z\w
+Strip trailing zeros (star form):\MFPstrip*\T\Z\W
+
+\noindent Original: $S = {}${\tt"\S"}\\
+Round to 3 decimals:\MFPround{3}\S\Z\w
+Round to 5 decimals:\MFPround{5}\S\Z\w
+Round to 0 decimals:\MFPround{0}\S\Z\w
+Round to 100s:\MFPround{-2}\S\Z\W
+
+\def\T{-333.00000000}
+\def\S{-1357.12345678}
+
+\filbreak
+\noindent All that again with negative numbers.
+
+\medskip
+\noindent This is original: $T ={}${\tt"\T"}\\
+Truncate to 4 digits right of decimal:\MFPtruncate{4}\T\Z\w
+Truncate to the decimal:\MFPtruncate{0}\T\Z\w
+Truncate to 2 digits left of decimal:\MFPtruncate{-2}\T\Z\w
+Strip trailing zeros:\MFPstrip\T\Z\w
+Strip trailing zeros (star form):\MFPstrip*\T\Z\W
+
+\noindent Original: $S = {}${\tt"\S"}\\
+Round to 3 decimals:\MFPround{3}\S\Z\w
+Round to 5 decimals:\MFPround{5}\S\Z\w
+Round to 0 decimals:\MFPround{0}\S\Z\w
+Round to 100s:\MFPround{-2}\S\Z\W
+
+\end{document}
diff --git a/Master/texmf-dist/doc/generic/minifp/test2.tex b/Master/texmf-dist/doc/generic/minifp/test2.tex
new file mode 100644
index 00000000000..8cd7ab278c5
--- /dev/null
+++ b/Master/texmf-dist/doc/generic/minifp/test2.tex
@@ -0,0 +1,376 @@
+\errorcontextlines999\relax
+X\input minifp.sty\relax X\MFPloadextra X
+\def\empty{}
+
+\def\frac#1#2{{#1\over#2}}
+\def\cs#1{{\tt \char`\\#1}}
+\def\mybreak{\vskip 0pt plus 100pt\penalty 0 \vskip 0pt plus -100pt\relax}
+\def\\{\hfil\break\ignorespaces}
+\def\y{Rpop\Z\Z\\}
+\def\Y{Rpop\Z\Z}
+\everymath{\displaystyle}
+
+{\bf Stack-only operations:}\\
+Example of a program. Computes the solution of $ax^2 + bx + c = 0$ using
+the quadratic formula. If the result is complex, it detects this.
+Coefficients stored in \cs{A}, \cs{B} and \cs{C}. First case: $4x^2 +
+5y^2 - 1= 0$. Solutions are $x = -\frac{5}{8} \pm \frac{1}{8}\sqrt{41}$
+
+\def\A{4}\def\B{5}\def\C{-1}
+
+X\startMFPprogram % stack
+\Rpush\B\Rdup\Rsq % B(B^2)
+\Rpush\A\Rpush\C\Rmul\Rdbl\Rdbl % B(B^2)(4AC)
+\Rsub % B(B^2-4AC)
+\IFneg{\def\I{i}\Rchs}{\def\I{}}% % B(|B^2-4AC|)
+\Rsqrt\Rpush\A\Rdbl\Rdiv % B(sqrt(|B^2-4AC|)/2A)
+\Rpop\Ypart % B
+\Rpush\A\Rdbl\Rdiv\Rchs % (-B/2A)
+\Rpop\Xpart %
+%\expandafter\show\csname MFP@Rstack\endcsname
+\Rpush\Xpart\Rpush\Ypart\Radd\Rpop\Broot
+\Rpush\Xpart\Rpush\Ypart\Rsub\Rpop\Sroot
+\Export\Xpart
+\Export\Ypart
+\Export\Broot
+\Export\Sroot
+\Export\I
+\stopMFPprogram X
+
+\indent Solution: $x = \Xpart \pm \I\Ypart = \Broot$ and $\Sroot$.
+
+Second case $2x^2 - 2x + 3 = 0$. Solutions are $x = \frac{1}{2} \pm
+\frac{i}{2}\sqrt{5}$.
+
+\def\A{2}\def\B{-2}\def\C{3}
+
+X\startMFPprogram % stack
+\Rpush\B\Rdup\Rsq % B(B^2)
+\Rpush\A\Rpush\C\Rmul\Rdbl\Rdbl % B(B^2)(4AC)
+\Rsub % B(B^2-4AC)
+\IFneg{\def\I{i}\Rchs}{\def\I{}}% % B(|B^2-4AC|)
+\Rsqrt\Rpush\A\Rdbl\Rdiv % B(sqrt(|B^2-4AC|)/2A)
+\Rpop\Ypart % B
+\Rpush\A\Rdbl\Rdiv\Rchs % (-B/2A)
+\Rpop\Xpart %
+\Export\Xpart
+\Export\Ypart
+\Export\I
+\stopMFPprogram X
+
+%\expandafter\show\csname MFP@Rstack\endcsname
+\indent Solution: $x = \Xpart \pm \I\Ypart$.
+
+Now try square roots (should be exactly 1234.5678 and 1524):
+X\startMFPprogram % stack
+\Rpush{1524157.65279684}\Rsqrt\Rpop\X
+\Rpush{1524}\Rsq\Rsqrt\Rpop\Y
+\Export\X
+\Export\Y
+\stopMFPprogram X \X { and }\Y.
+
+
+Below we test for speed and to check for any space characters
+accidentally produced. You should see only a few xX pairs with hopefully
+no spaces in between them. As curently set up, these tests perform about
+34000 numerical operations. It all takes about 31 seconds on a
+moderately old (2 years?) Windows 7 running plain tex from
+TeX~Live~2012.
+
+This operation count does not distinguish between basic operations like
+addition and multiplication, and those operations from mfpextra that are
+probably each equivalent to a dozen or more multiplications. Counting
+each such operation with the an estimated multiplicity, the tests
+probably perform 400 thousand or more basic operations.
+
+Of the basic operations, multiplication is (by measurement) 4 times as
+lengthy as addition, and division is about twice as lengthy as
+multiplication. Actual times depend on the machine, but the ratios remain
+pretty much the same. Here is a summary of timings on my fastest
+machine; each operation is run 500 times in a loop:
+
+\medskip
+
+\indent\vtop{\halign{\hfil$#$&\quad$#\,$sec\cr
+\noalign{\hrule\smallskip}
+2.54321+22432.87654321 &0.015\cr
+2.54321\times22432.87654321 &0.06\cr
+22432.87654321/2.54321 &0.14\cr
+\sqrt{23456789.54321} &0.20\cr
+1.00001234^{8000} &0.73\cr
+\exp(2.54321) &0.41\cr
+\sin(2.54321) &0.45\cr
+\log(2.54321) &0.53\cr
+\mathop{\fam0 angle}(254.321,100) &1.17\cr
+\noalign{\smallskip\hrule}
+}}
+
+\medskip
+
+Originally, all the tests combined took 21 seconds on a 4-year-old
+Windows XP under TeX Live 2011. But since then I have changed angle and
+power computations so that they are considerably more accurate, but with
+a possible reduction in speed. Of course, some of the speed loss may be
+due to the operating system.
+
+On a Windows 7 machine, 64-bit, laptop, it takes 32 seconds to process
+this file. On another Win7, machine, 32-bit, desktop, it takes 10
+seconds.
+
+The difference could be explained partially by the fact that the second
+machine is newer and partially by the fact that TeX is a 32-bit program,
+and therefore a better match to the operating system of the second
+system.
+
+\def\testi{% stack forms
+\startMFPprogram
+\Rpush{0.000 001}\Rpop\X
+\Rpush{1.2}\Rpush{-2.3}\Rexch\Rdup
+\Rpop\X\Rpop\X
+\Rpop\X\Rpush{21.34}\Rchs
+\Rpop\X\Rpush{21.34}\Rabs
+\Rpop\X\Rpush{21.34}\Rchs
+\Rpop\X\Rpush{21.34}\Rint
+\Rpop\X\Rpush{21.34}\Rfrac
+\Rpop\X\Rpush{21.34}\Rdbl
+\Rpop\X\Rpush{21.34}\Rhalve
+\Rpop\X\Rpush{21.34}\Rsgn
+\Rpop\X\Rpush{21.34}\Rsin
+\Rpop\X\Rpush{21.34}\Rcos
+\Rpop\X\Rpush{21.34}\Rdeg
+\Rpop\X\Rpush{21.34}\Rrad
+\Rpop\X\Rpush{21.34}\Rlog
+\Rpop\X\Rpush{21.34}\Rln
+\Rpop\X\Rpush{-1.34}\Rexp
+\Rpop\X\Rpush{3.3}\Rexp
+\Rpop\X\Rpush{21.34}\Rsq
+\Rpop\X\Rpush{21.34}\Rinv
+\Rpop\X\Rpush{21.34}\Rfloor
+\Rpop\X\Rpush{21.34}\Rceil
+\Rpop\X\Rpush{21.34}\Rsqrt
+\Rpop\X\Rpush{21.34}\Rpush{12.34}\Rcmp
+\IFlt{}{}\IFgt{}{}\IFeq{}{}\Rsub
+\IFneg{}{}\IFpos{}{}\IFzero{}{}\Rpop\X
+\Rpush{1.2}\Rpush{-2.3}\Radd
+\Rpop\X\Rpush{1.2}\Rpush{-2.3}\Rsub
+\Rpop\X\Rpush{1.2}\Rpush{-2.3}\Rmul
+\Rpop\X\Rpush{1.2}\Rpush{-2.3}\Rdiv
+\Rpop\X\Rpush{2.3}\Rpush{17}\Rpow
+\Rpop\X\Rpush{2.3}\Rpush{-17}\Rpow
+\Rpop\X\Rpush{1.2}\Rpush{-2.3}\Rmax
+\Rpop\X\Rpush{1.2}\Rpush{-2.3}\Rmin
+\stopMFPprogram}
+
+\def\testii{% unary operand forms, including
+\MFPchs\X\Z % extra tests of sin, log, exp and pow
+\MFPchs\Y\Z
+\MFPabs\X\Z
+\MFPabs\Y\Z
+\MFPdbl\X\Z
+\MFPdbl\Y\Z
+\MFPhalve\X\Z
+\MFPhalve\Y\Z
+\MFPint\X\Z
+\MFPint\Y\Z
+\MFPsgn\X\Z
+\MFPsgn\Y\Z
+\MFPsq\X\Z
+\MFPsq\Y\Z
+\MFPinv\X\Z
+\MFPinv\Y\Z
+\MFPfrac\X\Z
+\MFPfrac\Y\Z
+\MFPfloor\X\Z
+\MFPfloor\Y\Z
+\MFPceil\X\Z
+\MFPceil\Y\Z
+\MFPsin{30}\Z
+\MFPsin{420}\Z
+\MFPcos{60}\Z
+\MFPcos{390}\Z
+\MFPlog\X\Z
+\MFPln\X\Z
+\MFPexp\X\Z
+\MFPexp\Y\Z
+\MFPsin{1}\Z
+\MFPsin{2}\Z
+\MFPsin{3}\Z
+\MFPsin{4}\Z
+\MFPsin{5}\Z
+\MFPsin{6}\Z
+\MFPsin{7}\Z
+\MFPsin{8}\Z
+\MFPsin{9}\Z
+\MFPsin{10}\Z
+\MFPsin{20}\Z
+\MFPsin{30}\Z
+\MFPsin{40}\Z
+\MFPsin{50}\Z
+\MFPsin{60}\Z
+\MFPsin{70}\Z
+\MFPsin{80}\Z
+\MFPsin{90}\Z
+\MFPlog{.1}\Z
+\MFPlog{.2}\Z
+\MFPlog{.3}\Z
+\MFPlog{.4}\Z
+\MFPlog{.5}\Z
+\MFPlog{.6}\Z
+\MFPlog{.7}\Z
+\MFPlog{.8}\Z
+\MFPlog{.9}\Z
+\MFPlog{1}\Z
+\MFPlog{1.01}\Z
+\MFPlog{1.02}\Z
+\MFPlog{1.03}\Z
+\MFPlog{1.04}\Z
+\MFPlog{1.05}\Z
+\MFPlog{1.06}\Z
+\MFPlog{1.07}\Z
+\MFPlog{1.08}\Z
+\MFPlog{1.09}\Z
+\MFPexp{.000001}\Z
+\MFPexp{.00001}\Z
+\MFPexp{.0001}\Z
+\MFPexp{.001}\Z
+\MFPexp{.01}\Z
+\MFPexp{.1}\Z
+\MFPexp{1}\Z
+\MFPexp{2}\Z
+\MFPexp{3}\Z
+\MFPexp{4}\Z
+\MFPexp{5}\Z
+\MFPexp{6}\Z
+\MFPexp{7}\Z
+\MFPexp{8}\Z
+\MFPexp{9}\Z
+\MFPexp{10}\Z
+\MFPexp{-8.3254}\Z
+\MFPpow\MFPe{-10}\Z
+\MFPpow\MFPe{-9}\Z
+\MFPpow\MFPe{-8}\Z
+\MFPpow\MFPe{-7}\Z
+\MFPpow\MFPe{-6}\Z
+\MFPpow\MFPe{-5}\Z
+\MFPpow\MFPe{-4}\Z
+\MFPpow\MFPe{-3}\Z
+\MFPpow\MFPe{-2}\Z
+\MFPpow\MFPe{-1}\Z
+\MFPpow\MFPe{0}\Z
+\MFPpow\MFPe{1}\Z
+\MFPpow\MFPe{2}\Z
+\MFPpow\MFPe{3}\Z
+\MFPpow\MFPe{4}\Z
+\MFPpow\MFPe{5}\Z
+\MFPpow\MFPe{6}\Z
+\MFPpow\MFPe{7}\Z
+\MFPpow\MFPe{8}\Z
+\MFPpow\MFPe{9}\Z
+\MFPpow\MFPe{10}\Z}
+
+\def\testiii{%% binary operand forms and print formating, plus
+\MFPsqrt{0}\Z % additional tests of sqrt
+\MFPsqrt{1}\Z
+\MFPsqrt{2}\Z
+\MFPsqrt{3}\Z
+\MFPsqrt{4}\Z
+\MFPsqrt{5}\Z
+\MFPsqrt{6}\Z
+\MFPsqrt{7}\Z
+\MFPsqrt{8}\Z
+\MFPsqrt{9}\Z
+\MFPsqrt{10}\Z
+\MFPsqrt{1524157.65279684}\Z
+\MFPadd\X\Y\Z
+\MFPsub\X\Y\Z
+\MFPsub\Y\X\Z
+\MFPsub\X\X\Z
+\MFPsub\Y\Y\Z
+\MFPmul\X\Y\Z
+\MFPdiv\X\Y\Z
+\MFPdiv\Y\X\Z
+\MFPmax\X\Y\Z
+\MFPmin\X\Y\Z
+\MFPpow\X{5}\Z
+\MFPpow\X{-5}\Z
+\MFPpow\Y{5}\Z
+\MFPpow\Y{-5}\Z
+\MFPcmp\X\Y
+\IFlt{}{}\IFgt{}{}\IFeq{}{}%
+\MFPsub\X\Y\Z
+\IFneg{}{}\IFpos{}{}\IFzero{}{}%
+\def\T{333.00000000}%
+\def\S{1357.12345678}%
+\MFPtruncate{4}\T\Z
+\MFPtruncate{0}\T\Z
+\MFPtruncate{-2}\T\Z
+\MFPstrip\T\Z
+\MFPstrip*\T\Z
+\MFPround{3}\S\Z
+\MFPround{5}\S\Z
+\MFPround{0}\S\Z
+\MFPround{-2}\S\Z
+\def\T{-333.00000000}%
+\def\S{-1357.12345678}%
+\MFPtruncate{4}\T\Z
+\MFPtruncate{0}\T\Z
+\MFPtruncate{-2}\T\Z
+\MFPstrip\T\Z
+\MFPstrip*\T\Z
+\MFPround{3}\S\Z
+\MFPround{5}\S\Z
+\MFPround{0}\S\Z
+\MFPround{-2}\S\Z}
+
+Three test loops follow. The first repeats 500 times a stack program
+that performs each available command followed by popping the result and
+repushing the original value(s).
+
+\newcount\n
+\def\testloopi{%
+ \ifnum \n>0
+ \advance\n -1
+ \testi
+ \expandafter
+ \testloopi
+ \fi
+}
+\n=500
+x\testloopi X
+
+
+The second repeats 100 times a sequence in which all the unary operand
+commands are performed twice, plus extra of sine, log and exp.
+
+\def\testloopii{%
+ \ifnum \n>0
+ \advance\n -1
+ \testii
+ \expandafter
+ \testloopii
+ \fi
+}
+\def\X{1.2}
+\def\Y{-2.3}
+\n=100
+x\testloopii X
+
+
+The third repeats 100 times a sequence in which all the binary operand
+commands are performed, plus some extra tests of sqrt and then all the
+print-preparation commands.
+
+\def\testloopiii{%
+ \ifnum \n>0
+ \advance\n -1
+ \testiii
+ \expandafter
+ \testloopiii
+ \fi
+}
+
+\n=100
+x\testloopiii X
+\end
+
+\end{document}
diff --git a/Master/texmf-dist/source/generic/minifp/minifp.dtx b/Master/texmf-dist/source/generic/minifp/minifp.dtx
new file mode 100644
index 00000000000..3c3ff629144
--- /dev/null
+++ b/Master/texmf-dist/source/generic/minifp/minifp.dtx
@@ -0,0 +1,3937 @@
+% \iffalse
+% -------------------------------------------------------------------
+%
+% Copyright 2008--2013, Daniel H. Luecking
+%
+% minifp may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License, either version 1.3b of this license or (at
+% your option) any later version. The latest version of this license is in
+% <http://www.latex-project.org/lppl.txt>
+% and version 1.3c or later is part of all distributions of LaTeX version
+% 2008/12/01 or later.
+%
+% minifp has maintenance status "author-maintained". The Current Maintainer
+% is Daniel H. Luecking. The Base Interpreter is TeX (plain TeX or LaTeX).
+%<*driver|sty>
+\def\MFPfiledate{2013/01/01}%
+\def\MFPfileversion{0.9}%
+%</driver|sty>
+%
+%<*driver>
+\ProvidesFile{minifp.dtx}
+ [\MFPfiledate\space v\MFPfileversion. Macros for real number operations and a
+ stack-based programing language.]%
+\documentclass[draft]{ltxdoc}
+
+\addtolength{\textwidth}{1pt}
+
+\usepackage[morefloats=2]{morefloats}
+
+% This avoids messages about nonexistent font variants (e.g., in \section):
+\def\mytt{\upshape\mdseries\ttfamily}
+% I use it instead of \texttt:
+\renewcommand\marg[1]{{\mytt\{#1\}}}
+\renewcommand\oarg[1]{{\mytt [#1]}}
+\renewcommand\parg[1]{{\mytt (#1)}}
+\renewcommand \arg[1]{{\mytt \##1}}
+\renewcommand\#{\char`\#\relax}
+\DeclareRobustCommand\cs[1]{{\mytt\char`\\#1}}
+% sometimes I want a <meta> without enclosing braces:
+\renewcommand{\meta}[1]{\mbox{$\langle$\rmfamily\itshape#1\/$\rangle$}}
+% and sometimes I want the braces:
+\newcommand\mmarg[1]{\marg{\meta{#1}}}
+
+\def\prog#1{{\mdseries\scshape #1}}
+\def\mfp{\prog{minifp}}
+\def\Mfp{\prog{Minifp}}
+\def\file#1{{\mytt #1}}
+\let\dim\file
+\let\env\file
+\def\sgn{\mathop{\mathrm{sgn}}\nolimits}
+% \op is for abstract operations (e.g., \op{add}) as opposed to
+% the macro that performs it (e.g., \cs{Radd}).
+\let\op\textit
+% The occasional bare \tt braces
+\renewcommand\{{\char`\{}
+\renewcommand\}{\char`\}}
+% this gives the alternative symbol in BNF productions, i.e., the bar
+% in: { this | that }
+\renewcommand\|{${}\mathrel{|}{}$}
+
+\makeatletter
+\newcommand\bsl{{\mytt\@backslashchar}}
+% Stupid lists!
+\def\@listi{\leftmargin\leftmargini
+ \parsep \z@ \@plus\p@ \@minus\z@
+ \topsep 4\p@ \@plus\p@ \@minus2\p@
+ \itemsep\parsep}
+\let\@listI\@listi \@listi
+\renewcommand\labelitemi{\normalfont\bfseries \textendash}
+\renewcommand\labelitemii{\textasteriskcentered}
+\renewcommand\labelitemiii{\textperiodcentered}
+\leftmargini\parindent
+% Stupid index!
+\def\usage#1{\textrm{#1}}
+\def\index@prologue{\section*{Index}\markboth{Index}{Index}%
+ Numbers refer to the page(s) where the corresponding entry is described.
+}
+\def\IndexParms{%
+ \parindent \z@ \columnsep 15pt
+ \parskip 0pt plus 1pt
+ \rightskip 5pt plus2em \mathsurround \z@
+ \parfillskip-5pt \small
+ % less hanging:
+ \def\@idxitem{\par\hangindent 20pt}%
+ \def\subitem{\@idxitem\hspace*{15pt}}%
+ \def\subsubitem{\@idxitem\hspace*{25pt}}%
+ \def\indexspace{\par\vspace{10pt plus 2pt minus 3pt}}}
+\makeatother
+
+\title{The \mfp{} package\thanks{This file has version number
+ \fileversion, last revised \filedate. The code described here
+ was developed by Dan Luecking.}}
+\author{Dan Luecking}
+\date{\filedate}
+\DisableCrossrefs
+\CodelineIndex
+\AlsoImplementation
+
+\begin{document}
+ \DeleteShortVerb{\|}
+ \DocInput{minifp.dtx}
+\end{document}
+%</driver>
+%\fi
+% \CheckSum{3325}
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+% \GetFileInfo{minifp.dtx}
+% \maketitle
+%
+% \begin{abstract}
+% This package provides minimal fixed point exact decimal arithmetic
+% operations. `Minimal' means numbers are limited to eight digits on
+% either side of the decimal point. `Exact' means that when a number
+% \emph{can} be represented exactly within those limits, it will be.
+% \end{abstract}
+%
+% \StopEventually{\PrintIndex}
+% \tableofcontents
+%
+% \section{Introduction}
+% In working on an application that needed to be able to automatically
+% generate numeric labels on the axes of a graph, I needed to be able
+% to make simple calculations with real numbers. What \TeX{} provides is
+% far to limited. In fact, its only native user-level support for real
+% numbers is as factors for dimensions. For example one can ``multiply''
+% $3.1\times 0.2$ by \verb$\dimen0=0.2pt \dimen0=3.1\dimen0 $.
+%
+% Unfortunately \TeX{} stores dimensions as integer multiples of of the
+% ``scaled point'' (\dim{sp}) with \dim{sp}${}=2^{-16}$\dim{pt}, and
+% therefore \dim{.2pt} is approximated by $\frac{13107}{65536}$, which is
+% not exact. Then mutiplying by $3.1$ produces $\frac{40631}{65536}$. If
+% we ask for 5 digit accuracy, this produces $0.61998$\dim{pt} and not the
+% exact value $0.62$. This is sufficiently accurate for positioning
+% elements on a page, but not for displaying automatically computed axis
+% labels if 5 digit accuracy is needed.
+%
+% The \mfp{} package was written to provide the necessary calculations
+% with the necessary accuracy for this application. The implementation
+% would have been an order of magnitude smaller and faster if only 4 digit
+% accuracy were provided (and I may eventually do that for the application
+% under consideration), but I have decided to clean up what I have
+% produced and release it as is. The full \mfp{} package provides nearly
+% the same operations as a subset of the \prog{fp} package, but the latter
+% carries calculations to 18 decimal places, which is far more than
+% necessary for my purposes. I want something small and fast to embed in
+% the \prog{mfpic} drawing package.
+%
+% I decided on eight digits on both sides of the decimal point essentially
+% because I wanted at least 5 digits and the design I chose made multiples
+% of 4 the easiest to work with.
+%
+% \Mfp{} also provides a simple stack-based language for writing assembly
+% language-like programs. Originally, this was to be the native
+% calculation method, but it turned out to be too unwieldy for ordinary
+% use. I left it in because it adds only about 10\% overhead to the code.
+%
+% But why \emph{only} eight digits? \TeX{} only works with integers, and
+% since the maximum integer allowed is about $2\,000\,000\,000$, the
+% largest numbers that can be added are limited to about $999\,999\,999$.
+% It is very little trouble to add numbers by adding their fractional
+% parts and integer parts separately as 9-digit integers. So it would seem
+% multiples of $9$ digits would be easy to implement.
+%
+% However, something we have to do repeatedly in \emph{division} is
+% multiply the integer and fractional parts of a number by a one-digit
+% number. For that purpose, nine digits would be too much, but eight
+% digits is just right. For nine digits, we would have to inconveniently
+% break the number into more than two parts. Limiting our numbers to
+% eight-digit parts drastically simplifies division.
+%
+% Another simplification: multiplication has to be done by breaking the
+% number into parts. \TeX{} can multiply any two 4-digit integers without
+% overflow, but it cannot multiply most pairs of 5-digit integers. Two
+% 8-digit numbers conveniently break ito four 4-digit parts. To get even
+% nine digits of accuracy would require six parts (five, if we don't
+% insist on a separation occuring at the decimal point). The complexity of
+% the multiplication process goes up as the square of the number of parts,
+% so six parts would more than double the complexity.
+%
+% A final simplification: \TeX{} places a limit of 9 on the number of
+% arguments a macro can have. Quite often the last argument is needed
+% clear out unused text to be discarded. Thus, a string of eight digits
+% can quite often be processed with one execution of one nine-argument
+% macro.
+%
+% Addition and subtraction can be exact, multiplication and division can
+% extend numbers past the 8-digit limit so they might be rounded.
+% However, when the exact answer fits in the 8-digit limit, our code
+% should produce it. Overflow (in the sense that the integer part can
+% exceed the allowed eight digits) is always possible, but is much more
+% likely with multiplication and division.
+%
+% Multiplication is carried out internally to an exact 16-digit answer,
+% which is then rounded to an 8-digit result. Overflow (more than 8
+% digits in the integer part) is discarded. Division is internally
+% carried to 9 digits after the decimal, which is then also rounded to
+% an 8-digit result.
+%
+% We supply two kinds of operations in this package. There are stack-based
+% operations, in which the operands are popped from a stack and the
+% results pushed onto it, and argument-based, in which the operands (and a
+% macro to hold the result^^A
+% \footnote{Unlike most other packages for floating point
+% arithmetic, \mfp{} puts the macro to hold the result
+% last. This allows the calculation to be performed before the
+% macro is even read, and makes it somewhat easier for the
+% stack- and argument-based versions to share code.}^^A
+% ) are arguments of a macro. Both types load the arguments into internal
+% macros (think ``registers''), then call internal commands
+% (think ``microcode'') which return the results in internal macros.
+% These results are then pushed onto the stack (stack-based operations) or
+% stored in a supplied macro argument (think ``variable'').
+%
+% The stack is implemented as an internal macro which is redefined with
+% each command. The binary operations act on the last two pushed objects
+% in the order they were pushed. For example, the sequence ``\op{push} 5,
+% \op{push} 3, \op{subtract}'' performs $5-3$ by popping $3$ and $5$ into
+% registers (thereby removing them from the stack), subtracting them
+% and then pushing the result ($2$) onto the stack.
+%
+% Our implementation of the \op{push} operation first prepares the number
+% in a standard form. Thus, stack-based operations always obtain numbers
+% in this form. The argument based operations will prepare the arguments
+% in the same way. The internal commands will thus have a standard form to
+% operate on. All results are returned in standard form.
+%
+% The standard form referred to above is an integer part (1 to 8 digits
+% with no unnecessary leading zeros nor unnecessary sign) followed by the
+% decimal point (always a dot, which is ASCII \number`\.), followed by exactly
+% 8 digits, all of this preceded by a minus sign if the number is
+% negative. Thus, $-{-0.25}$ would be processed and stored as
+% ``\texttt{0.25000000}'' and $-.333333$ as ``\texttt{-0.33333300}''.
+%
+%
+% \section{User macros}
+%
+% \Mfp{} provides (so far) six binary operations (that act on a pair of
+% numbers): addition, subtraction, multiplication, division, maximum and
+% minimum, as well as fourteen unary operations (that act on one number):
+% negation, absolute value, doubling, halving, integer part, fractional
+% part, floor, ceiling, signum, squaring, increment, decrement and
+% inversion. With the ``\texttt{extra}'' option, the unary operations
+% sine, cosine, logarithm, powers and square root are available, and the
+% binary operation angle. See section~\ref{extras}.
+%
+% These extra operations are made available using the \texttt{extra}
+% option in \LaTeX{}:
+% \begin{verbatim}
+% \usepackage[extra]{minifp} \end{verbatim}
+% In plain \TeX{}, they will be loaded if you give the macro
+% \cs{MFPextra} a definition (any definition) before inputting
+% \file{minifp.sty}:
+% \begin{verbatim}
+% \def\MFPextra{} \input minifp.sty \end{verbatim}
+% The extras can also be loaded by means of the command
+% \cs{MFPloadextra}, issued after \file{minifp.sty} is loaded.
+%
+% If the extra operations are not needed, some memory and time might be
+% saved by using \file{minifp.sty} alone.
+%
+% As previously mentioned, each of these operations come in two versions:
+% a version that acts on operands and stores the result in a macro, and a
+% version that acts on the stack. The former all have names that begin
+% \cs{MFP} and the latter begin with \cs{R}. The former can be used
+% anywhere, while the latter can only be used in a ``program''.
+% A program is started with \cs{startMFPprogram} and terminated with
+% \cs{stopMFPprogram}. The \texttt{R} in the names is for `real'. This is
+% because it is possible that stacks of other types will be implemented in
+% the future.
+%
+% For example, \verb$\MFPadd{1.3}{3.4}\X$ will add $1.20000000$ to
+% $3.40000000$ and then define \cs{X} to be the resulting
+% \texttt{4.60000000}. These operand forms do not alter or even address
+% the stack in any way. The stack-based version of the same operation
+% would look like the following:
+% \begin{verbatim}
+% \Rpush{1.2}
+% \Rpush{3.4}
+% \Radd
+% \Rpop\X \end{verbatim}
+% which would push first \texttt{1.20000000} then \texttt{3.40000000} onto
+% the stack, then replace them with \texttt{4.60000000}, then remove that
+% and store it in \verb$\X$. Clearly the stack is intended for
+% calculations that produce a lot of intermediate values and only the
+% final result needs to be stored.
+%
+% \SpecialUsageIndex{\startMFPprogram}
+% The command \cs{startMFPprogram} starts a group. That group should be
+% ended by \cs{stopMFPprogram}.
+% \SpecialUsageIndex{\stopMFPprogram}
+% Changes to the stack and defined macros are local to that group. Thus
+% the macro \cs{X} in the example above might seem to be useful only as a
+% temporary storage for later calculations in the same program group.
+% However, there are commands provided to force such a macro to survive
+% the group, and even to force the contents of the stack to survive the
+% group (see the end of subsection~\ref{stack}). Do not try to turn a
+% \mfp{} program into a \LaTeX{} environment. The extra grouping added by
+% environments would defeat the effects of these commands.
+%
+% \subsection{Nonstack-based operations}
+%
+% In the following tables, an argument designated
+% \meta{num} can be any decimal real number with at most 8
+% digits on each side of the decimal point, or they can be macros that
+% contain such a number. If the decimal dot is absent, the fractional part
+% will be taken to be 0, if the integer part or the fractional part is
+% absent, it will be taken to be 0. (One consequence of these rules is
+% that all the following arguments produce the same internal
+% representation of zero: \marg{0.0}, \marg{0.}, \marg{.0},
+% \marg{0}, \marg{.}, and \marg{}\,.) Spaces may appear anywhere in the
+% \meta{num} arguments and are stripped out before the number is used.
+% For example, \marg{3 . 1415 9265} is a valid argument. Commas are not
+% permitted. The decimal dot (period, fullstop) character must be
+% inactivated if some babel language makes it a shorthand.
+%
+% The \cs{macro} argument is any legal macro. The result of using one of
+% these commands is that the macro is defined (or redefined, there is no
+% checking done) to contain the standard form of the result. If the
+% \meta{num} is a macro, the braces surrounding it are optional.
+%
+% \medskip
+% \centerline{%
+% \begin{tabular}{lp{3in}}
+% \textit{Binary Operations}&\\[3pt]
+% \hline \hline
+% \textbf{Command}&\textbf{operation}\\
+% \hline
+% \SpecialUsageIndex{\MFPadd}^^A
+% \cs{MFPadd}\mmarg{num$_1$}\mmarg{num$_2$}\cs{macro}&
+% Stores the result of \meta{num$_1$}${}+{}$\meta{num$_2$} in \cs{macro}\\
+% \SpecialUsageIndex{\MFPsub}^^A
+% \cs{MFPsub}\mmarg{num$_1$}\mmarg{num$_2$}\cs{macro}&
+% Stores the result of \meta{num$_1$}${}-{}$\meta{num$_2$} in \cs{macro}\\
+% \SpecialUsageIndex{\MFPmul}^^A
+% \cs{MFPmul}\mmarg{num$_1$}\mmarg{num$_2$}\cs{macro}&
+% Stores the result of \meta{num$_1$}${}\times{}$\meta{num$_2$},
+% rounded to 8 places after the decimal point, in \cs{macro}\\
+% \SpecialUsageIndex{\MFPmpy}^^A
+% \cs{MFPmpy}\mmarg{num$_1$}\mmarg{num$_2$}\cs{macro}&
+% Same as \cs{MFPmul}\\
+% \SpecialUsageIndex{\MFPdiv}^^A
+% \cs{MFPdiv}\mmarg{num$_1$}\mmarg{num$_2$}\cs{macro}&
+% Stores the result of \meta{num$_1$}${}/{}$\meta{num$_2$},
+% rounded to 8 places after the decimal point, in \cs{macro}\\
+% \SpecialUsageIndex{\MFPmin}^^A
+% \cs{MFPmin}\mmarg{num$_1$}\mmarg{num$_2$}\cs{macro}&
+% Stores the smaller of \meta{num$_1$} and \meta{num$_2$} in \cs{macro}\\
+% \SpecialUsageIndex{\MFPmax}^^A
+% \cs{MFPmax}\mmarg{num$_1$}\mmarg{num$_2$}\cs{macro}&
+% Stores the larger of \meta{num$_1$} and \meta{num$_2$} in \cs{macro}
+% \end{tabular}}
+%
+%\bigskip
+%
+% \centerline{%
+% \begin{tabular}{lp{3.4in}}
+% \textit{Unary Operations}&\\[3pt]
+% \hline\hline
+% \textbf{Command}&\textbf{operation}\\
+% \hline
+% \SpecialUsageIndex{\MFPchs}^^A
+% \cs{MFPchs}\mmarg{num}\cs{macro}&
+% Stores $-{}$\meta{num} in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPabs}^^A
+% \cs{MFPabs}\mmarg{num}\cs{macro}&
+% Stores $|$\meta{num}$|$ in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPdbl}^^A
+% \cs{MFPdbl}\mmarg{num}\cs{macro}&
+% Stores 2\meta{num} in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPhalve}^^A
+% \cs{MFPhalve}\mmarg{num}\cs{macro}&
+% Stores \meta{num}/2, rounded to 8 places after the decimal point, in
+% \cs{macro}.\\
+% \SpecialUsageIndex{\MFPint}^^A
+% \cs{MFPint}\mmarg{num}\cs{macro}&
+% Replaces the part of \meta{num} after the decimal point with zeros
+% (keeps the sign unless the result is zero) and stores the result in
+% \cs{macro}.\\
+% \SpecialUsageIndex{\MFPfrac}^^A
+% \cs{MFPfrac}\mmarg{num}\cs{macro}&
+% Replaces the part of \meta{num} before the decimal point with zero
+% (keeps the sign unless the result is zero) and stores the result in
+% \cs{macro}.\\
+% \SpecialUsageIndex{\MFPfloor}^^A
+% \cs{MFPfloor}\mmarg{num}\cs{macro}&
+% Stores the largest integer not more than \meta{num} in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPceil}^^A
+% \cs{MFPceil}\mmarg{num}\cs{macro}&
+% Stores the smallest integer not less than \meta{num} in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPsgn}^^A
+% \cs{MFPsgn}\mmarg{num}\cs{macro}&
+% Stores $-1$, $0$ or $1$ (in standard form) in \cs{macro} according
+% to whether \meta{num} is negative, zero, or positive.\\
+% \SpecialUsageIndex{\MFPsq}^^A
+% \cs{MFPsq}\mmarg{num}\cs{macro}&
+% Stores the square of \meta{num} in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPinv}^^A
+% \cs{MFPinv}\mmarg{num}\cs{macro}&
+% Stores 1/\meta{num}, rounded to 8 places after the decimal point, in
+% \cs{macro}.\\
+% \SpecialUsageIndex{\MFPincr}^^A
+% \cs{MFPincr}\mmarg{num}\cs{macro}&
+% Stores \meta{num}${}+1$ in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPdecr}^^A
+% \cs{MFPdecr}\mmarg{num}\cs{macro}&
+% Stores \meta{num}${}-1$ in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPzero}^^A
+% \cs{MFPzero}\mmarg{num}\cs{macro}&
+% Ignores \meta{num} and stores {0.00000000} in the \cs{macro}.\\
+% \SpecialUsageIndex{\MFPstore}^^A
+% \cs{MFPstore}\mmarg{num}\cs{macro}&
+% Stores the \meta{num}, converted to standard form, in \cs{macro}
+% \end{tabular}}
+%
+%\bigskip
+%
+% The command \cs{MFPzero} is useful for ``macro programs''. If you want
+% to do something to a number depending on the outcome of a test, you may
+% occasionally want to simply absorbed the number and output a default
+% result. (There are more efficient ways to simply store 0 in a macro.)
+%
+% Note that one could easily double, halve, square, increment,
+% decrement or invert a \meta{num} using the binary versions of
+% \cs{MFPadd}, \cs{MFPsub}, \cs{MFPmul} or \cs{MFPdiv}. The commands
+% \cs{MFPdbl}, \cs{MFPhalve}, \cs{MFPsq}, \cs{MFPincr}, \cs{MFPdecr} and
+% \cs{MFPinv} are designed to be more efficient versions, since they are
+% used repeatedly in internal code.
+%
+% Also, multiplication is far more efficient than division, so even if you
+% use the two argument versions, \cs{MFPmul}\mmarg{num}\marg{.5} is faster than
+% \cs{MFPdiv}\mmarg{num}\marg{2}.
+%
+% There is one command that takes no argument:
+%
+% \medskip
+% \centerline{%
+% \begin{tabular}{lp{3.4in}}
+% \textit{Nullary Operations}&\\[3pt]
+% \hline\hline
+% \textbf{Command}&\textbf{operation}\\
+% \hline
+% \SpecialUsageIndex{\MFPnoop}^^A
+% \cs{MFPnoop}& Does nothing.
+% \end{tabular}}
+%
+% \bigskip
+% The following are not commands at all, but macros that contain
+% convenient constants.
+%
+% \medskip
+% \centerline{%
+% \begin{tabular}{lp{3.9in}}
+% \textit{Constants}&\\[3pt]
+% \hline\hline
+% \textbf{Constant}&\textbf{value}\\
+% \hline
+% \SpecialUsageIndex{\MFPpi}^^A
+% \cs{MFPpi}& \texttt{3.14159265}, the eight-digit approximation to
+% $\pi$.\\
+% \SpecialUsageIndex{\MFPe}^^A
+% \cs{MFPe}& \texttt{2.71828183}, the eight-digit approximation to
+% $e$.\\
+% \SpecialUsageIndex{\MFPphi}^^A
+% \cs{MFPphi}& \texttt{1.61803399}, the eight-digit approximation to
+% the golden ratio $\phi.$
+% \end{tabular}}
+%
+% \bigskip
+% There also exist commands to check the sign of a number and the
+% relative size of two numbers:
+%
+% \medskip
+% \indent \SpecialUsageIndex{\MFPchk}\cs{MFPchk}\mmarg{num}\\
+% \indent \SpecialUsageIndex{\MFPcmp}\cs{MFPcmp}\mmarg{num$_1$}\mmarg{num$_2$}
+%
+% \medskip
+% \noindent These influence the behavior of six commands:
+%
+% \medskip
+% \indent \SpecialUsageIndex{\IFneg}\cs{IFneg}\mmarg{true text}\mmarg{false text}\\
+% \indent \SpecialUsageIndex{\IFzero}\cs{IFzero}\mmarg{true text}\mmarg{false text}\\
+% \indent \SpecialUsageIndex{\IFpos}\cs{IFpos}\mmarg{true text}\mmarg{false text}\\
+% \indent \SpecialUsageIndex{\IFlt}\cs{IFlt}\mmarg{true text}\mmarg{false text}\\
+% \indent \SpecialUsageIndex{\IFeq}\cs{IFeq}\mmarg{true text}\mmarg{false text}\\
+% \indent \SpecialUsageIndex{\IFgt}\cs{IFgt}\mmarg{true text}\mmarg{false text}
+%
+% \medskip
+% Issuing \verb$\MFPchk{\X}$ will check the sign of the number stored in
+% the macro \cs{X}. Then \verb$\IFneg{A}{B}$ will produce `\verb$A$' if it
+% is negative and `\verb$B$' if it is 0 or positive. Similarly,
+% \verb$\MFPcmp{\X}{1}$ will compare the number stored in \cs{X} to $1$.
+% Afterward, \verb$\IFlt{A}{B}$ will produce `\verb$A$' if \cs{X} is less
+% than $1$ and `\verb$B$' if \cs{X} is equal to or greater than 1.
+%
+% If users finds it tiresome to type two separate commands, they can
+% easily define a single command that both checks a value and runs
+% \cs{IF...}. For example\\
+% \indent\verb$\def\IFisneg#1{\MFPchk{#1}\IFneg}$\\
+% Used like\\
+% \indent\verb$\IFisneg{\X}{A}{B}$\\
+% this will check the value of \cs{X} and run \cs{IFneg} on the pair of
+% alternatives that follow.
+%
+% The user might never need to use \cs{MFPchk} because every one of the
+% operators provided by the \mfp{} package runs an internal version of
+% \cs{MFPchk} on the result of the operation before storing it in the
+% \cs{macro}. For example, after \cs{MFPzero} the command \cs{IFzero} will
+% always return the first argument. For this reason one should not insert
+% any \mfp{} operations between a check/compare and the \cs{IF...} command
+% that depends on it.
+%
+% Note: the behavior of all six \cs{IF...} commands is influenced by
+% \emph{both} \cs{MFPchk} and \cs{MFPcmp}. This is because internally
+% \verb$\MFPchk{\X}$ (for example) and \verb$\MFPcmp{\X}{0}$ do
+% essentially the same thing. In fact there are only three internal
+% booleans that govern the behavior of the six \cs{IF...} commands. The
+% different names are for clarity: \cs{IFgt} after a compare is less
+% confusing than the entirely equivalent \cs{IFpos}.
+%
+% It should probably be pointed out that the settings for the \cs{IF...}
+% macros are local to any \TeX{} groups they are contained in.
+%
+%
+% \subsection{Commands to process numbers for printing}
+%
+% After \verb$\MFPadd{1}{2}\X$ one can use \cs{X} anywhere and get
+% $3.00000000$. One might may well prefer $3.0$, and so commands are
+% provided to truncate a number or round it to some number of decimal
+% places. Note: these are provided for printing and they will not invoke
+% the above \cs{MFPchk}. They do not have any stack-based versions.
+% The commands are\\
+% \indent\SpecialUsageIndex{\MFPtruncate}\cs{MFPtruncate}\mmarg{int}\mmarg{num}\cs{macro}\\
+% \indent\SpecialUsageIndex{\MFPround}\cs{MFPround}\mmarg{int}\mmarg{num}\cs{macro}\\
+% \indent\SpecialUsageIndex{\MFPstrip}\cs{MFPstrip}\mmarg{num}\cs{macro}\\
+% where \meta{int} is a whole number between $-8$ and $8$ (inclusive). The
+% other two arguments are as before.
+%
+% These commands merely process \meta{num} and define \cs{macro} to
+% produce a truncated or rounded version, or one stripped of trailing
+% zeros, or one with added trailing zeros. Note that truncating or
+% rounding a number to a number of digits greater than it already has will
+% actually lengthen it with added zeros. For example,
+% \verb$\MFPround{4}{3.14159}\X$
+% will cause \cs{X} to be defined to contain \texttt{3.1416}, while
+% \verb$\MFPround{6}{3.14159}\X$
+% will cause \cs{X} to contain \texttt{3.141590}.
+% If \cs{Y} contains \texttt{3.14159}, then
+% \verb$\MFPtruncate{4}\Y\Y$
+% will redefine \cs{Y} to contain \texttt{3.1415}. Also,
+% \verb$\MFPstrip{1.20000000}\Z$
+% will cause \cs{Z} to contain \texttt{1.2}. All these commands first
+% normalize the \meta{num}, so any spaces are removed and redundant signs
+% are discarded.
+%
+% If \meta{int} is negative, places are counted to the left of the decimal
+% point and $0$\,s are substituted for lower order digits. That is,
+% \verb$\MFPtruncate{-2}{1864.3}\X$
+% will give \cs{X} the value \texttt{1800} and
+% \verb$\MFPround{-2}{1864}\X$
+% will give \cs{X} the value \texttt{1900}.
+%
+% If the first argument of \cs{MFPround} or \cs{MFPtruncate} is zero or
+% negative then the dot is also omitted from the result. If \cs{MFPstrip} is
+% applied to a number with all zeros after the dot, then one 0 is
+% retained. There is a star form where the dot and the zero are dropped.
+%
+% For these three commands, the sign of the number is irrelevant. That
+% is, the results for negative numbers are the negatives of the results
+% for the absolute values. The processing will remove redundant signs
+% along with redundant leading zeros: \verb$\MFPtruncate{-3}{-+123.456}$
+% will produce \texttt{0}. The rounding rule is as follows: round up if
+% the digit to the right of the rounding point is 5 or more, round down if
+% the digit is 4 or less.
+%
+%
+% \subsection{Stack-based macros}\label{stack}
+%
+% The stack-based macros can only be used in a \mfp{} program group.
+% This group is started by the command \cs{startMFPprogram} and ended by
+% \cs{stopMFPprogram}. None of the stack-based macros takes an argument,
+% but merely operate on values on the stack, replacing them with the
+% results. There are also commands to manipulate the stack and save a
+% value on the stack into a macro. Finally, since all changes to the stack
+% (and to macros) are local and therefore lost after \cs{stopMFPprogram},
+% there are commands to selectively cause them to be retained.
+%
+% To place numbers on the stack we have \cs{Rpush} and to get them
+% off we have \cs{Rpop}. The syntax is\\
+% \indent \SpecialUsageIndex{\Rpush}\cs{Rpush}\marg{\meta{num}}\\
+% \indent \SpecialUsageIndex{\Rpop}\cs{Rpop}\cs{macro}\\
+% The first will preprocess the \meta{num} as previously discussed and
+% put it on the stack, the second will remove the last number from the stack
+% and define the given macro to have that number as its definition.
+%
+% All the binary operations remove the last two numbers from the stack,
+% operate on them in the order they were put on the stack, and push the
+% result on the stack. Thus the program
+% \begin{verbatim}
+% \Rpush{1.2}
+% \Rpush{3.4}
+% \Rsub \end{verbatim}
+% will first put \texttt{1.20000000} and \texttt{3.40000000} on the stack
+% and then replace them with \texttt{-2.20000000}. Note the order: $1.2-3.4$.
+%
+% \medskip
+% \centerline{%
+% \begin{tabular}{lp{4.0in}}
+% \multicolumn2{c}{\textit{Binary Operations}}\\
+% \hline\hline
+% \textbf{Command}&\textbf{operation}\\
+% \hline
+% \SpecialUsageIndex{\Radd}\cs{Radd}&
+% Adds the last two numbers on the stack.\\
+% \SpecialUsageIndex{\Rsub}\cs{Rsub}&
+% Subtracts the last two numbers on the stack.\\
+% \SpecialUsageIndex{\Rmul}\cs{Rmul}&
+% Multiplies the last two numbers on the stack, rounding to 8 decimal
+% places.\\
+% \SpecialUsageIndex{\Rmpy}\cs{Rmpy}&
+% Same as \cs{Rmul}.\\
+% \SpecialUsageIndex{\Rdiv}\cs{Rdiv}&
+% Divides the last two numbers on the stack, rounding to 8 decimal
+% places.\\
+% \SpecialUsageIndex{\Rmin}\cs{Rmin}&
+% Replaces the last two elements on the stack with the smaller one.\\
+% \SpecialUsageIndex{\Rmax}\cs{Rmax}&
+% Replaces the last two elements on the stack with the larger one.
+% \end{tabular}}
+%
+%\bigskip
+%
+% The unary operations replace the last number on the stack with the
+% result of the operation performed on it.
+%
+% \medskip
+% \centerline{%
+% \begin{tabular}{lp{4.0in}}
+% \multicolumn2{c}{\textit{Unary Operations}}\\
+% \hline\hline
+% \textbf{Command}&\textbf{operation}\\
+% \hline
+% \SpecialUsageIndex{\Rchs}\cs{Rchs}&
+% Changes the sign.\\
+% \SpecialUsageIndex{\Rabs}\cs{Rabs}&
+% Obtains the absolute value.\\
+% \SpecialUsageIndex{\Rdbl}\cs{Rdbl}&
+% Doubles the value.\\
+% \SpecialUsageIndex{\Rhalve}\cs{Rhalve}&
+% Halves the value, rounding to 8 places.\\
+% \SpecialUsageIndex{\Rint}\cs{Rint}&
+% Replaces the fractional part with zeros. If the result equals $0.0$, any
+% negative sign will be dropped.\\
+% \SpecialUsageIndex{\Rfrac}\cs{Rfrac}&
+% Replaces the integer part with \texttt{0}. If the result equals
+% $0.0$, any negative sign will be dropped.\\
+% \SpecialUsageIndex{\Rfloor}\cs{Rfloor}&
+% Obtains the largest integer not greater than the number.\\
+% \SpecialUsageIndex{\Rceil}\cs{Rceil}&
+% Obtains the smallest integer not less than the number.\\
+% \SpecialUsageIndex{\Rsgn}\cs{Rsgn}&
+% Obtains $-1$, $0$ or $1$ according to whether the number
+% is negative, zero, or positive. These numbers are pushed onto the
+% stack with the usual decimal point followed by 8 zeros.\\
+% \SpecialUsageIndex{\Rsq}\cs{Rsq}&
+% Obtains the square. Slightly more efficient than the equivalent
+% \cs{Rdup}\cs{Rmul}. See below for \cs{Rdup}.\\
+% \SpecialUsageIndex{\Rinv}\cs{Rinv}&
+% Obtains the reciprocal. Slightly more efficient than the equivalent
+% division.\\
+% \SpecialUsageIndex{\Rincr}\cs{Rincr}&
+% Increases by 1. Slightly more efficient than the equivalent
+% addition.\\
+% \SpecialUsageIndex{\Rdecr}\cs{Rdecr}&
+% Decreases by 1. Slightly more efficient than the equivalent
+% subtraction.\\
+% \SpecialUsageIndex{\Rzero}\cs{Rzero}&
+% Replaces the number with zero. Slightly more convenient than the
+% equivalent \cs{Rpop}\cs{X} followed by a \cs{Rpush}\marg{0}.\\
+% \end{tabular}}
+%
+%\bigskip
+%
+%
+% There is one nullary operation, which does not read the stack nor
+% change it.
+%
+% \medskip
+% \centerline{%
+% \begin{tabular}{lp{3.8in}}
+% \multicolumn2{c}{\textit{Nullary Operations}}\\
+% \hline\hline
+% \textbf{Command}&\textbf{operation}\\
+% \hline
+% \SpecialUsageIndex{\Rnoop}\cs{Rnoop}&
+% Does nothing.
+% \end{tabular}}
+%
+% \bigskip
+% There also exist commands to check the sign of the last number, and the
+% relative size of the last two numbers on the stack:\\
+% \indent \SpecialUsageIndex{\Rchk}\cs{Rchk}\\
+% \indent \SpecialUsageIndex{\Rcmp}\cs{Rcmp}\\
+% They do not remove anything from the stack.
+% Just like the nonstack counterparts, they influence the behavior of
+% six commands: \cs{IFneg}, \cs{IFzero}, \cs{IFpos}, \cs{IFlt},
+% \cs{IFeq} and \cs{IFgt}. Issuing \verb$\Rchk$ will check the sign of the
+% last number on the stack, while \verb$\Rcmp$ will compare the last two
+% in the order they were pushed. For example, in the following
+% \begin{verbatim}
+% \Rpush{1.3}
+% \Rpush{-2.3}
+% \Rcmp
+% \IFgt{\Radd}{\Rsub}
+% \Rpush\X
+% \Rchk
+% \IFneg{\Radd}{\Rsub} \end{verbatim}
+% \verb$\Rcmp$ will compare $1.3$ to $-2.3$. Since the first is greater
+% than the second, \verb$\IFgt$ will be true and they will be added,
+% producing $-1.0$. Following this the contents of the macro \cs{X} are
+% pushed, it is examined by \verb$\Rchk$ and then either added to or
+% subtracted from $-1.0$.
+%
+% The user might never need to use \cs{Rchk} because every operator that
+% puts something on the stack also runs \cs{Rchk}. In the above program,
+% in fact, \verb$\Rchk$ is redundant since \verb$\Rpush$ will already have
+% run it on the contents of \cs{X}.
+%
+% There exist stack manipulation commands that allow the contents of the
+% stack to be changed without performing any operations. These are really
+% just conveniences, as there effects could be obtained with appropriate
+% combinations of \verb$\Rpop$ and \verb$\Rpush$. These commands, however, do
+% not run \verb$\Rchk$ as \cs{Rpush} would.
+%
+% \medskip
+% \centerline{%
+% \begin{tabular}{lp{3.8in}}
+% \multicolumn2{c}{\textit{Stack Manipulations}}\\
+% \hline\hline
+% \textbf{Command}&\textbf{operation}\\
+% \hline
+% \SpecialUsageIndex{\Rdup}\cs{Rdup}&
+% Puts another copy of the last element of the stack onto the stack.\\
+% \SpecialUsageIndex{\Rexch}\cs{Rexch}&
+% Exchanges the last two elements on the stack.
+% \end{tabular}}
+%
+% \bigskip
+%
+% After \cs{stopMFPprogram}, any changes to macros or to the stack are
+% lost, unless arrangements have been made to save them. There are four
+% commands provided. Two act on a macro which is the only argument, the
+% other two have no arguments and act on the stack. The macro must
+% simply contain a value, it cannot be more complicated and certainly
+% cannot take an argument.
+%
+% \medskip
+% \centerline{%
+% \begin{tabular}{lp{3.8in}}
+% \multicolumn2{c}{\textit{Exporting changed values}}\\
+% \hline\hline
+% \textbf{Command}&\textbf{operation}\\
+% \hline
+% \SpecialUsageIndex{\Export}\cs{Export}\cs{macro}&
+% \raggedright
+% Causes the definition of \cs{macro} to survive the
+% program group.\tabularnewline
+% \SpecialUsageIndex{\Global}\cs{Global}\cs{macro}&
+% Causes the definition of \cs{macro} to be global.\\
+% \SpecialUsageIndex{\ExportStack}\cs{ExportStack}&
+% \raggedright
+% Causes the contents of the stack to survive the program
+% group.\tabularnewline
+% \SpecialUsageIndex{\GlobalStack}\cs{GlobalStack}&
+% Causes the contents of the stack to be global.\\
+% \end{tabular}}
+%
+% \bigskip
+% The difference between \cs{Export} and \cs{Global} is solely in how
+% \emph{other} grouping is handled. If the program group is contained in
+% another group (for example, inside an environment), then the result of
+% \cs{Global}\cs{X} is that the definition of \cs{X} survives that group
+% (and all containing groups) as well. On the other hand, after
+% \cs{Export}\cs{X}, then the definition survives the program group, but
+% not other containing groups.
+%
+% If \TeX{} grouping is used \emph{inside} a program group, then using
+% \cs{Export} inside that group has no effect at all, while \cs{Global}
+% works as before.
+%
+% The stack versions are implemented by running \cs{Export} or
+% \cs{Global} on the internal macro that defines the stack, so they
+% have the same behavior.
+%
+% \subsection{Errors}
+%
+% If one tries to pop from an empty stack, an error message will be
+% issued. Ignoring the error causes the macro to have the value stored
+% in the macro \SpecialUsageIndex{\EndofStack}\verb$\EndofStack$.
+% Its default is \texttt{0.00000000}.
+%
+% If one tries to divide by zero, an error message will be issued.
+% Ignoring the error causes the result to be one of the following:
+% \begin{itemize}
+% \item Dividing $0$ by $0$ gives a result whose integer part is stored
+% in \verb$\ZeroOverZeroInt$\SpecialUsageIndex{\ZeroOverZeroInt}
+% and whose fractional part is stored in
+% \SpecialUsageIndex{\ZeroOverZeroFrac}\verb$\ZeroOverZeroFrac$.
+% The default is \texttt{0.00000000}
+% \item Dividing a nonzero $x$ by $0$ gives a result whose integer part is
+% stored in \SpecialUsageIndex{\xOverZeroInt}\verb$\xOverZeroInt$
+% and whose fractional part is stored in
+% \SpecialUsageIndex{\xOverZeroFrac}\verb$\xOverZeroFrac$. The
+% defaults are both equal to \texttt{99999999}. The sign of the
+% result will be the sign of $x$.
+% \end{itemize}
+%
+% You can change any of these macros, but make sure they produce a
+% result which is a number in standard form (as described earlier).
+% These macros are copied directly into the result without checking.
+% Then further processing steps may require the result to be a number in
+% standard form.
+%
+% Error messages may result from trying to process numbers given in
+% incorrect format. However, there are so many ways for numbers to be
+% incorrect that this package does not even try to detect them. Thus, they
+% will only be caught if some \TeX{} operation encounters something it
+% cannot handle. (The \LaTeX{} manual calls these ``weird errors'' because
+% the messages tend to be uninformative.) Incorrect numbers may even
+% pass unnoticed, but leave random printed characters on the paper, or odd
+% spacing.
+%
+% \section{Implementation}
+%
+% \subsection{Utility macros}
+%
+% We announce ourself, and our purpose. We save the catcode of
+% \texttt{@} and change it to letter. Several other catcodes are saved
+% and set to other in this file. We also make provisions to load the
+% extra definitions, either directly with \cs{MFPloadextra} or through a
+% declared option in \LaTeX{}.
+% \begin{macrocode}
+%<*sty>
+\expandafter
+\ifx \csname MFP@finish\endcsname\relax
+\else \expandafter\endinput \fi
+\expandafter\edef\csname MFP@finish\endcsname{%
+ \catcode64=\the\catcode64 \space % @
+ \catcode46=\the\catcode46 \space % .
+ \catcode60=\the\catcode60 \space % <
+ \catcode62=\the\catcode62 \space}% >
+\ifx\ProvidesPackage\UndEfInEd
+ \newlinechar`\^^J%
+ \message{%
+ Package minifp: \MFPfiledate\space v\MFPfileversion. %
+ Macros for real number operations %
+ ^^Jand a stack-based programing language.^^J}%
+\else
+ \ProvidesPackage{minifp}[\MFPfiledate\space v\MFPfileversion. %
+ Macros for real number operations %
+ and a stack-based programing language.]%
+ \DeclareOption{extra}{\def\MFPextra{}}%
+ \ProcessOptions\relax
+\fi
+\catcode64=11 % @=letter (already is in LaTeX)
+\ifx\MFPextra\UndEfInEd
+ \def\MFP@loadextra{}%
+\else
+ \def\MFP@loadextra{\input mfpextra\relax}%
+\fi
+\def\MFPloadextra{%
+ \edef\MFP@load@extra{%
+ \catcode46=12 \catcode60=12 \catcode62=12 \catcode64=11
+ \noexpand\input mfpextra\relax
+ \catcode46=\the\catcode46\relax\catcode60=\the\catcode60\relax
+ \catcode62=\the\catcode62\relax\catcode64=\the\catcode64\relax}%
+ \MFP@load@extra}%
+\catcode46=12 % .
+\catcode60=12 % <
+\catcode62=12 % >
+% \end{macrocode}
+%
+% We check for \LaTeX{} (ignoring \LaTeX209); \cs{MFP@ifnoLaTeX}\dots\cs{mfp@end}
+% is skipped in LateX and executed otherwise.
+% \begin{macrocode}
+\long\def\gobbleto@mfp@end#1\mfp@end{}%
+\ifx\mfp@end\UndEfInEd\def\mfp@end{\@empty}\fi
+\ifx\documentclass\UndEfInEd
+ \def\MFP@ifnoLaTeX{}%
+\else
+ \let\MFP@ifnoLaTeX\gobbleto@mfp@end
+\fi
+% \end{macrocode}
+%
+% We have \LaTeX{}'s \cs{zap@space}. It pretty much \emph{must} be used
+% inside \cs{edef} or other purely expansion context. The rest of these
+% are standard \LaTeX{} internals. Note that the token list that
+% \cs{zap@space} is applied to should probably never contain braces or
+% expandable tokens.\\
+% \indent Usage: \verb*$\edef\X{\zap@space<tokens> \@empty}$\\
+% The space is necessary in case none exist; the \cs{@empty} terminates
+% the loop.
+% \begin{macrocode}
+\let\@xp\expandafter
+\def\@XP{\@xp\@xp\@xp}%
+\MFP@ifnoLaTeX
+ \def\@empty{}%
+ \long\def\@gobble#1{}%
+ \def\zap@space#1 #2{#1\ifx#2\@empty\else\@xp\zap@space\fi#2}%
+ \long\def\@ifnextchar#1#2#3{%
+ \let\reserved@d#1%
+ \def\reserved@a{#2}%
+ \def\reserved@b{#3}%
+ \futurelet\@let@token\@ifnch}%
+ \def\@ifnch{%
+ \ifx\@let@token\@sptoken
+ \let\reserved@c\@xifnch
+ \else
+ \ifx\@let@token\reserved@d
+ \let\reserved@c\reserved@a
+ \else
+ \let\reserved@c\reserved@b
+ \fi
+ \fi
+ \reserved@c}%
+ {%
+ \def\:{\global\let\@sptoken= }\: %
+ \def\:{\@xifnch}\@xp\gdef\: {\futurelet\@let@token\@ifnch}%
+ }%
+ \def\@ifstar#1{\@ifnextchar*{\@firstoftwo{#1}}}%
+ \long\def\@firstofone #1{#1}%
+ \long\def\@firstoftwo #1#2{#1}%
+ \long\def\@secondoftwo#1#2{#2}%
+\mfp@end
+% \end{macrocode}
+%
+% We need to divide by both $10^4$ and $10^8$ several times. I could
+% have allocated two count registers, but have taken the approach of only
+% using those for intermediate calculations.
+% \begin{macrocode}
+\def\MFP@tttfour {10000}% ttt = Ten To The
+\def\MFP@ttteight{100000000}%
+% \end{macrocode}
+%
+% These are for manipulating digits. The \verb$\...ofmany$ commands
+% require a sequence of arguments (brace groups or tokens) followed by
+% \verb$\mfp@end$. The minimum number of required parameters is surely
+% obvious. For example, \cs{MFP@ninthofmany} must be used like\\
+% \indent\cs{MFP@ninthofmany}\meta{9 or more arguments}\cs{mfp@end}
+% All these are fully expandable.
+% \begin{macrocode}
+\def\MFP@firstofmany#1#2\mfp@end{#1}%
+\def\MFP@fifthofmany#1#2#3#4#5#6\mfp@end{#5}%
+\def\MFP@ninthofmany#1#2#3#4#5#6#7#8{\MFP@firstofmany}%
+\def\MFP@firsteightofmany#1#2#3#4#5#6#7#8#9\mfp@end{#1#2#3#4#5#6#7#8}%
+% \end{macrocode}
+%
+% \subsection{Processing numbers and the stack}
+%
+% Our stack stores elements in groups, like \\
+% \indent \verb${-1.234567890}{0.00001234}\MFP@eos$\\
+% with an end marker. The purpose of the marker is to prevent certain
+% parameter manipulations from stripping off braces. This means we can't
+% use \cs{@empty} to test for an empty stack. At the moment, only
+% \cs{Rpop} actually checks, but all other stack commands (so far) use
+% \cs{Rpop} to get their arguments.
+% \begin{macrocode}
+\let\MFP@eos\relax
+\def\MFP@EOS{\MFP@eos}%
+\def\MFP@initRstack{\def\MFP@Rstack{\MFP@eos}}%
+\MFP@initRstack
+% \end{macrocode}
+%
+% Define some scratch registers for arithmetic operations. We don't care
+% that these might be already in use, as we only use them inside a group.
+% However, we need one counter that will not be messed with by any of
+% our operations. I must be sure not to use commands that change
+% \cs{MFP@loopctr} in code that depends on it.
+% \begin{macrocode}
+\countdef \MFP@tempa 0
+\countdef \MFP@tempb 2
+\countdef \MFP@tempc 4
+\countdef \MFP@tempd 6
+\countdef \MFP@tempe 8
+\countdef \MFP@tempf 10
+\newcount \MFP@loopctr
+% \end{macrocode}
+%
+% The following can only be used where unrestricted expansion is robust.
+% It will allow results obtained inside a group to survive the group,
+% but not be unrestrictedly global.
+% Example: the code\\
+% \indent \verb$\MFP@endgroup@after{\def\noexpand\MFP@z@Val{\MFP@z@Val}}$\\
+% becomes\\
+% \indent \verb$\edef\x{\endgroup\def\noexpand\MFP@z@Val{\MFP@z@Val}}\x$\\
+% which gives, upon expansion of \verb$\x$,\\
+% \indent
+% \cs{endgroup}\cs{def}\cs{MFP@z@Val}\marg{\meta{expansion-of-\cs{MFP@z@Val}}}\\
+% which defines \cs{MFP@z@Val} outside the current group to equal its expansion
+% within the current group, provided it was started with \cs{begingroup}.
+%
+% We define a \cs{MFP@returned@values} to make all the conceivable produced
+% values survive the group. The \cs{MFPcurr@Sgn} part is to permit testing
+% the sign of the result and allow conditional code based on it.
+%
+% I have been lax at making sure \cs{MFP@z@Ovr} is properly initiallized
+% and properly checked whenever it could be relevant, and properly
+% passed on. I think every internal command \cs{MFP@R}\textit{xxx}
+% should ensure it starts being 0 and ends with a numerical value. I
+% notice that division might make it empty.
+%
+% \cs{MFP@subroutine} executes its argument (typically a single command) with
+% a wrapper that initializes all the macros that might need initializing,
+% and returns the necessary results.
+% \begin{macrocode}
+\def\MFP@endgroup@after#1{\edef\x{\endgroup#1}\x}%
+\def\MFP@endgroup@return{\MFP@endgroup@after\MFP@returned@values}%
+\def\MFP@def@after{\def\noexpand}%
+\def\MFP@returned@values{%
+ \MFP@def@after\MFP@z@Val{\MFP@z@Sign\MFP@z@Int.\MFP@z@Frc}%
+ \MFP@def@after\MFP@z@Ovr{\MFP@z@Ovr}%
+ \MFP@def@after\MFP@z@Und{\MFP@z@Und}%
+ \MFP@def@after\MFPcurr@Sgn{\MFP@z@Sgn}}%
+\def\MFP@subroutine#1{%
+ \begingroup
+ \MFP@basic@init@z
+ #1%
+ \MFP@endgroup@return}%
+\def\MFP@basic@init@z{%
+ \MFP@Rzero
+ \def\MFP@z@Ovr{0}%
+ \def\MFP@z@Und{0}}%
+\def\MFP@Rzero{%
+ \def\MFP@z@Sgn{0}%
+ \def\MFP@z@Int{0}%
+ \def\MFP@z@Frc{00000000}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\EndofStack}
+% We define here the error messages: popping from an empty stack and
+% dividing by zero. In addition to the error messages, we provide some
+% default values that hopefully allow some operations to continue.
+%
+% We also have a warning or two.
+% \begin{macrocode}
+\def\MFP@errmsg#1#2{%
+\begingroup
+ \newlinechar`\^^J\let~\space
+ \def\MFP@msgbreak{^^J~~~~~~~~~~~~~~}%
+ \edef\reserved@a{\errhelp{#2}}\reserved@a
+ \errmessage{MiniFP error: #1}%
+\endgroup}%
+\def\MFP@popempty@err{%
+ \MFP@errmsg{cannot pop from an empty stack}%
+ {There were no items on the stack for the POP operation. %
+ If you continue, ^^Jthe macro will contain the %
+ value \EndofStack.}}%
+\def\EndofStack{0.00000000}%
+\def\MFP@dividebyzero@err{%
+ \MFP@errmsg{division by zero}%
+ {You tried to divide by zero. What were you thinking? %
+ If you continue, ^^Jthe value assigned will be either %
+ \ZeroOverZeroInt.\ZeroOverZeroFrac~(numerator=0) or %
+ ^^J+/-\xOverZeroInt.\xOverZeroFrac~(numerator<>0).}}%
+\def\MFP@warn#1{%
+\begingroup
+ \newlinechar`\^^J\let~\space
+ \def\MFP@msgbreak{^^J~~~~~~~~~~~~~~~~}%
+ \immediate\write16{^^JMiniFP warning: #1.^^J}%
+\endgroup}%
+% \end{macrocode}
+%
+% \DescribeMacro{\MaxRealInt}These are the largest possible integer and
+% fractional parts of a real
+% \DescribeMacro{\MaxRealFrac}number. They are returned for division by
+% zero, for logarithm of 0, and when overflow is detected in the
+% exponential function.
+% \begin{macrocode}
+\def\MaxRealInt {99999999}%
+\def\MaxRealFrac {99999999}%
+% \end{macrocode}
+%
+% \SpecialUsageIndex{\MaxRealInt}
+% \SpecialUsageIndex{\MaxRealFrac}
+% These are the results returned when trying to divide by zero. Two are
+% \DescribeMacro{\xOverZeroInt}
+% \DescribeMacro{\xOverZeroFrac}
+% used when dividing a nonzero number by zero and and two when trying to
+% divide zero by zero.
+% \DescribeMacro{\ZeroOverZeroInt}
+% \DescribeMacro{\ZeroOverZeroFrac}
+% \begin{macrocode}
+\def\xOverZeroInt {\MaxRealInt}%
+\def\xOverZeroFrac {\MaxRealFrac}%
+\def\ZeroOverZeroInt {0}%
+\def\ZeroOverZeroFrac{00000000}%
+% \end{macrocode}
+%
+% These macros strip the spaces, process a number into sign, integer and
+% fractional parts, and pad the fractional part out to 8 decimals. They
+% are used in PUSH so that the stack will only contains reals in a
+% normalized form. Some of them are also used to preprocess the reals in
+% the operand versions of commands
+%
+% The \cs{MFP@*@Int} and \cs{MFP@*@Frc} parts are always positive, the sign being
+% stored in \cs{MFP@*@Sgn} as $-1$, $0$ or $1$.
+%
+% We strip the spaces and pad the fractional parts separately because
+% they are unnecessary when processing POPed reals (though they wouldn't
+% hurt).
+%
+% The number to be parsed is \arg4 and the macros to contain the parts
+% are the first three arguments. Since we normally call \cs{MFPparse@real}
+% with one of two sets of macros, we have two shortcuts for those cases.
+% \begin{macrocode}
+\def\MFPparse@real#1#2#3#4{%
+ \MFPnospace@def\MFPtemp@Val{#4}%
+ \MFPprocess@into@parts\MFPtemp@Val#1#2#3%
+ \MFPpadto@eight#3}%
+\def\MFPparse@x{\MFPparse@real\MFP@x@Sgn\MFP@x@Int\MFP@x@Frc}%
+\def\MFPparse@y{\MFPparse@real\MFP@y@Sgn\MFP@y@Int\MFP@y@Frc}%
+% \end{macrocode}
+%
+% This macro strips all spaces out of the number (not just before and
+% after). It takes a macro that will hold the result, followed by the
+% number (as a macro or a group of actual digits).
+% \begin{macrocode}
+\def\MFPnospace@def#1#2{%
+ \edef#1{#2\space}\edef#1{\@xp\zap@space#1\@empty}}%
+% \end{macrocode}
+%
+% This is the process that splits a number into parts. The biggest
+% difficulty is obtaining the sign. All four arguments are macros, with
+% the first one holding the number. Following that are the macros to hold
+% the sign, integer and fractional parts.
+% \begin{macrocode}
+\def\MFPprocess@into@parts#1#2#3#4{%
+ \@xp\MFPsplit@dot#1..\mfp@end #3#4%
+% \end{macrocode}
+%
+% This is the first place where having at most 8 digits simplifies things.
+% At this point \arg3 could contain any number of consecutive signs
+% followed by any 8 digits. It could be zero, so to avoid losing the sign
+% we append a \texttt{1} (for up to 9 digits). We temporarily define the
+% sign based on the result, but may need to drop it if both the integer
+% and fractional parts are zero.
+%
+% Prepending a zero to the fractional part pemits it to be empty.
+% In the final \cs{edef}, \arg3 is made positive.
+% \begin{macrocode}
+ \ifnum#31<0
+ \def#2{-1}%
+ \else
+ \def#2{1}%
+ \fi
+ \ifnum #30=0
+ \def#3{0}%
+ \ifnum 0#4=0
+ \def#2{0}%
+ \fi
+ \fi
+ \edef#3{\number \ifnum #2<0 -\fi#3}}%
+% \end{macrocode}
+%
+% This only copies the parts before and after the dot, \arg1 and \arg2,
+% into macros \arg4 and \arg5.
+% \begin{macrocode}
+\def\MFPsplit@dot#1.#2.#3\mfp@end#4#5{\edef#4{#1}\edef#5{#2}}%
+% \end{macrocode}
+%
+% This is used to pad the fractional part to eight places with zeros. If
+% a number with more than 8 digits survives to this point, it gets
+% truncated.
+% \begin{macrocode}
+\def\MFPpadto@eight#1{%
+ \edef#1{\@xp\MFP@firsteightofmany#100000000\mfp@end}}%
+% \end{macrocode}
+%
+% These take operands off the stack. We know already that there are no
+% spaces and that the fractional part has 8 digits.
+% \begin{macrocode}
+\def\MFPgetoperand@x{\Rpop\MFP@x@Val
+ \MFPprocess@into@parts\MFP@x@Val\MFP@x@Sgn\MFP@x@Int\MFP@x@Frc}%
+\def\MFPgetoperand@y{\Rpop\MFP@y@Val
+ \MFPprocess@into@parts\MFP@y@Val\MFP@y@Sgn\MFP@y@Int\MFP@y@Frc}%
+% \end{macrocode}
+%
+% Concatenate an argument (or two) to the front of stack. The material
+% must already be in correct format.
+% \begin{macrocode}
+\def\MFP@Rcat#1{\edef\MFP@Rstack{{#1}\MFP@Rstack}}%
+\def\MFP@Rcattwo#1#2{\edef\MFP@Rstack{{#1}{#2}\MFP@Rstack}}%
+% \end{macrocode}
+%
+% Convert from a signum (a number) to a sign ($-$ or nothing):
+% \begin{macrocode}
+\def\MFP@Sign#1{\ifnum#1<0 -\fi}%
+\def\MFP@x@Sign{\MFP@Sign\MFP@x@Sgn}%
+\def\MFP@y@Sign{\MFP@Sign\MFP@y@Sgn}%
+\def\MFP@z@Sign{\MFP@Sign\MFP@z@Sgn}%
+% \end{macrocode}
+%
+% Sometimes only parts of the number needs changing (used in CHS, ABS).
+% \begin{macrocode}
+\def\copyMFP@x{\edef\MFP@z@Int{\MFP@x@Int}\edef\MFP@z@Frc{\MFP@x@Frc}}%
+% \end{macrocode}
+%
+% We use \cs{MFPpush@result} to put the result of internal operations onto
+% the stack. For convenience, we also have it set the sign flags.
+% \begin{macrocode}
+\def\MFPpush@result{\MFP@Rchk\MFPcurr@Sgn\MFP@Rcat\MFP@z@Val}%
+% \end{macrocode}
+%
+% When POP encounters an empty stack it gobbles the code that would
+% perform the pop (\arg1) and defines the macro (\arg2) to contain
+% \cs{EndofStack}. The default meaning for this macro is $0$.
+% \begin{macrocode}
+\def\if@EndofStack{%
+ \ifx\MFP@EOS\MFP@Rstack
+ \@xp\@firstoftwo
+ \else
+ \@xp\@secondoftwo
+ \fi}%
+% \end{macrocode}
+%
+% The macro \cs{Rpop} calls \cs{MFP@popit} followed by the contents of the
+% stack, the token \cs{mfp@end} and the macro to pop into. If the stack is
+% not empty, \cs{doMFP@popit} will read the first group \arg1 into that macro
+% \arg3, and then redefine the stack to be the rest of the argument \arg2.
+% If the stack is empty, \cs{doMFP@EOS} will equate the macro to
+% \cs{EndofStack} (initialized to {\tt0.00000000}) after issuing an error
+% message.
+% \begin{macrocode}
+\def\MFP@popit{\if@EndofStack\doMFP@EOS\doMFP@popit}%
+\def\doMFP@EOS#1\mfp@end#2{\MFP@popempty@err\let#2\EndofStack}%
+\def\doMFP@popit#1#2\mfp@end#3{\edef\MFP@Rstack{#2}\edef#3{#1}}%
+% \end{macrocode}
+%
+% \subsection{The user-level operations}
+%
+% All operations that can be done on arguments as well as the stack will
+% have a common format: The stack version pops the requisite numbers and
+% splits them into internal macros (\cs{MFPgetoperand@*}), runs an internal
+% command that operates on these internal macros, then ``pushes'' the result
+% returned. The internal commands take care to return the result in proper
+% form so we don't actually run \cs{Rpush}, but only \cs{MFPpush@result}.
+%
+% The operand version processes the operands into normalized form (as if
+% pushed, using \cs{MFPparse@*}), then proceeds as in the stack version, but
+% copies the result into the named macro instead of to the stack
+% (\cs{MFPstore@result}).
+%
+% For unary operations we process one argument or stack element. We call
+% it $x$ and use the \texttt{x} version of all macros. All internal
+% commands (\arg1) return the results in \texttt{z} versions.
+%
+% \DescribeMacro{\MFPchk}
+% The \cs{MFPchk} command examines its argument and sets a flag according to
+% its sign.
+% \begin{macrocode}
+\def\MFPchk#1{%
+ \MFPparse@x{#1}%
+ \MFP@Rchk\MFP@x@Sgn}%
+% \end{macrocode}
+%
+% We make \cs{MFP@Rchk} a little more general than is strictly needed here,
+% by giving it an argument (instead of only examining \cs{MFP@x@Sgn}). This is
+% so we can apply it to the results of operations (which would be in
+% \cs{MFPcurr@Sgn}).
+% \begin{macrocode}
+\def\MFP@Rchk#1{%
+ \MFPclear@flags
+ \ifnum#1>0 \MFP@postrue
+ \else\ifnum#1<0 \MFP@negtrue
+ \else \MFP@zerotrue
+ \fi\fi}%
+\def\MFPclear@flags{\MFP@zerofalse \MFP@negfalse \MFP@posfalse}%
+% \end{macrocode}
+%
+% \DescribeMacro{\IFzero}
+% \DescribeMacro{\IFneg}
+% \DescribeMacro{\IFpos}
+% These are the user interface to the internal \cs{ifMFP@zero},
+% \cs{ifMFP@neg}, \cs{ifMFP@pos}
+% \begin{macrocode}
+\def\IFzero{\ifMFP@zero\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+\def\IFneg {\ifMFP@neg \@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+\def\IFpos {\ifMFP@pos \@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+\newif\ifMFP@zero \newif\ifMFP@neg \newif\ifMFP@pos
+% \end{macrocode}
+%
+% Our comparison commands parallel the check-sign commands. They even
+% \DescribeMacro{\MFPcmp}
+% reuse the same internal booleans. The differences: the internal
+% \DescribeMacro{\IFeq}
+% \cs{MFP@Rcmp} doesn't take arguments and the comparison test is a little
+% \DescribeMacro{\IFlt}
+% more involved. We could simply subtract, which automatically sets the
+% \DescribeMacro{\IFgt}
+% internal booleans, but it is way more efficient to compare sizes
+% directly.
+% \begin{macrocode}
+\newif\ifMFPdebug
+\def\MFPcmp#1#2{\MFPparse@x{#1}\MFPparse@y{#2}\MFP@Rcmp}%
+\def\MFP@Rcmp{\MFPclear@flags
+ \ifnum \MFP@x@Sign\MFP@x@Int>\MFP@y@Sign\MFP@y@Int\relax
+ \MFP@postrue
+ \else\ifnum \MFP@x@Sign\MFP@x@Int<\MFP@y@Sign\MFP@y@Int\relax
+ \MFP@negtrue
+ \else\ifnum \MFP@x@Sign\MFP@x@Frc>\MFP@y@Sign\MFP@y@Frc\relax
+ \MFP@postrue
+ \else\ifnum \MFP@x@Sign\MFP@x@Frc<\MFP@y@Sign\MFP@y@Frc\relax
+ \MFP@negtrue
+ \else
+ \MFP@zerotrue
+ \fi\fi\fi\fi}%
+\let\IFeq\IFzero\let\IFlt\IFneg \let\IFgt\IFpos
+% \end{macrocode}
+%
+% Given an operation (\op{pop}, \op{chs}, or whatever), the stack version will
+% have the same name with ``\texttt{R}'' (for ``real'') prepended. The operand
+% versions will have the same name with ``\texttt{MFP}'' prepended. The
+% internal version has the same name as the stack version, with an
+% ``\texttt{MFP@}'' prepended.
+%
+% The unary operations are:
+% \begin{description}
+% \item[chs] change sign of $x$.
+% \item[abs] absolute value of $x$.
+% \item[dbl] double $x$.
+% \item[halve] halve $x$.
+% \item[sgn] $+1$, $-1$ or $0$ depending on the sign of $x$.
+% \item[sq] square $x$.
+% \item[int] zero out the fractional part of $x$.
+% \item[frac] zero out the integer part of $x$.
+% \item[floor] largest integer not exceeding $x$.
+% \item[ceil] smallest integer not less than $x$.
+% \end{description}
+%
+% The binary operations are ($x$ represents the first and $y$ second):
+% \begin{description}
+% \item[add] add $x$ and $y$.
+% \item[sub] subtract $y$ from $x$.
+% \item[mul] multiply $x$ and $y$.
+% \item[div] divide $x$ by $y$.
+% \end{description}
+%
+% There are also some operations that do not actually change any
+% values, but may change the stack or the state of some boolean:
+% \begin{description}
+% \item[cmp] compare $x$ and $y$ (stack version does not change stack).
+% \item[chk] examine the sign of $x$ (stack version does not change stack).
+% \item[dup] stack only, duplicate the top element of the stack.
+% \item[push] stack only, push a value onto the stack.
+% \item[pop] stack only, remove the top element of the stack,
+% store it in a variable.
+% \item[exch] stack only, exchange top two elements of the stack.
+% \end{description}
+%
+% \DescribeMacro{\startMFPprogram}
+% The purpose of \cs{startMFPprogram} is to start the group, inside of
+% which all the stack operations can be used. The ensuing
+% \DescribeMacro{\stopMFPprogram}
+% \cs{stopMFPprogram} closes the group.
+% \begin{macrocode}
+\def\startMFPprogram{%
+\begingroup
+% \end{macrocode}
+%
+% \DescribeMacro{\Rchs}
+% \DescribeMacro{\Rabs}
+% \DescribeMacro{\Rdbl}
+% \DescribeMacro{\Rhalve}
+% \DescribeMacro{\Rsgn}
+% Then we give definitions to all the stack-based macros.
+% These definitions are all lost after the group ends.
+%
+% \DescribeMacro{\Rsq}
+% \DescribeMacro{\Rinv}
+% \DescribeMacro{\Rint}
+% \DescribeMacro{\Rfrac}
+% \DescribeMacro{\Rfloor}
+% \DescribeMacro{\Rceil}
+% \DescribeMacro{\Rincr}
+% \DescribeMacro{\Rdecr}
+% \DescribeMacro{\Rzero}
+% We start with the unary operations. Note that all they do is call a
+% wrapper macro \cs{MFP@stack@Unary} with an argument which is the internal
+% version of the command.
+% \begin{macrocode}
+ \def\Rchs {\MFP@stack@Unary\MFP@Rchs}%
+ \def\Rabs {\MFP@stack@Unary\MFP@Rabs}%
+ \def\Rdbl {\MFP@stack@Unary\MFP@Rdbl}%
+ \def\Rhalve{\MFP@stack@Unary\MFP@Rhalve}%
+ \def\Rsgn {\MFP@stack@Unary\MFP@Rsgn}%
+ \def\Rsq {\MFP@stack@Unary\MFP@Rsq}%
+ \def\Rinv {\MFP@stack@Unary\MFP@Rinv}%
+ \def\Rint {\MFP@stack@Unary\MFP@Rint}%
+ \def\Rfrac {\MFP@stack@Unary\MFP@Rfrac}%
+ \def\Rfloor{\MFP@stack@Unary\MFP@Rfloor}%
+ \def\Rceil {\MFP@stack@Unary\MFP@Rceil}%
+ \def\Rincr {\MFP@stack@Unary\MFP@Rincr}%
+ \def\Rdecr {\MFP@stack@Unary\MFP@Rdecr}%
+ \def\Rzero {\MFP@stack@Unary\MFP@Rzero}%
+% \end{macrocode}
+%
+% \DescribeMacro{\Radd}
+% \DescribeMacro{\Rsub}
+% \DescribeMacro{\Rmul}
+% \DescribeMacro{\Rmpy}
+% \DescribeMacro{\Rdiv}
+% \DescribeMacro{\Rmin}
+% \DescribeMacro{\Rmax}
+% Then the binary operations, which again call a wrapper around
+% the internal version.
+% \begin{macrocode}
+ \def\Radd {\MFP@stack@Binary\MFP@Radd}%
+ \def\Rmul {\MFP@stack@Binary\MFP@Rmul}%
+ \let\Rmpy\Rmul
+ \def\Rsub {\MFP@stack@Binary\MFP@Rsub}%
+ \def\Rdiv {\MFP@stack@Binary\MFP@Rdiv}%
+ \def\Rmin {\MFP@stack@Binary\MFP@Rmin}%
+ \def\Rmax {\MFP@stack@Binary\MFP@Rmax}%
+% \end{macrocode}
+%
+% \DescribeMacro{\Rnoop}
+% \DescribeMacro{\Rcmp}
+% \DescribeMacro{\Rchk}
+% \DescribeMacro{\Rpush}
+% \DescribeMacro{\Rpop}
+% \DescribeMacro{\Rexch}
+% \DescribeMacro{\Rdup}
+% And finally some special commands. There is a no-op and commands for
+% comparing, checking, and manipulation of the stack.
+% \begin{macrocode}
+ \let\Rnoop\relax
+ \def\Rcmp{%
+ \MFPgetoperand@y\MFPgetoperand@x % get operands (last pushed is y)
+ \MFP@Rcat\MFP@x@Val\MFP@Rcat\MFP@y@Val % put back: LOFI
+ \MFP@Rcmp}%
+ \def\Rchk{%
+ \MFPgetoperand@x
+ \MFP@Rcat\MFP@x@Val
+ \MFP@Rchk\MFP@x@Sgn}%
+ \def\Rpush##1{%
+ \MFPparse@x{##1}%
+ \edef\MFP@z@Val{\MFP@x@Sign\MFP@x@Int.\MFP@x@Frc}%
+ \edef\MFPcurr@Sgn{\MFP@x@Sgn}%
+ \MFPpush@result}%
+ \def\Rpop{\@xp\MFP@popit\MFP@Rstack\mfp@end}%
+ \def\Rexch{%
+ \Rpop\MFP@x@Val\Rpop\MFP@y@Val
+ \MFP@Rcattwo\MFP@y@Val\MFP@x@Val}%
+ \def\Rdup{%
+ \Rpop\MFP@x@Val
+ \MFP@Rcattwo\MFP@x@Val\MFP@x@Val}%
+% \end{macrocode}
+%
+% If \file{mfpextra.tex} is input, then \cs{MFP@Rextra} makes the
+% additional commands in that file available to an \mfp{} program.
+%
+% \DescribeMacro{\Global}
+% \DescribeMacro{\GlobalStack}
+% \DescribeMacro{\Export}
+% \DescribeMacro{\ExportStack}
+% The last four commands allow computed values to be made available
+% outside the program group
+% \begin{macrocode}
+ \MFP@Rextra
+ \let\Global\MFP@Global
+ \let\GlobalStack\MFP@GlobalStack
+ \let\Export\MFP@Export
+ \let\ExportStack\MFP@ExportStack}%
+\def\stopMFPprogram{\@xp\endgroup\MFPprogram@returns}%
+\let\MFP@Rextra\@empty
+\let\MFPprogram@returns\@empty
+% \end{macrocode}
+%
+% \DescribeMacro{\MFPchs}
+% \DescribeMacro{\MFPabs}
+% \DescribeMacro{\MFPdbl}
+% \DescribeMacro{\MFPhalve}
+% \DescribeMacro{\MFPsgn}
+% \DescribeMacro{\MFPsq}
+% \DescribeMacro{\MFPinv}
+% Now we define the operand versions. These also are defined via a
+% wrapper command that executes the very same internal commands as the
+% stack versions.
+%
+% \DescribeMacro{\MFPint}
+% \DescribeMacro{\MFPfrac}
+% \DescribeMacro{\MFPfloor}
+% \DescribeMacro{\MFPceil}
+% \DescribeMacro{\MFPincr}
+% \DescribeMacro{\MFPdecr}
+% \DescribeMacro{\MFPzero}
+% \DescribeMacro{\MFPstore}
+% First the unary operations.
+% \begin{macrocode}
+\def\MFPchs {\MFP@op@Unary\MFP@Rchs}%
+\def\MFPabs {\MFP@op@Unary\MFP@Rabs}%
+\def\MFPdbl {\MFP@op@Unary\MFP@Rdbl}%
+\def\MFPhalve{\MFP@op@Unary\MFP@Rhalve}%
+\def\MFPsgn {\MFP@op@Unary\MFP@Rsgn}%
+\def\MFPsq {\MFP@op@Unary\MFP@Rsq}%
+\def\MFPinv {\MFP@op@Unary\MFP@Rinv}%
+\def\MFPint {\MFP@op@Unary\MFP@Rint}%
+\def\MFPfrac {\MFP@op@Unary\MFP@Rfrac}%
+\def\MFPfloor{\MFP@op@Unary\MFP@Rfloor}%
+\def\MFPceil {\MFP@op@Unary\MFP@Rceil}%
+\def\MFPincr {\MFP@op@Unary\MFP@Rincr}%
+\def\MFPdecr {\MFP@op@Unary\MFP@Rdecr}%
+\def\MFPzero {\MFP@op@Unary\MFP@Rzero}%
+\def\MFPstore{\MFP@op@Unary\MFP@Rstore}%
+% \end{macrocode}
+%
+% \DescribeMacro{\MFPadd}
+% \DescribeMacro{\MFPsub}
+% \DescribeMacro{\MFPmul}
+% \DescribeMacro{\MFPmpy}
+% \DescribeMacro{\MFPdiv}
+% \DescribeMacro{\MFPmin}
+% \DescribeMacro{\MFPmax}
+% Then the binary operations.
+% \begin{macrocode}
+\def\MFPadd{\MFP@op@Binary\MFP@Radd}%
+\def\MFPmul{\MFP@op@Binary\MFP@Rmul}%
+\let\MFPmpy\MFPmul
+\def\MFPsub{\MFP@op@Binary\MFP@Rsub}%
+\def\MFPdiv{\MFP@op@Binary\MFP@Rdiv}%
+\def\MFPmin{\MFP@op@Binary\MFP@Rmin}%
+\def\MFPmax{\MFP@op@Binary\MFP@Rmax}%
+% \end{macrocode}
+%
+% These are the wrappers for unary operations. The operand versions have a
+% second argument, the macro that stores the result. But this will be the
+% argument of \cs{MFPstore@result}.
+% \begin{macrocode}
+\def\MFP@stack@Unary#1{%
+ \MFPgetoperand@x
+ \MFP@subroutine{#1}\MFPpush@result}%
+\def\MFP@op@Unary#1#2{%
+ \MFPparse@x{#2}%
+ \MFP@subroutine{#1}\MFPstore@result}%
+\def\MFPstore@result#1{\MFP@Rchk\MFPcurr@Sgn\edef#1{\MFP@z@Val}}%
+% \end{macrocode}
+%
+% These are the wrappers for binary operations. The top level definitions
+% are almost identical to those of the unary operations. The only difference
+% is they pop or parse two operands.
+% \begin{macrocode}
+\def\MFP@stack@Binary#1{%
+ \MFPgetoperand@y \MFPgetoperand@x
+ \MFP@subroutine{#1}\MFPpush@result}%
+\def\MFP@op@Binary#1#2#3{%
+ \MFPparse@x{#2}\MFPparse@y{#3}%
+ \MFP@subroutine{#1}\MFPstore@result}%
+% \end{macrocode}
+%
+% \DescribeMacro{\MFPnoop}
+% We end with a traditional, but generally useless command, the no-op,
+% which does nothing. It doesn't even have a wrapper.
+% \begin{macrocode}
+\let\MFPnoop\relax
+% \end{macrocode}
+%
+% \subsection{The internal computations}
+%
+% To change the sign or get the absolute value, we just need to set the
+% value of \cs{MFP@x@Sgn}.
+% \begin{macrocode}
+\def\MFP@Rabs{%
+ \copyMFP@x \edef\MFP@z@Sgn{\ifnum\MFP@x@Sgn=0 0\else1\fi}}%
+\def\MFP@Rchs{\copyMFP@x \edef\MFP@z@Sgn{\number-\MFP@x@Sgn}}%
+% \end{macrocode}
+%
+% The doubling and halving operations are more efficient ways to
+% multiply or divide a number by 2. For doubling, copy $x$ to $y$
+% and add. For halving, we use basic \TeX{} integer division, more
+% efficient than multiplying by $0.5$ and far more than using
+% \cs{MFP@Rdiv}.
+%
+% In \cs{MFP@Rhalve}. we add 1 to the fractional part for rounding
+% purposes, and we move any odd 1 from the end of the integer part to the
+% start of the fractional part.
+% \begin{macrocode}
+\def\MFP@Rdbl{\MFP@Rcopy xy\MFP@Radd}%
+\def\MFP@Rhalve{%
+ \MFP@tempa\MFP@x@Int
+ \MFP@tempb\MFP@x@Frc\relax
+ \ifodd\MFP@tempb
+ \def\MFP@z@Und{5}%
+ \advance\MFP@tempb 1 % round up
+ \ifnum\MFP@ttteight=\MFP@tempb
+ \MFP@tempb0 \advance\MFP@tempa1
+ \fi
+ \fi
+ \ifodd \MFP@tempa
+ \advance\MFP@tempb \MFP@ttteight\relax
+ \fi
+ \divide\MFP@tempa 2
+ \divide\MFP@tempb 2
+ \MFP@Rloadz\MFP@x@Sgn\MFP@tempa\MFP@tempb}%
+% \end{macrocode}
+%
+% The signum is $0.0$, $1.0$ or $-1.0$ to match the sign of $x$.
+% \begin{macrocode}
+\def\MFP@Rsgn{\MFP@Rloadz \MFP@x@Sgn{\ifnum\MFP@x@Sgn=0 0\else1\fi}0}%
+% \end{macrocode}
+%
+% The squaring operation just calls \cs{MFP@Rmul} after copying $x$ to
+% $y$.
+% \begin{macrocode}
+\def\MFP@Rsq{\MFP@Rcopy xy\MFP@Rmul}%
+% \end{macrocode}
+%
+% The inversion operation just calls \cs{MFP@Rdiv} after copying $x$ to
+% $y$ and 1 to $x$.
+% \begin{macrocode}
+\def\MFP@Rinv{\MFP@Rcopy xy\MFP@Rload x110\MFP@Rdiv}%
+% \end{macrocode}
+%
+% Integer part: replace fractional part with zeros.
+% \begin{macrocode}
+\def\MFP@Rint{%
+ \MFP@Rloadz {\ifnum\MFP@x@Int=0 0\else\MFP@x@Sgn\fi}\MFP@x@Int 0}%
+% \end{macrocode}
+%
+% Fractional part: replace integer part with a zero.
+% \begin{macrocode}
+\def\MFP@Rfrac{%
+ \MFP@Rloadz {\ifnum\MFP@x@Frc=0 0\else\MFP@x@Sgn\fi}0\MFP@x@Frc}%
+% \end{macrocode}
+%
+% To increment and decrement by 1, except in border cases, we need only
+% address the integer part of a number. This doesn't seem so simple
+% written out but, even so, it is more efficient than full-blown addition.
+% It would be very slightly more efficient to repeat the increment code in
+% decrementing, but it would be annoying to do so,
+% \begin{macrocode}
+\def\MFP@Rincr{%
+ \ifnum\MFP@x@Sgn<0
+ \ifcase\MFP@x@Int
+ \MFP@tempa\MFP@ttteight
+ \advance\MFP@tempa -\MFP@x@Frc\relax
+ \MFP@Rloadz 10\MFP@tempa
+ \or
+ \MFP@Rloadz{\ifnum\MFP@x@Frc=0 0\else -1\fi}0\MFP@x@Frc
+ \else
+ \MFP@tempa\MFP@x@Int
+ \advance\MFP@tempa -1
+ \MFP@Rloadz{-1}\MFP@tempa\MFP@x@Frc
+ \fi
+ \else
+ \MFP@tempa\MFP@x@Int
+ \advance\MFP@tempa 1
+ \MFP@Rloadz 1\MFP@tempa\MFP@x@Frc
+ \fi}%
+\def\MFP@Rdecr{%
+ \edef\MFP@x@Sgn{\number -\MFP@x@Sgn}\MFP@Rincr
+ \edef\MFP@z@Sgn{\number -\MFP@z@Sgn}}%
+\def\MFP@Rstore{\MFP@Rcopy xz}%
+% \end{macrocode}
+%
+% The floor of a real number $x$ is the largest integer not larger than
+% $x$. The ceiling is the smallest integer not less than $x$. For
+% positive $x$, floor is the same as integer part. Not true for negative
+% $x$. Example: $\mathop{\mathrm{int}}(-1.5) = -1$ but
+% $\mathop{\mathrm{floor}}=-2$
+%
+% We use the same code to get floor or ceiling, the
+% appropriate inequality character being its argument.
+% \begin{macrocode}
+\def\MFP@Rfloororceil#1{%
+ \MFP@tempa\MFP@x@Int\relax
+ \ifnum 0#1\MFP@x@Sgn
+ \ifnum\MFP@x@Frc=0
+ \else
+ \advance\MFP@tempa1
+ \fi
+ \fi
+ \MFP@Rloadz{\ifnum\MFP@z@Int=0 0\else\MFP@x@Sgn\fi}\MFP@tempa0}%
+\def\MFP@Rfloor{\MFP@Rfloororceil>}%
+\def\MFP@Rceil {\MFP@Rfloororceil<}%
+% \end{macrocode}
+%
+% For multiplication, after the usual break into integer and fractional
+% parts, we further split these parts into $4$-digit pieces with
+% \cs{MFP@split}. The first argument (\arg1) holds the eight digit number,
+% then \arg2 is a macro that will hold the top four digits and \arg3 will
+% hold the bottom four.
+% \begin{macrocode}
+\def\MFP@split#1#2#3{%
+ \begingroup
+ \MFP@tempa#1\relax
+ \MFP@tempb\MFP@tempa
+ \divide\MFP@tempb by\MFP@tttfour
+ \edef#2{\number\MFP@tempb}%
+ \multiply\MFP@tempb by\MFP@tttfour
+ \advance\MFP@tempa-\MFP@tempb
+ \MFP@endgroup@after{%
+ \MFP@def@after#2{#2}%
+ \MFP@def@after#3{\number\MFP@tempa}%
+ }}%
+%
+\def\MFP@x@split{%
+ \MFP@split\MFP@x@Int\MFP@x@Int@ii\MFP@x@Int@i
+ \MFP@split\MFP@x@Frc\MFP@x@Frc@i\MFP@x@Frc@ii}%
+\def\MFP@y@split{%
+ \MFP@split\MFP@y@Int\MFP@y@Int@ii\MFP@y@Int@i
+ \MFP@split\MFP@y@Frc\MFP@y@Frc@i\MFP@y@Frc@ii}%
+% \end{macrocode}
+%
+% We will store the intermediate and final products in \cs{MFP@z@*}. Each one
+% is ultimately reduced to 4 digits, like the parts of $x$ and $y$. As each
+% base-$10000$ digit of $y$ is multiplied by a digit of $x$, we add the
+% result to the appropriate digit of the partial result $z$. Thus, we need
+% to zero out $z$ at the start (or treat the first iteration differently):
+%
+% The underflow ends up in \cs{MFP@z@Frc@iv} and \cs{MFP@z@Frc@iii}.
+% Overflow will be in \cs{MFP@z@Int@iii}. Unlike the rest, it can be up to
+% 8 digits because we do not need to carry results out of it.
+% \begin{macrocode}
+\def\MFPmore@init@z{%
+ \def\MFP@z@Frc@iv {0}%
+ \def\MFP@z@Frc@iii{0}%
+ \def\MFP@z@Frc@ii {0}%
+ \def\MFP@z@Frc@i {0}%
+ \def\MFP@z@Int@i {0}%
+ \def\MFP@z@Int@ii {0}%
+ \def\MFP@z@Int@iii{0}}%
+% \end{macrocode}
+%
+% This command prepends zeros so a number fills four slots. In the
+% ``make'' version, \arg1 is a macro holding the value and is redefined to
+% contain the result. A macro that calls these should ensure that \arg1 is
+% not empty and is less than 10,000.
+% \begin{macrocode}
+\def\MFP@fourdigits#1{%
+ \@xp\MFP@fifthofmany\number#1{}{0}{00}{000}\mfp@end\number#1}%
+\def\makeMFP@fourdigits#1{\edef#1{\MFP@fourdigits{#1}}}%
+% \end{macrocode}
+%
+% This is the same, but produce eight digits.
+% \begin{macrocode}
+\def\MFP@eightdigits#1{%
+ \@xp\MFP@ninthofmany\number#1%
+ {}{0}{00}{000}{0000}{00000}{000000}{0000000}\mfp@end\number#1}%
+\def\makeMFP@eightdigits#1{\edef#1{\MFP@eightdigits{#1}}}%
+% \end{macrocode}
+%
+% The following macros implement carrying. The macros \cs{MFP@carrya} and
+% \cs{MFP@carrym} should be followed by two macros that hold numbers. The
+% first number can have too many digits. These macros remove extra digits
+% from the front and add their value to the number in the second macro
+% (the ``carry''). Both act by calling \cs{MFP@carry}, which is told the
+% number of digits to keep via \arg1 (10,000 for four digits,
+% 100,000,000 for eight). The ``\texttt{a}'' in \cs{MFP@carrya} is for
+% addition and ``\texttt{m}'' is for multiplication, which indicates where
+% these will mainly be used.
+% \begin{macrocode}
+\def\MFP@carrya{\MFP@carry\MFP@ttteight}%
+\def\MFP@carrym{\MFP@carry\MFP@tttfour}%
+\def\MFP@carry#1#2#3{%
+ \begingroup
+ \MFP@carryi{#1}#2#3%
+ \MFP@endgroup@after{%
+ \MFP@def@after#3{\number\MFP@tempa}%
+ \MFP@def@after#2{\number\MFP@tempb}%
+ }}%
+% \end{macrocode}
+%
+% This is the ``internal'' carry. \arg1, \arg2, and \arg3 are as in
+% \cs{MFP@carry}. Its advantage is that it can be used used where \arg2 and
+% \arg3 are not macros, leaving the result in \cs{MFP@tempa} and \cs{MFP@tempb}
+% with \cs{MFP@tempb} in the correct range, $[0,\mbox{\arg1})$. Its
+% disadvantage is it does not protect temporary registers. Warning:
+% never use it in the form \cs{MFP@carryi}\meta{num}\cs{MFP@tempa},
+% because this would copy \meta{num} to \cs{MFP@tempa}, losing the value
+% in the second argument before anything can be done. The other order is
+% okay, and \cs{MFP@tempb} can be used in either slot. Do not use it
+% without grouping if you want the values in the temp registers \texttt{a},
+% \texttt{b} or \texttt{c} preserved.
+% \begin{macrocode}
+\def\MFP@carryi#1#2#3{%
+ \MFP@tempa=#3\relax
+ \MFP@tempb=#2\relax
+ \MFP@tempc=\MFP@tempb
+ \divide \MFP@tempc #1\relax
+ \advance \MFP@tempa \MFP@tempc
+ \multiply\MFP@tempc #1\relax
+ \advance \MFP@tempb -\MFP@tempc}%
+% \end{macrocode}
+%
+% This adds \arg1 to \arg2, the result goes into macro \arg3. This does no
+% checking. It is basicly used to add with macros instead of registers.
+% \begin{macrocode}
+\def\MFP@addone#1#2#3{%
+ \begingroup
+ \MFP@tempa#1%
+ \advance\MFP@tempa#2\relax
+ \MFP@endgroup@after{%
+ \MFP@def@after#3{\number\MFP@tempa}%
+ }}%
+% \end{macrocode}
+%
+% Multiply \arg1 by \cs{MFP@tempb} and add to \arg2. \cs{MFP@tempb} is one digit
+% (base=10000) of $y$ in multiplying $x\times y$, \arg1 (usually a macro)
+% holds one digit of $x$. \arg2 is a macro that will hold one digit of the
+% final product $z$. The product is added to it (overflow is taken care of
+% later by the carry routines).
+% \begin{macrocode}
+\def\MFP@multiplyone#1#2{%
+ \MFP@tempa#1%
+ \multiply\MFP@tempa\MFP@tempb
+ \advance\MFP@tempa#2%
+ \edef#2{\number\MFP@tempa}}%
+% \end{macrocode}
+%
+% This does the above multiplication-addition for all four ``digits'' of
+% $x$. This is where \cs{MFP@tempb} is initialized for \cs{MFP@multiplyone}. The
+% first argument represents a digit of $y$, the remaining four arguments
+% are macros representing the digits of $z$ that are involved in
+% multiplying the digits of $x$ by \arg1.
+% \begin{macrocode}
+\def\MFP@multiplyfour#1#2#3#4#5{%
+ \MFP@tempb #1\relax
+ \MFP@multiplyone\MFP@x@Int@ii #2%
+ \MFP@multiplyone\MFP@x@Int@i #3%
+ \MFP@multiplyone\MFP@x@Frc@i #4%
+ \MFP@multiplyone\MFP@x@Frc@ii #5}%
+% \end{macrocode}
+%
+% Now we begin the internal implementations of the binary operations. All
+% four expect macros \cs{MFP@x@Sgn}, \cs{MFP@x@Int}, \cs{MFP@x@Frc}, \cs{MFP@y@Sgn},
+% \cs{MFP@y@Int} and \cs{MFP@y@Frc} to be the normalized parts of two real numbers
+% $x$ and $y$.
+%
+% \cs{MFP@Rsub} just changes the sign of $y$ and then calls \cs{MFP@Radd}.
+%
+% \cs{MFP@Radd} checks whether $x$ and $y$ have same or different signs. In
+% the first case we need only add absolute values and the sign of the
+% result will match that of the operands. In the second case, finding the
+% sign of the result is a little more involve (and ``borrowing'' may be
+% needed).
+% \begin{macrocode}
+\def\MFP@Rsub{\edef\MFP@y@Sgn{\number-\MFP@y@Sgn}\MFP@Radd}%
+\def\MFP@Radd{%
+ \MFP@tempa\MFP@x@Sgn
+ \multiply\MFP@tempa\MFP@y@Sgn\relax
+ \ifcase\MFP@tempa
+ \ifnum \MFP@x@Sgn=0
+ \MFP@Rcopy yz%
+ \else
+ \MFP@Rcopy xz%
+ \fi
+ \or
+ \@xp\MFP@Radd@same
+ \else
+ \@xp\MFP@Radd@diff
+ \fi}%
+% \end{macrocode}
+%
+% \cs{MFP@Radd@same} adds two numbers which have the same sign. The sign
+% of the result is the common sign. The fractional and integer parts are
+% added separately, then a carry is invoked. The overflow (\cs{MFP@z@Ovr})
+% could be only a single digit 0 or 1.
+% \begin{macrocode}
+\def\MFP@Radd@same{%
+ \MFP@addone\MFP@x@Frc\MFP@y@Frc\MFP@z@Frc
+ \MFP@addone\MFP@x@Int\MFP@y@Int\MFP@z@Int
+ \MFP@carrya\MFP@z@Frc\MFP@z@Int
+ \MFP@carrya\MFP@z@Int\MFP@z@Ovr
+ \makeMFP@eightdigits\MFP@z@Frc
+ \edef\MFP@z@Sgn{\MFP@x@Sgn}}%
+% \end{macrocode}
+%
+% We are now adding two numbers with opposite sign. Since $x\ne 0$ this
+% is the same as $\sgn(x)(|x| - |y|)$ . So we subtract absolute values,
+% save the result in \cs{MFP@z@Sgn}, \cs{MFP@z@Int} and \cs{MFP@z@Frc}
+% (with the last two nonnegative, as usual), then change the sign of
+% \cs{MFP@z@Sgn} if \cs{MFP@x@Sgn} is negative. Since the difference
+% between numbers in $[0,10^8)$ has absolute value in that range, there is
+% no carrying. However, there may be borrowing.
+% \begin{macrocode}
+\def\MFP@Radd@diff{%
+ \MFP@addone\MFP@x@Frc{-\MFP@y@Frc}\MFP@z@Frc
+ \MFP@addone\MFP@x@Int{-\MFP@y@Int}\MFP@z@Int
+% \end{macrocode}
+%
+% Now we need to establish the sign and arrange the borrow. The sign of
+% the result is the sign of \cs{MFP@z@Int} unless it is 0; in that case
+% it, is the sign of \cs{MFP@z@Frc}. There must be a simpler coding,
+% though.
+% \begin{macrocode}
+ \MFP@tempa=\MFP@z@Int
+ \MFP@tempb=\MFP@z@Frc\relax
+ \ifnum\MFP@tempa=0 \else \MFP@tempa=\MFP@Sign\MFP@tempa 1 \fi
+ \ifnum\MFP@tempb=0 \else \MFP@tempb=\MFP@Sign\MFP@tempb 1 \fi
+ \ifnum\MFP@tempa=0 \MFP@tempa=\MFP@tempb \fi
+% \end{macrocode}
+%
+% Now we have the sign of $|x| - |y|$ in \cs{MFP@tempa}, and we multiply
+% that sign by the sign of $x$ to get \cs{MFP@z@Sgn}. Then we multiply the
+% current value of $z$ by that sign to get the absolute value, stored in
+% \cs{MFP@tempa} and \cs{MFP@tempb}.
+% \begin{macrocode}
+ \edef\MFP@z@Sgn{\number\MFP@x@Sign\MFP@tempa}%
+ \MFP@tempb\MFP@tempa
+ \multiply\MFP@tempa \MFP@z@Int
+ \multiply\MFP@tempb \MFP@z@Frc\relax
+% \end{macrocode}
+%
+% What we should have now is a positive number which might still be
+% represented with a negative fractional part. A human being performing
+% the subtraction would have borrowed first. Being a computer, we do it
+% last, and we're done.
+% \begin{macrocode}
+ \ifnum\MFP@tempb<0
+ \advance\MFP@tempb\MFP@ttteight
+ \advance\MFP@tempa-1
+ \fi
+ \edef\MFP@z@Int{\number\MFP@tempa}%
+ \edef\MFP@z@Frc{\number\MFP@tempb}%
+ \makeMFP@eightdigits\MFP@z@Frc}%
+% \end{macrocode}
+%
+% \cs{MFP@Rmul} first computes the (theoretical) sign of the product: if
+% zero return 0, otherwise provisionally set the sign of the product and
+% call \cs{MFP@@Rmul}.
+% \begin{macrocode}
+\def\MFP@Rmul{%
+ \MFP@tempa\MFP@x@Sgn \multiply\MFP@tempa\MFP@y@Sgn\relax
+ \ifnum 0=\MFP@tempa
+ \MFP@Rzero
+ \else
+ \edef\MFP@z@Sgn{\number\MFP@tempa}%
+ \@xp\MFP@@Rmul
+ \fi}%
+% \end{macrocode}
+%
+% \cs{MFP@@Rmul} splits the four expected macros into eight macros
+% considered to be four base-10000 digits for each of $x$ and $y$.
+% Then each digit of $y$ is used to multiply the 4 digits of $x$ and the
+% results are added to corresponding digits of $z$, which have been
+% initialized to 0 by \cs{MFPmore@init@z}.
+% \begin{macrocode}
+\def\MFP@@Rmul{%
+ \MFPmore@init@z
+ \MFP@x@split\MFP@y@split
+ \MFP@multiplyfour \MFP@y@Frc@ii \MFP@z@Frc@i
+ \MFP@z@Frc@ii \MFP@z@Frc@iii\MFP@z@Frc@iv
+ \MFP@multiplyfour \MFP@y@Frc@i \MFP@z@Int@i
+ \MFP@z@Frc@i \MFP@z@Frc@ii \MFP@z@Frc@iii
+ \MFP@multiplyfour \MFP@y@Int@i \MFP@z@Int@ii
+ \MFP@z@Int@i \MFP@z@Frc@i \MFP@z@Frc@ii
+ \MFP@multiplyfour \MFP@y@Int@ii \MFP@z@Int@iii
+ \MFP@z@Int@ii \MFP@z@Int@i \MFP@z@Frc@i
+% \end{macrocode}
+% Now apply the carry routines on the underflow digits\dots
+% \begin{macrocode}
+ \MFP@carrym\MFP@z@Frc@iv\MFP@z@Frc@iii
+ \MFP@carrym\MFP@z@Frc@iii\MFP@z@Frc@ii
+% \end{macrocode}
+% \dots pause to round the lowest digit that will be kept\dots
+% \begin{macrocode}
+ \ifnum\MFP@z@Frc@iii<5000 \else
+ \MFP@tempb\MFP@z@Frc@ii
+ \advance\MFP@tempb1
+ \edef\MFP@z@Frc@ii{\number\MFP@tempb}%
+ \fi
+% \end{macrocode}
+% \dots and continue carrying.
+% \begin{macrocode}
+ \MFP@carrym\MFP@z@Frc@ii\MFP@z@Frc@i
+ \MFP@carrym\MFP@z@Frc@i \MFP@z@Int@i
+ \MFP@carrym\MFP@z@Int@i \MFP@z@Int@ii
+ \MFP@carrym\MFP@z@Int@ii\MFP@z@Int@iii
+% \end{macrocode}
+% To end, we arrange for all macros to hold 4 digits (except
+% \cs{MFP@z@Int@ii} which doesn't need leading 0s, and \cs{MFP@z@Int@iii}
+% which also doesn't) and load them into the appropriate 8-digit macros.
+% The underflow digits are stored in \cs{MFP@z@Und} in case we ever need
+% to examine them, and the overflow in \cs{MFP@z@Ovr} in case we ever need
+% to implement an overflow error. Theoretically $z \ne 0$, but it is
+% possible that $z=0$ after rounding to 8 places. If so, we must reset
+% \cs{MFP@z@Sgn}.
+% \begin{macrocode}
+ \makeMFP@fourdigits\MFP@z@Frc@iv
+ \makeMFP@fourdigits\MFP@z@Frc@iii
+ \makeMFP@fourdigits\MFP@z@Frc@ii
+ \makeMFP@fourdigits\MFP@z@Frc@i
+ \makeMFP@fourdigits\MFP@z@Int@i
+ \edef\MFP@z@Int{\number\MFP@z@Int@ii\MFP@z@Int@i}%
+ \edef\MFP@z@Frc{\MFP@z@Frc@i\MFP@z@Frc@ii}%
+ \edef\MFP@z@Ovr{\number\MFP@z@Int@iii}%
+ \edef\MFP@z@Und{\MFP@z@Frc@iii\MFP@z@Frc@iv}%
+ \ifnum\MFP@z@Int>0
+ \else\ifnum\MFP@z@Frc>0
+ \else
+ \def\MFP@z@Sgn{0}%
+ \fi\fi}%
+% \end{macrocode}
+%
+% For division, we will obtain the result one digit at a time until the
+% $9$th digit after the decimal is found. That $9$th will be used to round
+% to eight digits (and stored as underflow). We normalize the denominator
+% by shifting left until the integer part is 8 digits. We do the same for
+% the numerator. The integer quotient of the integer parts will be 1 digit
+% (possibly 0). If the denominator is shifted $d$ digits left and the
+% numerator $n$ digits left, the quotient will have to be shifted $n-d$
+% places right or $d-n$ places left. Since the result is supposed to have
+% $9$ digits after the dot, our quotient needs $9+d-n+1$ total digits.
+% Since $d$ can be as high as $15$ and $n$ as low as $0$, we could need
+% $25$ repetitions. However, that extreme would put $15$ or $16$ digits in
+% the integer part, a $7$ or $8$ digit overflow. (It can be argued that
+% only $16$ significant digits should be retained in any case.) If $d$ is
+% $0$ and $n$ is $15$ we would need $-5$ digits. That means the first
+% nonzero digit is in the 15th or 16th place after the dot and the
+% quotient is effectively 0.
+%
+% Here I explain why we normalize the parts in this way. If a numerator
+% has the form $n_1.n_2$ and the denominator has the form $d_1.d_2$ then
+% TeX can easily obtain the integer part of $n_1/d_1$, because these are
+% within its range for integers. The resulting quotient (let's call it
+% $q_1$) is the largest integer satisfying $q_1d_1 \le n_1$. What we seek,
+% however is the largest integer $q$ such that $q(d_1.d_2) \le n_1.n_2$.
+% It can easily be shown that $q \le q_1$. It is true, but not so easily
+% shown, that $q \ge q_1 - 1$. This is only true if $d_1$ is large enough,
+% in our case it has to be at least 5 digits. Thus we only have to do one
+% simple division and decide if we need to reduce the quotient by one. If
+% we arrange for $d_1$ to have 8 digits, then $q_1$ will be one digit and
+% the test for whether we need to reduce it becomes easier.
+%
+% This test is done as follows. The first trial quotient, $q_1$, will work
+% if
+% \[
+% q_1 d_1 (10)^8 + q_1 d_2 \le n_1 (10)^8 + n_2
+% \]
+% This means
+% \begin{equation}\label{crucial}
+% 0 \le (n_1 - q_1 d_1) (10)^8 + n_2 - q_1 d_2 .
+% \end{equation}
+% Since $d_2$ is no more than eight digits, $q_1 d_2$ is less than $9
+% (10)^8$. Inequality (\ref{crucial}) is therefore satisfied if $n_1 - q_1
+% d_1 \ge 9$. If that is not the case then the right side of
+% (\ref{crucial}) is computable within TeX's integer ranges and we can
+% easily test the inequality. If the inequality holds, then $q = q_1$,
+% otherwise $q = q_1 - 1$.
+%
+% Note also that when $q = q_1$, then both terms in (\ref{crucial})
+% (ignoring the $10^8$ factor) will be needed to calculate the remainder.
+% If $q = q_1 - 1$, we simply add $d_1$ and $d_2$ to the respective parts.
+% Thus we will save these values for that use.
+%
+% Now I need to get it organized. \cs{MFP@Rdiv} will have \cs{MFP@x@*} and
+% \cs{MFP@y@*} available. One step (could be first or last). Is to calculate
+% the sign. Let's do it first (because we need to check for 0 anyway).
+%
+% We invoke an error message upon division by 0, but nevertheless return
+% a value. By default they are $0$ for $0/0$ and the maximum possible real
+% for $x/0$ when $x$ is not zero. If the numerator is 0 and the
+% denominator not, we do nothing as $z$ was initialized to be 0.
+%
+% If neither is 0, we calculate the sign of the result and call
+% \cs{MFP@@Rdiv} to divide the absolute values.
+% \begin{macrocode}
+\def\MFP@Rdiv{%
+ \ifnum\MFP@y@Sgn=0
+ \MFP@dividebyzero@err
+ \ifnum\MFP@x@Sgn=0
+ \edef\MFP@z@Int{\ZeroOverZeroInt}%
+ \edef\MFP@z@Frc{\ZeroOverZeroFrac}%
+ \else
+ \edef\MFP@z@Int{\xOverZeroInt}%
+ \edef\MFP@z@Frc{\xOverZeroFrac}%
+ \fi
+ \edef\MFP@z@Sgn{\MFP@x@Sgn}%
+ \else\ifnum\MFP@x@Sgn=0
+ \MFP@Rzero
+ \else
+ \MFP@tempa\MFP@x@Sgn
+ \multiply\MFP@tempa\MFP@y@Sgn
+ \edef\MFP@z@Sgn{\number\MFP@tempa}%
+ \MFP@@Rdiv
+ \fi\fi}%
+% \end{macrocode}
+%
+% Now we have two positive values to divide. Our first step is to shift
+% the denominator ($y$) left and keep track of how many places. We store
+% the shift in \cs{MFP@tempa}. This actually changes the value of $y$,
+% but knowing the shift will give us the correct quotient in the end.
+%
+% We first arrange that \cs{MFP@y@Int} is nonzero by making it \cs{MFP@y@Frc} if
+% it is zero (a shift of eight digits). Then the macro
+% \cs{MFP@numdigits@toshift} computes $8$ minus the number of digits in
+% \cs{MFP@y@Int}, which is how many positions left $y$ will be shifted.
+% We then call \cs{MFP@doshift@y} on the concatenation of the digits in
+% the integer and fractional parts (padded with zeros to ensure there are
+% at least 16). All this macro does is read the first eight digits into
+% \cs{MFP@y@Int} and the next eight into \cs{MFP@y@Frc}.
+% \begin{macrocode}
+\def\MFP@@Rdiv{%
+ \ifnum\MFP@y@Int=0
+ \edef\MFP@y@Int{\number\MFP@y@Frc}%
+ \def\MFP@y@Frc{00000000}%
+ \MFP@tempa=8
+ \else
+ \MFP@tempa=0
+ \fi
+ \advance\MFP@tempa\MFP@numdigits@toshift\MFP@y@Int\relax
+ \@XP\MFP@doshift@y\@xp\MFP@y@Int\MFP@y@Frc0000000\mfp@end
+% \end{macrocode}
+%
+% We repeat all that on the numerator $x$, except shifting its digits
+% left means the final outcome will need a corresponding \emph{right}
+% shift. We record that fact by reducing \cs{MFP@tempa}, which ends up
+% holding the net shift necesary.
+%
+% This has the advantage that we know the result will be in the range
+% $[0.1, 10)$. It also means we can reduce the number of places we will
+% need to shift left as well as reduce the number of iterations of the
+% loop that calculates the digits.
+% \begin{macrocode}
+ \ifnum\MFP@x@Int=0
+ \edef\MFP@x@Int{\number\MFP@x@Frc}%
+ \def\MFP@x@Frc{00000000}%
+ \advance\MFP@tempa -8
+ \fi
+ \advance\MFP@tempa-\MFP@numdigits@toshift\MFP@x@Int\relax
+ \@XP\MFP@doshift@x\@xp\MFP@x@Int\MFP@x@Frc0000000\mfp@end
+% \end{macrocode}
+%
+% Since our result will have at most one digit in the integer part, a
+% rightward shift of $10$ places will make every digit $0$, including the
+% rounding digit, so we do nothing (returning $0$).
+% \begin{macrocode}
+ \ifnum\MFP@tempa<-9
+ \else
+% \end{macrocode}
+%
+% Now we perform the division, which is a loop repeated $10 +
+% {}$\cs{MFP@tempa} times. Therefore, we add 10 to \cs{MFP@tempa} in
+% \cs{MFP@tempf}, our loop counter. We also initialize the macro that
+% will store the digits and then, after the division, shift and split it
+% into parts.
+% \begin{macrocode}
+ \MFP@tempf\MFP@tempa
+ \advance\MFP@tempf 10
+ \def\MFP@z@digits{}%
+ \MFP@Rdivloop
+ \MFPshiftandsplit@z@digits
+% \end{macrocode}
+%
+% The last remaining step is to round and carry and get the fractional
+% part in the appropriate 8-digit form..
+% \begin{macrocode}
+ \ifnum\MFP@z@Und>4
+ \MFP@addone\MFP@z@Frc1\MFP@z@Frc
+ \MFP@carrya\MFP@z@Frc\MFP@z@Int
+ \MFP@carrya\MFP@z@Int\MFP@z@Ovr
+ \makeMFP@eightdigits\MFP@z@Frc
+ \fi
+ \fi}%
+% \end{macrocode}
+%
+% If \arg1 of \cs{MFP@numdigits@toshift}, has $n$ digits then
+% \cs{MFP@numdigits@toshift} picks out the value $8-n$. \cs{MFP@doshift@x}
+% reads the first eight digits into \cs{MFP@x@Int} and then pulls out 8 more
+% from the rest (\arg9) inside \cs{MFP@x@Frc}. The same with
+% \cs{MFP@doshift@y}.
+% \begin{macrocode}
+\def\MFP@numdigits@toshift#1{\@xp\MFP@ninthofmany#101234567\mfp@end}%
+\def\MFP@doshift@x#1#2#3#4#5#6#7#8#9\mfp@end{%
+ \def\MFP@x@Int{#1#2#3#4#5#6#7#8}%
+ \edef\MFP@x@Frc{\MFP@firsteightofmany#9\mfp@end}}%
+\def\MFP@doshift@y#1#2#3#4#5#6#7#8#9\mfp@end{%
+ \def \MFP@y@Int{#1#2#3#4#5#6#7#8}%
+ \edef\MFP@y@Frc{\MFP@firsteightofmany#9\mfp@end}}%
+% \end{macrocode}
+%
+% The loop counter is \cs{MFP@tempf}, \cs{MFP@tempa} is reserved for the
+% shift required later, the quotient digit will be \cs{MFP@tempb}. The
+% remainder will be calculated in \cs{MFP@tempc} and \cs{MFP@tempd}.
+% \cs{MFP@tempe} will hold the value whose size determines whether the
+% quotient needs to be reduced.
+% \begin{macrocode}
+\def\MFP@Rdivloop{%
+ \MFP@tempb\MFP@x@Int % \MFP@tempb = n_1
+ \MFP@tempc\MFP@y@Int % \MFP@tempc = d_1
+ \divide\MFP@tempb \MFP@tempc % \MFP@tempb = n_1/d_1 = q_1
+ \multiply \MFP@tempc \MFP@tempb % \MFP@tempc = q_1 d_1
+ \MFP@tempd \MFP@y@Frc % \MFP@tempd = d_2
+ \multiply \MFP@tempd \MFP@tempb % \MFP@tempd = q_1 d_2
+ \MFP@tempe \MFP@tempc
+ \advance \MFP@tempe -\MFP@x@Int\relax % \MFP@tempe = -n_1 + q_1 d_1
+ \ifnum \MFP@tempe > -9 % n_1 - q_1 d_1 < 9
+ \multiply \MFP@tempe\MFP@ttteight % -(n_1 - q_1 d_1)(10)^8
+ \advance \MFP@tempe \MFP@tempd % add q_1 d_2
+ \advance \MFP@tempe -\MFP@x@Frc\relax % add -n_2
+ \ifnum \MFP@tempe>0 % Crucial inequality fails
+ \advance\MFP@tempb -1 % new q = q_1 - 1
+ \advance\MFP@tempc -\MFP@y@Int % q_1 d_1 - d_1 = q d_1
+ \advance\MFP@tempd -\MFP@y@Frc\relax% q_1 d_2 - d_2 = q d_2
+ \fi
+ \fi
+ \edef\MFP@z@digits{\MFP@z@digits\number\MFP@tempb}%
+% \end{macrocode}
+%
+% It remains to:
+% \begin{itemize}
+% \item Do the carry from \cs{MFP@tempd} to \cs{MFP@tempc}. Then
+% \cs{MFP@tempc.}\cs{MFP@tempd} will represent $q\cdot y$.
+% \item Subtract them from \cs{MFP@x@Int} and \cs{MFP@x@Frc} (i.e. remainder =
+% $x - qy$).
+% \item Borrow, if needed, and we will have the remainder in
+% \cs{MFP@x@Int.}\cs{MFP@x@Frc}.
+% \end{itemize}
+% Then we decrement the loop counter, and decide whether to repeat this
+% loop. If so, we need to shift the remainder right one digit (multiply
+% by 10). We don't use \cs{MFP@carrya} since it requires macros; its
+% internal code, \cs{MFP@carryi} just leaves the results in
+% \cs{MFP@tempa.}\cs{MFP@tempb}.
+% \begin{macrocode}
+ \begingroup
+ \MFP@carryi\MFP@ttteight\MFP@tempd\MFP@tempc
+ \MFP@endgroup@after{%
+ \MFP@tempc=\number\MFP@tempa
+ \MFP@tempd=\number\MFP@tempb\relax
+ }%
+% subtract
+ \MFP@addone\MFP@x@Int{-\MFP@tempc}\MFP@x@Int
+ \MFP@addone\MFP@x@Frc{-\MFP@tempd}\MFP@x@Frc
+% borrow
+ \ifnum\MFP@x@Frc<0
+ \MFP@addone\MFP@x@Frc\MFP@ttteight\MFP@x@Frc
+ \MFP@addone\MFP@x@Int{-1}\MFP@x@Int
+ \fi
+ \advance\MFP@tempf -1
+ \ifnum\MFP@tempf>0
+ \edef\MFP@x@Int{\MFP@x@Int0}% easy multiplications by 10
+ \edef\MFP@x@Frc{\MFP@x@Frc0}%
+ \MFP@carrya\MFP@x@Frc\MFP@x@Int
+ \@xp\MFP@Rdivloop
+ \fi}%
+% \end{macrocode}
+%
+% Now \cs{MFPshiftandsplit@z@digits}. At this point, the digits of the
+% quotient are stored in \cs{MFP@z@digits}. We need to shift the decimal
+% \cs{MFP@tempa} places left, and perform the rounding. There are
+% \cs{MFP@tempa}${}+10$ digits. This could be as little as $1$ or as great
+% as $25$. In the first case \cs{MFP@tempa} is $-9$, and this (rightward)
+% shift produces $0$ plus a rounding digit. In the latter case \cs{MFP@tempa}
+% is $15$, and the shift produces $8$ digits overflow, an $8$-digit
+% integer part, an $8$-digit fractional part and a rounding digit. In the
+% example $0123456$, \cs{MFP@tempa}${}+10$ is $7$, so \cs{MFP@tempa} is $-3$.
+% The shift produces $0.0001\,2345\,6$. The rounding digit ($6$) makes the
+% answer $0.0001\,2346$.
+%
+% We take two cases:
+% \begin{itemize}
+% \item \cs{MFP@tempa}${}\le 7$, prepend $7-{}$\cs{MFP@tempa} zeros. The first
+% $8$ digits will become the integer part, and there should be
+% exactly $9$ more digits.
+% \item \cs{MFP@tempa}${} > 7$, pluck \cs{MFP@tempa}${}-7$ digits for
+% overflow, the next $8$ for integer part, leaving $9$ more digits
+% \end{itemize}
+% In either case, the $9$ last digits will be processed into a fractional
+% part (with possible carry if the rounding increases it to $10^8$).
+%
+% After this, we will return to \cs{MFP@Rdiv} so overwriting \cs{MFP@temp*}
+% won't cause any problems.
+% \begin{macrocode}
+\def\MFPshiftandsplit@z@digits{%
+ \advance \MFP@tempa -7
+ \ifnum\MFP@tempa>0
+ \def\MFP@z@Ovr{}%
+ \@xp\MFPget@Ovrdigits\MFP@z@digits\mfp@end
+ \else
+ \ifnum\MFP@tempa<-7
+ \edef\MFP@z@digits{00000000\MFP@z@digits}%
+ \advance\MFP@tempa8
+ \fi
+ \ifnum\MFP@tempa<-3
+ \edef\MFP@z@digits{0000\MFP@z@digits}%
+ \advance\MFP@tempa4
+ \fi
+ \edef\MFP@z@digits{%
+ \ifcase-\MFP@tempa\or
+ 0\or
+ 00\or
+ 000\or
+ 0000\else
+ 00000%
+ \fi \MFP@z@digits}%
+ \@xp\MFPget@Intdigits\MFP@z@digits\mfp@end
+ \fi}%
+% \end{macrocode}
+%
+% The macro \cs{MFPget@Ovrdigits} is a loop that loads the first \cs{MFP@tempa}
+% digits of what follows into \cs{MFP@z@Ovr}. It does this one digit (\arg1)
+% at a time. Once the counter reaches $0$, we call the macro that
+% processes the integer part digits.
+% \begin{macrocode}
+\def\MFPget@Ovrdigits#1{%
+ \edef\MFP@z@Ovr{\MFP@z@Ovr#1}%
+ \advance\MFP@tempa -1
+ \ifnum\MFP@tempa>0
+ \@xp\MFPget@Ovrdigits
+ \else
+ \@xp\MFPget@Intdigits
+ \fi}%
+% \end{macrocode}
+%
+% The macro \cs{MFPget@Intdigits} should have exactly 17 digits following it.
+% It puts eight of them in \cs{MFP@z@Int}, then calls \cs{MFPget@Frcdigits} to
+% read the fractional part. That requires exactly 9 digits follow it,
+% putting eight in \cs{MFP@z@Frc} and the last in \cs{MFP@z@Und}. Still, to
+% allow a graceful exit should there be more, we gobble the rest of the
+% digits.
+% \begin{macrocode}
+\def\MFPget@Intdigits#1#2#3#4#5#6#7#8{%
+ \def\MFP@z@Int{\number#1#2#3#4#5#6#7#8}%
+ \MFPget@Frcdigits}%
+\def\MFPget@Frcdigits#1#2#3#4#5#6#7#8#9{%
+ \def\MFP@z@Frc{#1#2#3#4#5#6#7#8}%
+ \def\MFP@z@Und{#9}\gobbleto@mfp@end}%
+% \end{macrocode}
+%
+% The max amd min operations simply run the compare operation and use
+% and use the resultant booleans to copy $x$ or $y$ to $z$.
+% \begin{macrocode}
+\def\MFP@Rmax{%
+ \MFP@Rcmp \ifMFP@neg \MFP@Rcopy yz\else\MFP@Rcopy xz\fi}%
+\def\MFP@Rmin{%
+ \MFP@Rcmp \ifMFP@pos \MFP@Rcopy yz\else\MFP@Rcopy xz\fi}%
+% \end{macrocode}
+%
+% \subsection{Commands to format for printing}
+%
+% \DescribeMacro{\MFPtruncate}
+% This first runs the parsing command so the fractional part has exactly
+% eight digits. These become the arguments of \cs{MFP@@Rtrunc}, which just
+% keeps the right number. For negative truncations we prepend zeros to the
+% integer part so it too is exactly eight digits. These become the
+% arguments of \cs{MFP@@iRtrunc}, which substitutes 0 for the last
+% \texttt{-\cs{MFP@tempa}} of them.
+%
+% The macro to store the result in follows \arg2. It is read and
+% defined by either \cs{MFP@Rtrunc} or \cs{MFP@iRtrunc}.
+% \begin{macrocode}
+\def\MFPtruncate#1#2{%
+ \begingroup
+ \MFP@tempa#1\relax
+ \MFPparse@x{#2}%
+ \ifnum\MFP@tempa<1
+ \@xp\MFP@iRtrunc
+ \else
+ \@xp\MFP@Rtrunc
+ \fi}%
+\def\MFP@Rtrunc#1{%
+ \edef\MFP@x@Frc{\@xp\MFP@@Rtrunc\MFP@x@Frc\mfp@end}%
+ \ifnum\MFP@x@Int=0 % possibly returns 0
+ \ifnum\MFP@x@Frc=0
+ \def\MFP@x@Sgn{0}%
+ \fi
+ \fi
+ \MFP@endgroup@after{%
+ \MFP@def@after#1{\MFP@x@Sign\MFP@x@Int.\MFP@x@Frc}}}%
+\def\MFP@@Rtrunc#1#2#3#4#5#6#7#8#9\mfp@end{%
+ \ifcase\MFP@tempa\or
+ #1\or
+ #1#2\or
+ #1#2#3\or
+ #1#2#3#4\or
+ #1#2#3#4#5\or
+ #1#2#3#4#5#6\or
+ #1#2#3#4#5#6#7\else
+ #1#2#3#4#5#6#7#8\fi}%
+\def\MFP@iRtrunc#1{%
+ \makeMFP@eightdigits\MFP@x@Int
+ \edef\MFP@x@Val{\number\MFP@x@Sign\@xp\MFP@@iRtrunc\MFP@x@Int\mfp@end}%
+ \MFP@endgroup@after{\MFP@def@after#1{\MFP@x@Val}}}%
+\def\MFP@@iRtrunc#1#2#3#4#5#6#7#8#9\mfp@end{%
+ \ifcase-\MFP@tempa
+ #1#2#3#4#5#6#7#8\or
+ #1#2#3#4#5#6#70\or
+ #1#2#3#4#5#600\or
+ #1#2#3#4#5000\or
+ #1#2#3#40000\or
+ #1#2#300000\or
+ #1#2000000\or
+ #10000000\else
+ 00000000\fi}%
+% \end{macrocode}
+%
+% \DescribeMacro{\MFPround}
+% For rounding we simply add the appropriate fraction and truncate.
+% The macro in which to store the result will follow \arg2, and be
+% picked up by the \cs{MFPtruncate} command.
+% \begin{macrocode}
+\def\MFPround#1#2{%
+ \begingroup
+ \MFP@tempa#1\relax
+ \ifnum 0>\MFP@tempa
+ \edef\MFP@y@Tmp{%
+ \ifcase-\MFP@tempa\or
+ 5\or % .5 x 10^1
+ 50\or % .5 x 10^2
+ 500\or % .5 x 10^3
+ 5000\or % .5 x 10^4
+ 50000\or % .5 x 10^5
+ 500000\or % .5 x 10^6
+ 5000000\else % .5 x 10^7
+ 50000000\fi % .5 x 10^8
+ }%
+ \else
+ \edef\MFP@y@Tmp{%
+ \ifcase\MFP@tempa
+ .5\or % .5 x 10^0
+ .05\or % .5 x 10^{-1}
+ .005\or % .5 x 10^{-2}
+ .0005\or % .5 x 10^{-3}
+ .00005\or % .5 x 10^{-4}
+ .000005\or % .5 x 10^{-5}
+ .0000005\or % .5 x 10^{-6}
+ .00000005\else% .5 x 10^{-7}
+ 0\fi %
+ }%
+ \fi
+ \MFPchk{#2}\ifMFP@neg\edef\MFP@y@Tmp{-\MFP@y@Tmp}\fi
+ \MFPadd{#2}\MFP@y@Tmp\MFP@z@Tmp
+ \MFP@endgroup@after{\MFP@def@after\MFP@z@Tmp{\MFP@z@Tmp}}%
+ \MFPtruncate{#1}\MFP@z@Tmp}%
+% \end{macrocode}
+%
+% \DescribeMacro{\MFPstrip}
+% Stripping zeros from the right end of the fractional part. The star form
+% differs only in the handling of a zero fractional part. So we check
+% whether it is zero and when it is, we either append `\texttt{.0}' or
+% nothing. The rest of the code grabs a digit at a time and stops when the
+% rest are zero.
+% \begin{macrocode}
+\def\MFPstrip{%
+ \@ifstar{\MFP@strip{}}{\MFP@strip{.0}}}%
+\def\MFP@strip#1#2#3{%
+ \MFPparse@x{#2}%
+ \ifnum \MFP@x@Frc=0
+ \edef#3{\MFP@x@Sign\MFP@x@Int#1}%
+ \else
+ \edef#3{\MFP@x@Sign\MFP@x@Int.\@xp\MFP@@strip\MFP@x@Frc\mfp@end}%
+ \fi}%
+\def\MFP@@strip#1#2\mfp@end{%
+ #1%
+ \ifnum 0#2>0
+ \@xp\MFP@@strip
+ \else
+ \@xp\gobbleto@mfp@end
+ \fi#2\mfp@end}%
+% \end{macrocode}
+%
+% \subsection{Miscellaneous}
+%
+% Here is the code that allows definitions to survive after
+% \cs{stopMFPprogram}. The \cs{Global} variants are easiest.
+% \begin{macrocode}
+\def\MFP@Global#1{\toks@\@xp{#1}\xdef#1{\the\toks@}}%
+\def\MFP@GlobalStack{\MFP@Global\MFP@Rstack}%
+% \end{macrocode}
+%
+% The \cs{Export} command adds the command and its definition to a macro
+% that is executed after the closing group of the program.
+% \begin{macrocode}
+\def\MFP@Export#1{%
+ \begingroup
+ \toks@\@xp{\MFPprogram@returns}%
+ \MFP@endgroup@after{%
+ \MFP@def@after\MFPprogram@returns{\the\toks@ \MFP@def@after#1{#1}}%
+ }}%
+\def\MFP@ExportStack{\MFP@Export\MFP@Rstack}%
+% \end{macrocode}
+%
+% The various operations \cs{MFP@R...} together make up a ``microcode'' in
+% terms of which the stack language and the operand language are both
+% defined. As a language in its own right, it lacks only convenient ways
+% to move numbers around, as well as a few extra registers for saving
+% intermediate results. In this language, numbers are represented by a
+% three part data structure, consisting of a signum, an integer part and a
+% fractional part.
+%
+% Here we define extra commands to remedy this lack, starting with a way
+% to load a number (or rather, a three part data structure representing a
+% number) directly into a register. Here \arg1 is a register name (we
+% always us a single letter) and the remaining arguments are the signum,
+% the integer part and the fractional part (automatically normalized to 8
+% digits). The ``register'' is just a set of three macros created from the
+% name given.
+%
+% We make loading a number into a register a little more general than
+% strictly needed, allowing the parts to be specified as anything \TeX{}
+% recognizes as a number and allowing any register name. This generality
+% might reduce efficiency but it simplifies code. Because register
+% \texttt{z} is by far the most common one to load, we make more efficient
+% version of it.
+% \begin{macrocode}
+\def\MFP@Rload #1#2#3#4{%
+ \@xp\edef\csname MFP@#1@Sgn\endcsname{\number#2}%
+ \@xp\edef\csname MFP@#1@Int\endcsname{\number#3}%
+ \@xp\edef\csname MFP@#1@Frc\endcsname{\number#4}%
+ \@xp\makeMFP@eightdigits\csname MFP@#1@Frc\endcsname}%
+\def\MFP@Rcopy#1#2{%
+ \MFP@Rload #2{\csname MFP@#1@Sgn\endcsname}%
+ {\csname MFP@#1@Int\endcsname}%
+ {\csname MFP@#1@Frc\endcsname}}%
+\def\MFP@Rloadz#1#2#3{%
+ \edef\MFP@z@Sgn{\number#1}%
+ \edef\MFP@z@Int{\number#2}%
+ \edef\MFP@z@Frc{\number#3}%
+ \makeMFP@eightdigits\MFP@z@Frc}%
+% \end{macrocode}
+%
+% \DescribeMacro{\MFPpi}
+% These are some miscellaneous constants. The 8-digit approximation to
+% $\pi$, is \cs{MFPpi} and the constant mathematicians call $e$ is
+% \DescribeMacro{\MFPe}
+% \cs{MFPe}. Finally, the golden ratio (often called $\phi$) is obtained
+% by
+% \DescribeMacro{\MFPphi}
+% \cs{MFPphi}.
+% \begin{macrocode}
+\def\MFPpi{3.14159265}%
+\def\MFPe{2.71828183}%
+\def\MFPphi{1.61803399}%
+% \end{macrocode}
+% Load (conditionally) \file{mfpextra.tex}.
+% \begin{macrocode}
+\MFP@loadextra
+\MFP@finish
+%</sty>
+% \end{macrocode}
+%
+% \section{Extras}\label{extras}
+%
+% The extras consist so far of sine, cosine, angle, logarithm, powers, and
+% square root. For completeness, here is the table of user-level commands
+% available.
+%
+% \medskip
+% \centerline{%
+% \begin{tabular}{lp{3.4in}}
+% \textit{Operand versions}&\\[3pt]
+% \hline\hline
+% \textbf{Command}&\textbf{operation}\\
+% \hline
+% \SpecialUsageIndex{\MFPsin}^^A
+% \cs{MFPsin}\mmarg{num}\cs{macro}&
+% Stores $\sin(\meta{num})$ in \cs{macro}, where \meta{num} is an
+% angle in degrees.\\
+% \SpecialUsageIndex{\MFPcos}^^A
+% \cs{MFPcos}\mmarg{num}\cs{macro}&
+% Stores $\cos(\meta{num})$ in \cs{macro}, where \meta{num} is an
+% angle in degrees.\\
+% \SpecialUsageIndex{\MFPangle}^^A
+% \cs{MFPangle}\mmarg{$x$}\mmarg{$y$}\cs{macro}&
+% Stores in \cs{macro} the polar angle coordinate $\theta$ of the point
+% $(x,y)$, where $-180<\theta\le 180$.\\
+% \SpecialUsageIndex{\MFPrad}^^A
+% \cs{MFPrad}\mmarg{num}\cs{macro}&
+% The angle \meta{num} in degrees is converted to radians,
+% and result is stored in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPdeg}^^A
+% \cs{MFPdeg}\mmarg{num}\cs{macro}&
+% The angle \meta{num} in radians is converted to degrees,
+% and result is stored in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPlog}^^A
+% \cs{MFPlog}\mmarg{num}\cs{macro}&
+% Stores $\log(\meta{num})$ in \cs{macro} (base 10 logarithm).\\
+% \SpecialUsageIndex{\MFPln}^^A
+% \cs{MFPln}\mmarg{num}\cs{macro}&
+% Stores $\ln(\meta{num})$ in \cs{macro} (natural logarithm).\\
+% \SpecialUsageIndex{\MFPexp}^^A
+% \cs{MFPexp}\mmarg{num}\cs{macro}&
+% Stores $\exp(\meta{num})$ (i.e., $e^x$) in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPsqrt}^^A
+% \cs{MFPsqrt}\mmarg{num}\cs{macro}&
+% Stores the square root of \meta{num} in \cs{macro}.\\
+% \SpecialUsageIndex{\MFPpow}^^A
+% \cs{MFPpow}\mmarg{num}\mmarg{int}\cs{macro}&
+% Stores the \meta{int} power of \meta{num} in \cs{macro}. The
+% second operand must be an integer (positive or negative).
+% \end{tabular}}
+%
+% \bigskip
+% \centerline{%
+% \begin{tabular}{lp{3.9in}}
+% \multicolumn2{c}{\textit{Stack versions}}\\
+% \hline\hline
+% \textbf{Command}&\textbf{operation}\\
+% \hline
+% \SpecialUsageIndex{\Rsin}\cs{Rsin}&
+% The number is interpreted as degrees, and its sine is computed.\\
+% \SpecialUsageIndex{\Rcos}\cs{Rcos}&
+% The number is interpreted as degrees, and its cosine is computed.\\
+% \SpecialUsageIndex{\Rangle}\cs{Rangle}&
+% The top two numbers are interpreted as coordinates of a point $P$
+% in the order they were pushed. The polar angle coordinate $\theta$
+% of $P$, with $-180 < \theta \le 180$ is computed.\\
+% \SpecialUsageIndex{\Rrad}\cs{Rrad}&
+% The number of degrees is converted to radians.\\
+% \SpecialUsageIndex{\Rdeg}\cs{Rdeg}&
+% The number of radians is converted to degrees.\\
+% \SpecialUsageIndex{\Rlog}\cs{Rlog}&
+% Computes the base-10 logarithm.\\
+% \SpecialUsageIndex{\Rln}\cs{Rln}&
+% Computes the natural logarithm.\\
+% \SpecialUsageIndex{\Rexp}\cs{Rexp}&
+% Computes the exponential of the number (i.e., $e^x$).\\
+% \SpecialUsageIndex{\Rsqrt}\cs{Rsqrt}&
+% Computes the square root of the number.\\
+% \SpecialUsageIndex{\Rpow}\cs{Rpow}&
+% Computes $x^y$. The last number pushed ($y$) must be an
+% integer.
+% \end{tabular}}
+%
+% \bigskip
+% The user could easily convert between radians and degrees using
+% multiplication and/or division. The commands \cs{Rdeg}, \cs{Rrad},
+% etc., aim to be a little more accurate.
+%
+% \subsection{Additional errors}
+%
+% These extra commands come with a few possible warnings and errors.
+%
+% \DescribeMacro{\LogOfZeroInt}
+% \DescribeMacro{\LogOfZeroFrac}
+% Trying to take the logarithm of 0 will result in an error message.
+% If one allows \TeX{} to continue, the returned value will be negative,
+% with an integer part equal to the contents of \cs{LogOfZeroInt} and a
+% fractional part equal to the contents of \cs{LogOfZeroFrac}. The
+% defaults are both $99999999$.
+%
+% Trying to take the logarithm of a negative number will produce the
+% warning
+% \begin{verbatim}
+% MFP warning: Log of a negative number is complex.
+% Computing real part only. \end{verbatim}
+% The log of the absolute value is returned.
+%
+% Trying to take the square root of a negative number results in an
+% error. If you continue after the error message, the value $0$ is
+% returned.
+%
+% \SpecialUsageIndex{\MaxRealInt}
+% \SpecialUsageIndex{\MaxRealFrac}
+% Trying to take the exponential of a number larger than about $18.42$
+% will cause an error and the number returned has integer part
+% $99999999$ and fractional part $99999999$.
+%
+% Trying to take a negative power of $0$ returns the same as trying
+% to divide $1$ by $0$.
+%
+% \subsection{Loading the extras}
+%
+% \DescribeMacro{\Rsin}\DescribeMacro{\Rcos}
+% \DescribeMacro{\Rangle}
+% \DescribeMacro{\Rrad}\DescribeMacro{\Rdeg}
+% \DescribeMacro{\Rlog}\DescribeMacro{\Rln}
+% \DescribeMacro{\Rexp}\DescribeMacro{\Rsqrt}
+% \DescribeMacro{\Rpow}
+% We start \file{mfpextra} with the hook \cs{MFP@Rextra} that
+% \cs{starMFPprogram} will call to make available the extra operations
+% defined here.
+% \begin{macrocode}
+%<*extra>
+\def\MFP@Rextra{%
+ \def\Rcos {\MFP@stack@Unary\MFP@Rcos }%
+ \def\Rsin {\MFP@stack@Unary\MFP@Rsin }%
+ \def\Rangle{\MFP@stack@Binary\MFP@Rangle}%
+ \def\Rrad {\MFP@stack@Unary\MFP@Rrad }%
+ \def\Rdeg {\MFP@stack@Unary\MFP@Rdeg }%
+ \def\Rlog {\MFP@stack@Unary\MFP@Rlog }%
+ \def\Rln {\MFP@stack@Unary\MFP@Rln }%
+ \def\Rexp {\MFP@stack@Unary\MFP@Rexp }%
+ \def\Rsqrt {\MFP@stack@Unary\MFP@Rsqrt}%
+ \def\Rpow {\MFP@stack@Binary\MFP@Rpow}}%
+% \end{macrocode}
+%
+% \DescribeMacro{\MFPsin}\DescribeMacro{\MFPcos}
+% \DescribeMacro{\MFPrad}\DescribeMacro{\MFPdeg}
+% \DescribeMacro{\MFPlog}\DescribeMacro{\MFPln}
+% \DescribeMacro{\MFPexp}\DescribeMacro{\MFPsqrt}
+% \DescribeMacro{\MFPpow}
+% Then the wrappers for the operand versions.
+% \begin{macrocode}
+\def\MFPcos {\MFP@op@Unary\MFP@Rcos }%
+\def\MFPsin {\MFP@op@Unary\MFP@Rsin }%
+\def\MFPangle {\MFP@op@Binary\MFP@Rangle}%
+\def\MFPrad {\MFP@op@Unary\MFP@Rrad }%
+\def\MFPdeg {\MFP@op@Unary\MFP@Rdeg }%
+\def\MFPlog {\MFP@op@Unary\MFP@Rlog }%
+\def\MFPln {\MFP@op@Unary\MFP@Rln }%
+\def\MFPexp {\MFP@op@Unary\MFP@Rexp }%
+\def\MFPsqrt {\MFP@op@Unary\MFP@Rsqrt}%
+\def\MFPpow {\MFP@op@Binary\MFP@Rpow}%
+% \end{macrocode}
+%
+% \subsection{Error messages}
+%
+% Messages for errors related to impossible powers, roots and logarithms.
+% \begin{macrocode}
+\def\MFP@logofzero@err{%
+ \MFP@errmsg{logarithm of zero}%
+ {You tried to take the logarithm of zero. What were you %
+ thinking? If you ^^Jcontinue, the value %
+ assigned will be -\LogOfZeroInt.\LogOfZeroFrac.}}%
+\def\LogOfZeroInt {\MaxRealInt}%
+\def\LogOfZeroFrac{\MaxRealFrac}%
+\def\MFP@expoverflow@err{%
+ \MFP@errmsg{Power too large}%
+ {The power you tried to calcualate is too large for %
+ 8 digits. If you continue, ^^Jthe value assigned will be %
+ \MaxRealInt.\MaxRealFrac.}}%
+\def\MFP@sqrtofneg@err{%
+ \MFP@errmsg{square root of a negative number}%
+ {You tried to take the square root of a negative value. What %
+ were you thinking? If you continue, zero will be returned.}}%
+\def\MFP@badpower@err{%
+ \MFP@errmsg{negative power of zero}%
+ {You tried to take a negative power of zero. What were you
+ thinking? If you ^^Jcontinue, the value assigned will be %
+ \xOverZeroInt.\xOverZeroFrac.}}%
+% \end{macrocode}
+%
+% \subsection{Sine and Cosine}
+%
+% For iterated code, the most common register to copy is \texttt{z} and
+% the most common place to copy it is to \texttt{x} or \texttt{y} so we
+% make single commands to do those.
+% \begin{macrocode}
+\def\MFP@Rcopyz#1{\MFP@Rload {#1}\MFP@z@Sgn\MFP@z@Int\MFP@z@Frc}%
+\def\MFP@Rcopyzx{\MFP@Rcopyz x}%
+\def\MFP@Rcopyzy{\MFP@Rcopyz y}%
+% \end{macrocode}
+%
+% Our code assumes the number $x$ is an angle in degrees. To get sine and
+% cosine of numbers as radians, simply convert your radians to degrees
+% using \cs{MFPdeg} or \cs{Rdeg}. Then find the sine or cosine of the
+% result. For example, if \cs{X} holds the angle in in radians and you
+% want the result to be stored in \cs{S}:
+% \begin{verbatim}
+% \MFPdeg\X\Y \MFPsin\Y\S \end{verbatim}
+%
+% Our degree/radian conversions try to be more accurate than a simple
+% multiplication by $57.2957 7951$ or $0.0174 5329$. These conversion
+% factors are accurate to only 8 digits, and the rounding error is
+% magnified by multiplication. Thus we will use 16 digits for these
+% constants. That is, we multiply first by $57.2957 7951$, then by the
+% next eight digits ($.30823208\times 10^{-8}$), performing the ``${}\times
+% 10^{-8}$'' by using the (rounded) integer part as the fractional part.
+%
+% The copying of \texttt{x} to \texttt{t} beforehand is so that we don't have to
+% remember which operations (in this case only \cs{MFP@Rmul} and
+% \cs{MFP@Radd}) leave register \texttt{x} unchanged. All operations
+% defined in \file{mfpextra.tex} overwrite the \texttt{x} register, as do
+% a few others.
+% \begin{macrocode}
+\def\MFP@Rdeg{%
+ \MFP@Rcopy xt\MFP@Rload y1{57}{29577951}\MFP@Rmul
+ \MFP@Rcopyz s\MFP@Rcopy tx\MFP@Rload y10{30823209}\MFP@Rmul
+ \MFP@tempa\MFP@z@Int\relax
+ \ifnum\MFP@z@Frc<50000000 \else \advance\MFP@tempa 1 \fi
+ \MFP@Rload x{\ifnum\MFP@tempa>0 \MFP@z@Sgn\else0\fi}0\MFP@tempa
+ \MFP@Rcopy sy\MFP@Radd}%
+\def\MFP@Rrad{%
+ \MFP@Rcopy xt\MFP@Rload y10{0174 5329}\MFP@Rmul
+ \MFP@Rcopyz s\MFP@Rcopy tx\MFP@Rload y10{25199433}\MFP@Rmul
+ \MFP@tempa\MFP@z@Int\relax
+ \ifnum\MFP@z@Frc<50000000 \else \advance\MFP@tempa 1 \fi
+ \MFP@Rload x{\ifnum\MFP@tempa>0 \MFP@z@Sgn\else0\fi}0\MFP@tempa
+ \MFP@Rcopy sy\MFP@Radd}%
+% \end{macrocode}
+%
+% There are very few angles that are expressible in 8 digits whose sine
+% or cosine can be expressed exactly in 8 digits. For these, we do obtain
+% an exact result. Other values produce inexact results. It would be nice
+% if we could at least obtain these correctly rounded to 8 decimals, but
+% unfortunately our methods will often produce a result off by 1 in the
+% eighth decimal from the correctly rounded value. Anything that
+% involves the addition of two or more rounded results can have this
+% problem. The only way to get correctly rounded results is to carry out
+% all operations internally to additional places. Even then, there will be
+% the occasional $.4999\dots$ that should round to 0 but rounds to 1
+% instead.
+%
+% For the cosine, just compute $\sin(90-x)$.
+% \begin{macrocode}
+\def\MFP@Rcos{%
+ \MFP@Rcopy xy\MFP@Rload x1{90}0\MFP@Rsub
+ \MFP@Rcopyzx\MFP@Rsin}%
+% \end{macrocode}
+%
+% Return $0$ if $x$ is $0$. Then reduce $|x|$ by subtracting $360$ from
+% the integer part until it is less than $360$. Of course,
+% $\sin x = \sgn(x)\sin(|x|)$ so we only need to compute $\sin(|x|)$. For
+% $|x| < 180$, the sign will be that of $x$. For $|x| >= 180$, calculate
+% $\sin(|x| - 180)$ and the sign will be opposite that of $x$. Then again
+% return $0$ if $x$ is $0$. Finally, call \cs{MFP@@Rsin} to finish.
+% \begin{macrocode}
+\def\MFP@Rsin{%
+ \ifnum \MFP@x@Sgn=0 % return 0
+ \MFP@Rzero
+ \else
+ \MFP@tempa\MFP@x@Int\relax
+ \MFP@reduce@angle
+ \ifnum \MFP@tempa<180
+ \edef\MFP@sin@Sgn{\MFP@x@Sgn}%
+ \else
+ \edef\MFP@sin@Sgn{\number-\MFP@x@Sgn}%
+ \advance \MFP@tempa-180
+ \fi
+ \MFP@tempb\MFP@x@Frc\relax
+ \ifnum\MFP@tempa>0
+ \MFP@@Rsin
+ \else\ifnum\MFP@tempb>0
+ \MFP@@Rsin
+ \else
+ \MFP@Rzero
+ \fi\fi
+ \fi}%
+% \end{macrocode}
+%
+% This following reduces $|x|$ to the case $0 <= |x| < 360$. It assumes
+% the integer part is in count register \cs{MFP@tempa}.
+% \begin{macrocode}
+\def\MFP@reduce@angle{%
+ \ifnum\MFP@tempa<360
+ \else
+ \advance\MFP@tempa-360
+ \@xp\MFP@reduce@angle
+ \fi}%
+% \end{macrocode}
+%
+% At this point, $|x|$ is represented by \cs{MFP@tempa} (integer part) and
+% \cs{MFP@tempb} (fractional part). Also, we already know the sign, stored
+% in \cs{MFP@sin@Sgn}. Moreover $0 < {}$\cs{MFP@tempa}${} < 180$. We now
+% reduce to $0 < |x| \le 90$ using $\sin(x) = \sin(180-|x|)$, and return
+% $1$ if equal to $90$.
+%
+% The calculation of $180-x$ is optimized, taking advantage of the fact
+% that both $x$ and the result are known to be positive. If the fractional
+% part is positive, we would normally borrow $1$ by reducing $180$, but
+% instead we increase the integer part of $x$ by one.
+% \begin{macrocode}
+\def\MFP@@Rsin{%
+ \ifnum\MFP@tempa<90
+ \else
+ \ifnum\MFP@tempb>0
+ \advance\MFP@tempa 1
+ \MFP@tempb -\MFP@tempb
+ \advance\MFP@tempb \MFP@ttteight\relax
+ \fi
+ \MFP@tempa -\MFP@tempa
+ \advance\MFP@tempa 180
+ \fi
+ \ifnum\MFP@tempa=90
+ \MFP@Rloadz \MFP@sin@Sgn10%
+ \else
+% \end{macrocode}
+%
+% We would need to convert $x$ to radians (multiply by $\pi/180$) to use
+% the standard power series, but instead we will incorporate the
+% conversion factor into the power series coefficients.
+%
+% We will, however, try to increase accuracy by reducing the size of $x$
+% and correspondingly increasing the appropriate factors. Since the
+% number of significant figures of a product is limited by the least
+% number of significant figures of the two factors, the bottleneck on
+% accuracy is that of the smaller term: all our numbers have 8 digits
+% so if a number is small, the number of nonzero digits is small.
+%
+% Dividing by 100 seems a good choice (so our units are
+% ``hectodegrees''). This makes $0 < x < .9$ and the integer part
+% (\cs{MFP@tempa}) will be henceforth ignored.
+%
+% The addition of 50 is for rounding purposes. After that, our
+% computations amount to concatenating the top six digits of
+% \cs{MFP@tempb} to the digits of \cs{MFP@tempa}. This will produce the
+% integer form of the fractional part of $x/100$ (the integer part of
+% $x/100$ is 0).
+% \begin{macrocode}
+ \advance\MFP@tempb 50
+ \divide\MFP@tempb 100
+ \multiply\MFP@tempa 1000000
+ \advance\MFP@tempb\MFP@tempa
+ \MFP@Rsin@prog
+ \fi}%
+% \end{macrocode}
+%
+% \cs{MFP@Rsin@prog} is the power series computation. We save some
+% multiplications by working with $t=x^2$. As we don't need the original
+% $x$ anymore, we simply replace it with the new reduced value. We also
+% save this $x$ in another register, \texttt{s}, as we will need it again
+% at the end, and our intermediate calculations do not preserve the
+% \texttt{x} register. Then we square $x$ and save it in another temporary
+% register \texttt{t}:
+% \begin{macrocode}
+\def\MFP@Rsin@prog{%
+ \MFP@Rload x10\MFP@tempb
+ \MFP@Rcopy xs%
+ \MFP@Rsq
+ \MFP@Rcopyz t%
+% \end{macrocode}
+%
+% The power series need only go to 8 terms as the ninth would be less than
+% $.5*10^{-8}$ and so our 8-place computations would return $0$. Our
+% 8-term series is:
+% $$
+% rx(1 - r^2t/3! + r^4t^2/5! - r^6t^3/7! + r^8t^4/9! - r^{10}t^5/11! +
+% r^{12}t^6/13! - r^{14}t^7/15!)
+% $$
+% where $r$ is the factor that converts $x$ to radian measure
+% (hectodegrees to radians). We minimize any multiplications of tiny
+% numbers by computing this as
+% $$
+% r(1 - gt(1 - ft(1 - et(1 - dt(1 - ct(1 - bt(1 - at))))))).
+% $$
+% Now $r = 1.74532925$ and $a$, $b$, etc., have formulas:
+% $$
+% \vcenter{\centering
+% $\displaystyle a = r^2/15/14,\ b = r^2/13/12,\ c = r^2/11/10,\ d = r^2/9/8$,\\
+% $\displaystyle e = r^2/7/6,\ f = r^2/5/4,\ g = r^2/3/2$.\par
+% }
+% $$
+% An alternative method would be to accumulate a sum, computing each term
+% from the previous one (e.g., if $u = t^3/7!$ is the fourth term, the next
+% one is $u*t*(1/(8*9))$). This is a bit more complicated to code and requires
+% moving values around more. It would have the advantage that we can stop
+% whenever a term evaluates to 0, making computation faster for small
+% values of $x$.
+%
+% We avoid divisions by precomputing the coefficients $a$, $b$, $c$, etc.
+% Note that without the reduction in $x$, the value of $a$ for example
+% would be $0.00000145$, with only 3 significant figures of accuracy.
+% Now we can have 7, and the accuracy is more-or-less determined by that
+% of the reduced x.
+% $$
+% \vcenter{\centering
+% $\displaystyle a = 0.01450559,\ b = 0.01952675,\ c = 0.02769249$,\\
+% $\displaystyle d = 0.04230797,\ e = 0.07252796,\ f = 0.15230871$,\\
+% $\displaystyle g = 0.50769570$.\par
+% }
+% $$
+% It is important to note that the following operations step all over
+% the \cs{MFP@temp}\textit{x} \cs{count} registers, so we have made sure
+% that we no longer need them.
+%
+% The \cs{MFP@flipz} computes $1-z$, where $z$ is the result of the
+% previous operation. Instead of simply subtracting, we optimize based
+% on the fact that $z$ is known to be nonnegative and not larger than $1$.
+%
+% The macro \cs{MFP@com@iter} `flips' the previous result then multiplies
+% by $t$ and the indicated coefficient. (The name of this macro stands for
+% ``common iterated'' code; it is reused for other power series
+% computations.)
+%
+% Despite what I said above, our chosen method of computation has a
+% slightly improved accuracy (in numerical experiments) if we take it one
+% step further, but adding only half the last term. This splits the
+% difference between stopping at the 15th power or continuing to the 17th.
+% It has provably better worst-case accuracy, but on average, who knows?
+% We are right at the edge of our 8-digit accuracy anyway. The constant
+% \texttt{00559959} corresponds to half of $r^2/16/17$.
+%
+% For extra efficiency I am using a ``small'' version of multiplication
+% \cs{MFP@Rsmul}, used only when the multiplicands are sure to lie in
+% $[0,1]$.
+% \begin{macrocode}
+ \MFP@Rcopy tx%
+ \MFP@Rload y10{00559959}\MFP@Rsmul\MFP@com@iter{01450559}%
+ \MFP@com@iter{01952675}\MFP@com@iter{02769249}\MFP@com@iter{04230797}%
+ \MFP@com@iter{07252796}\MFP@com@iter{15230871}\MFP@com@iter{50769570}%
+ \MFP@flipz\MFP@Rcopyzx\MFP@Rcopy sy\MFP@Rsmul
+ \MFP@Rcopyzx\MFP@Rload y11{74532925}\MFP@Rmul
+ \let\MFP@z@Sgn\MFP@sin@Sgn}%
+\def\MFP@flipz{%
+ \ifnum\MFP@z@Sgn=0
+ \MFP@Rloadz 110%
+ \else
+ \MFP@tempa\MFP@ttteight % representing 1.00000000
+ \advance\MFP@tempa-\MFP@z@Frc\relax
+ \MFP@Rloadz{\ifcase\MFP@tempa 0\else1\fi}0\MFP@tempa
+ \fi}%
+\def\MFP@com@iter#1{\MFP@flipz
+ \MFP@Rcopyzx\MFP@Rcopy ty\MFP@Rsmul
+ \MFP@Rcopyzx\MFP@Rload y10{#1}\MFP@Rsmul}%
+% \end{macrocode}
+%
+% As to the accuracy of these computations, we can certainly lose accuracy
+% at each step. In principle, if $x$ is known to 10 significant figures
+% ($x \ge 10$~degrees), then even though we lose 2 figures with division
+% by 100, the accuracy bottleneck is the fact that our coefficients have
+% only seven figures. Now we have 17 multiplications, and while products
+% are said to have the same number of significant figures as the factors,
+% in the worse case we can accumulate inaccuracy of about $.5\times
+% 10^{-8}$ per multiplication. So we are not guaranteed an accuracy of
+% more than about $\pm 10^{-7}$. Numerical tests, however, show that it
+% isn't that bad, probably because the direction of inaccuracies usually
+% varies randomly, and inaccuracies in one direction compensate for those
+% going the other way. I have not seen a case where the result is off by
+% more than 1 in the last decimal place (i.e., $\pm 1.5\times 10^{-8}$).
+% In the case where we can know the result exactly, $x=30$, we get an
+% exact answer, even though we don't single it out (as we do 0, 90 and
+% 180).
+%
+% The following is the ``small'' version of \cs{MFP@Rmul}. Limited to
+% non-negative numbers less than or equal to 1. Theoretically all the
+% numbers are strictly between $0$ and $1$, but in practice a
+% multiplication could round to $0$ and then, after subtraction, a $1$
+% could occur. We handle those easy cases separately, so that in
+% \cs{MFP@@Rsmul} we don't have to wory about the integer parts at all.
+% \begin{macrocode}
+\def\MFP@Rsmul{%
+ \ifnum \MFP@x@Sgn=0
+ \MFP@Rzero
+ \else\ifnum \MFP@y@Sgn=0
+ \MFP@Rzero
+ \else\ifnum\MFP@x@Int>0 % x must be 1.0
+ \MFP@Rcopy yz%
+ \else\ifnum\MFP@y@Int>0 % y must be 1.0
+ \MFP@Rcopy xz%
+ \else
+ \MFP@@Rsmul
+ \fi\fi\fi\fi}%
+\def\MFP@@Rsmul{%
+ \MFP@split\MFP@x@Frc\MFP@x@Frc@i\MFP@x@Frc@ii
+ \MFP@split\MFP@y@Frc\MFP@y@Frc@i\MFP@y@Frc@ii
+ \def\MFP@z@Frc@i {0}\def\MFP@z@Frc@ii {0}%
+ \def\MFP@z@Frc@iii{0}\def\MFP@z@Frc@iv {0}%
+ \MFP@tempb\MFP@y@Frc@ii\relax
+ \MFP@multiplyone\MFP@x@Frc@ii\MFP@z@Frc@iv
+ \MFP@multiplyone\MFP@x@Frc@i\MFP@z@Frc@iii
+ \MFP@tempb\MFP@y@Frc@i\relax
+ \MFP@multiplyone\MFP@x@Frc@ii\MFP@z@Frc@iii
+ \MFP@multiplyone\MFP@x@Frc@i\MFP@z@Frc@ii
+ \MFP@carrym\MFP@z@Frc@iv\MFP@z@Frc@iii
+ \MFP@carrym\MFP@z@Frc@iii\MFP@z@Frc@ii
+ \ifnum\MFP@z@Frc@iii<5000 \else
+ \MFP@tempb\MFP@z@Frc@ii
+ \advance\MFP@tempb1
+ \edef\MFP@z@Frc@ii{\number\MFP@tempb}\fi
+ \MFP@carrym\MFP@z@Frc@ii\MFP@z@Frc@i
+ \makeMFP@fourdigits\MFP@z@Frc@iv
+ \makeMFP@fourdigits\MFP@z@Frc@iii
+ \makeMFP@fourdigits\MFP@z@Frc@ii
+ \makeMFP@fourdigits\MFP@z@Frc@i
+ \def\MFP@z@Int{0}%
+ \edef\MFP@z@Frc{\MFP@z@Frc@i\MFP@z@Frc@ii}%
+ \edef\MFP@z@Sgn{\ifnum\MFP@z@Frc=0 0\else 1\fi}%
+ \edef\MFP@z@Und{\MFP@z@Frc@iii\MFP@z@Frc@iv}%
+ \edef\MFP@z@Ovr{0}}%
+% \end{macrocode}
+%
+% \subsection{Polar angle}
+%
+% Instead of supplying the arcsine and arccosine functions, we supply the
+% more general angle function. This is a binary operation that accepts
+% the two coordinates of a point and computes its angle in polar
+% coordinates. One then has, for example, $\arctan x =
+% \mathop{\rm angle}(1,x)$ and $\arccos x = \angle(x, \sqrt{1-x^2})$.
+% The latter could be obtain in a program by:
+% \begin{verbatim}
+% \Rpush\X \Rdup
+% \Rsq \Rchs
+% \Rincr \Rsqrt
+% \Rangle \end{verbatim}
+%
+% We start, as usual, with a few reductions. When the $y$-part is $0$, we
+% immediately return $0$ or $180$. If the $y$-part is negative, we compute
+% the angle for $(x,|y|)$ and negate it. If the $x$-part is negative, we
+% compute the angle for $|x|$ and subtract it from $180$. Finally,
+% reduced to both coordinates positive, if $y>x$ we compute the angle of
+% $(y,x)$ and subtract that from $90$. Ultimately, we apply a power
+% series formula for $\angle(1,y/x)$ and get convergence when the
+% argument is less than $1$, but convergence is poor unless the argument
+% is less than $1/2$. When that is not the case, conceptually, we rotate
+% the picture clockwise by the arctangent of $1/2$, compute the angle of
+% the new point and then add a precomputed value of $\arctan(1/2)$.
+% \begin{macrocode}
+\def\MFP@Rangle{%
+ \ifcase\MFP@y@Sgn\relax
+ \ifcase\MFP@x@Sgn\relax
+ \MFP@warn{Point (0,0) has no angle. Returning 0 anyway}%
+ \MFP@Rzero
+ \or
+ \MFP@Rzero
+ \else
+ \MFP@Rloadz 1{180}0%
+ \fi
+ \@xp\@gobble
+ \or
+ \def\MFP@angle@Sgn{1}\@xp\@firstofone
+ \else
+ \def\MFP@y@Sgn{1}%
+ \def\MFP@angle@Sgn{-1}\@xp\@firstofone
+ \fi
+ {\ifcase\MFP@x@Sgn\relax
+ \MFP@Rloadz1{90}0%
+ \or \MFP@@Rangle
+ \else
+ \def\MFP@x@Sgn{1}\MFP@@Rangle
+ \MFP@Rcopyzy\MFP@Rload x1{180}0\MFP@Rsub
+ \fi
+ \let\MFP@z@Sgn\MFP@angle@Sgn
+ }}%
+\def\MFP@@Rangle{%
+ \MFP@Rcmp
+ \ifMFP@neg
+ \MFP@Rcopy xs\MFP@Rcopy yx\MFP@Rcopy sy%
+ \MFP@@@Rangle
+ \MFP@Rload x1{90}0\MFP@Rcopyzy\MFP@Rsub
+ \else
+ \MFP@@@Rangle
+ \fi
+}%
+% \end{macrocode}
+%
+% Precisely what we do when we are finally in the case $0<y<x$ is perform
+% a couple of reductions. Ultimately we want to compute the arctan of
+% $z = y/x$. We once again use a power series but, for fast convergence,
+% we require $z$ to be considerably less than $1$. For reasons we discuss
+% later, we won't be able to use the more efficient \cs{MFP@Rsmul} so we
+% want to keep the number of iterations of our power series calculations
+% low.
+%
+% So we start with two iterations of the algorithm used by Knuth: if $y/x
+% > 1/2$ we transform the pair $(x,y)$ to a new one whose angle has been
+% reduced by $\arctan (1/2)$. The new pair is $(x',y') = (2x+y, 2y-x)$.
+% If we still have $y/x > 1/4$, we perform $(x'',y'') = (4x + y, 4y - x)$,
+% which then satisfies $y''/x'' \le 1/4$. When either of these
+% transformations is performed, we add the corresponding angle to the
+% ``angle-so-far'' in register \texttt{a}.
+%
+% We could continue this iteration 32 times to get (theoretically) the
+% angle in degrees to $\pm 10^{-8}$. That seems a bit long, plus the
+% accumulation of errors over $32$ iterations could (in the worst case)
+% produce less than $\pm10^{-7}$ accuracy.
+%
+% To get the accuracy we need we work in ``scaled reals''. That is, we
+% get 10 decimal places of accuracy by letting two digits of the integer
+% part represent the first two digits after the decimal point, and the
+% 8 digits of the fractional part represent digits 3 through 10 after the
+% point. The macro \cs{MFP@RmulC} (around line 19 of the definition of
+% \cs{MFP@@@Rangle}) is a quick multiplication by 100, converting the
+% argument of the arctangent command to a scaled real.
+%
+% Since we ultimately take the arctangent of $y/x$ we get best accuracy if
+% $y$ is first scaled, which means it must necessarily be smaller than
+% $10^6$ to start with. Our initial reductions can double its size, so we
+% first make sure it is smaller than $500\,000$, dividing by $200$. This
+% can actually reduce accuracy, but as it is only done when $y$ already
+% has $14$ significant figures, and since the quotient $100y/x$ has at
+% most $10$, the loss is not significant.
+% \begin{macrocode}
+\def\MFP@Rquad{\MFP@Rdbl\MFP@Rcopyzx\MFP@Rdbl}%
+\def\MFP@@@Rangle{%
+ \MFP@Rcopy xs\MFP@Rcopy yt%
+ \ifnum\MFP@y@Int<500000
+ \else
+ \MFP@Rload y1{200}0\MFP@Rdiv
+ \MFP@Rcopyz s\MFP@Rcopy tx%
+ \MFP@Rload y1{200}0\MFP@Rdiv
+ \MFP@Rcopyz t%
+ \fi
+ \MFP@Rcopy tx\MFP@Rdbl\MFP@Rcopyzx\MFP@Rcopy sy\MFP@Rcmp
+ \ifMFP@pos
+ \MFP@Rsub\MFP@Rcopyz u\MFP@Rcopy sx\MFP@Rdbl
+ \MFP@Rcopyzx\MFP@Rcopy ty\MFP@Radd
+ \MFP@Rcopyz s\MFP@Rcopy ut%
+ \MFP@Rload a1{2656}{50511771}%
+ \else
+ \MFP@Rload a000%
+ \fi
+ \MFP@Rcopy tx\MFP@Rquad\MFP@Rcopyzx\MFP@Rcopy sy\MFP@Rcmp
+ \ifMFP@pos
+ \MFP@Rsub\MFP@Rcopyz u\MFP@Rcopy sx\MFP@Rquad
+ \MFP@Rcopyzx\MFP@Rcopy ty\MFP@Radd
+ \MFP@Rcopyz s\MFP@Rcopy ut%
+ \MFP@Rcopy ax\MFP@Rload y1{1403}{62434679}%
+ \MFP@Radd\MFP@Rcopy za%
+ \fi
+ \MFP@Rcopy tx\MFP@RmulC
+ \MFP@Rcopyzx\MFP@Rcopy sy\MFP@Rdiv
+ \MFP@Rcopyzx\MFP@Ratanc
+ \MFP@Rcopyzx\MFP@Rdeg
+ \MFP@Rcopyzx\MFP@Rcopy ay\MFP@Radd
+ \MFP@Rcopyzx\MFP@RdivC}%
+% \end{macrocode}
+%
+% Here are fast multiplication and division by 100. We need these because
+% we are going to comput the arctangent in radians to ten decimal places.
+% We do this by computing with scaled reals in which, for example, $0.5$
+% is represented by $50.0$. When we do this, multiplication requires a
+% division by 100: $.5\times.5 = .25$ would be computed as $(50\times50) /
+% 100 = 25$.
+% \begin{macrocode}
+\def\MFP@RmulC{%
+ \makeMFP@eightdigits\MFP@x@Frc
+ \edef\MFP@Tmp{\number\MFP@x@Int.\MFP@x@Frc}%
+ \@xp\MFP@@RmulC\MFP@Tmp\mfp@end}%
+\def\MFP@@RmulC#1.#2#3#4\mfp@end{%
+ \MFP@Rloadz\MFP@x@Sgn{#1#2#3}{#400}}%
+\def\MFP@RdivC{%
+ \makeMFP@eightdigits\MFP@x@Int
+ \makeMFP@eightdigits\MFP@x@Frc
+ \@XP\MFP@@RdivC\@xp\MFP@x@Int\MFP@x@Frc\mfp@end}%
+\def\MFP@@RdivC#1#2#3#4#5#6{%
+ \edef\MFP@z@Int{\number#1#2#3#4#5#6}%
+ \MFP@@@RdivC}%
+\def\MFP@@@RdivC#1#2#3#4#5#6#7#8#9\mfp@end{%
+ \MFP@tempa#1#2#3#4#5#6#7#8\relax
+ \ifnum#9>49 \advance\MFP@tempa1 \fi
+ \edef\MFP@z@Sgn{\MFP@x@Sgn}%
+ \ifnum\MFP@tempa=0 \ifnum\MFP@x@Int=0 \def\MFP@z@Sgn{0}\fi\fi
+ \MFP@Rloadz\MFP@z@Sgn\MFP@z@Int\MFP@tempa}%
+% \end{macrocode}
+%
+% Finally, we compute the arctan of a scaled real producing a result
+% as a scaled number (i..e., as ``centiradians''---$100$ times the number
+% of radians) using a power series. Since that number could be
+% around $0.25$ (represented by $25.0$), we have to sum to at least its
+% $15$th power ($4^{-15}/15 \approx .6\times 10^{-10}$ and the next term
+% in the series is effectively $0$). Fortunately, the power series has
+% only odd terms, so there are only 8 terms we actually need to calculate.
+% The calculation proceeds much like the one for the sine, starting with
+% the sum
+% $$
+% x\left(1 - \frac{u}{3} + \frac{u^2}{5} - \frac{u^3}{7} + \cdots
+% - \frac{u^7}{2\cdot 15}\right),
+% $$
+% where $u = x^2$.
+%
+% We start with the common iterated code. It assumes a scaled value in x
+% to be multiplied by the saved (scaled) value of $x^2$ (in register u)
+% and by a coefficient (supplied in separate integer and fractional
+% parts). It ends with the new value in x.
+% \begin{macrocode}
+\def\MFP@scaledmul{\MFP@Rmul\MFP@Rcopyzx\MFP@RdivC}%
+\def\MFP@atan@iter#1#2{%
+ \MFP@Rcopy uy\MFP@scaledmul
+ \MFP@Rcopyzx\MFP@Rload y1{#1}{#2}\MFP@scaledmul
+ \MFP@Rcopyzy\MFP@Rload x1{100}{00000000}%
+ \MFP@Rsub\MFP@Rcopyzx}%
+\def\MFP@Ratanc{%
+ \MFP@Rcopy xs%
+ \MFP@Rcopy xy\MFP@scaledmul\MFP@Rcopyz u%
+ \MFP@Rcopyzx\MFP@Rload y1{86}{66666667}%
+ \MFP@scaledmul
+ \MFP@Rcopyzy\MFP@Rload x1{100}{00000000}%
+ \MFP@Rsub\MFP@Rcopyzx
+ \MFP@atan@iter{84}{61538462}\MFP@atan@iter{81}{81818182}%
+ \MFP@atan@iter{77}{77777778}\MFP@atan@iter{71}{42857143}%
+ \MFP@atan@iter{60}{00000000}\MFP@atan@iter{33}{33333333}%
+ \MFP@Rcopy sy\MFP@scaledmul}%
+% \end{macrocode}
+%
+% \subsection{Logarithms}
+%
+% Now for logarithms. We are going to compute a base 10 logarithm. This
+% allows the first step of the calculation to be essentially trivial: to
+% get the integer part of the log for numbers with positive integer part,
+% count the digits in the integer part and subtract 1. For numbers less
+% than one, count the number of zeros at the beginning of the fractional
+% part and add 1 (subtract this from the result of the second part). This
+% reduces the problem to numbers $1 \le x < 10$. A few divisions (when
+% necessary) reduce to the case where $x = 1 + u$ with $u$ small enough
+% that the power series for $\log (1 + u)$ can be computed accurately in
+% an acceptable number of of terms. Then we proceed as in the code for
+% sine.
+%
+% We keep the value-so-far in register \texttt{s} and the modified
+% $x$-value in register \texttt{t}. The log of \texttt{t} need only be
+% added to register \texttt{s} for the final result.
+% \begin{macrocode}
+\def\MFP@Rlog{%
+ \ifnum\MFP@x@Sgn=0
+ \MFP@logofzero@err
+ \MFP@Rloadz{-1}\LogOfZeroInt\LogOfZeroFrac
+ \else
+ \ifnum \MFP@x@Sgn<0
+ \MFP@warn{The logarithm of a negative number is complex.%
+ \MFP@msgbreak Only the real part will be computed}%
+ \fi
+ \MFP@Rload s000%
+% \end{macrocode}
+%
+% If the integer part is zero, the fractional part is not. Save the
+% number of places that will be shifted in \cs{MFP@tempa}. We use
+% \cs{number} to strip the leading zeros and (essentially) we count
+% the number of digits that remain. Then we shift left, putting the first
+% digit into the integer part of \texttt{s} and the rest into the
+% fractional part. Despite its name, \cs{MFP@numzeros} actually returns
+% one more than the number of zeros, which is the number of places to
+% shift, and the integer part of the logarithm.
+% \begin{macrocode}
+ \ifnum \MFP@x@Int=0
+ \edef\MFP@x@Tmp{\number\MFP@x@Frc}%
+ \MFP@tempa=\MFP@numzeros\MFP@x@Tmp\relax
+ \def\MFP@s@Sgn{-1}%
+ \edef\MFP@t@Int{\@xp\MFP@firstofmany\MFP@x@Tmp\mfp@end}%
+ \edef\MFP@t@Frc{\@xp\@gobble\MFP@x@Tmp0}%
+ \MFPpadto@eight\MFP@t@Frc
+ \else
+% \end{macrocode}
+% When the integer part is not zero, we get the number of digits to
+% shift again in \cs{MFP@tempa}. We actually want one less than the
+% number of digits, so that is what \cs{MFP@numdigits} actually produces.
+% \begin{macrocode}
+ \MFP@tempa\MFP@numdigits\MFP@x@Int
+ \edef\MFP@x@Tmp{\MFP@x@Int\MFP@x@Frc}% gather all digits
+ \edef\MFP@s@Sgn{1}%
+ \edef\MFP@t@Int{\@xp\MFP@firstofmany\MFP@x@Tmp\mfp@end}%
+ \edef\MFP@x@Tmp{\@xp\@gobble\MFP@x@Tmp}%
+ \edef\MFP@t@Frc{\@xp\MFP@firsteightofmany\MFP@x@Tmp\mfp@end}%
+ \fi
+% \end{macrocode}
+%
+% The integer part of $\log x$ is now known, so save it in value-so-far.
+% Also, set the sign of the reduced argument to positive. Then call
+% \cs{MFP@log@reduce}, which reduces $x$ to at most $10^{1/16} \approx
+% 1.155\,$. Finally, if the reduced $x$ is 1, return the value so far,
+% otherwise call the power series program.
+% \begin{macrocode}
+ \edef\MFP@s@Int{\number\MFP@tempa}%
+ \def\MFP@t@Sgn{1}%
+ \MFP@Rlog@reduce
+ \ifnum\MFP@t@Frc=0
+ \MFP@Rcopy sz%
+ \else
+ \MFP@Rlog@prog
+ \fi
+ \fi}%
+\def\showreg #1{% for debugging
+\begingroup
+ \edef\reg{%
+ #1 = (\csname MFP@#1@Sgn\endcsname)%
+ \csname MFP@#1@Int\endcsname.%
+ \csname MFP@#1@Frc\endcsname}%
+ \show\reg
+\endgroup}%
+% \end{macrocode}
+%
+% We count the number of digits by lining them up, followed by the
+% possible numbers, and picking out the ninth argument. We count leading
+% zeros in the fractional part by removing leading zeros, lining up the
+% remaining digits, followed by the possible numbers, and again picking
+% the ninth. In \cs{MFP@Rlog@reduce} we divide by the square root of 10 if
+% the number is larger than that (adding $.5$ to value-so-far). We repeat
+% with the 4th, 8th and 16th roots. For speed, instead of dividing, we
+% actually multiply by the precalculated reciprocal, passed as the third
+% argument.
+% \begin{macrocode}
+\def\MFP@numdigits#1{\@xp\MFP@ninthofmany#176543210\mfp@end}%
+\def\MFP@numzeros#1{%
+ \@xp\MFP@ninthofmany#112345678\mfp@end}%
+\def\MFP@Rlog@reduce{%
+ \MFP@reduceonce 3{16227766}{31622777}{50000000}%
+ \MFP@reduceonce 1{77827941}{56234133}{25000000}%
+ \MFP@reduceonce 1{33352143}{74989421}{12500000}%
+ \MFP@reduceonce 1{15478198}{86596433}{06250000}}%
+\def\MFP@reduceonce#1#2#3#4{%
+ \MFP@Rcopy tx\MFP@Rload y1{#1}{#2}\MFP@Rcmp
+ \ifMFP@neg\else
+ \MFP@Rload y10{#3}\MFP@Rmul
+ \MFP@Rcopyz t\MFP@Rcopy sx\MFP@Rload y10{#4}\MFP@Radd
+ \MFP@Rcopyz s%
+ \fi}%
+% \end{macrocode}
+%
+% Now we have a value for $t$ of the form $1 + u$ with $0\le u < 0.155$
+% (approx.) We will use the formula
+% $$
+% \log (1 + u) = \frac{1}{\ln 10} \sum_{n=0}^\infty (-1)^n \frac{u^{n+1}}{n+1}.
+% $$
+% We only need to carry it far enough to assure that the next term would
+% be 0 in our finite resolution arithmetic, that is $.155^{k}/k/\ln10 < .5\times
+% 10^{-8}$. This is satisfied by $k=9$, so we only need 8 terms.
+%
+% Again, we compute this by
+% $$
+% ru(1 - au(1 - bu(1-cu(1-du(1-eu(1-fu(1-gu(1-hu))))))))
+% $$
+% where $a= 1/2$, $b = 2/3$,\dots,$h=7/8/2$, and $r = 1/ln 10 = \log e$.
+% This allows us to reuse \cs{MFP@com@iter}.
+%
+% The for the natural log $\ln x$ we multiply the common logarithm by
+% $\ln 10$. It seems we are redundantly canceling the earlier division
+% by $\ln 10$, but remember we are also multiplying the integer part,
+% which did not have such a division in its code.
+% \begin{macrocode}
+\def\MFP@Rlog@prog{%
+ \MFP@Rcopy tx\MFP@Rdecr
+ \MFP@Rcopyz t%
+ \MFP@Rcopyzx\MFP@Rload y10{43750000}\MFP@Rsmul
+ \MFP@com@iter{85714286}\MFP@com@iter{83333333}\MFP@com@iter{80000000}%
+ \MFP@com@iter{75000000}\MFP@com@iter{66666667}\MFP@com@iter{50000000}%
+ \MFP@com@iter{43429448}\MFP@Rcopyzx\MFP@Rcopy sy\MFP@Radd}%
+\def\MFP@Rln{%
+ \MFP@Rlog\MFP@Rcopyzx\MFP@Rload y12{30258509}\MFP@Rmul}%
+% \end{macrocode}
+%
+% \subsection{Powers}
+%
+% With the exponential function we immediately return 1 if $x=0$. We
+% call two separate handlers for positive and negative $x$. This is
+% because the issues are different between positive and negative
+% exponents.
+% \begin{macrocode}
+\def\MFP@Rexp{%
+ \ifcase\MFP@x@Sgn\relax
+ \MFP@Rloadz 110%
+ \or
+ \MFP@Rexp@pos
+ \else
+ \def\MFP@x@Sgn{1}%
+ \MFP@Rexp@neg % computes e^{-x}, not e^x
+ \fi}%
+% \end{macrocode}
+%
+% One issue for positive exponents is overflow, so we issue an error
+% message for that case. The largest mumber that will not produce
+% overflow is $18.42068074$ so we first compare to that; if larger,
+% issue the error message and return $99999999.99999999$.
+%
+% We compute the integer power first, using an \cs{ifcase}, because
+% there are only 19 cases to consider.
+%
+% Then, we examine the first digit $d$ after the decimal and compute
+% $e^{0.d}$, again by cases. This is multiplied by the integer power
+% previously found. What remains is the rest of the fractional part of
+% $x$, which is strictly less than $0.1$. The exponential of this is
+% computed using the first several terms of the power series for $e^x$.
+% \begin{macrocode}
+\def\MFP@Rexp@pos{%
+ \MFP@Rload y1{18}{42068074}\MFP@Rcmp
+ \ifMFP@pos % overflow
+ \MFP@expoverflow@err
+ \MFP@Rloadz 1\MaxRealInt\MaxRealFrac
+ \else % handle integer part
+ \MFP@tempa\MFP@x@Int
+ \edef\MFP@powerof@e{%
+ 1\ifcase\MFP@tempa
+ 10\or
+ 2{71828183}\or
+ 7{38905610}\or
+ {20}{08553692}\or
+ {54}{59815003}\or
+ {148}{41315910}\or
+ {403}{42879349}\or
+ {1096}{63315843}\or
+ {2980}{95798704}\or
+ {8103}{08392758}\or
+ {22026}{46579481}\or
+ {59874}{14171520}\or
+ {162754}{79141900}\or
+ {442413}{39200892}\or
+ {1202604}{28416478}\or
+ {3269017}{37247211}\or
+ {8886110}{52050787}\or
+ {24154952}{75357530}\or
+ {65659969}{13733051}\else
+ {\MaxRealInt}{\MaxRealFrac}\fi}%
+ \@xp\MFP@Rloadz\MFP@powerof@e
+ \ifnum\MFP@x@Frc=0
+ \else
+ \MFP@Rcopyz s%
+ \MFP@tempa=\@xp\MFP@firstofmany\MFP@x@Frc\mfp@end
+ \edef\MFP@powerof@e{%
+ y1\ifcase\MFP@tempa
+ 10\or
+ 1{10517092}\or
+ 1{22140276}\or
+ 1{34985881}\or
+ 1{49182470}\or
+ 1{64872127}\or
+ 1{82211880}\or
+ 2{01375271}\or
+ 2{22554093}\or
+ 2{45960311}\else
+ 10\fi}%
+ \edef\MFP@t@Frc{0\@xp\@gobble\MFP@x@Frc}%
+ \MFP@Rcopy sx\@xp\MFP@Rload\MFP@powerof@e\MFP@Rmul
+ \ifnum\MFP@t@Frc=0
+ \else % handle the rest
+ \MFP@Rcopyz s\MFP@Rload t10\MFP@t@Frc
+ \MFP@Rexp@pos@prog
+ \MFP@Rcopy sx\MFP@Rcopyzy\MFP@Rmul
+ \fi
+ \fi
+ \fi}%
+% \end{macrocode}
+%
+% Since the $x$ value is now less than $0.1$, we can get 8 places of
+% accuracy with only 6 terms of the power series. We can also arrange to
+% use the more efficient \cs{MFP@Rsmul} for multiplication.
+%
+% We organize the computation thusly
+% $$
+% 1 + (x + x/2(x + x/3(x + x/4(x + x/5(x + x/6)))))
+% $$
+% We start by loading $x$ (now in register \texttt{t}) into register
+% \texttt{z}, then repeatedly run \cs{MFP@Rexp@iter} feeding it the
+% successive values of $1/n$. This iterator first multiplies the most
+% recent result (the \texttt{z} register) by $1/n$, then that by $x$ and
+% then adds $x$ to that. The final step is to add 1.
+% \begin{macrocode}
+\def\MFP@Rexp@pos@prog{%
+ \MFP@Rcopy tz\MFP@Rexp@iter{16666667}\MFP@Rexp@iter{20000000}%
+ \MFP@Rexp@iter{25000000}\MFP@Rexp@iter{33333333}%
+ \MFP@Rexp@iter{50000000}\MFP@Rcopyzx\MFP@Rincr}%
+\def\MFP@Rexp@iter#1{%
+ \MFP@Rcopyzx\MFP@Rload y10{#1}\MFP@Rsmul
+ \MFP@Rcopyzx\MFP@Rcopy ty\MFP@Rsmul
+ \MFP@Rcopyzx\MFP@Rcopy ty\MFP@Radd}%
+% \end{macrocode}
+% It is impossible to get accuracy to the last digit when $e^x$ is large.
+% This is because an absolute error in $x$ converts to a relative error
+% in $e^x$, That is, knowing $x$ only to $10^{-8}$ means $e^x$ is off by
+% (about) $e^x\cdot 10^{-8}$. Roughly speaking, this means only about $8$
+% places of $e^x$ are accurate, so if the integer part of $e^x$ has six
+% places then only 2 places after the decimal are significant. Even if
+% $x$ is exact (say $x=10$), we can only represent $e$ itself to 8
+% decimals and the repeated multiplications accumulate errors in such a
+% way that one still cannot get more than 8 significant figures.
+%
+% \bigskip
+% The first issue with negative exponents is that it doesn't take much to
+% produce a value of $e^{-x}$ that rounds to 0. Any $x > 19.11382792$. So
+% we start by comparing to that value and simply return 0 if $x$ is
+% larger.
+%
+% We perform exactly the same reductions as for positive exponents,
+% handling the integer part and the first decimal separately. Then we call
+% the power series program (not the same).
+% \begin{macrocode}
+\def\MFP@Rexp@neg{%
+ \MFP@Rload y1{19}{11382792}%
+ \MFP@Rcmp
+ \ifMFP@pos
+ \MFP@Rloadz 000%
+ \else % handle integer part
+ \MFP@tempa\MFP@x@Int
+ \edef\MFP@powerof@e{%
+ \ifcase\MFP@tempa
+ 11{0}\or
+ 10{36787944}\or
+ 10{13533528}\or
+ 10{04978707}\or
+ 10{01831564}\or
+ 10{00673795}\or
+ 10{00247875}\or
+ 10{00091188}\or
+ 10{00033546}\or
+ 10{00012341}\or
+ 10{00004540}\or
+ 10{00001670}\or
+ 10{00000614}\or
+ 10{00000226}\or
+ 10{00000083}\or
+ 10{00000031}\or
+ 10{00000011}\or
+ 10{00000004}\or
+ 10{00000002}\or
+ 10{00000001}\else
+ 000\fi}%
+ \@xp\MFP@Rloadz\MFP@powerof@e
+ \ifnum\MFP@x@Frc=0
+ \else % handle first decimal digit
+ \MFP@Rcopyz s%
+ \MFP@tempa=\@xp\MFP@firstofmany\MFP@x@Frc\mfp@end
+ \edef\MFP@powerof@e{%
+ y1\ifcase\MFP@tempa
+ 10\or
+ 0{90483742}\or
+ 0{81873075}\or
+ 0{74081822}\or
+ 0{67032005}\or
+ 0{60653066}\or
+ 0{54881164}\or
+ 0{49658530}\or
+ 0{44932896}\or
+ 0{40656966}\else
+ 10\fi}%
+ \edef\MFP@t@Frc{0\@xp\@gobble\MFP@x@Frc}%
+ \MFP@Rcopy sx\@xp\MFP@Rload\MFP@powerof@e\MFP@Rmul
+ \ifnum\MFP@t@Frc=0
+ \else % handle the rest
+ \MFP@Rcopyz s\MFP@Rload t10\MFP@t@Frc
+ \MFP@Rexp@neg@prog
+ \MFP@Rcopy sx\MFP@Rcopyzy\MFP@Rmul
+ \fi
+ \fi
+ \fi}%
+% \end{macrocode}
+%
+% Since $x$ is now positive we calculate $e^{-x}$. Again we need only up
+% to the 6th power, organized as follows
+% $$
+% 1 - x(1 - x/2(1 - x/3(1 - x/4(1 - x/5(1 - x/6)))))
+% $$
+% Since this has exactly the same form as the the power series calculation
+% for $\log$ and $\sin$, we can reuse the code in \cs{MFP@com@iter}. We
+% end with the final multiplication by $x$ and the subtraction from 1
+% rather than call \cs{MFP@com@iter} with a useless multiplication by 1.
+% \begin{macrocode}
+\def\MFP@Rexp@neg@prog{%
+ \MFP@Rcopy tx\MFP@Rload y10{16666667}\MFP@Rsmul
+ \MFP@com@iter{20000000}\MFP@com@iter{25000000}%
+ \MFP@com@iter{33333333}\MFP@com@iter{50000000}%
+ \MFP@flipz\MFP@Rcopyzx\MFP@Rcopy ty\MFP@Rsmul\MFP@flipz}%
+% \end{macrocode}
+%
+% The most efficient way to take an integer power of a number $x$ is to
+% scan the binary code for the exponent. Each digit $1$ in this code
+% corresponds to a $2^k$ power of $x$, which can be computed by repeatedly
+% squaring $x$. These \emph{dyadic} powers are mutiplied together. We can
+% convert this idea to a simple loop illustrated by this example of
+% finding $x^{13}$ ($13 = 1101$ in base $2$). Here $p$ holds the current
+% product and $q$ holds the current dyadic power of $x$, initialized with
+% $p=1$ and $q=x$:
+% \begin{enumerate}
+% \item Rightmost digit 1: update $p\leftarrow pq = x$ and $q\leftarrow
+% q^2 = x^2$.
+% \item Next digit 0: Just update $q\leftarrow q^2 = x^4$.
+% \item Next digit 1: update $p \leftarrow pq = x^5$ and $q\leftarrow
+% q^2 = x^8$.
+% \item Next digit 1: update $p \leftarrow pq = x^{13}$, detect that we
+% are at the end and skip the update of $q$. Return $p$.
+% \end{enumerate}
+% Of course, this requires the binary digits of the exponent $n$. But the
+% rightmost digit of $n$ is $1$ if and only if $n$ is odd, and we can
+% examine each digit in turn if we divide $n$ by $2$ (discarding the
+% remainder) at each stage. We detect the end when $n$ is reduced to $1$.
+%
+% Accuracy is partly a function of the number of multiplications.
+% The above scheme requires at most $\lfloor\log_2 n\rfloor$ squarings
+% and at most $\lceil \log_2 n \rceil$ multiplications for $x^n$, while
+% directly multiplying $x\cdot x \cdots x$ would require $n-1$
+% multiplications.
+%
+% For negative powers we can either find the positive power and take its
+% reciprocal or take the reciprocal of $x$ and find its positive power. We
+% do the first so that overflow can be detected in \cs{MFP@@Rpow}.
+% \begin{macrocode}
+\def\MFP@Rpow{%
+ \ifnum\MFP@y@Frc>0
+ \MFP@warn{The "pow" function requires an integer power.
+ \MFP@msgbreak The fractional part will be ignored}%
+ \fi
+ \MFP@loopctr=\MFP@y@Int\relax
+ \ifnum\MFP@loopctr=0 % zero power = 1
+ \MFP@Rloadz 110%
+ \else
+ \ifnum\MFP@x@Sgn=0
+ \ifnum\MFP@y@Sgn>0 % + powers of zero are 0
+ \MFP@Rloadz 000%
+ \else % - powers are errors
+ \MFP@badpower@err
+ \MFP@Rloadz 1\xOverZeroInt\xOverZeroFrac
+ \fi
+ \else % integer power of nonzero number
+ % get the sign in case an overflow interrupts the calculations.
+ \ifnum\MFP@x@Sgn>0
+ \def\MFP@power@Sgn{1}%
+ \else
+ \edef\MFP@power@Sgn{\ifodd\MFP@loopctr -\fi 1}%
+\ifMFPdebug
+ \show\MFP@power@Sgn
+\fi
+ \fi
+ \ifnum\MFP@y@Sgn<0 \MFP@Rinv \MFP@Rcopyzx\fi
+ \ifnum\MFP@loopctr=1
+ \MFP@Rloadz \MFP@power@Sgn\MFP@x@Int\MFP@x@Frc
+ \else
+ \MFP@@Rpow
+\ifMFPdebug
+ \showreg z%
+\fi
+ \fi
+ \fi
+ \fi}% %
+% \end{macrocode}
+%
+% This implements the algorithm discussed above. We save $x$ in register
+% \texttt{q}, initialize the starting value of $1$ in \texttt{p} and then
+% run the loop. If the binary digit just read is a 1 (i.e., \cs{ifodd} is
+% true), it multiplies $p$ and $q$. It also saves the last product (copies
+% \texttt{z} to \texttt{p}). This need not be done on the last iteration,
+% but must not be moved out of the \cs{ifodd} conditional because
+% intervening computations modify $z$. If there are more iterations to do
+% (i.e., the \cs{ifnum} is true), this squares $q$ and reduces the
+% counter. Note that the exponents $0$ and $1$ do not occur since we have
+% handled them separately.
+%
+% In case of overflow (either the multiplication or the squaring) we
+% break the loop and return $\pm\infty$.
+% \begin{macrocode}
+\def\MFP@@Rpow{%
+ \MFP@Rcopy xq% initialize register to be squared
+ \MFP@Rload p110% initialize register to hold partial products
+ \MFP@Rpow@loop}%
+\def\MFP@Rpow@loop{%
+ \ifodd\MFP@loopctr
+ \MFP@Rcopy px\MFP@Rcopy qy\MFP@Rmul
+ \ifnum \MFP@z@Ovr>0 \MFP@handle@expoverflow
+ \else
+ \ifnum\MFP@loopctr>1 \MFP@Rcopyz p\fi
+ \fi
+ \fi
+ \ifnum\MFP@loopctr>1
+ \MFP@Rcopy qx\MFP@Rsq
+ \ifnum \MFP@z@Ovr>0 \MFP@handle@expoverflow
+ \else
+ \MFP@Rcopyz q%
+ \divide\MFP@loopctr 2
+ \@XP\MFP@Rpow@loop
+ \fi
+ \fi}%
+\def\MFP@handle@expoverflow{%
+ \MFP@expoverflow@err
+ \MFP@loopctr=0
+ \MFP@Rloadz\MFP@power@Sgn\MaxRealInt\MaxRealFrac
+}%
+% \end{macrocode}
+%
+% \subsection{The square root}
+%
+% One can combine logarithms and exponentials to can get any power: to get
+% $x^y$, compute $e^{y\ln x}$. This has the disadvantage that it doesn't
+% work if $x$ is negative. Most powers of negative numbers are not
+% defined, but certainly integer powers are. Thus we have defined
+% \cs{MFPpow} and \cs{Rpow} for that case.
+%
+% If we enforce a positive $x$, then $y$ can have any value. However,
+% the computation of $e^{.5\ln x}$ cannot give a result as good as one can
+% get from a special purpose algorithm for the square root. For example,
+% the inaccuracies in computing $\ln x$ will make $e^{.5\ln 9}$ inexact,
+% while the square root function we implement below will produce exactly
+% $\sqrt{9} = 3$. In fact, if a square root can be expressed exactly
+% within our 8-digit precision, our code will find it.
+%
+% For the square root we return 0 if $x$ is not positive. If the integer
+% part of $x$ is $0$, we copy the fractional part to the integer part
+% (that is, we multiply by $10^{8}$, remembering to multiply by $10^{-4}$
+% later). This makes the square root of such numbers slightly more
+% accurate. We then compute the square root using an algorithm that will
+% be exact whenever possible. We perform one additional processing step.
+% To explain it, note that our algorithm actually produces the largest
+% number $s$ with 4 digits right of the decimal place that satisfies $s^2
+% \le x$. That is
+% $$
+% s^2 \le x < \left( s + 10^{-4} \right)^2
+% $$
+% From this it follows that $x = (s+\epsilon)^2 = s^2 + 2s\epsilon +
+% \epsilon^2$ with $\epsilon < 10^{-4}$ (and so $\epsilon^2 < 10^{-8}$).
+% We estimate this $\epsilon$ and add that estimate to $s$. The estimate
+% we use is obtained by discarding the very small $\epsilon^2$ and solving
+% for the remaining $\epsilon$ get
+% $$
+% \epsilon \approx \bar\epsilon = \frac{x-s^2}{2s}
+% $$
+% With this value, $s + \bar\epsilon$ misses the exact square root by at
+% most $\epsilon^2/(2s) < .5\cdot 10^{-8}$, because $s \ge 1$.
+% The final result $s + \bar\epsilon$ is equivalent to computing the
+% average $s$ and $x/s$. This, possibly divided by $10^4$ is the
+% returned value.
+%
+% I originally tried power series methods, but they failed to produce
+% exact answers when they existed (unless they were inconveniently carried
+% to 9 decimals and then rounded to 8). Then I tried the ``exact when
+% possible'' algorithm to get $s$, but correcting it as follows: find
+% $\sqrt{x/s^2}$ by power series and multiply by $s$. But this turned out
+% to be remarkably inaccurate, being paradoxically worst when $s$ is
+% already close, but not equal, to $\sqrt{x}$. Finally, I hit on the above
+% simple and efficient correction, which turns out to be also the most
+% accurate. By tests it produces a result correct in all but the last
+% (eighth) decimal place, and within $1$ of the correct value in that
+% place. Of course, it still produces exact results when that is possible
+% within our digit limits.
+% \begin{macrocode}
+\def\MFP@Rsqrt{%
+ \ifcase\MFP@x@Sgn\relax
+ \MFP@Rzero
+ \or
+ \ifnum\MFP@x@Int=0
+ \let\MFP@sqrt@reduce=Y%
+ \edef\MFP@x@Int{\number\MFP@x@Frc}%
+ \edef\MFP@x@Frc{00000000}%
+ \else
+ \let\MFP@sqrt@reduce=N%
+ \fi
+ \MFP@Rcopy xt%
+ \MFP@Isqrt
+ \MFP@Rcopyz s\MFP@Rcopyzy
+ \MFP@Rcopy tx\MFP@Rdiv
+ \MFP@Rcopy sx\MFP@Rcopyzy\MFP@Radd
+ \MFP@Rcopyzx\MFP@Rhalve
+ \ifx Y\MFP@sqrt@reduce
+ \MFP@Rcopyzx\MFP@Rload y10{10000}\MFP@Rmul
+ \fi
+ \else
+ \MFP@sqrtofneg@err
+ \MFP@Rzero
+ \fi}%
+% \end{macrocode}
+%
+% There is a rather straightforward pencil and paper algorithm that
+% provides the square root digit by digit, and it produces an exact answer
+% when that is possible. Unfortunately, the decimal version is not easy to
+% code. Fortunately the same algorithm works in any number base and it is
+% rather simple to code the binary version (because we only need to decide
+% at each stage whether the ``next digit'' is $0$ or $1$. This produces a
+% square root in binary digits, from which it is easy to compute the
+% number itself. The result is exact if the answer would be a finite
+% number of binary digits. We apply it to the integer $10^8 x$. While this
+% number is too large for \TeX{} to handle as an integer, it is not that
+% hard to convert it to a string of binary digits stored in a macro.
+%
+% The process turns out to be simpler if we convert $10^8 x$ to base 4
+% rather than binary. Also, instead of producing the square root encoded
+% in a string of binary digits, we simply build the numerical result as we
+% discover the binary digits (multiply previous value by 2 and add the
+% new digit.) Fortunately, the square root of $10^8 x$ (and the
+% temporary scratch registers used in the code) will never exceed \TeX{}'s
+% limit for integers.
+%
+% The macro \cs{MFP@ItoQ} implements the conversion to base 4 digits.
+% The two arguments are the integer and fractional part of $x$. The
+% result is stored in \cs{MFP@ItoQ@Tmp}, which is so far only used by the
+% square root code.
+%
+% The test \cs{ifodd}\cs{MFP@tempb} is used to get the binary digits.
+% Combining two of them yields the quadrenary digits. The
+% \cs{ifodd}\cs{MFP@tempa} tests are there to check whether there
+% will be a remainder after division by $2$, which should then be
+% inserted at the front of \cs{MFP@tempb} before division by 2. Two
+% divisions by 2 each iteration amounts to division by 4. This is slightly
+% more efficient than dividing by 4 and determining the remainder.
+% \begin{macrocode}
+\def\MFP@ItoQ#1#2{%
+ \MFP@tempa#1\relax\MFP@tempb#2\relax
+ \def\MFP@ItoQ@Tmp{}\MFP@ItoQ@loop}%
+\def\MFP@ItoQ@loop{%
+ \ifodd\MFP@tempb
+ \ifodd\MFP@tempa \advance\MFP@tempb \MFP@ttteight\relax\fi
+ \divide\MFP@tempa2 \divide\MFP@tempb2
+ \edef\MFP@ItoQ@Tmp{\ifodd\MFP@tempb 3\else 1\fi\MFP@ItoQ@Tmp}%
+ \else
+ \ifodd\MFP@tempa \advance\MFP@tempb \MFP@ttteight\relax\fi
+ \divide\MFP@tempa2 \divide\MFP@tempb2
+ \edef\MFP@ItoQ@Tmp{\ifodd\MFP@tempb 2\else 0\fi\MFP@ItoQ@Tmp}%
+ \fi
+ \ifodd\MFP@tempa \advance\MFP@tempb \MFP@ttteight\relax\fi
+ \divide\MFP@tempa 2 \divide\MFP@tempb 2
+ \ifnum\MFP@tempa>0
+ \@xp\MFP@ItoQ@loop
+ \else\ifnum\MFP@tempb>0
+ \@XP\MFP@ItoQ@loop
+ \fi\fi}%
+% \end{macrocode}
+%
+% This integer square root $n$ is $10^4$ times the largest number $y$
+% satisfying $y^2 \le x$ and having at most 4 decimal places. The rest of
+% the code after the \cs{MFP@Isqrt@loop} is intended to divide $n$
+% (returned in \cs{MFP@tempc}) by $10^4$ in order to get the number $y$
+% itself.
+% \begin{macrocode}
+\def\MFP@Isqrt{%
+ \MFP@ItoQ\MFP@x@Int\MFP@x@Frc
+ \MFP@tempa=0 \MFP@tempb=0 \MFP@tempc=0
+ \expandafter\MFP@Isqrt@loop\MFP@ItoQ@Tmp\mfp@end
+ \MFP@tempa=\MFP@tempc
+ \divide\MFP@tempc\MFP@tttfour
+ \edef\MFP@z@Int{\number\MFP@tempc}%
+ \multiply\MFP@tempc \MFP@tttfour
+ \advance\MFP@tempa -\MFP@tempc
+ \edef\MFP@z@Frc{\number\MFP@tempa}%
+ \makeMFP@fourdigits\MFP@z@Frc
+ \edef\MFP@z@Frc{\MFP@z@Frc0000}%
+ \def\MFP@z@Sgn{1}}%
+% \end{macrocode}
+%
+% The following is a loop that essentially performs a base-2 version of
+% the base-10 algorithm that I learned at age 12 from my father
+% (apparently it was taught in 8th or 9th grade in his day: he never
+% finished grade 9). Seeing it written out, I am surprise at how concise
+% and elegant it is!
+% \begin{macrocode}
+\def\MFP@Isqrt@loop#1{%
+ \ifx\mfp@end #1%
+ \else
+ \multiply\MFP@tempa 2 \multiply\MFP@tempb 4 \multiply\MFP@tempc 2
+ \advance \MFP@tempb#1\relax
+ \ifnum\MFP@tempa<\MFP@tempb
+ \advance\MFP@tempc 1 \advance\MFP@tempa 1
+ \advance\MFP@tempb -\MFP@tempa
+ \advance\MFP@tempa 1
+ \fi
+ \expandafter\MFP@Isqrt@loop
+ \fi
+}%
+%</extra>
+% \end{macrocode}
+% For my own benefit: this finds the next binary digit and updates the
+% square root (in \cs{MFP@tempc}) by appending that digit. The new digit
+% is also appended to the end of \cs{MFP@tempa}. This is subtracted from
+% \cs{MFP@tempb}, but only if the last digit is a 1. Then the next
+% quadrenary digit is appended to \cs{MFP@tempb}. Finally, the last binary
+% digit found is added (not appended) to \cs{MFP@tempa}. The ``appending''
+% of a digit means a multiplication by 2 (or 4) and the addition of the
+% digit. We perform such additions only if the digit is a 1, and we
+% determine if the digit is 1 or 0 by the \cs{ifnum} test.
+%\Finale
+%
diff --git a/Master/texmf-dist/source/generic/minifp/minifp.ins b/Master/texmf-dist/source/generic/minifp/minifp.ins
new file mode 100644
index 00000000000..a3e0d22d5dc
--- /dev/null
+++ b/Master/texmf-dist/source/generic/minifp/minifp.ins
@@ -0,0 +1,51 @@
+\input docstrip
+\keepsilent
+\preamble
+
+-------------------------------------------------------------------
+
+Copyright 2008--2010, Daniel H. Luecking
+
+Minifp may be distributed and/or modified under the conditions of the
+LaTeX Project Public License, either version 1.3b of this license or (at
+your option) any later version. The latest version of this license is in
+ <http://www.latex-project.org/lppl.txt>
+and version 1.3c or later is part of all distributions of LaTeX version
+2008/12/01 or later.
+
+Minifp has maintenance status "author-maintained". The Current Maintainer
+is Daniel H. Luecking. The Base Interpreters associated
+with minifp are plain TeX and LaTeX.
+
+\endpreamble
+\askforoverwritefalse
+\generate{%
+ \file{minifp.sty}{\from{minifp.dtx}{sty}}%
+ \file{mfpextra.tex}{\from{minifp.dtx}{extra}}%
+}
+
+\def\sps{\space\space\space\space}
+\def\sJ{^^J\sps}
+\immediate\write16{%
+^^J*******************************************************************
+^^J
+^^J To finish the installation:
+^^J
+^^J -- Copy the file minifp.sty to a location where TeX and LaTeX
+\sJ will find them. For example, in a TDS compliant system,
+\sJ the directory TEXMF/tex/generic/minifp/
+^^J
+^^J -- To obtain the documentation (minifp.pdf) if not provided, run
+\sJ\sps pdflatex minifp.dtx
+\sJ\sps pdflatex minifp.dtx
+\sJ\sps pdflatex minifp.dtx
+\sJ\sps makeindex -s gind.ist minifp.idx
+\sJ\sps pdflatex minifp.dtx
+\sJ and copy minifp.pdf and README wherever you keep documentation
+\sJ (for example, TEXMF/doc/generic/minifp/).
+^^J
+^^J -- Refresh the filename database if your TeX system requires it.
+^^J
+^^J*******************************************************************}
+
+\endbatchfile
diff --git a/Master/texmf-dist/tex/generic/minifp/mfpextra.tex b/Master/texmf-dist/tex/generic/minifp/mfpextra.tex
new file mode 100644
index 00000000000..7d541bd4747
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/minifp/mfpextra.tex
@@ -0,0 +1,638 @@
+%%
+%% This is file `mfpextra.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% minifp.dtx (with options: `extra')
+%%
+%% -------------------------------------------------------------------
+%%
+%% Copyright 2008--2010, Daniel H. Luecking
+%%
+%% Minifp may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License, either version 1.3b of this license or (at
+%% your option) any later version. The latest version of this license is in
+%% <http://www.latex-project.org/lppl.txt>
+%% and version 1.3c or later is part of all distributions of LaTeX version
+%% 2008/12/01 or later.
+%%
+%% Minifp has maintenance status "author-maintained". The Current Maintainer
+%% is Daniel H. Luecking. The Base Interpreters associated
+%% with minifp are plain TeX and LaTeX.
+%%
+\def\MFP@Rextra{%
+ \def\Rcos {\MFP@stack@Unary\MFP@Rcos }%
+ \def\Rsin {\MFP@stack@Unary\MFP@Rsin }%
+ \def\Rangle{\MFP@stack@Binary\MFP@Rangle}%
+ \def\Rrad {\MFP@stack@Unary\MFP@Rrad }%
+ \def\Rdeg {\MFP@stack@Unary\MFP@Rdeg }%
+ \def\Rlog {\MFP@stack@Unary\MFP@Rlog }%
+ \def\Rln {\MFP@stack@Unary\MFP@Rln }%
+ \def\Rexp {\MFP@stack@Unary\MFP@Rexp }%
+ \def\Rsqrt {\MFP@stack@Unary\MFP@Rsqrt}%
+ \def\Rpow {\MFP@stack@Binary\MFP@Rpow}}%
+\def\MFPcos {\MFP@op@Unary\MFP@Rcos }%
+\def\MFPsin {\MFP@op@Unary\MFP@Rsin }%
+\def\MFPangle {\MFP@op@Binary\MFP@Rangle}%
+\def\MFPrad {\MFP@op@Unary\MFP@Rrad }%
+\def\MFPdeg {\MFP@op@Unary\MFP@Rdeg }%
+\def\MFPlog {\MFP@op@Unary\MFP@Rlog }%
+\def\MFPln {\MFP@op@Unary\MFP@Rln }%
+\def\MFPexp {\MFP@op@Unary\MFP@Rexp }%
+\def\MFPsqrt {\MFP@op@Unary\MFP@Rsqrt}%
+\def\MFPpow {\MFP@op@Binary\MFP@Rpow}%
+\def\MFP@logofzero@err{%
+ \MFP@errmsg{logarithm of zero}%
+ {You tried to take the logarithm of zero. What were you %
+ thinking? If you ^^Jcontinue, the value %
+ assigned will be -\LogOfZeroInt.\LogOfZeroFrac.}}%
+\def\LogOfZeroInt {\MaxRealInt}%
+\def\LogOfZeroFrac{\MaxRealFrac}%
+\def\MFP@expoverflow@err{%
+ \MFP@errmsg{Power too large}%
+ {The power you tried to calcualate is too large for %
+ 8 digits. If you continue, ^^Jthe value assigned will be %
+ \MaxRealInt.\MaxRealFrac.}}%
+\def\MFP@sqrtofneg@err{%
+ \MFP@errmsg{square root of a negative number}%
+ {You tried to take the square root of a negative value. What %
+ were you thinking? If you continue, zero will be returned.}}%
+\def\MFP@badpower@err{%
+ \MFP@errmsg{negative power of zero}%
+ {You tried to take a negative power of zero. What were you
+ thinking? If you ^^Jcontinue, the value assigned will be %
+ \xOverZeroInt.\xOverZeroFrac.}}%
+\def\MFP@Rcopyz#1{\MFP@Rload {#1}\MFP@z@Sgn\MFP@z@Int\MFP@z@Frc}%
+\def\MFP@Rcopyzx{\MFP@Rcopyz x}%
+\def\MFP@Rcopyzy{\MFP@Rcopyz y}%
+\def\MFP@Rdeg{%
+ \MFP@Rcopy xt\MFP@Rload y1{57}{29577951}\MFP@Rmul
+ \MFP@Rcopyz s\MFP@Rcopy tx\MFP@Rload y10{30823209}\MFP@Rmul
+ \MFP@tempa\MFP@z@Int\relax
+ \ifnum\MFP@z@Frc<50000000 \else \advance\MFP@tempa 1 \fi
+ \MFP@Rload x{\ifnum\MFP@tempa>0 \MFP@z@Sgn\else0\fi}0\MFP@tempa
+ \MFP@Rcopy sy\MFP@Radd}%
+\def\MFP@Rrad{%
+ \MFP@Rcopy xt\MFP@Rload y10{0174 5329}\MFP@Rmul
+ \MFP@Rcopyz s\MFP@Rcopy tx\MFP@Rload y10{25199433}\MFP@Rmul
+ \MFP@tempa\MFP@z@Int\relax
+ \ifnum\MFP@z@Frc<50000000 \else \advance\MFP@tempa 1 \fi
+ \MFP@Rload x{\ifnum\MFP@tempa>0 \MFP@z@Sgn\else0\fi}0\MFP@tempa
+ \MFP@Rcopy sy\MFP@Radd}%
+\def\MFP@Rcos{%
+ \MFP@Rcopy xy\MFP@Rload x1{90}0\MFP@Rsub
+ \MFP@Rcopyzx\MFP@Rsin}%
+\def\MFP@Rsin{%
+ \ifnum \MFP@x@Sgn=0 % return 0
+ \MFP@Rzero
+ \else
+ \MFP@tempa\MFP@x@Int\relax
+ \MFP@reduce@angle
+ \ifnum \MFP@tempa<180
+ \edef\MFP@sin@Sgn{\MFP@x@Sgn}%
+ \else
+ \edef\MFP@sin@Sgn{\number-\MFP@x@Sgn}%
+ \advance \MFP@tempa-180
+ \fi
+ \MFP@tempb\MFP@x@Frc\relax
+ \ifnum\MFP@tempa>0
+ \MFP@@Rsin
+ \else\ifnum\MFP@tempb>0
+ \MFP@@Rsin
+ \else
+ \MFP@Rzero
+ \fi\fi
+ \fi}%
+\def\MFP@reduce@angle{%
+ \ifnum\MFP@tempa<360
+ \else
+ \advance\MFP@tempa-360
+ \@xp\MFP@reduce@angle
+ \fi}%
+\def\MFP@@Rsin{%
+ \ifnum\MFP@tempa<90
+ \else
+ \ifnum\MFP@tempb>0
+ \advance\MFP@tempa 1
+ \MFP@tempb -\MFP@tempb
+ \advance\MFP@tempb \MFP@ttteight\relax
+ \fi
+ \MFP@tempa -\MFP@tempa
+ \advance\MFP@tempa 180
+ \fi
+ \ifnum\MFP@tempa=90
+ \MFP@Rloadz \MFP@sin@Sgn10%
+ \else
+ \advance\MFP@tempb 50
+ \divide\MFP@tempb 100
+ \multiply\MFP@tempa 1000000
+ \advance\MFP@tempb\MFP@tempa
+ \MFP@Rsin@prog
+ \fi}%
+\def\MFP@Rsin@prog{%
+ \MFP@Rload x10\MFP@tempb
+ \MFP@Rcopy xs%
+ \MFP@Rsq
+ \MFP@Rcopyz t%
+ \MFP@Rcopy tx%
+ \MFP@Rload y10{00559959}\MFP@Rsmul\MFP@com@iter{01450559}%
+ \MFP@com@iter{01952675}\MFP@com@iter{02769249}\MFP@com@iter{04230797}%
+ \MFP@com@iter{07252796}\MFP@com@iter{15230871}\MFP@com@iter{50769570}%
+ \MFP@flipz\MFP@Rcopyzx\MFP@Rcopy sy\MFP@Rsmul
+ \MFP@Rcopyzx\MFP@Rload y11{74532925}\MFP@Rmul
+ \let\MFP@z@Sgn\MFP@sin@Sgn}%
+\def\MFP@flipz{%
+ \ifnum\MFP@z@Sgn=0
+ \MFP@Rloadz 110%
+ \else
+ \MFP@tempa\MFP@ttteight % representing 1.00000000
+ \advance\MFP@tempa-\MFP@z@Frc\relax
+ \MFP@Rloadz{\ifcase\MFP@tempa 0\else1\fi}0\MFP@tempa
+ \fi}%
+\def\MFP@com@iter#1{\MFP@flipz
+ \MFP@Rcopyzx\MFP@Rcopy ty\MFP@Rsmul
+ \MFP@Rcopyzx\MFP@Rload y10{#1}\MFP@Rsmul}%
+\def\MFP@Rsmul{%
+ \ifnum \MFP@x@Sgn=0
+ \MFP@Rzero
+ \else\ifnum \MFP@y@Sgn=0
+ \MFP@Rzero
+ \else\ifnum\MFP@x@Int>0 % x must be 1.0
+ \MFP@Rcopy yz%
+ \else\ifnum\MFP@y@Int>0 % y must be 1.0
+ \MFP@Rcopy xz%
+ \else
+ \MFP@@Rsmul
+ \fi\fi\fi\fi}%
+\def\MFP@@Rsmul{%
+ \MFP@split\MFP@x@Frc\MFP@x@Frc@i\MFP@x@Frc@ii
+ \MFP@split\MFP@y@Frc\MFP@y@Frc@i\MFP@y@Frc@ii
+ \def\MFP@z@Frc@i {0}\def\MFP@z@Frc@ii {0}%
+ \def\MFP@z@Frc@iii{0}\def\MFP@z@Frc@iv {0}%
+ \MFP@tempb\MFP@y@Frc@ii\relax
+ \MFP@multiplyone\MFP@x@Frc@ii\MFP@z@Frc@iv
+ \MFP@multiplyone\MFP@x@Frc@i\MFP@z@Frc@iii
+ \MFP@tempb\MFP@y@Frc@i\relax
+ \MFP@multiplyone\MFP@x@Frc@ii\MFP@z@Frc@iii
+ \MFP@multiplyone\MFP@x@Frc@i\MFP@z@Frc@ii
+ \MFP@carrym\MFP@z@Frc@iv\MFP@z@Frc@iii
+ \MFP@carrym\MFP@z@Frc@iii\MFP@z@Frc@ii
+ \ifnum\MFP@z@Frc@iii<5000 \else
+ \MFP@tempb\MFP@z@Frc@ii
+ \advance\MFP@tempb1
+ \edef\MFP@z@Frc@ii{\number\MFP@tempb}\fi
+ \MFP@carrym\MFP@z@Frc@ii\MFP@z@Frc@i
+ \makeMFP@fourdigits\MFP@z@Frc@iv
+ \makeMFP@fourdigits\MFP@z@Frc@iii
+ \makeMFP@fourdigits\MFP@z@Frc@ii
+ \makeMFP@fourdigits\MFP@z@Frc@i
+ \def\MFP@z@Int{0}%
+ \edef\MFP@z@Frc{\MFP@z@Frc@i\MFP@z@Frc@ii}%
+ \edef\MFP@z@Sgn{\ifnum\MFP@z@Frc=0 0\else 1\fi}%
+ \edef\MFP@z@Und{\MFP@z@Frc@iii\MFP@z@Frc@iv}%
+ \edef\MFP@z@Ovr{0}}%
+\def\MFP@Rangle{%
+ \ifcase\MFP@y@Sgn\relax
+ \ifcase\MFP@x@Sgn\relax
+ \MFP@warn{Point (0,0) has no angle. Returning 0 anyway}%
+ \MFP@Rzero
+ \or
+ \MFP@Rzero
+ \else
+ \MFP@Rloadz 1{180}0%
+ \fi
+ \@xp\@gobble
+ \or
+ \def\MFP@angle@Sgn{1}\@xp\@firstofone
+ \else
+ \def\MFP@y@Sgn{1}%
+ \def\MFP@angle@Sgn{-1}\@xp\@firstofone
+ \fi
+ {\ifcase\MFP@x@Sgn\relax
+ \MFP@Rloadz1{90}0%
+ \or \MFP@@Rangle
+ \else
+ \def\MFP@x@Sgn{1}\MFP@@Rangle
+ \MFP@Rcopyzy\MFP@Rload x1{180}0\MFP@Rsub
+ \fi
+ \let\MFP@z@Sgn\MFP@angle@Sgn
+ }}%
+\def\MFP@@Rangle{%
+ \MFP@Rcmp
+ \ifMFP@neg
+ \MFP@Rcopy xs\MFP@Rcopy yx\MFP@Rcopy sy%
+ \MFP@@@Rangle
+ \MFP@Rload x1{90}0\MFP@Rcopyzy\MFP@Rsub
+ \else
+ \MFP@@@Rangle
+ \fi
+}%
+\def\MFP@Rquad{\MFP@Rdbl\MFP@Rcopyzx\MFP@Rdbl}%
+\def\MFP@@@Rangle{%
+ \MFP@Rcopy xs\MFP@Rcopy yt%
+ \ifnum\MFP@y@Int<500000
+ \else
+ \MFP@Rload y1{200}0\MFP@Rdiv
+ \MFP@Rcopyz s\MFP@Rcopy tx%
+ \MFP@Rload y1{200}0\MFP@Rdiv
+ \MFP@Rcopyz t%
+ \fi
+ \MFP@Rcopy tx\MFP@Rdbl\MFP@Rcopyzx\MFP@Rcopy sy\MFP@Rcmp
+ \ifMFP@pos
+ \MFP@Rsub\MFP@Rcopyz u\MFP@Rcopy sx\MFP@Rdbl
+ \MFP@Rcopyzx\MFP@Rcopy ty\MFP@Radd
+ \MFP@Rcopyz s\MFP@Rcopy ut%
+ \MFP@Rload a1{2656}{50511771}%
+ \else
+ \MFP@Rload a000%
+ \fi
+ \MFP@Rcopy tx\MFP@Rquad\MFP@Rcopyzx\MFP@Rcopy sy\MFP@Rcmp
+ \ifMFP@pos
+ \MFP@Rsub\MFP@Rcopyz u\MFP@Rcopy sx\MFP@Rquad
+ \MFP@Rcopyzx\MFP@Rcopy ty\MFP@Radd
+ \MFP@Rcopyz s\MFP@Rcopy ut%
+ \MFP@Rcopy ax\MFP@Rload y1{1403}{62434679}%
+ \MFP@Radd\MFP@Rcopy za%
+ \fi
+ \MFP@Rcopy tx\MFP@RmulC
+ \MFP@Rcopyzx\MFP@Rcopy sy\MFP@Rdiv
+ \MFP@Rcopyzx\MFP@Ratanc
+ \MFP@Rcopyzx\MFP@Rdeg
+ \MFP@Rcopyzx\MFP@Rcopy ay\MFP@Radd
+ \MFP@Rcopyzx\MFP@RdivC}%
+\def\MFP@RmulC{%
+ \makeMFP@eightdigits\MFP@x@Frc
+ \edef\MFP@Tmp{\number\MFP@x@Int.\MFP@x@Frc}%
+ \@xp\MFP@@RmulC\MFP@Tmp\mfp@end}%
+\def\MFP@@RmulC#1.#2#3#4\mfp@end{%
+ \MFP@Rloadz\MFP@x@Sgn{#1#2#3}{#400}}%
+\def\MFP@RdivC{%
+ \makeMFP@eightdigits\MFP@x@Int
+ \makeMFP@eightdigits\MFP@x@Frc
+ \@XP\MFP@@RdivC\@xp\MFP@x@Int\MFP@x@Frc\mfp@end}%
+\def\MFP@@RdivC#1#2#3#4#5#6{%
+ \edef\MFP@z@Int{\number#1#2#3#4#5#6}%
+ \MFP@@@RdivC}%
+\def\MFP@@@RdivC#1#2#3#4#5#6#7#8#9\mfp@end{%
+ \MFP@tempa#1#2#3#4#5#6#7#8\relax
+ \ifnum#9>49 \advance\MFP@tempa1 \fi
+ \edef\MFP@z@Sgn{\MFP@x@Sgn}%
+ \ifnum\MFP@tempa=0 \ifnum\MFP@x@Int=0 \def\MFP@z@Sgn{0}\fi\fi
+ \MFP@Rloadz\MFP@z@Sgn\MFP@z@Int\MFP@tempa}%
+\def\MFP@scaledmul{\MFP@Rmul\MFP@Rcopyzx\MFP@RdivC}%
+\def\MFP@atan@iter#1#2{%
+ \MFP@Rcopy uy\MFP@scaledmul
+ \MFP@Rcopyzx\MFP@Rload y1{#1}{#2}\MFP@scaledmul
+ \MFP@Rcopyzy\MFP@Rload x1{100}{00000000}%
+ \MFP@Rsub\MFP@Rcopyzx}%
+\def\MFP@Ratanc{%
+ \MFP@Rcopy xs%
+ \MFP@Rcopy xy\MFP@scaledmul\MFP@Rcopyz u%
+ \MFP@Rcopyzx\MFP@Rload y1{86}{66666667}%
+ \MFP@scaledmul
+ \MFP@Rcopyzy\MFP@Rload x1{100}{00000000}%
+ \MFP@Rsub\MFP@Rcopyzx
+ \MFP@atan@iter{84}{61538462}\MFP@atan@iter{81}{81818182}%
+ \MFP@atan@iter{77}{77777778}\MFP@atan@iter{71}{42857143}%
+ \MFP@atan@iter{60}{00000000}\MFP@atan@iter{33}{33333333}%
+ \MFP@Rcopy sy\MFP@scaledmul}%
+\def\MFP@Rlog{%
+ \ifnum\MFP@x@Sgn=0
+ \MFP@logofzero@err
+ \MFP@Rloadz{-1}\LogOfZeroInt\LogOfZeroFrac
+ \else
+ \ifnum \MFP@x@Sgn<0
+ \MFP@warn{The logarithm of a negative number is complex.%
+ \MFP@msgbreak Only the real part will be computed}%
+ \fi
+ \MFP@Rload s000%
+ \ifnum \MFP@x@Int=0
+ \edef\MFP@x@Tmp{\number\MFP@x@Frc}%
+ \MFP@tempa=\MFP@numzeros\MFP@x@Tmp\relax
+ \def\MFP@s@Sgn{-1}%
+ \edef\MFP@t@Int{\@xp\MFP@firstofmany\MFP@x@Tmp\mfp@end}%
+ \edef\MFP@t@Frc{\@xp\@gobble\MFP@x@Tmp0}%
+ \MFPpadto@eight\MFP@t@Frc
+ \else
+ \MFP@tempa\MFP@numdigits\MFP@x@Int
+ \edef\MFP@x@Tmp{\MFP@x@Int\MFP@x@Frc}% gather all digits
+ \edef\MFP@s@Sgn{1}%
+ \edef\MFP@t@Int{\@xp\MFP@firstofmany\MFP@x@Tmp\mfp@end}%
+ \edef\MFP@x@Tmp{\@xp\@gobble\MFP@x@Tmp}%
+ \edef\MFP@t@Frc{\@xp\MFP@firsteightofmany\MFP@x@Tmp\mfp@end}%
+ \fi
+ \edef\MFP@s@Int{\number\MFP@tempa}%
+ \def\MFP@t@Sgn{1}%
+ \MFP@Rlog@reduce
+ \ifnum\MFP@t@Frc=0
+ \MFP@Rcopy sz%
+ \else
+ \MFP@Rlog@prog
+ \fi
+ \fi}%
+\def\showreg #1{% for debugging
+\begingroup
+ \edef\reg{%
+ #1 = (\csname MFP@#1@Sgn\endcsname)%
+ \csname MFP@#1@Int\endcsname.%
+ \csname MFP@#1@Frc\endcsname}%
+ \show\reg
+\endgroup}%
+\def\MFP@numdigits#1{\@xp\MFP@ninthofmany#176543210\mfp@end}%
+\def\MFP@numzeros#1{%
+ \@xp\MFP@ninthofmany#112345678\mfp@end}%
+\def\MFP@Rlog@reduce{%
+ \MFP@reduceonce 3{16227766}{31622777}{50000000}%
+ \MFP@reduceonce 1{77827941}{56234133}{25000000}%
+ \MFP@reduceonce 1{33352143}{74989421}{12500000}%
+ \MFP@reduceonce 1{15478198}{86596433}{06250000}}%
+\def\MFP@reduceonce#1#2#3#4{%
+ \MFP@Rcopy tx\MFP@Rload y1{#1}{#2}\MFP@Rcmp
+ \ifMFP@neg\else
+ \MFP@Rload y10{#3}\MFP@Rmul
+ \MFP@Rcopyz t\MFP@Rcopy sx\MFP@Rload y10{#4}\MFP@Radd
+ \MFP@Rcopyz s%
+ \fi}%
+\def\MFP@Rlog@prog{%
+ \MFP@Rcopy tx\MFP@Rdecr
+ \MFP@Rcopyz t%
+ \MFP@Rcopyzx\MFP@Rload y10{43750000}\MFP@Rsmul
+ \MFP@com@iter{85714286}\MFP@com@iter{83333333}\MFP@com@iter{80000000}%
+ \MFP@com@iter{75000000}\MFP@com@iter{66666667}\MFP@com@iter{50000000}%
+ \MFP@com@iter{43429448}\MFP@Rcopyzx\MFP@Rcopy sy\MFP@Radd}%
+\def\MFP@Rln{%
+ \MFP@Rlog\MFP@Rcopyzx\MFP@Rload y12{30258509}\MFP@Rmul}%
+\def\MFP@Rexp{%
+ \ifcase\MFP@x@Sgn\relax
+ \MFP@Rloadz 110%
+ \or
+ \MFP@Rexp@pos
+ \else
+ \def\MFP@x@Sgn{1}%
+ \MFP@Rexp@neg % computes e^{-x}, not e^x
+ \fi}%
+\def\MFP@Rexp@pos{%
+ \MFP@Rload y1{18}{42068074}\MFP@Rcmp
+ \ifMFP@pos % overflow
+ \MFP@expoverflow@err
+ \MFP@Rloadz 1\MaxRealInt\MaxRealFrac
+ \else % handle integer part
+ \MFP@tempa\MFP@x@Int
+ \edef\MFP@powerof@e{%
+ 1\ifcase\MFP@tempa
+ 10\or
+ 2{71828183}\or
+ 7{38905610}\or
+ {20}{08553692}\or
+ {54}{59815003}\or
+ {148}{41315910}\or
+ {403}{42879349}\or
+ {1096}{63315843}\or
+ {2980}{95798704}\or
+ {8103}{08392758}\or
+ {22026}{46579481}\or
+ {59874}{14171520}\or
+ {162754}{79141900}\or
+ {442413}{39200892}\or
+ {1202604}{28416478}\or
+ {3269017}{37247211}\or
+ {8886110}{52050787}\or
+ {24154952}{75357530}\or
+ {65659969}{13733051}\else
+ {\MaxRealInt}{\MaxRealFrac}\fi}%
+ \@xp\MFP@Rloadz\MFP@powerof@e
+ \ifnum\MFP@x@Frc=0
+ \else
+ \MFP@Rcopyz s%
+ \MFP@tempa=\@xp\MFP@firstofmany\MFP@x@Frc\mfp@end
+ \edef\MFP@powerof@e{%
+ y1\ifcase\MFP@tempa
+ 10\or
+ 1{10517092}\or
+ 1{22140276}\or
+ 1{34985881}\or
+ 1{49182470}\or
+ 1{64872127}\or
+ 1{82211880}\or
+ 2{01375271}\or
+ 2{22554093}\or
+ 2{45960311}\else
+ 10\fi}%
+ \edef\MFP@t@Frc{0\@xp\@gobble\MFP@x@Frc}%
+ \MFP@Rcopy sx\@xp\MFP@Rload\MFP@powerof@e\MFP@Rmul
+ \ifnum\MFP@t@Frc=0
+ \else % handle the rest
+ \MFP@Rcopyz s\MFP@Rload t10\MFP@t@Frc
+ \MFP@Rexp@pos@prog
+ \MFP@Rcopy sx\MFP@Rcopyzy\MFP@Rmul
+ \fi
+ \fi
+ \fi}%
+\def\MFP@Rexp@pos@prog{%
+ \MFP@Rcopy tz\MFP@Rexp@iter{16666667}\MFP@Rexp@iter{20000000}%
+ \MFP@Rexp@iter{25000000}\MFP@Rexp@iter{33333333}%
+ \MFP@Rexp@iter{50000000}\MFP@Rcopyzx\MFP@Rincr}%
+\def\MFP@Rexp@iter#1{%
+ \MFP@Rcopyzx\MFP@Rload y10{#1}\MFP@Rsmul
+ \MFP@Rcopyzx\MFP@Rcopy ty\MFP@Rsmul
+ \MFP@Rcopyzx\MFP@Rcopy ty\MFP@Radd}%
+\def\MFP@Rexp@neg{%
+ \MFP@Rload y1{19}{11382792}%
+ \MFP@Rcmp
+ \ifMFP@pos
+ \MFP@Rloadz 000%
+ \else % handle integer part
+ \MFP@tempa\MFP@x@Int
+ \edef\MFP@powerof@e{%
+ \ifcase\MFP@tempa
+ 11{0}\or
+ 10{36787944}\or
+ 10{13533528}\or
+ 10{04978707}\or
+ 10{01831564}\or
+ 10{00673795}\or
+ 10{00247875}\or
+ 10{00091188}\or
+ 10{00033546}\or
+ 10{00012341}\or
+ 10{00004540}\or
+ 10{00001670}\or
+ 10{00000614}\or
+ 10{00000226}\or
+ 10{00000083}\or
+ 10{00000031}\or
+ 10{00000011}\or
+ 10{00000004}\or
+ 10{00000002}\or
+ 10{00000001}\else
+ 000\fi}%
+ \@xp\MFP@Rloadz\MFP@powerof@e
+ \ifnum\MFP@x@Frc=0
+ \else % handle first decimal digit
+ \MFP@Rcopyz s%
+ \MFP@tempa=\@xp\MFP@firstofmany\MFP@x@Frc\mfp@end
+ \edef\MFP@powerof@e{%
+ y1\ifcase\MFP@tempa
+ 10\or
+ 0{90483742}\or
+ 0{81873075}\or
+ 0{74081822}\or
+ 0{67032005}\or
+ 0{60653066}\or
+ 0{54881164}\or
+ 0{49658530}\or
+ 0{44932896}\or
+ 0{40656966}\else
+ 10\fi}%
+ \edef\MFP@t@Frc{0\@xp\@gobble\MFP@x@Frc}%
+ \MFP@Rcopy sx\@xp\MFP@Rload\MFP@powerof@e\MFP@Rmul
+ \ifnum\MFP@t@Frc=0
+ \else % handle the rest
+ \MFP@Rcopyz s\MFP@Rload t10\MFP@t@Frc
+ \MFP@Rexp@neg@prog
+ \MFP@Rcopy sx\MFP@Rcopyzy\MFP@Rmul
+ \fi
+ \fi
+ \fi}%
+\def\MFP@Rexp@neg@prog{%
+ \MFP@Rcopy tx\MFP@Rload y10{16666667}\MFP@Rsmul
+ \MFP@com@iter{20000000}\MFP@com@iter{25000000}%
+ \MFP@com@iter{33333333}\MFP@com@iter{50000000}%
+ \MFP@flipz\MFP@Rcopyzx\MFP@Rcopy ty\MFP@Rsmul\MFP@flipz}%
+\def\MFP@Rpow{%
+ \ifnum\MFP@y@Frc>0
+ \MFP@warn{The "pow" function requires an integer power.
+ \MFP@msgbreak The fractional part will be ignored}%
+ \fi
+ \MFP@loopctr=\MFP@y@Int\relax
+ \ifnum\MFP@loopctr=0 % zero power = 1
+ \MFP@Rloadz 110%
+ \else
+ \ifnum\MFP@x@Sgn=0
+ \ifnum\MFP@y@Sgn>0 % + powers of zero are 0
+ \MFP@Rloadz 000%
+ \else % - powers are errors
+ \MFP@badpower@err
+ \MFP@Rloadz 1\xOverZeroInt\xOverZeroFrac
+ \fi
+ \else % integer power of nonzero number
+ % get the sign in case an overflow interrupts the calculations.
+ \ifnum\MFP@x@Sgn>0
+ \def\MFP@power@Sgn{1}%
+ \else
+ \edef\MFP@power@Sgn{\ifodd\MFP@loopctr -\fi 1}%
+\ifMFPdebug
+ \show\MFP@power@Sgn
+\fi
+ \fi
+ \ifnum\MFP@y@Sgn<0 \MFP@Rinv \MFP@Rcopyzx\fi
+ \ifnum\MFP@loopctr=1
+ \MFP@Rloadz \MFP@power@Sgn\MFP@x@Int\MFP@x@Frc
+ \else
+ \MFP@@Rpow
+\ifMFPdebug
+ \showreg z%
+\fi
+ \fi
+ \fi
+ \fi}% %
+\def\MFP@@Rpow{%
+ \MFP@Rcopy xq% initialize register to be squared
+ \MFP@Rload p110% initialize register to hold partial products
+ \MFP@Rpow@loop}%
+\def\MFP@Rpow@loop{%
+ \ifodd\MFP@loopctr
+ \MFP@Rcopy px\MFP@Rcopy qy\MFP@Rmul
+ \ifnum \MFP@z@Ovr>0 \MFP@handle@expoverflow
+ \else
+ \ifnum\MFP@loopctr>1 \MFP@Rcopyz p\fi
+ \fi
+ \fi
+ \ifnum\MFP@loopctr>1
+ \MFP@Rcopy qx\MFP@Rsq
+ \ifnum \MFP@z@Ovr>0 \MFP@handle@expoverflow
+ \else
+ \MFP@Rcopyz q%
+ \divide\MFP@loopctr 2
+ \@XP\MFP@Rpow@loop
+ \fi
+ \fi}%
+\def\MFP@handle@expoverflow{%
+ \MFP@expoverflow@err
+ \MFP@loopctr=0
+ \MFP@Rloadz\MFP@power@Sgn\MaxRealInt\MaxRealFrac
+}%
+\def\MFP@Rsqrt{%
+ \ifcase\MFP@x@Sgn\relax
+ \MFP@Rzero
+ \or
+ \ifnum\MFP@x@Int=0
+ \let\MFP@sqrt@reduce=Y%
+ \edef\MFP@x@Int{\number\MFP@x@Frc}%
+ \edef\MFP@x@Frc{00000000}%
+ \else
+ \let\MFP@sqrt@reduce=N%
+ \fi
+ \MFP@Rcopy xt%
+ \MFP@Isqrt
+ \MFP@Rcopyz s\MFP@Rcopyzy
+ \MFP@Rcopy tx\MFP@Rdiv
+ \MFP@Rcopy sx\MFP@Rcopyzy\MFP@Radd
+ \MFP@Rcopyzx\MFP@Rhalve
+ \ifx Y\MFP@sqrt@reduce
+ \MFP@Rcopyzx\MFP@Rload y10{10000}\MFP@Rmul
+ \fi
+ \else
+ \MFP@sqrtofneg@err
+ \MFP@Rzero
+ \fi}%
+\def\MFP@ItoQ#1#2{%
+ \MFP@tempa#1\relax\MFP@tempb#2\relax
+ \def\MFP@ItoQ@Tmp{}\MFP@ItoQ@loop}%
+\def\MFP@ItoQ@loop{%
+ \ifodd\MFP@tempb
+ \ifodd\MFP@tempa \advance\MFP@tempb \MFP@ttteight\relax\fi
+ \divide\MFP@tempa2 \divide\MFP@tempb2
+ \edef\MFP@ItoQ@Tmp{\ifodd\MFP@tempb 3\else 1\fi\MFP@ItoQ@Tmp}%
+ \else
+ \ifodd\MFP@tempa \advance\MFP@tempb \MFP@ttteight\relax\fi
+ \divide\MFP@tempa2 \divide\MFP@tempb2
+ \edef\MFP@ItoQ@Tmp{\ifodd\MFP@tempb 2\else 0\fi\MFP@ItoQ@Tmp}%
+ \fi
+ \ifodd\MFP@tempa \advance\MFP@tempb \MFP@ttteight\relax\fi
+ \divide\MFP@tempa 2 \divide\MFP@tempb 2
+ \ifnum\MFP@tempa>0
+ \@xp\MFP@ItoQ@loop
+ \else\ifnum\MFP@tempb>0
+ \@XP\MFP@ItoQ@loop
+ \fi\fi}%
+\def\MFP@Isqrt{%
+ \MFP@ItoQ\MFP@x@Int\MFP@x@Frc
+ \MFP@tempa=0 \MFP@tempb=0 \MFP@tempc=0
+ \expandafter\MFP@Isqrt@loop\MFP@ItoQ@Tmp\mfp@end
+ \MFP@tempa=\MFP@tempc
+ \divide\MFP@tempc\MFP@tttfour
+ \edef\MFP@z@Int{\number\MFP@tempc}%
+ \multiply\MFP@tempc \MFP@tttfour
+ \advance\MFP@tempa -\MFP@tempc
+ \edef\MFP@z@Frc{\number\MFP@tempa}%
+ \makeMFP@fourdigits\MFP@z@Frc
+ \edef\MFP@z@Frc{\MFP@z@Frc0000}%
+ \def\MFP@z@Sgn{1}}%
+\def\MFP@Isqrt@loop#1{%
+ \ifx\mfp@end #1%
+ \else
+ \multiply\MFP@tempa 2 \multiply\MFP@tempb 4 \multiply\MFP@tempc 2
+ \advance \MFP@tempb#1\relax
+ \ifnum\MFP@tempa<\MFP@tempb
+ \advance\MFP@tempc 1 \advance\MFP@tempa 1
+ \advance\MFP@tempb -\MFP@tempa
+ \advance\MFP@tempa 1
+ \fi
+ \expandafter\MFP@Isqrt@loop
+ \fi
+}%
+\endinput
+%%
+%% End of file `mfpextra.tex'.
diff --git a/Master/texmf-dist/tex/generic/minifp/minifp.sty b/Master/texmf-dist/tex/generic/minifp/minifp.sty
new file mode 100644
index 00000000000..21462ece64f
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/minifp/minifp.sty
@@ -0,0 +1,806 @@
+%%
+%% This is file `minifp.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% minifp.dtx (with options: `sty')
+%%
+%% -------------------------------------------------------------------
+%%
+%% Copyright 2008--2010, Daniel H. Luecking
+%%
+%% Minifp may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License, either version 1.3b of this license or (at
+%% your option) any later version. The latest version of this license is in
+%% <http://www.latex-project.org/lppl.txt>
+%% and version 1.3c or later is part of all distributions of LaTeX version
+%% 2008/12/01 or later.
+%%
+%% Minifp has maintenance status "author-maintained". The Current Maintainer
+%% is Daniel H. Luecking. The Base Interpreters associated
+%% with minifp are plain TeX and LaTeX.
+%%
+\def\MFPfiledate{2013/01/01}%
+\def\MFPfileversion{0.9}%
+\expandafter
+\ifx \csname MFP@finish\endcsname\relax
+\else \expandafter\endinput \fi
+\expandafter\edef\csname MFP@finish\endcsname{%
+ \catcode64=\the\catcode64 \space % @
+ \catcode46=\the\catcode46 \space % .
+ \catcode60=\the\catcode60 \space % <
+ \catcode62=\the\catcode62 \space}% >
+\ifx\ProvidesPackage\UndEfInEd
+ \newlinechar`\^^J%
+ \message{%
+ Package minifp: \MFPfiledate\space v\MFPfileversion. %
+ Macros for real number operations %
+ ^^Jand a stack-based programing language.^^J}%
+\else
+ \ProvidesPackage{minifp}[\MFPfiledate\space v\MFPfileversion. %
+ Macros for real number operations %
+ and a stack-based programing language.]%
+ \DeclareOption{extra}{\def\MFPextra{}}%
+ \ProcessOptions\relax
+\fi
+\catcode64=11 % @=letter (already is in LaTeX)
+\ifx\MFPextra\UndEfInEd
+ \def\MFP@loadextra{}%
+\else
+ \def\MFP@loadextra{\input mfpextra\relax}%
+\fi
+\def\MFPloadextra{%
+ \edef\MFP@load@extra{%
+ \catcode46=12 \catcode60=12 \catcode62=12 \catcode64=11
+ \noexpand\input mfpextra\relax
+ \catcode46=\the\catcode46\relax\catcode60=\the\catcode60\relax
+ \catcode62=\the\catcode62\relax\catcode64=\the\catcode64\relax}%
+ \MFP@load@extra}%
+\catcode46=12 % .
+\catcode60=12 % <
+\catcode62=12 % >
+\long\def\gobbleto@mfp@end#1\mfp@end{}%
+\ifx\mfp@end\UndEfInEd\def\mfp@end{\@empty}\fi
+\ifx\documentclass\UndEfInEd
+ \def\MFP@ifnoLaTeX{}%
+\else
+ \let\MFP@ifnoLaTeX\gobbleto@mfp@end
+\fi
+\let\@xp\expandafter
+\def\@XP{\@xp\@xp\@xp}%
+\MFP@ifnoLaTeX
+ \def\@empty{}%
+ \long\def\@gobble#1{}%
+ \def\zap@space#1 #2{#1\ifx#2\@empty\else\@xp\zap@space\fi#2}%
+ \long\def\@ifnextchar#1#2#3{%
+ \let\reserved@d#1%
+ \def\reserved@a{#2}%
+ \def\reserved@b{#3}%
+ \futurelet\@let@token\@ifnch}%
+ \def\@ifnch{%
+ \ifx\@let@token\@sptoken
+ \let\reserved@c\@xifnch
+ \else
+ \ifx\@let@token\reserved@d
+ \let\reserved@c\reserved@a
+ \else
+ \let\reserved@c\reserved@b
+ \fi
+ \fi
+ \reserved@c}%
+ {%
+ \def\:{\global\let\@sptoken= }\: %
+ \def\:{\@xifnch}\@xp\gdef\: {\futurelet\@let@token\@ifnch}%
+ }%
+ \def\@ifstar#1{\@ifnextchar*{\@firstoftwo{#1}}}%
+ \long\def\@firstofone #1{#1}%
+ \long\def\@firstoftwo #1#2{#1}%
+ \long\def\@secondoftwo#1#2{#2}%
+\mfp@end
+\def\MFP@tttfour {10000}% ttt = Ten To The
+\def\MFP@ttteight{100000000}%
+\def\MFP@firstofmany#1#2\mfp@end{#1}%
+\def\MFP@fifthofmany#1#2#3#4#5#6\mfp@end{#5}%
+\def\MFP@ninthofmany#1#2#3#4#5#6#7#8{\MFP@firstofmany}%
+\def\MFP@firsteightofmany#1#2#3#4#5#6#7#8#9\mfp@end{#1#2#3#4#5#6#7#8}%
+\let\MFP@eos\relax
+\def\MFP@EOS{\MFP@eos}%
+\def\MFP@initRstack{\def\MFP@Rstack{\MFP@eos}}%
+\MFP@initRstack
+\countdef \MFP@tempa 0
+\countdef \MFP@tempb 2
+\countdef \MFP@tempc 4
+\countdef \MFP@tempd 6
+\countdef \MFP@tempe 8
+\countdef \MFP@tempf 10
+\newcount \MFP@loopctr
+\def\MFP@endgroup@after#1{\edef\x{\endgroup#1}\x}%
+\def\MFP@endgroup@return{\MFP@endgroup@after\MFP@returned@values}%
+\def\MFP@def@after{\def\noexpand}%
+\def\MFP@returned@values{%
+ \MFP@def@after\MFP@z@Val{\MFP@z@Sign\MFP@z@Int.\MFP@z@Frc}%
+ \MFP@def@after\MFP@z@Ovr{\MFP@z@Ovr}%
+ \MFP@def@after\MFP@z@Und{\MFP@z@Und}%
+ \MFP@def@after\MFPcurr@Sgn{\MFP@z@Sgn}}%
+\def\MFP@subroutine#1{%
+ \begingroup
+ \MFP@basic@init@z
+ #1%
+ \MFP@endgroup@return}%
+\def\MFP@basic@init@z{%
+ \MFP@Rzero
+ \def\MFP@z@Ovr{0}%
+ \def\MFP@z@Und{0}}%
+\def\MFP@Rzero{%
+ \def\MFP@z@Sgn{0}%
+ \def\MFP@z@Int{0}%
+ \def\MFP@z@Frc{00000000}}%
+\def\MFP@errmsg#1#2{%
+\begingroup
+ \newlinechar`\^^J\let~\space
+ \def\MFP@msgbreak{^^J~~~~~~~~~~~~~~}%
+ \edef\reserved@a{\errhelp{#2}}\reserved@a
+ \errmessage{MiniFP error: #1}%
+\endgroup}%
+\def\MFP@popempty@err{%
+ \MFP@errmsg{cannot pop from an empty stack}%
+ {There were no items on the stack for the POP operation. %
+ If you continue, ^^Jthe macro will contain the %
+ value \EndofStack.}}%
+\def\EndofStack{0.00000000}%
+\def\MFP@dividebyzero@err{%
+ \MFP@errmsg{division by zero}%
+ {You tried to divide by zero. What were you thinking? %
+ If you continue, ^^Jthe value assigned will be either %
+ \ZeroOverZeroInt.\ZeroOverZeroFrac~(numerator=0) or %
+ ^^J+/-\xOverZeroInt.\xOverZeroFrac~(numerator<>0).}}%
+\def\MFP@warn#1{%
+\begingroup
+ \newlinechar`\^^J\let~\space
+ \def\MFP@msgbreak{^^J~~~~~~~~~~~~~~~~}%
+ \immediate\write16{^^JMiniFP warning: #1.^^J}%
+\endgroup}%
+\def\MaxRealInt {99999999}%
+\def\MaxRealFrac {99999999}%
+\def\xOverZeroInt {\MaxRealInt}%
+\def\xOverZeroFrac {\MaxRealFrac}%
+\def\ZeroOverZeroInt {0}%
+\def\ZeroOverZeroFrac{00000000}%
+\def\MFPparse@real#1#2#3#4{%
+ \MFPnospace@def\MFPtemp@Val{#4}%
+ \MFPprocess@into@parts\MFPtemp@Val#1#2#3%
+ \MFPpadto@eight#3}%
+\def\MFPparse@x{\MFPparse@real\MFP@x@Sgn\MFP@x@Int\MFP@x@Frc}%
+\def\MFPparse@y{\MFPparse@real\MFP@y@Sgn\MFP@y@Int\MFP@y@Frc}%
+\def\MFPnospace@def#1#2{%
+ \edef#1{#2\space}\edef#1{\@xp\zap@space#1\@empty}}%
+\def\MFPprocess@into@parts#1#2#3#4{%
+ \@xp\MFPsplit@dot#1..\mfp@end #3#4%
+ \ifnum#31<0
+ \def#2{-1}%
+ \else
+ \def#2{1}%
+ \fi
+ \ifnum #30=0
+ \def#3{0}%
+ \ifnum 0#4=0
+ \def#2{0}%
+ \fi
+ \fi
+ \edef#3{\number \ifnum #2<0 -\fi#3}}%
+\def\MFPsplit@dot#1.#2.#3\mfp@end#4#5{\edef#4{#1}\edef#5{#2}}%
+\def\MFPpadto@eight#1{%
+ \edef#1{\@xp\MFP@firsteightofmany#100000000\mfp@end}}%
+\def\MFPgetoperand@x{\Rpop\MFP@x@Val
+ \MFPprocess@into@parts\MFP@x@Val\MFP@x@Sgn\MFP@x@Int\MFP@x@Frc}%
+\def\MFPgetoperand@y{\Rpop\MFP@y@Val
+ \MFPprocess@into@parts\MFP@y@Val\MFP@y@Sgn\MFP@y@Int\MFP@y@Frc}%
+\def\MFP@Rcat#1{\edef\MFP@Rstack{{#1}\MFP@Rstack}}%
+\def\MFP@Rcattwo#1#2{\edef\MFP@Rstack{{#1}{#2}\MFP@Rstack}}%
+\def\MFP@Sign#1{\ifnum#1<0 -\fi}%
+\def\MFP@x@Sign{\MFP@Sign\MFP@x@Sgn}%
+\def\MFP@y@Sign{\MFP@Sign\MFP@y@Sgn}%
+\def\MFP@z@Sign{\MFP@Sign\MFP@z@Sgn}%
+\def\copyMFP@x{\edef\MFP@z@Int{\MFP@x@Int}\edef\MFP@z@Frc{\MFP@x@Frc}}%
+\def\MFPpush@result{\MFP@Rchk\MFPcurr@Sgn\MFP@Rcat\MFP@z@Val}%
+\def\if@EndofStack{%
+ \ifx\MFP@EOS\MFP@Rstack
+ \@xp\@firstoftwo
+ \else
+ \@xp\@secondoftwo
+ \fi}%
+\def\MFP@popit{\if@EndofStack\doMFP@EOS\doMFP@popit}%
+\def\doMFP@EOS#1\mfp@end#2{\MFP@popempty@err\let#2\EndofStack}%
+\def\doMFP@popit#1#2\mfp@end#3{\edef\MFP@Rstack{#2}\edef#3{#1}}%
+\def\MFPchk#1{%
+ \MFPparse@x{#1}%
+ \MFP@Rchk\MFP@x@Sgn}%
+\def\MFP@Rchk#1{%
+ \MFPclear@flags
+ \ifnum#1>0 \MFP@postrue
+ \else\ifnum#1<0 \MFP@negtrue
+ \else \MFP@zerotrue
+ \fi\fi}%
+\def\MFPclear@flags{\MFP@zerofalse \MFP@negfalse \MFP@posfalse}%
+\def\IFzero{\ifMFP@zero\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+\def\IFneg {\ifMFP@neg \@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+\def\IFpos {\ifMFP@pos \@xp\@firstoftwo\else\@xp\@secondoftwo\fi}%
+\newif\ifMFP@zero \newif\ifMFP@neg \newif\ifMFP@pos
+\newif\ifMFPdebug
+\def\MFPcmp#1#2{\MFPparse@x{#1}\MFPparse@y{#2}\MFP@Rcmp}%
+\def\MFP@Rcmp{\MFPclear@flags
+ \ifnum \MFP@x@Sign\MFP@x@Int>\MFP@y@Sign\MFP@y@Int\relax
+ \MFP@postrue
+ \else\ifnum \MFP@x@Sign\MFP@x@Int<\MFP@y@Sign\MFP@y@Int\relax
+ \MFP@negtrue
+ \else\ifnum \MFP@x@Sign\MFP@x@Frc>\MFP@y@Sign\MFP@y@Frc\relax
+ \MFP@postrue
+ \else\ifnum \MFP@x@Sign\MFP@x@Frc<\MFP@y@Sign\MFP@y@Frc\relax
+ \MFP@negtrue
+ \else
+ \MFP@zerotrue
+ \fi\fi\fi\fi}%
+\let\IFeq\IFzero\let\IFlt\IFneg \let\IFgt\IFpos
+\def\startMFPprogram{%
+\begingroup
+ \def\Rchs {\MFP@stack@Unary\MFP@Rchs}%
+ \def\Rabs {\MFP@stack@Unary\MFP@Rabs}%
+ \def\Rdbl {\MFP@stack@Unary\MFP@Rdbl}%
+ \def\Rhalve{\MFP@stack@Unary\MFP@Rhalve}%
+ \def\Rsgn {\MFP@stack@Unary\MFP@Rsgn}%
+ \def\Rsq {\MFP@stack@Unary\MFP@Rsq}%
+ \def\Rinv {\MFP@stack@Unary\MFP@Rinv}%
+ \def\Rint {\MFP@stack@Unary\MFP@Rint}%
+ \def\Rfrac {\MFP@stack@Unary\MFP@Rfrac}%
+ \def\Rfloor{\MFP@stack@Unary\MFP@Rfloor}%
+ \def\Rceil {\MFP@stack@Unary\MFP@Rceil}%
+ \def\Rincr {\MFP@stack@Unary\MFP@Rincr}%
+ \def\Rdecr {\MFP@stack@Unary\MFP@Rdecr}%
+ \def\Rzero {\MFP@stack@Unary\MFP@Rzero}%
+ \def\Radd {\MFP@stack@Binary\MFP@Radd}%
+ \def\Rmul {\MFP@stack@Binary\MFP@Rmul}%
+ \let\Rmpy\Rmul
+ \def\Rsub {\MFP@stack@Binary\MFP@Rsub}%
+ \def\Rdiv {\MFP@stack@Binary\MFP@Rdiv}%
+ \def\Rmin {\MFP@stack@Binary\MFP@Rmin}%
+ \def\Rmax {\MFP@stack@Binary\MFP@Rmax}%
+ \let\Rnoop\relax
+ \def\Rcmp{%
+ \MFPgetoperand@y\MFPgetoperand@x % get operands (last pushed is y)
+ \MFP@Rcat\MFP@x@Val\MFP@Rcat\MFP@y@Val % put back: LOFI
+ \MFP@Rcmp}%
+ \def\Rchk{%
+ \MFPgetoperand@x
+ \MFP@Rcat\MFP@x@Val
+ \MFP@Rchk\MFP@x@Sgn}%
+ \def\Rpush##1{%
+ \MFPparse@x{##1}%
+ \edef\MFP@z@Val{\MFP@x@Sign\MFP@x@Int.\MFP@x@Frc}%
+ \edef\MFPcurr@Sgn{\MFP@x@Sgn}%
+ \MFPpush@result}%
+ \def\Rpop{\@xp\MFP@popit\MFP@Rstack\mfp@end}%
+ \def\Rexch{%
+ \Rpop\MFP@x@Val\Rpop\MFP@y@Val
+ \MFP@Rcattwo\MFP@y@Val\MFP@x@Val}%
+ \def\Rdup{%
+ \Rpop\MFP@x@Val
+ \MFP@Rcattwo\MFP@x@Val\MFP@x@Val}%
+ \MFP@Rextra
+ \let\Global\MFP@Global
+ \let\GlobalStack\MFP@GlobalStack
+ \let\Export\MFP@Export
+ \let\ExportStack\MFP@ExportStack}%
+\def\stopMFPprogram{\@xp\endgroup\MFPprogram@returns}%
+\let\MFP@Rextra\@empty
+\let\MFPprogram@returns\@empty
+\def\MFPchs {\MFP@op@Unary\MFP@Rchs}%
+\def\MFPabs {\MFP@op@Unary\MFP@Rabs}%
+\def\MFPdbl {\MFP@op@Unary\MFP@Rdbl}%
+\def\MFPhalve{\MFP@op@Unary\MFP@Rhalve}%
+\def\MFPsgn {\MFP@op@Unary\MFP@Rsgn}%
+\def\MFPsq {\MFP@op@Unary\MFP@Rsq}%
+\def\MFPinv {\MFP@op@Unary\MFP@Rinv}%
+\def\MFPint {\MFP@op@Unary\MFP@Rint}%
+\def\MFPfrac {\MFP@op@Unary\MFP@Rfrac}%
+\def\MFPfloor{\MFP@op@Unary\MFP@Rfloor}%
+\def\MFPceil {\MFP@op@Unary\MFP@Rceil}%
+\def\MFPincr {\MFP@op@Unary\MFP@Rincr}%
+\def\MFPdecr {\MFP@op@Unary\MFP@Rdecr}%
+\def\MFPzero {\MFP@op@Unary\MFP@Rzero}%
+\def\MFPstore{\MFP@op@Unary\MFP@Rstore}%
+\def\MFPadd{\MFP@op@Binary\MFP@Radd}%
+\def\MFPmul{\MFP@op@Binary\MFP@Rmul}%
+\let\MFPmpy\MFPmul
+\def\MFPsub{\MFP@op@Binary\MFP@Rsub}%
+\def\MFPdiv{\MFP@op@Binary\MFP@Rdiv}%
+\def\MFPmin{\MFP@op@Binary\MFP@Rmin}%
+\def\MFPmax{\MFP@op@Binary\MFP@Rmax}%
+\def\MFP@stack@Unary#1{%
+ \MFPgetoperand@x
+ \MFP@subroutine{#1}\MFPpush@result}%
+\def\MFP@op@Unary#1#2{%
+ \MFPparse@x{#2}%
+ \MFP@subroutine{#1}\MFPstore@result}%
+\def\MFPstore@result#1{\MFP@Rchk\MFPcurr@Sgn\edef#1{\MFP@z@Val}}%
+\def\MFP@stack@Binary#1{%
+ \MFPgetoperand@y \MFPgetoperand@x
+ \MFP@subroutine{#1}\MFPpush@result}%
+\def\MFP@op@Binary#1#2#3{%
+ \MFPparse@x{#2}\MFPparse@y{#3}%
+ \MFP@subroutine{#1}\MFPstore@result}%
+\let\MFPnoop\relax
+\def\MFP@Rabs{%
+ \copyMFP@x \edef\MFP@z@Sgn{\ifnum\MFP@x@Sgn=0 0\else1\fi}}%
+\def\MFP@Rchs{\copyMFP@x \edef\MFP@z@Sgn{\number-\MFP@x@Sgn}}%
+\def\MFP@Rdbl{\MFP@Rcopy xy\MFP@Radd}%
+\def\MFP@Rhalve{%
+ \MFP@tempa\MFP@x@Int
+ \MFP@tempb\MFP@x@Frc\relax
+ \ifodd\MFP@tempb
+ \def\MFP@z@Und{5}%
+ \advance\MFP@tempb 1 % round up
+ \ifnum\MFP@ttteight=\MFP@tempb
+ \MFP@tempb0 \advance\MFP@tempa1
+ \fi
+ \fi
+ \ifodd \MFP@tempa
+ \advance\MFP@tempb \MFP@ttteight\relax
+ \fi
+ \divide\MFP@tempa 2
+ \divide\MFP@tempb 2
+ \MFP@Rloadz\MFP@x@Sgn\MFP@tempa\MFP@tempb}%
+\def\MFP@Rsgn{\MFP@Rloadz \MFP@x@Sgn{\ifnum\MFP@x@Sgn=0 0\else1\fi}0}%
+\def\MFP@Rsq{\MFP@Rcopy xy\MFP@Rmul}%
+\def\MFP@Rinv{\MFP@Rcopy xy\MFP@Rload x110\MFP@Rdiv}%
+\def\MFP@Rint{%
+ \MFP@Rloadz {\ifnum\MFP@x@Int=0 0\else\MFP@x@Sgn\fi}\MFP@x@Int 0}%
+\def\MFP@Rfrac{%
+ \MFP@Rloadz {\ifnum\MFP@x@Frc=0 0\else\MFP@x@Sgn\fi}0\MFP@x@Frc}%
+\def\MFP@Rincr{%
+ \ifnum\MFP@x@Sgn<0
+ \ifcase\MFP@x@Int
+ \MFP@tempa\MFP@ttteight
+ \advance\MFP@tempa -\MFP@x@Frc\relax
+ \MFP@Rloadz 10\MFP@tempa
+ \or
+ \MFP@Rloadz{\ifnum\MFP@x@Frc=0 0\else -1\fi}0\MFP@x@Frc
+ \else
+ \MFP@tempa\MFP@x@Int
+ \advance\MFP@tempa -1
+ \MFP@Rloadz{-1}\MFP@tempa\MFP@x@Frc
+ \fi
+ \else
+ \MFP@tempa\MFP@x@Int
+ \advance\MFP@tempa 1
+ \MFP@Rloadz 1\MFP@tempa\MFP@x@Frc
+ \fi}%
+\def\MFP@Rdecr{%
+ \edef\MFP@x@Sgn{\number -\MFP@x@Sgn}\MFP@Rincr
+ \edef\MFP@z@Sgn{\number -\MFP@z@Sgn}}%
+\def\MFP@Rstore{\MFP@Rcopy xz}%
+\def\MFP@Rfloororceil#1{%
+ \MFP@tempa\MFP@x@Int\relax
+ \ifnum 0#1\MFP@x@Sgn
+ \ifnum\MFP@x@Frc=0
+ \else
+ \advance\MFP@tempa1
+ \fi
+ \fi
+ \MFP@Rloadz{\ifnum\MFP@z@Int=0 0\else\MFP@x@Sgn\fi}\MFP@tempa0}%
+\def\MFP@Rfloor{\MFP@Rfloororceil>}%
+\def\MFP@Rceil {\MFP@Rfloororceil<}%
+\def\MFP@split#1#2#3{%
+ \begingroup
+ \MFP@tempa#1\relax
+ \MFP@tempb\MFP@tempa
+ \divide\MFP@tempb by\MFP@tttfour
+ \edef#2{\number\MFP@tempb}%
+ \multiply\MFP@tempb by\MFP@tttfour
+ \advance\MFP@tempa-\MFP@tempb
+ \MFP@endgroup@after{%
+ \MFP@def@after#2{#2}%
+ \MFP@def@after#3{\number\MFP@tempa}%
+ }}%
+\def\MFP@x@split{%
+ \MFP@split\MFP@x@Int\MFP@x@Int@ii\MFP@x@Int@i
+ \MFP@split\MFP@x@Frc\MFP@x@Frc@i\MFP@x@Frc@ii}%
+\def\MFP@y@split{%
+ \MFP@split\MFP@y@Int\MFP@y@Int@ii\MFP@y@Int@i
+ \MFP@split\MFP@y@Frc\MFP@y@Frc@i\MFP@y@Frc@ii}%
+\def\MFPmore@init@z{%
+ \def\MFP@z@Frc@iv {0}%
+ \def\MFP@z@Frc@iii{0}%
+ \def\MFP@z@Frc@ii {0}%
+ \def\MFP@z@Frc@i {0}%
+ \def\MFP@z@Int@i {0}%
+ \def\MFP@z@Int@ii {0}%
+ \def\MFP@z@Int@iii{0}}%
+\def\MFP@fourdigits#1{%
+ \@xp\MFP@fifthofmany\number#1{}{0}{00}{000}\mfp@end\number#1}%
+\def\makeMFP@fourdigits#1{\edef#1{\MFP@fourdigits{#1}}}%
+\def\MFP@eightdigits#1{%
+ \@xp\MFP@ninthofmany\number#1%
+ {}{0}{00}{000}{0000}{00000}{000000}{0000000}\mfp@end\number#1}%
+\def\makeMFP@eightdigits#1{\edef#1{\MFP@eightdigits{#1}}}%
+\def\MFP@carrya{\MFP@carry\MFP@ttteight}%
+\def\MFP@carrym{\MFP@carry\MFP@tttfour}%
+\def\MFP@carry#1#2#3{%
+ \begingroup
+ \MFP@carryi{#1}#2#3%
+ \MFP@endgroup@after{%
+ \MFP@def@after#3{\number\MFP@tempa}%
+ \MFP@def@after#2{\number\MFP@tempb}%
+ }}%
+\def\MFP@carryi#1#2#3{%
+ \MFP@tempa=#3\relax
+ \MFP@tempb=#2\relax
+ \MFP@tempc=\MFP@tempb
+ \divide \MFP@tempc #1\relax
+ \advance \MFP@tempa \MFP@tempc
+ \multiply\MFP@tempc #1\relax
+ \advance \MFP@tempb -\MFP@tempc}%
+\def\MFP@addone#1#2#3{%
+ \begingroup
+ \MFP@tempa#1%
+ \advance\MFP@tempa#2\relax
+ \MFP@endgroup@after{%
+ \MFP@def@after#3{\number\MFP@tempa}%
+ }}%
+\def\MFP@multiplyone#1#2{%
+ \MFP@tempa#1%
+ \multiply\MFP@tempa\MFP@tempb
+ \advance\MFP@tempa#2%
+ \edef#2{\number\MFP@tempa}}%
+\def\MFP@multiplyfour#1#2#3#4#5{%
+ \MFP@tempb #1\relax
+ \MFP@multiplyone\MFP@x@Int@ii #2%
+ \MFP@multiplyone\MFP@x@Int@i #3%
+ \MFP@multiplyone\MFP@x@Frc@i #4%
+ \MFP@multiplyone\MFP@x@Frc@ii #5}%
+\def\MFP@Rsub{\edef\MFP@y@Sgn{\number-\MFP@y@Sgn}\MFP@Radd}%
+\def\MFP@Radd{%
+ \MFP@tempa\MFP@x@Sgn
+ \multiply\MFP@tempa\MFP@y@Sgn\relax
+ \ifcase\MFP@tempa
+ \ifnum \MFP@x@Sgn=0
+ \MFP@Rcopy yz%
+ \else
+ \MFP@Rcopy xz%
+ \fi
+ \or
+ \@xp\MFP@Radd@same
+ \else
+ \@xp\MFP@Radd@diff
+ \fi}%
+\def\MFP@Radd@same{%
+ \MFP@addone\MFP@x@Frc\MFP@y@Frc\MFP@z@Frc
+ \MFP@addone\MFP@x@Int\MFP@y@Int\MFP@z@Int
+ \MFP@carrya\MFP@z@Frc\MFP@z@Int
+ \MFP@carrya\MFP@z@Int\MFP@z@Ovr
+ \makeMFP@eightdigits\MFP@z@Frc
+ \edef\MFP@z@Sgn{\MFP@x@Sgn}}%
+\def\MFP@Radd@diff{%
+ \MFP@addone\MFP@x@Frc{-\MFP@y@Frc}\MFP@z@Frc
+ \MFP@addone\MFP@x@Int{-\MFP@y@Int}\MFP@z@Int
+ \MFP@tempa=\MFP@z@Int
+ \MFP@tempb=\MFP@z@Frc\relax
+ \ifnum\MFP@tempa=0 \else \MFP@tempa=\MFP@Sign\MFP@tempa 1 \fi
+ \ifnum\MFP@tempb=0 \else \MFP@tempb=\MFP@Sign\MFP@tempb 1 \fi
+ \ifnum\MFP@tempa=0 \MFP@tempa=\MFP@tempb \fi
+ \edef\MFP@z@Sgn{\number\MFP@x@Sign\MFP@tempa}%
+ \MFP@tempb\MFP@tempa
+ \multiply\MFP@tempa \MFP@z@Int
+ \multiply\MFP@tempb \MFP@z@Frc\relax
+ \ifnum\MFP@tempb<0
+ \advance\MFP@tempb\MFP@ttteight
+ \advance\MFP@tempa-1
+ \fi
+ \edef\MFP@z@Int{\number\MFP@tempa}%
+ \edef\MFP@z@Frc{\number\MFP@tempb}%
+ \makeMFP@eightdigits\MFP@z@Frc}%
+\def\MFP@Rmul{%
+ \MFP@tempa\MFP@x@Sgn \multiply\MFP@tempa\MFP@y@Sgn\relax
+ \ifnum 0=\MFP@tempa
+ \MFP@Rzero
+ \else
+ \edef\MFP@z@Sgn{\number\MFP@tempa}%
+ \@xp\MFP@@Rmul
+ \fi}%
+\def\MFP@@Rmul{%
+ \MFPmore@init@z
+ \MFP@x@split\MFP@y@split
+ \MFP@multiplyfour \MFP@y@Frc@ii \MFP@z@Frc@i
+ \MFP@z@Frc@ii \MFP@z@Frc@iii\MFP@z@Frc@iv
+ \MFP@multiplyfour \MFP@y@Frc@i \MFP@z@Int@i
+ \MFP@z@Frc@i \MFP@z@Frc@ii \MFP@z@Frc@iii
+ \MFP@multiplyfour \MFP@y@Int@i \MFP@z@Int@ii
+ \MFP@z@Int@i \MFP@z@Frc@i \MFP@z@Frc@ii
+ \MFP@multiplyfour \MFP@y@Int@ii \MFP@z@Int@iii
+ \MFP@z@Int@ii \MFP@z@Int@i \MFP@z@Frc@i
+ \MFP@carrym\MFP@z@Frc@iv\MFP@z@Frc@iii
+ \MFP@carrym\MFP@z@Frc@iii\MFP@z@Frc@ii
+ \ifnum\MFP@z@Frc@iii<5000 \else
+ \MFP@tempb\MFP@z@Frc@ii
+ \advance\MFP@tempb1
+ \edef\MFP@z@Frc@ii{\number\MFP@tempb}%
+ \fi
+ \MFP@carrym\MFP@z@Frc@ii\MFP@z@Frc@i
+ \MFP@carrym\MFP@z@Frc@i \MFP@z@Int@i
+ \MFP@carrym\MFP@z@Int@i \MFP@z@Int@ii
+ \MFP@carrym\MFP@z@Int@ii\MFP@z@Int@iii
+ \makeMFP@fourdigits\MFP@z@Frc@iv
+ \makeMFP@fourdigits\MFP@z@Frc@iii
+ \makeMFP@fourdigits\MFP@z@Frc@ii
+ \makeMFP@fourdigits\MFP@z@Frc@i
+ \makeMFP@fourdigits\MFP@z@Int@i
+ \edef\MFP@z@Int{\number\MFP@z@Int@ii\MFP@z@Int@i}%
+ \edef\MFP@z@Frc{\MFP@z@Frc@i\MFP@z@Frc@ii}%
+ \edef\MFP@z@Ovr{\number\MFP@z@Int@iii}%
+ \edef\MFP@z@Und{\MFP@z@Frc@iii\MFP@z@Frc@iv}%
+ \ifnum\MFP@z@Int>0
+ \else\ifnum\MFP@z@Frc>0
+ \else
+ \def\MFP@z@Sgn{0}%
+ \fi\fi}%
+\def\MFP@Rdiv{%
+ \ifnum\MFP@y@Sgn=0
+ \MFP@dividebyzero@err
+ \ifnum\MFP@x@Sgn=0
+ \edef\MFP@z@Int{\ZeroOverZeroInt}%
+ \edef\MFP@z@Frc{\ZeroOverZeroFrac}%
+ \else
+ \edef\MFP@z@Int{\xOverZeroInt}%
+ \edef\MFP@z@Frc{\xOverZeroFrac}%
+ \fi
+ \edef\MFP@z@Sgn{\MFP@x@Sgn}%
+ \else\ifnum\MFP@x@Sgn=0
+ \MFP@Rzero
+ \else
+ \MFP@tempa\MFP@x@Sgn
+ \multiply\MFP@tempa\MFP@y@Sgn
+ \edef\MFP@z@Sgn{\number\MFP@tempa}%
+ \MFP@@Rdiv
+ \fi\fi}%
+\def\MFP@@Rdiv{%
+ \ifnum\MFP@y@Int=0
+ \edef\MFP@y@Int{\number\MFP@y@Frc}%
+ \def\MFP@y@Frc{00000000}%
+ \MFP@tempa=8
+ \else
+ \MFP@tempa=0
+ \fi
+ \advance\MFP@tempa\MFP@numdigits@toshift\MFP@y@Int\relax
+ \@XP\MFP@doshift@y\@xp\MFP@y@Int\MFP@y@Frc0000000\mfp@end
+ \ifnum\MFP@x@Int=0
+ \edef\MFP@x@Int{\number\MFP@x@Frc}%
+ \def\MFP@x@Frc{00000000}%
+ \advance\MFP@tempa -8
+ \fi
+ \advance\MFP@tempa-\MFP@numdigits@toshift\MFP@x@Int\relax
+ \@XP\MFP@doshift@x\@xp\MFP@x@Int\MFP@x@Frc0000000\mfp@end
+ \ifnum\MFP@tempa<-9
+ \else
+ \MFP@tempf\MFP@tempa
+ \advance\MFP@tempf 10
+ \def\MFP@z@digits{}%
+ \MFP@Rdivloop
+ \MFPshiftandsplit@z@digits
+ \ifnum\MFP@z@Und>4
+ \MFP@addone\MFP@z@Frc1\MFP@z@Frc
+ \MFP@carrya\MFP@z@Frc\MFP@z@Int
+ \MFP@carrya\MFP@z@Int\MFP@z@Ovr
+ \makeMFP@eightdigits\MFP@z@Frc
+ \fi
+ \fi}%
+\def\MFP@numdigits@toshift#1{\@xp\MFP@ninthofmany#101234567\mfp@end}%
+\def\MFP@doshift@x#1#2#3#4#5#6#7#8#9\mfp@end{%
+ \def\MFP@x@Int{#1#2#3#4#5#6#7#8}%
+ \edef\MFP@x@Frc{\MFP@firsteightofmany#9\mfp@end}}%
+\def\MFP@doshift@y#1#2#3#4#5#6#7#8#9\mfp@end{%
+ \def \MFP@y@Int{#1#2#3#4#5#6#7#8}%
+ \edef\MFP@y@Frc{\MFP@firsteightofmany#9\mfp@end}}%
+\def\MFP@Rdivloop{%
+ \MFP@tempb\MFP@x@Int % \MFP@tempb = n_1
+ \MFP@tempc\MFP@y@Int % \MFP@tempc = d_1
+ \divide\MFP@tempb \MFP@tempc % \MFP@tempb = n_1/d_1 = q_1
+ \multiply \MFP@tempc \MFP@tempb % \MFP@tempc = q_1 d_1
+ \MFP@tempd \MFP@y@Frc % \MFP@tempd = d_2
+ \multiply \MFP@tempd \MFP@tempb % \MFP@tempd = q_1 d_2
+ \MFP@tempe \MFP@tempc
+ \advance \MFP@tempe -\MFP@x@Int\relax % \MFP@tempe = -n_1 + q_1 d_1
+ \ifnum \MFP@tempe > -9 % n_1 - q_1 d_1 < 9
+ \multiply \MFP@tempe\MFP@ttteight % -(n_1 - q_1 d_1)(10)^8
+ \advance \MFP@tempe \MFP@tempd % add q_1 d_2
+ \advance \MFP@tempe -\MFP@x@Frc\relax % add -n_2
+ \ifnum \MFP@tempe>0 % Crucial inequality fails
+ \advance\MFP@tempb -1 % new q = q_1 - 1
+ \advance\MFP@tempc -\MFP@y@Int % q_1 d_1 - d_1 = q d_1
+ \advance\MFP@tempd -\MFP@y@Frc\relax% q_1 d_2 - d_2 = q d_2
+ \fi
+ \fi
+ \edef\MFP@z@digits{\MFP@z@digits\number\MFP@tempb}%
+ \begingroup
+ \MFP@carryi\MFP@ttteight\MFP@tempd\MFP@tempc
+ \MFP@endgroup@after{%
+ \MFP@tempc=\number\MFP@tempa
+ \MFP@tempd=\number\MFP@tempb\relax
+ }%
+ \MFP@addone\MFP@x@Int{-\MFP@tempc}\MFP@x@Int
+ \MFP@addone\MFP@x@Frc{-\MFP@tempd}\MFP@x@Frc
+ \ifnum\MFP@x@Frc<0
+ \MFP@addone\MFP@x@Frc\MFP@ttteight\MFP@x@Frc
+ \MFP@addone\MFP@x@Int{-1}\MFP@x@Int
+ \fi
+ \advance\MFP@tempf -1
+ \ifnum\MFP@tempf>0
+ \edef\MFP@x@Int{\MFP@x@Int0}% easy multiplications by 10
+ \edef\MFP@x@Frc{\MFP@x@Frc0}%
+ \MFP@carrya\MFP@x@Frc\MFP@x@Int
+ \@xp\MFP@Rdivloop
+ \fi}%
+\def\MFPshiftandsplit@z@digits{%
+ \advance \MFP@tempa -7
+ \ifnum\MFP@tempa>0
+ \def\MFP@z@Ovr{}%
+ \@xp\MFPget@Ovrdigits\MFP@z@digits\mfp@end
+ \else
+ \ifnum\MFP@tempa<-7
+ \edef\MFP@z@digits{00000000\MFP@z@digits}%
+ \advance\MFP@tempa8
+ \fi
+ \ifnum\MFP@tempa<-3
+ \edef\MFP@z@digits{0000\MFP@z@digits}%
+ \advance\MFP@tempa4
+ \fi
+ \edef\MFP@z@digits{%
+ \ifcase-\MFP@tempa\or
+ 0\or
+ 00\or
+ 000\or
+ 0000\else
+ 00000%
+ \fi \MFP@z@digits}%
+ \@xp\MFPget@Intdigits\MFP@z@digits\mfp@end
+ \fi}%
+\def\MFPget@Ovrdigits#1{%
+ \edef\MFP@z@Ovr{\MFP@z@Ovr#1}%
+ \advance\MFP@tempa -1
+ \ifnum\MFP@tempa>0
+ \@xp\MFPget@Ovrdigits
+ \else
+ \@xp\MFPget@Intdigits
+ \fi}%
+\def\MFPget@Intdigits#1#2#3#4#5#6#7#8{%
+ \def\MFP@z@Int{\number#1#2#3#4#5#6#7#8}%
+ \MFPget@Frcdigits}%
+\def\MFPget@Frcdigits#1#2#3#4#5#6#7#8#9{%
+ \def\MFP@z@Frc{#1#2#3#4#5#6#7#8}%
+ \def\MFP@z@Und{#9}\gobbleto@mfp@end}%
+\def\MFP@Rmax{%
+ \MFP@Rcmp \ifMFP@neg \MFP@Rcopy yz\else\MFP@Rcopy xz\fi}%
+\def\MFP@Rmin{%
+ \MFP@Rcmp \ifMFP@pos \MFP@Rcopy yz\else\MFP@Rcopy xz\fi}%
+\def\MFPtruncate#1#2{%
+ \begingroup
+ \MFP@tempa#1\relax
+ \MFPparse@x{#2}%
+ \ifnum\MFP@tempa<1
+ \@xp\MFP@iRtrunc
+ \else
+ \@xp\MFP@Rtrunc
+ \fi}%
+\def\MFP@Rtrunc#1{%
+ \edef\MFP@x@Frc{\@xp\MFP@@Rtrunc\MFP@x@Frc\mfp@end}%
+ \ifnum\MFP@x@Int=0 % possibly returns 0
+ \ifnum\MFP@x@Frc=0
+ \def\MFP@x@Sgn{0}%
+ \fi
+ \fi
+ \MFP@endgroup@after{%
+ \MFP@def@after#1{\MFP@x@Sign\MFP@x@Int.\MFP@x@Frc}}}%
+\def\MFP@@Rtrunc#1#2#3#4#5#6#7#8#9\mfp@end{%
+ \ifcase\MFP@tempa\or
+ #1\or
+ #1#2\or
+ #1#2#3\or
+ #1#2#3#4\or
+ #1#2#3#4#5\or
+ #1#2#3#4#5#6\or
+ #1#2#3#4#5#6#7\else
+ #1#2#3#4#5#6#7#8\fi}%
+\def\MFP@iRtrunc#1{%
+ \makeMFP@eightdigits\MFP@x@Int
+ \edef\MFP@x@Val{\number\MFP@x@Sign\@xp\MFP@@iRtrunc\MFP@x@Int\mfp@end}%
+ \MFP@endgroup@after{\MFP@def@after#1{\MFP@x@Val}}}%
+\def\MFP@@iRtrunc#1#2#3#4#5#6#7#8#9\mfp@end{%
+ \ifcase-\MFP@tempa
+ #1#2#3#4#5#6#7#8\or
+ #1#2#3#4#5#6#70\or
+ #1#2#3#4#5#600\or
+ #1#2#3#4#5000\or
+ #1#2#3#40000\or
+ #1#2#300000\or
+ #1#2000000\or
+ #10000000\else
+ 00000000\fi}%
+\def\MFPround#1#2{%
+ \begingroup
+ \MFP@tempa#1\relax
+ \ifnum 0>\MFP@tempa
+ \edef\MFP@y@Tmp{%
+ \ifcase-\MFP@tempa\or
+ 5\or % .5 x 10^1
+ 50\or % .5 x 10^2
+ 500\or % .5 x 10^3
+ 5000\or % .5 x 10^4
+ 50000\or % .5 x 10^5
+ 500000\or % .5 x 10^6
+ 5000000\else % .5 x 10^7
+ 50000000\fi % .5 x 10^8
+ }%
+ \else
+ \edef\MFP@y@Tmp{%
+ \ifcase\MFP@tempa
+ .5\or % .5 x 10^0
+ .05\or % .5 x 10^{-1}
+ .005\or % .5 x 10^{-2}
+ .0005\or % .5 x 10^{-3}
+ .00005\or % .5 x 10^{-4}
+ .000005\or % .5 x 10^{-5}
+ .0000005\or % .5 x 10^{-6}
+ .00000005\else% .5 x 10^{-7}
+ 0\fi %
+ }%
+ \fi
+ \MFPchk{#2}\ifMFP@neg\edef\MFP@y@Tmp{-\MFP@y@Tmp}\fi
+ \MFPadd{#2}\MFP@y@Tmp\MFP@z@Tmp
+ \MFP@endgroup@after{\MFP@def@after\MFP@z@Tmp{\MFP@z@Tmp}}%
+ \MFPtruncate{#1}\MFP@z@Tmp}%
+\def\MFPstrip{%
+ \@ifstar{\MFP@strip{}}{\MFP@strip{.0}}}%
+\def\MFP@strip#1#2#3{%
+ \MFPparse@x{#2}%
+ \ifnum \MFP@x@Frc=0
+ \edef#3{\MFP@x@Sign\MFP@x@Int#1}%
+ \else
+ \edef#3{\MFP@x@Sign\MFP@x@Int.\@xp\MFP@@strip\MFP@x@Frc\mfp@end}%
+ \fi}%
+\def\MFP@@strip#1#2\mfp@end{%
+ #1%
+ \ifnum 0#2>0
+ \@xp\MFP@@strip
+ \else
+ \@xp\gobbleto@mfp@end
+ \fi#2\mfp@end}%
+\def\MFP@Global#1{\toks@\@xp{#1}\xdef#1{\the\toks@}}%
+\def\MFP@GlobalStack{\MFP@Global\MFP@Rstack}%
+\def\MFP@Export#1{%
+ \begingroup
+ \toks@\@xp{\MFPprogram@returns}%
+ \MFP@endgroup@after{%
+ \MFP@def@after\MFPprogram@returns{\the\toks@ \MFP@def@after#1{#1}}%
+ }}%
+\def\MFP@ExportStack{\MFP@Export\MFP@Rstack}%
+\def\MFP@Rload #1#2#3#4{%
+ \@xp\edef\csname MFP@#1@Sgn\endcsname{\number#2}%
+ \@xp\edef\csname MFP@#1@Int\endcsname{\number#3}%
+ \@xp\edef\csname MFP@#1@Frc\endcsname{\number#4}%
+ \@xp\makeMFP@eightdigits\csname MFP@#1@Frc\endcsname}%
+\def\MFP@Rcopy#1#2{%
+ \MFP@Rload #2{\csname MFP@#1@Sgn\endcsname}%
+ {\csname MFP@#1@Int\endcsname}%
+ {\csname MFP@#1@Frc\endcsname}}%
+\def\MFP@Rloadz#1#2#3{%
+ \edef\MFP@z@Sgn{\number#1}%
+ \edef\MFP@z@Int{\number#2}%
+ \edef\MFP@z@Frc{\number#3}%
+ \makeMFP@eightdigits\MFP@z@Frc}%
+\def\MFPpi{3.14159265}%
+\def\MFPe{2.71828183}%
+\def\MFPphi{1.61803399}%
+\MFP@loadextra
+\MFP@finish
+\endinput
+%%
+%% End of file `minifp.sty'.
diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check
index 2619271395f..e762461c53c 100755
--- a/Master/tlpkg/bin/tlpkg-ctan-check
+++ b/Master/tlpkg/bin/tlpkg-ctan-check
@@ -278,7 +278,7 @@ my @TLP_working = qw(
method metre
mf2pt1 mfnfss mfpic mfpic4ode mftinc mh mhchem
mhequ microtype microtype-de midnight midpage mil3 miller
- minibox minipage-marginpar miniplot minitoc
+ minibox minifp minipage-marginpar miniplot minitoc
minted minutes
mkgrkindex mkjobtexmf mkpattern
mla-paper mlist mmap mnsymbol
diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
index aac575d4c76..f2f0d10054f 100644
--- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
+++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
@@ -474,6 +474,7 @@ depend metre
depend mftinc
depend midpage
depend minibox
+depend minifp
depend minipage-marginpar
depend minitoc
depend minted
diff --git a/Master/tlpkg/tlpsrc/minifp.tlpsrc b/Master/tlpkg/tlpsrc/minifp.tlpsrc
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Master/tlpkg/tlpsrc/minifp.tlpsrc