% Since we cannot be sure that this file is available at any % system, we have copied the original in this file. These % macros are encapsulates and extended in supp-ran.tex. % % This module is slightly recoded to bring it more in tune % with \CONTEXT's scratch registers and protection mechanisms. % 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 {} {} {}. 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. % original code % % \newcount\randomi % the random number seed (while executing) % \global\randomi\catcode`\@ % scratch variable during definitions % \catcode`\@=11 % % \def\nextrandom{\begingroup % \ifnum\randomi<\plusone % 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 % } % % \countdef\count@ii=2 % use only in boxes! % \ifx\@tempcnta\undefined \csname newcount\endcsname \@tempcnta \fi % \ifx\@tempcntb\undefined \csname newcount\endcsname \@tempcntb \fi % % \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\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 % } % % \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 % } % % %D The next macro is not needed in \CONTEXT, which provides % %D the \type {\withoutpt} macro. % %D % %D \starttyping % %D \def\pointless{\expandafter\PoinTless\the} % %D {\catcode`p=12 \catcode`t=12 \gdef\PoinTless#1pt{#1}} % %D \stoptyping % % \catcode`\@=\randomi % \global\randomi=0 % \newcount\ranval % the recoded version, using \CONTEXT\ methods and variables; % the magic is kept untouched \unprotect \newcount\randomi % the random number seed (while executing) \newcount\ranval \ifx\m!systems\undefined \def\m!systems{systems} \fi \def\nextrandom {\begingroup \ifnum\randomi<\plusone % then initialize with time \global\randomi\time \global\multiply\randomi388 \global\advance\randomi\year \global\multiply\randomi 31 \global\advance\randomi\day \global\multiply\randomi 97 \global\advance\randomi\month \writestatus\m!systems{randomizer starts with \the\randomi}% \nextrandom \nextrandom \nextrandom \fi \!!countd\randomi \divide\!!countd 127773 % modulus = multiplier * 127773 + 2836 \!!countc\!!countd \multiply\!!countd 127773 \global\advance\randomi-\!!countd % random mod 127773 \global\multiply\randomi 16807 \multiply\!!countc 2836 \global\advance\randomi-\!!countc\relax \ifnum\randomi<\zerocount \global\advance\randomi 2147483647 \fi \endgroup} \def\setrannum#1#2#3% count register, minimum, maximum {\!!counta#3% \advance\!!counta-#2% \advance\!!counta\plusone \!!countb 2147483645 % = m - 2 = 2^{31} - 3 \divide\!!countb\!!counta \getr@nval \advance\ranval#2% #1\ranval} \def\setrandim#1#2#3% dimen register, minimum length, maximum length {\!!dimenc#2% \!!dimend#3% \setrannum\ranval\!!dimenc\!!dimend #1\ranval\s!sp\relax} % \s!sp not needed \def\getr@nval % The values in \!!counta and \!!countb are parameters {\nextrandom \ranval\randomi \advance\ranval\minusone \divide\ranval\!!countb \ifnum\ranval<\!!counta \else \expandafter\getr@nval \fi} \protect \endinput