diff options
author | Karl Berry <karl@freefriends.org> | 2014-01-04 00:17:22 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2014-01-04 00:17:22 +0000 |
commit | 64cabb7b36a81f41f4bbe49f00cf5aa4fc83f66c (patch) | |
tree | a58cad8582cd6d596ac7c83e4c87166d009ea2f3 /Master/texmf-dist/source/generic/minifp | |
parent | 09a6ab34f799132f02f90e619fa695f2a07c426d (diff) |
minifp (3jan14)
git-svn-id: svn://tug.org/texlive/trunk@32559 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/generic/minifp')
-rw-r--r-- | Master/texmf-dist/source/generic/minifp/minifp.dtx | 292 |
1 files changed, 216 insertions, 76 deletions
diff --git a/Master/texmf-dist/source/generic/minifp/minifp.dtx b/Master/texmf-dist/source/generic/minifp/minifp.dtx index c3621aef2ba..2e88dd1e47f 100644 --- a/Master/texmf-dist/source/generic/minifp/minifp.dtx +++ b/Master/texmf-dist/source/generic/minifp/minifp.dtx @@ -13,8 +13,8 @@ % 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/05/28}% -\def\MFPfileversion{0.95}% +\def\MFPfiledate{2013/12/30}% +\def\MFPfileversion{0.96}% %</driver|sty> % %<*driver> @@ -25,8 +25,8 @@ \addtolength{\textwidth}{1pt} -\usepackage[morefloats=2]{morefloats} - +\usepackage[morefloats=5]{morefloats} +\usepackage{amssymb} % This avoids messages about nonexistent font variants (e.g., in \section): \def\mytt{\upshape\mdseries\ttfamily} % I use it instead of \texttt: @@ -104,7 +104,7 @@ \end{document} %</driver> %\fi -% \CheckSum{3402} +% \CheckSum{3541} % \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 @@ -262,8 +262,8 @@ % 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}. +% sine, cosine, logarithm, powers, square root and random number are +% available, and the binary operation angle. See section~\ref{extras}. % % These extra operations are made available using the \texttt{extra} % option in \LaTeX{}: @@ -326,19 +326,21 @@ % % \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 it can be a macro that -% contains such a number. If the decimal dot is absent, the fractional part -% will be taken to be zero, if the integer part or the fractional part is -% absent, it will be taken to be zero. (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. +% 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 it can be a macro that contains such a number. If the decimal +% dot is absent, the fractional part will be taken to be zero, if the +% integer part or the fractional part is absent, it will be taken to be +% zero. (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 point \emph{must} be +% ASCII 46 (variously called a dot, period, or fullstop) with category 12 +% (`other'). If an input encoding is used that allows more than one `dot', +% the user must be sure to enter this one. If some babel language +% definitions make it a shorthand, it must be inactivated before use. % % 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 @@ -632,7 +634,7 @@ % \medskip % \centerline{% % \begin{tabular}{lp{4.0in}} -% \multicolumn2{c}{\textit{Binary Operations}}\\ +% \textit{Binary Operations}&\\[3pt] % \hline\hline % \textbf{Command}&\textbf{operation}\\ % \hline @@ -662,7 +664,7 @@ % \medskip % \centerline{% % \begin{tabular}{lp{4.0in}} -% \multicolumn2{c}{\textit{Unary Operations}}\\ +% \textit{Unary Operations}&\\[3pt] % \hline\hline % \textbf{Command}&\textbf{operation}\\ % \hline @@ -714,7 +716,7 @@ % \medskip % \centerline{% % \begin{tabular}{lp{3.8in}} -% \multicolumn2{c}{\textit{Do Nothing}}\\ +% \textit{Do Nothing}&\\[3pt] % \hline\hline % \textbf{Command}&\textbf{operation}\\ % \hline @@ -761,7 +763,7 @@ % \medskip % \centerline{% % \begin{tabular}{lp{3.8in}} -% \multicolumn2{c}{\textit{Stack Manipulations}}\\ +% \textit{Stack Manipulations}&\\[3pt] % \hline\hline % \textbf{Command}&\textbf{operation}\\ % \hline @@ -783,7 +785,7 @@ % \medskip % \centerline{% % \begin{tabular}{lp{3.8in}} -% \multicolumn2{c}{\textit{Exporting changed values}}\\ +% \textit{Exporting changed values}&\\[3pt] % \hline\hline % \textbf{Command}&\textbf{operation}\\ % \hline @@ -852,8 +854,8 @@ % 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 +% the messages tend to be uninformative.) Incorrectly formed numbers may even +% pass unnoticed, but leave unexpected printed characters on the paper, or odd % spacing. % % \section{Implementation} @@ -955,8 +957,8 @@ % \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. +% have allocated two count registers, but have taken the approach of +% reserving those for intermediate calculations. % \begin{macrocode} \def\MFP@tttfour {10000}% ttt = Ten To The \def\MFP@ttteight{100000000}% @@ -1124,7 +1126,7 @@ % 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 \op{pop}ed reals (though they wouldn't +% they are unnecessary when processing \op{pop}ped reals (though they wouldn't % hurt). % % The number to be parsed is \arg4 and the macros to contain the parts @@ -1202,7 +1204,14 @@ % \end{macrocode} % % Concatenate an argument (or two) to the front of stack. The material -% must already be in correct format. +% must already be in correct format. Note: `front' is where they go +% visually (i.e., leftmost) but it can be useful to imagine the stack +% growin rightward (or sometimes even downward). +% +% Note that the result of \verb$\MFP@cattwo{#1}{#2}$ is the same as +% \verb$\MFP@cat{#2}$ followed by \verb$\MFP@cat{#1}$. It seemed that +% reversing the arguments in \cs{MFP@Rcattwo} confused me more than this +% fact. % \begin{macrocode} \def\MFP@Rcat#1{\edef\MFP@Rstack{{#1}\MFP@Rstack}}% \def\MFP@Rcattwo#1#2{\edef\MFP@Rstack{{#1}{#2}\MFP@Rstack}}% @@ -1448,12 +1457,16 @@ % \DescribeMacro{\Rexch} % \DescribeMacro{\Rdup} % And finally some special commands. There is a no-op and commands for -% comparing, checking, and manipulation of the stack. +% comparing, checking, and manipulation of the stack. Note that +% \cs{Rcmp} parses the last two elements on the stack, then puts them back +% before calling the internal command that operates on the parsed parts. +% The same is true of \cs{Rchk}, but only the last stack element is +% examined. % \begin{macrocode} \let\Rnoop\relax \def\Rcmp{% \MFPgetoperand@y\MFPgetoperand@x - \MFP@Rcat\MFP@x@Val\MFP@Rcat\MFP@y@Val + \MFP@Rcattwo\MFP@y@Val\MFP@x@Val \MFP@Rcmp}% \def\Rchk{% \MFPgetoperand@x @@ -1466,8 +1479,8 @@ \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}% + \Rpop\MFP@y@Val\Rpop\MFP@x@Val + \MFP@Rcattwo\MFP@x@Val\MFP@y@Val}% \def\Rdup{% \Rpop\MFP@x@Val \MFP@Rcattwo\MFP@x@Val\MFP@x@Val}% @@ -2074,7 +2087,8 @@ % We invoke an error message upon division by zero, but nevertheless return % a value. By default it is $0$ for $0/0$ and the maximum possible real % for $x/0$ when $x$ is not zero. If the numerator is zero and the -% denominator not, we do nothing as $z$ was initialized to be zero. +% denominator not, we could do nothing as $z$ was initialized to be zero. +% However, we play it safe by explicitly setting $z$ to zero. % % If neither is zero, we calculate the sign of the result and call % \cs{MFP@@Rdiv} to divide the absolute values. @@ -2140,10 +2154,11 @@ % \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$). +% rightward shift of $10$ places will make every digit $0$ including the +% rounding digit, so we return $0$. % \begin{macrocode} \ifnum\MFP@tempa<-9 + \MFP@Rzero \else % \end{macrocode} % @@ -2549,13 +2564,13 @@ % % \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. +% The extras consist so far of sine, cosine, angle, logarithm, powers, +% square root, and random number. For completeness, here is the table of +% user-level commands available. % % \medskip % \centerline{% -% \begin{tabular}{lp{3.4in}} +% \begin{tabular}{lp{3in}} % \textit{Operand versions}&\\[3pt] % \hline\hline % \textbf{Command}&\textbf{operation}\\ @@ -2592,16 +2607,39 @@ % \SpecialUsageIndex{\MFPsqrt}^^A % \cs{MFPsqrt}\mmarg{num}\cs{macro}& % Stores the square root of \meta{num} in \cs{macro}.\\ +% \SpecialUsageIndex{\MFPrand}^^A +% \cs{MFPrand}\mmarg{num}\cs{macro}& +% Stores a random real number between $0$ amd \meta{num} in +% \cs{macro}. If \meta{num} is negative, so is the result.\\ % \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}} % +% In addition, there is \SpecialUsageIndex{\MFPsetseed}\cs{MFPsetseed} for +% setting the internal random number seed. It takes one argument, the seed +% value, which must be an integer greater than or equal to $1$ and less +% than or equal to $2^{31}-2 = 2\,147\,483\,646$. If the seed is set to +% zero or a negative number then the first use of the random number +% generator will replace it with a seed value based on the current time +% and date. The randum number seed is a global value. +% +% There are actually three random number generators and they can be +% selected with the commands +% \SpecialUsageIndex{\MFPrandgenA}\cs{MFPrandgenA}, +% \SpecialUsageIndex{\MFPrandgenB}\cs{MFPrandgenB}, or +% \SpecialUsageIndex{\MFPrandgenC}\cs{MFPrandgenC}. The first uses the +% code and multiplier value from the well-known macro file +% \file{random.tex}. It is the default. The other two use different +% multipliers which are alleged to have better statistical behavior. If +% any of these commands is used inside a group, that generator is in force +% during that group only. +% % \bigskip % \centerline{% % \begin{tabular}{lp{3.9in}} -% \multicolumn2{c}{\textit{Stack versions}}\\ +% \textit{Stack versions}&\\[3pt] % \hline\hline % \textbf{Command}&\textbf{operation}\\ % \hline @@ -2625,6 +2663,9 @@ % Computes the exponential of the number (i.e., $e^x$).\\ % \SpecialUsageIndex{\Rsqrt}\cs{Rsqrt}& % Computes the square root of the number.\\ +% \SpecialUsageIndex{\Rrand}\cs{Rrand}& +% Returns a random real number between $0$ and the number, keeping the +% sign.\\ % \SpecialUsageIndex{\Rpow}\cs{Rpow}& % Computes $x^y$. The last number pushed ($y$) must be an % integer. @@ -2644,7 +2685,7 @@ % \DescribeMacro{\Rrad}\DescribeMacro{\Rdeg} % \DescribeMacro{\Rlog}\DescribeMacro{\Rln} % \DescribeMacro{\Rexp}\DescribeMacro{\Rsqrt} -% \DescribeMacro{\Rpow} +% \DescribeMacro{\Rrand}\DescribeMacro{\Rpow} % We start \file{mfpextra} with the hook \cs{MFP@Rextra} that % \cs{startMFPprogram} will call to make available the extra operations % defined here. If \file{minifp.sty} has been loaded, this macro is @@ -2684,6 +2725,7 @@ \def\Rln {\MFP@stack@Unary\MFP@Rln }% \def\Rexp {\MFP@stack@Unary\MFP@Rexp }% \def\Rsqrt {\MFP@stack@Unary\MFP@Rsqrt}% + \def\Rrand {\MFP@stack@Unary\MFP@Rrand}% \def\Rpow {\MFP@stack@Binary\MFP@Rpow}}% % \end{macrocode} % @@ -2691,7 +2733,7 @@ % \DescribeMacro{\MFPrad}\DescribeMacro{\MFPdeg} % \DescribeMacro{\MFPlog}\DescribeMacro{\MFPln} % \DescribeMacro{\MFPexp}\DescribeMacro{\MFPsqrt} -% \DescribeMacro{\MFPpow} +% \DescribeMacro{\MFPrand}\DescribeMacro{\MFPpow} % Then the wrappers for the operand versions. % \begin{macrocode} \def\MFPcos {\MFP@op@Unary\MFP@Rcos }% @@ -2703,6 +2745,7 @@ \def\MFPln {\MFP@op@Unary\MFP@Rln }% \def\MFPexp {\MFP@op@Unary\MFP@Rexp }% \def\MFPsqrt {\MFP@op@Unary\MFP@Rsqrt}% +\def\MFPrand {\MFP@op@Unary\MFP@Rrand}% \def\MFPpow {\MFP@op@Binary\MFP@Rpow}% % \end{macrocode} % @@ -2813,7 +2856,8 @@ % % The registers $w$ and $v$ are used to save intermediate results. % The ``\texttt{DP}'' in \cs{MFP@DPmul} refers to the fact that we are -% multiplying by a ``double precision'' real. +% multiplying by a ``double precision'' real. The conversion factors are +% required to be positive. % \begin{macrocode} \def\MFP@DPmul#1#2#3{% \ifnum\MFP@x@Sgn=0 @@ -3148,7 +3192,7 @@ % 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 $mathop{\mathrm{angle}}(1,y/x)$ and get convergence +% series formula for $\mathop{\mathrm{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 @@ -3303,10 +3347,10 @@ % $$ % where $u = x^2$. % -% We start with the common iterated code. It assumes a scaled value in x +% 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. +% 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{% @@ -3346,9 +3390,10 @@ % % The power series produces a logarithm in base $e$ so we ultimately get % the answer in two parts, with the parts calculated for different bases. -% The last step is to multiply the second part by a conversion factor and -% add the first to it. For natural log, convert the first and add the -% second. Which one is to be returned is passed as a boolean +% The last step for the common log is to multiply the second part by a +% conversion factor and add the first to it. For natural log, convert the +% first and add the second. Which one is to be returned is passed as a +% boolean. % % We keep the value-so-far in register $s$ and the modified % $x$-value in register $t$. @@ -3398,8 +3443,8 @@ \fi % \end{macrocode} % -% Now the integer part of $\log_{10} x$ is known. We save it in $s$ -% Also, set the sign of the reduced argument (positive). Then call +% Now the integer part of $\log_{10} x$ is known. We save it in $s$. +% Also set the sign of the reduced argument (positive). Then call % \cs{MFP@Rlog@reduce}, which reduces $x$ to less than $1.161\,$ while % possibly increasing $s$. For the natural log, we convert the value in % $s$. @@ -3720,9 +3765,17 @@ % 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. I have tested with an exponent equal to $8000$ and it -% takes only about $25$ times as long as a single multiplication (rather -% than $7999$ times). +% multiplications. +% +% I have tested with an exponents around $8000$, which has 13 binary +% digits. Each squaring could double the relative error. For that +% large a power, the base has to be near 1 to avoid overflow or underflow. +% So the relative error is about $.5(10)^{-8}$. Doubling that 12 times +% would increase it to about $.00004$, and the result could have as little +% as 4 or 5 significant figures. In these tests, the results were actually +% accurate to 5 or 6 significant figures, starting with 8 figures. Raising +% to this power takes only about $25$ times as long as a single +% multiplication (rather than $7999$ times). % % For negative powers we can either find the positive power of $x$ and % take its reciprocal or take the reciprocal of $x$ and find its positive @@ -3845,7 +3898,7 @@ % 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$ or $10^2$ is the +% average of $s$ and $x/s$. This, possibly divided by $10^4$ or $10^2$ is the % returned value. % % By tests, with rare exceptions, our computations produces a result @@ -3899,13 +3952,13 @@ % 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 two 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 algorithm simplifies somewhat if we proces a base 4 integer, +% producing a base 2 result. 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 two +% 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 @@ -3965,8 +4018,9 @@ % % 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 eighth or ninth grade in his day). Seeing -% it written out, I am surprise at how concise and elegant it is! +% (apparently it was taught in eighth or ninth grade in his day, but not +% in mine). 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% @@ -3980,17 +4034,103 @@ \fi \expandafter\MFP@Isqrt@loop \fi}% +% \end{macrocode} +% +%^^A For my own benefit: the above code finds the next binary digit and +%^^A updates the square root (in \cs{MFP@tempc}) by appending that digit. The +%^^A new digit is also appended to the end of \cs{MFP@tempa}. This is +%^^A subtracted from \cs{MFP@tempb}, but only if the last digit is a 1. Then +%^^A the next quadrenary digit is appended to \cs{MFP@tempb}. Finally, the +%^^A last binary digit found is added (not appended) to \cs{MFP@tempa}. The +%^^A ``appending'' of a digit means a multiplication by $2$ (or $4$) and the +%^^A addition of the digit. We perform such additions only if the digit is a +%^^A 1, and we determine if the digit is 1 or 0 by the \cs{ifnum} test. +% +% \subsection{Random numbers} +% +% We borrow the code of \file{random.tex} to generate a random integer in +% the range $1$ to $2^{31}-2$, inclusive. Mathematically, this works +% because the modulus $m = 2^{31}-1$ is a prime number, and the +% multiplicative group of nonzero elements of $\mathbb{Z}_m$ is cyclic. +% The multiplier chosen (in our cases $16\,807$, $48\,271$, or $69\,621$) +% has to be a generator of that group. +% +% The first step is the code for \cs{nextrandom} from \file{random.tex}. +% We could omit this if it is already defined, or we could even input +% \file{random.tex} but, for better control, we define it ourselves with +% an internal name. This code leaves the next random number in +% \cs{MFP@randseed}. The initial seed is calculated from the time and +% date if it was not positive +% \begin{macrocode} +\newcount\MFP@randseed % the random number (and starting seed) +\def\MFP@nextrand{\begingroup + \ifnum\MFP@randseed<1 + \global\MFP@randseed\time + \global\multiply\MFP@randseed388 \global\advance\MFP@randseed\year + \global\multiply\MFP@randseed31 \global\advance\MFP@randseed\day + \global\multiply\MFP@randseed97 \global\advance\MFP@randseed\month + \MFP@nextrand \MFP@nextrand \MFP@nextrand + \fi + \MFP@tempa\MFP@randseed + \divide\MFP@tempa \MFP@rand@q % modulus = m*q + r + \MFP@tempb\MFP@tempa + \multiply\MFP@tempa \MFP@rand@q + \global\advance\MFP@randseed-\MFP@tempa % seed mod q + \global\multiply\MFP@randseed \MFP@rand@m + \multiply\MFP@tempb \MFP@rand@r + \global\advance\MFP@randseed-\MFP@tempb + \ifnum\MFP@randseed<\z@ \global\advance\MFP@randseed "7FFFFFFF\relax\fi + \endgroup}% +% \end{macrocode} +% +% \DescribeMacro{\MFPrandgenA}\DescribeMacro{\MFPrandgenB} +% \DescribeMacro{\MFPrandgenC} +% We have paametrized \cs{MFP@nextrand} so that any suitable multiplier +% can be used. The following commands each select one of the three +% multipliers that we provide, plus precomputed values for the quotient +% and remainder. We default to generator ``A''. +% \begin{macrocode} +\def\MFPrandgenA{\def\MFP@rand@m{16807 }\def\MFP@rand@q{127773 }% + \def\MFP@rand@r{2836 }}% +\def\MFPrandgenB{\def\MFP@rand@m{48271 }\def\MFP@rand@q{44488 }% + \def\MFP@rand@r{3399 }}% +\def\MFPrandgenC{\def\MFP@rand@m{69621 }\def\MFP@rand@q{30845 }% + \def\MFP@rand@r{23902 }}% +\MFPrandgenA +% \end{macrocode} +% +% The command \verb$\MFPranr{$\meta{x}\verb$}\X$ will take a parameter $x$ +% and define \cs{X} to contain a (pseudo)random real number in the +% interval $[0,x]$. Theoretically, the number should lie in $[0,x)$, but +% rounding will make $x$ itself a possible value. Similarly, \cs{Rrand} +% will replace the $x$ on top of the stack with this random value. To get +% the result, we call \cs{MFP@getrand} twice to produce two random +% integers in the range $[0,99999999]$ and assemble them into a double +% precision multiplier less than $1$. Then we multiply $x$ by that with +% our \cs{MDP@DPmul}. +% +% The test at the end of \cs{MFP@getrand} fails only about 1 time in 50, +% so the odds are vanishingly small that more than a few tries are needed. +% \begin{macrocode} +\def\MFP@getrand{% leaves result in \MFP@tempa + \MFP@nextrand + \MFP@tempa\MFP@randseed + \advance\MFP@tempa-1 + \divide\MFP@tempa 21 % (2^31-3)= 100000000*21 + r + \ifnum \MFP@ttteight> \MFP@tempa + \else \@xp\MFP@getrand\fi}% +\def\MFP@Rrand{% + \MFP@getrand \edef\MFP@a@Tmp{\number\MFP@tempa}% + \MFP@getrand \edef\MFP@b@Tmp{\number\MFP@tempa}% + \MFP@DPmul0\MFP@a@Tmp\MFP@b@Tmp}% +% \end{macrocode} +% +% \DescribeMacro{\MFPsetseed} +% Finally, a user-level command to set the seed value. +% \begin{macrocode} +\def\MFPsetseed#1{\global\MFP@randseed #1\relax}% \MFP@xfinish %</extra> % \end{macrocode} -% For my own benefit: the above code 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 % |