summaryrefslogtreecommitdiff
path: root/tex/context/base/thrd-ran.tex
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/thrd-ran.tex')
-rw-r--r--tex/context/base/thrd-ran.tex149
1 files changed, 87 insertions, 62 deletions
diff --git a/tex/context/base/thrd-ran.tex b/tex/context/base/thrd-ran.tex
index 9372de5a1..ee3a7f6ac 100644
--- a/tex/context/base/thrd-ran.tex
+++ b/tex/context/base/thrd-ran.tex
@@ -1,70 +1,95 @@
-%D \module
-%D [ file=thrd-ran,
-%D version=1998.01.21,
-%D title=\CONTEXT\ Support Macros,
-%D subtitle=Random Number Generation,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
-%C details.
+% RANDOM.TEX v.1 (Donald Arseneau)
+% Generating "random" numbers in TeX.
+%
+% Random integers are generated in the range 1 to 2147483646 by the
+% macro \nextrandom. The result is returned in the counter \randomi.
+% Do not change \randomi except, perhaps, to initialize it at some
+% random value. If you do not initialize it, it will be initialized
+% using the time and date. (This is a sparse initialization, giving
+% fewer than a million different starting values, but you should use
+% other sources of numbers if they are available--just remember that
+% most of the numbers available to TeX are not at all random.)
+%
+% The \nextrandom command is not very useful by itself, unless you
+% have exactly 2147483646 things to choose from. Much more useful
+% is the \setrannum command which sets a given counter to a random
+% value within a specified range. There are three parameters:
+% \setrannum {<counter>} {<minimum>} {<maximum>}. For example, to
+% simulate a die-roll: \setrannum{\die}{1}{6} \ifcase\die... .
+%
+% If you need random numbers that are not integers, you will have to
+% use dimen registers and \setrandimen. For example, to set a random
+% page width: \setrandimen \hsize{3in}{6.5in}. The "\pointless" macro
+% will remove the "pt" that TeX gives so you can use the dimensions
+% as pure `real' numbers. In that case, specify the range in pt units.
+% For example,
+%
+% \setrandimen\answer{2.71828pt}{3.14159pt}
+% The answer is \pointless\answer.
+%
+% The random number generator is the one by Lewis, Goodman, and Miller
+% (1969) and used as "ran0" in "Numerical Recipies" using Schrage's
+% method for avoiding overflows. The multiplier is 16807 (7^5), the
+% added constant is 0, and the modulus is 2147483647 (2^{31}-1). The
+% range of integers generated is 1 - 2147483646. A smaller range would
+% reduce the complexity of the macros a bit, but not much--most of the
+% code deals with initialization and type-conversion. On the other hand,
+% the large range may be wasted due to the sparse seed initialization.
-\writestatus{loading}{Third Party Macros / Random Number Generation}
+\newcount\randomi % the random number seed (while executing)
+\global\randomi\catcode`\@ % scratch variable during definitions
+\catcode`\@=11
-%D \macros
-%D {getrandomcount, getrandomdimen,
-%D getrandomfloat, getrandomnumber}
-%D
-%D This module load Donald Arseneau's generic file
-%D \type{random.tex}. A small shell is needed because we
-%D redefine some \TEX\ primitives. We also use different names
-%D for the two generators and add an extra one.
-%D
-%D \starttypen
-%D \getrandomcount \countregister {minimum} {maximum}
-%D \getrandomdimen \dimenregister {minimum} {maximum}
-%D \getrandomnumber \macroname {minimum} {maximum}
-%D \getrandomfloat \macroname {minimum} {maximum}
-%D \stoptypen
-%D
-%D Of course the file \type{random.tex} needs to be present.
+\def\nextrandom{\begingroup
+ \ifnum\randomi<\@ne % then initialize with time
+ \global\randomi\time
+ \global\multiply\randomi388 \global\advance\randomi\year
+ \global\multiply\randomi31 \global\advance\randomi\day
+ \global\multiply\randomi97 \global\advance\randomi\month
+ \message{Randomizer initialized to \the\randomi.}%
+ \nextrandom \nextrandom \nextrandom
+ \fi
+ \count@ii\randomi
+ \divide\count@ii 127773 % modulus = multiplier * 127773 + 2836
+ \count@\count@ii
+ \multiply\count@ii 127773
+ \global\advance\randomi-\count@ii % random mod 127773
+ \global\multiply\randomi 16807
+ \multiply\count@ 2836
+ \global\advance\randomi-\count@
+ \ifnum\randomi<\z@ \global\advance\randomi 2147483647\relax\fi
+ \endgroup
+}
-\readfile{random.tex}
- {\writestatus{loading}{Donald Arseneau's 'random.tex' (found)}}
- {\writestatus{loading}{Donald Arseneau's 'random.tex' (not found)}}
+\countdef\count@ii=2 % use only in boxes!
+\ifx\@tempcnta\undefined \csname newcount\endcsname \@tempcnta \fi
+\ifx\@tempcntb\undefined \csname newcount\endcsname \@tempcntb \fi
-\ifx\nextrandom\undefined
+\def\setrannum#1#2#3{% count register, minimum, maximum
+ \@tempcnta#3\advance\@tempcnta-#2\advance\@tempcnta\@ne
+ \@tempcntb 2147483645 % = m - 2 = 2^{31} - 3
+ \divide\@tempcntb\@tempcnta
+ \getr@nval
+ \advance\ranval#2\relax
+ #1\ranval
+}
- \def\setrannum#1#2#3{#1=1 }
- \def\setrandim#1#2#3{#1=1pt}
+\def\setrandim#1#2#3{% dimen register, minimum length, maximum length
+ \dimen@#2\dimen@ii#3\relax
+ \setrannum\ranval\dimen@\dimen@ii
+ #1\ranval sp\relax
+}
-\else
+\def\getr@nval{% The values in \@tempcnta and \@tempcntb are parameters
+ \nextrandom
+ \ranval\randomi \advance\ranval\m@ne \divide\ranval\@tempcntb
+ \ifnum\ranval<\@tempcnta\else \expandafter\getr@nval \fi
+}
- \let\normalnextrandom=\nextrandom
+\def\pointless{\expandafter\PoinTless\the}
+{\catcode`p=12 \catcode`t=12
+\gdef\PoinTless#1pt{#1}}
- \def\nextrandom%
- {\bgroup
- \let\time =\normaltime
- \let\day =\normalday
- \let\month=\normalmonth
- \let\year =\normalyear
- \normalnextrandom
- \global\let\nextrandom=\normalnextrandom
- \egroup}
-
-\fi
-
-\let\getrandomcount = \setrannum
-\let\getrandomdimen = \setrandim
-
-\def\getrandomnumber#1#2#3%
- {\getrandomcount{\scratchcounter}{#2}{#3}%
- \edef#1{\the\scratchcounter}}
-
-\def\getrandomfloat#1#2#3%
- {\getrandomdimen{\scratchdimen}{#2pt}{#3pt}%
- \edef#1{\withoutpt\the\scratchdimen}}
-
-\endinput
+\catcode`\@=\randomi
+\global\randomi=0
+\newcount\ranval