1

I am currently trying to set up a conditional statement that takes a randomly assigned integer, and provides a specific output depending on if the integer is odd or even. I've written this so far

\documentclass[12pt]{article}
\usepackage[first=-20, last=20]{lcg}
\usepackage{tikz}
\usepackage{calculator}
\usepackage{calculus}
\usepackage{ifthen}

\newcommand{\randi}{\rand\arabic{rand}} \newcommand{\addsub}{\pgfmathrandomitem{\choice}{choices1}\choice} \pgfmathdeclarerandomlist{choices1}{{+}{-}}

\newcommand{\firstpower}{\chgrand[first=2, last=5] \randi}

\newcommand{\Oddleft}[1]{ \ifodd#1 | \else ( \fi }

\newcommand{\Oddright}[1]{ \ifodd#1 | \else ) \fi }

\begin{document}

\section*{Problem 1} Provide the output of the function $f(x) = \randi \Oddleft{\firstpower} x \addsub \chgrand[first=1, last=20] \randi \Oddright{\firstpower} ^{\firstpower}$ for values of $x = \chgrand[last=-50, last=50]$ \

\end{document}

The point of this code, for now, is to have my expression enclosed by absolute value bars if the power is odd and parentheses if the power is even. However, the commands \Oddleft and \Oddright do not interpret my command \firstpower as a number, thus the input is treated to be zero. How can I have a random number be declared / aliased so that it may be used as the input to another command?

David G.
  • 205
  • 1
    you can use \ExplSyntaxOn\newcommand{\firstpower}{\int_rand:nn{2}{5}}\ExplSyntaxOff that is an expandable number. – Ulrike Fischer Oct 12 '20 at 16:47
  • @UlrikeFischer This worked great! Would you care to write it as an answer so I can mark the question solved? – David G. Oct 12 '20 at 17:26

4 Answers4

1

you can use

\ExplSyntaxOn
\newcommand{\firstpower}{\int_rand:nn{2}{5}}
\ExplSyntaxOff 

that is an expandable number

Ulrike Fischer
  • 327,261
  • 2
    This would use a different value of the exponent at each call. And there are three of them. – egreg Oct 12 '20 at 17:34
  • @egreg yes, but didn't the original command did this too? – Ulrike Fischer Oct 12 '20 at 17:36
  • 1
    Just because the OP didn't realize it. The idea seems to use |<expr>|^<exp> if the exponent is odd, (<expr>)^<exp> if the exponent is even. You'll end up with |..| or |...|, but also with |...) or (...|; in the first two cases independently of the exponent. – egreg Oct 12 '20 at 17:39
  • @egreg Yes, you are right, I've run into this now. I suppose I was too overeager to accept the response as a solution. – David G. Oct 12 '20 at 18:16
1

You need to save first the exponent as a value that can be fed to \Oddleft or \Oddright (even if using \firstpower worked, it would compute different values at each usage).

Here's a different approach with expl3:

\documentclass[12pt]{article}
\usepackage{xfp}

\ExplSyntaxOn \NewDocumentCommand{\expression}{} { % a random sign, print nothing if positive \int_if_odd:nT { \int_rand:nn { 1 } { 2 } } { - } % the absolute value of the coefficient \int_rand:nn { 1 } { 20 } % compute a random exponent \int_set:Nn \l_tmpa_int { \int_rand:nn { 2 } { 5 } } % if odd exponent, use |, else ( \int_if_odd:nTF \l_tmpa_int { | } { ( } % the variable x % a random sign \int_if_odd:nTF { \int_rand:nn { 1 } { 2 } } { - } { + } % the absolute value of the summand \int_rand:nn { 1 } { 20 } % if odd exponent use |, else ) \int_if_odd:nTF \l_tmpa_int { | } { ) } % the exponent \sp { \int_use:N \l_tmpa_int } }

% print a row of values \NewDocumentCommand{\randomvalues}{m} { \int_rand:nn { -50 } { 50 } \prg_replicate:nn { #1 - 1 } { , \int_rand:nn { -50 } { 50 } } } \ExplSyntaxOff

\begin{document}

Provide the output of the function $f(x) = \expression$

Provide the output of the function $f(x) = \expression$

Provide the output of the function $f(x) = \expression$

Provide the output of the function $f(x) = \expression$

Provide the output of the function $f(x) = \expression$

Provide the output of the function $f(x) = \expression$

Provide the output of the function $f(x) = \expression$ for the values $x=\randomvalues{4}$

\end{document}

enter image description here

egreg
  • 1,121,712
  • This works, but I get a weird string of numbers and upside down questions marks at the beginning of my document, on its own page before the \maketitle page. – David G. Oct 12 '20 at 17:49
  • Also, spaces seem to be removed from my document entirely, I'm having to write in \: – David G. Oct 12 '20 at 18:13
  • @DavidG. Did you remember the \ExplSyntaxOn and \ExplSyntaxOff commands? – egreg Oct 12 '20 at 19:25
  • yes that did turn out to be the issue. I forgot to turn off explicit syntax – David G. Oct 12 '20 at 19:43
1

There are several issues that need to be taken into consideration:

The most noteworthy ones are:

  • Your code is intended to create and output a set of random numbers with each LaTeX-run.
    But often several LaTeX-runs are needed until everything (cross-references, table of contents etc) matches out.
    I think a mechanism is a good idea which creates random-numbers only if they cannot be retrieved from the previous LaTeX-run via the .aux-file. Otherwise you might end up needing a very long circle of compilations until everything matches out by accident:

    • Changing of random-variables changes the text of the document.
    • Changing the text of the document may change how the text is broken into pages.
    • Changing how the text is broken into pages may lead to cross-references and page-numbers of the table of contents etc not matching out.
    • Cross-references and page-numbers of the table of contents etc not matching out requires another LaTeX-run.
    • With that LaTeX-run the random-variables are changed.
    • Changing of random-variables changes the text of the document.
    • ...

    In the example below a referencing-label is written to the .aux-file from the numbers/coefficients used with an exercise. Numbers used with an exercise are created randomly only if they cannot be retrieved from the .aux-file's referencing-label.

  • You probably wish to prevent the same exercise/function-expression to be created twice. Therefore a macro \expressionlist is maintained which holds a list of non-delimited arguments, each argument holding the set of numbers/coefficients used with an exercise. Creation of random numbers is repeated until a constellation is obtained which is not already in the list. (If you are not in luck, this will never be the case. ;-) )

  • You probably wish the list of values for which the output of the function is to be provided not to contain the same value twice. Picking a random value for this list is repeated until finding one which is not already in the list. (If you are not in luck, this will never be the case. ;-) )

  • You probably wish the list of values for which the output of the function is to be provided to be sorted in ascending order.

  • With a expressions of pattern (+)(2) respective |+|(2+1) you probably wish to avoid cases/exercises where =0. That's why in the example below the coefficient is not picked as a random-number in range -20..20 but is picked in two steps: The sign of is from a random number in range 0..1. The absolute value of is from a random number in range 1..20. This way the case =0 is not possible.

Twice I used the phrase "If you are not in luck, this will never be the case".

Probably—instead of picking random numbers one by one—it is more safe to pick a (subset of a) random permutation. Algorithms like Fisher-Yates-Shuffle and Lehmer code come to my mind. The duration of the compilation of the document would become more predictable. ;-)


\documentclass[12pt]{article}
\usepackage[first=-20, last=20]{lcg}

\makeatletter %======================================================================== % \CreateListsOfRandomNumbers{<macro that gets all lists of random numbers as arguments>}{% % {{amount of random numbers}{lower bound}{upper bound}{List not in braces=0/list in braces=1}} % {{amount of random numbers}{lower bound}{upper bound}{List not in braces=0/list in braces=1}} % ... % {{amount of random numbers}{lower bound}{upper bound}{List not in braces=0/list in braces=1}} % }% % yields: % <macro that gets all lists of random numbers as arguments><list 1 of random numbers><list 2 of random numbers>..<list k of random numbers> % % Values in the lists are sorted in ascending order. % No value occurs twice within the same list. % % E.g., % % \CreateListsOfRandomNumbers{\foobar}{% % {{2}{3}{17}{0}}% % {{6}{1}{20}{1}}% % {{4}{20}{40}{0}} % }% % may yield: % \foobar{5}{17}% <-first list: 2 random numbers in range 3..17, list not in braces % {{4}{7}{9}{12}{15}{19}}% <-second list: 6 random numbers in range 1..20, list in braces % {20}{27}{34}{39}% <-third list: 4 random numbers in range 20..40, list not in braces % @ifdefinable\CreateListsOfRandomNumbers{% \DeclareRobustCommand\CreateListsOfRandomNumbers[2]{% % #1 = macro that gets all lists of random numbers as arguments % #2 = list of 4-tuples {{amount of random numbers}{lower bound}{upper bound}{List not in braces=0/list in braces=1}} \CreateListsOfRandomNumbersLoop{#1}{}#2{}% }% }% %======================================================================== \newcommand\CreateListsOfRandomNumbersLoop[3]{% % #1 = macro that gets all lists of random numbers as arguments % #2 = list of lists of random numbers created so far % #3 = 4-tuple {amount of random numbers}{lower bound}{upper bound}{List not in braces=0/list in braces=1} \ifx X#3X\expandafter@firstoftwo\else\expandafter@secondoftwo\fi {#1#2}{% \CreateRandomNumbersOfSameRange#3{\AppendToCreateListsOfRandomNumbersLoop{#1}{#2}}% }% }% \newcommand\AppendToCreateListsOfRandomNumbersLoop[3]{\CreateListsOfRandomNumbersLoop{#1}{#2#3}}% \newcommand\CreateRandomNumbersOfSameRange[5]{% \ifnum\numexpr((#3)-(#2)+1)-#1\relax<0 \expandafter@firstoftwo\else\expandafter@secondoftwo\fi {% \GenericError{\space@spaces@spaces}% {Error: Creation of list of random-numbers not possible}% {\space@spaces@spaces You cannot have #1 different random numbers if according\MessageBreak to the randomoize-ranges there are only (#3)-(#2)+1=\number\numexpr((#3)-(#2)+1)\relax\MessageBreak different numbers available.}% {Learn about Jean Leurechon's pigeonhole principle/Dirichlet's drawer principle.}% \ifnum\expandafter@firstofone\expandafter{\number#4}>0 % \expandafter@firstoftwo\else\expandafter@secondoftwo\fi {#5{{{0}}}}{#5{{0}}}% }{% \InnerCreateRandomNumbersOfSameRange{#1}{#2}{#3}{#4}{#5}% }% }% \newcommand\InnerCreateRandomNumbersOfSameRange[1]{% %#1 = amount of random numbers \expandafter\CreateRandomNumbersOfSameRangeLoop\expandafter{\romannumeral\number\number#1 000}{}% }% \newcommand\CreateRandomNumbersOfSameRangeLoop[6]{% %#1 = characters m in an amount corresponding to amount of numbers %#2 = list of random numbers created so far %#3 = lower bound %#4 = upper bound %#5 = 0/1 List not/in braces %#6 = Tokens where to append the list of random-numbers as argument \ifx X#1X\expandafter@secondoftwo\else\expandafter@firstoftwo\fi {% \randi[\CheckIfAlreadyInRandomlist#2{}{}\relax{#2}{#1}{#3}{#4}]{#3}{#4}% }{% \SortRandomNumbersLoop#2{}{}\relax{}% }% {#5}{#6}% }% @ifdefinable\CheckIfAlreadyInRandomlist{% \long\def\CheckIfAlreadyInRandomlist#1#2\relax#3#4#5#6#7{% %#1 = first element of list of random numbers created so far %#2 = remaining elements of list of random numbers created so far %#3 = list of random numbers created so far %#4 = characters m in an amount corresponding to amount of numbers %#5 = lower bound %#6 = upper bound %#7 = random number just created \ifx\relax#1\relax\expandafter@firstoftwo\else\expandafter@secondoftwo\fi {\expandafter\CreateRandomNumbersOfSameRangeLoop\expandafter{@gobble#4}{#3{#7}}{#5}{#6}}% {% \ifnum\expandafter@firstofone\expandafter{\number#1}=\expandafter@firstofone\expandafter{\number#7} % \expandafter@firstoftwo\else\expandafter@secondoftwo\fi {\CreateRandomNumbersOfSameRangeLoop{#4}{#3}{#5}{#6}}% {% \CheckIfAlreadyInRandomlist#2\relax{#3}{#4}{#5}{#6}{#7}% }% }% }% }% @ifdefinable\SortRandomNumbersLoop{% \long\def\SortRandomNumbersLoop#1#2\relax#3{% %#1 first element of list %#2 remaining elements of list %#3 list of sorted elements \ifx X#1X\expandafter@firstoftwo\else\expandafter@secondoftwo\fi {% \ReturnSortedList{#3}% }{% \InsertRandomNumberLoop{#1}{#2}\relax#3{}{}\relax{}{@firstoftwo}% }% }% }% @ifdefinable\InsertRandomNumberLoop{% \long\def\InsertRandomNumberLoop#1#2\relax#3#4\relax#5#6{% %#1 first element of list %#2 remaining elements of list %#3 first element of list of sorted elements %#4 remaining elements of list of sorted elements %#5 new list of sorted elements %#6 indicator whether element was already inserted \ifx X#3X\expandafter@firstoftwo\else\expandafter@secondoftwo\fi {% #6{\SortRandomNumbersLoop#2\relax{#5{#1}}}% {\SortRandomNumbersLoop#2\relax{#5}}% }{% #6{% \ifnum\expandafter@firstofone\expandafter{\number#3}>\expandafter@firstofone\expandafter{\number#1} % \expandafter@firstoftwo\else\expandafter@secondoftwo\fi {% \InsertRandomNumberLoop{#1}{#2}\relax#4\relax{#5{#1}{#3}}{@secondoftwo}% }{% \InsertRandomNumberLoop{#1}{#2}\relax#4\relax{#5{#3}}{#6}% }% }{% \InsertRandomNumberLoop{#1}{#2}\relax#4\relax{#5{#3}}{#6}% }% }% }% }% \newcommand\ReturnSortedList[3]{% %#1 = list of sorted elements %#2 = 0/1 List not/ in braces %#3 = Tokens where to append the list of random-numbers as argument \ifnum\expandafter@firstofone\expandafter{\number#2}>0 % \expandafter@firstoftwo\else\expandafter@secondoftwo\fi {#3{{#1}}}{#3{#1}}% }% %======================================================================== \newcommand\PassFirstToSecond[2]{#2{#1}} \newcommand{\randi}[3][@firstofone]{% % #1 = token(s) where to append the random-number after nesting it in braces % #2 = lower bound of randomize % #3 = upper bound of randomize \chgrand[first=#2,last=#3]% \rand \expandafter\PassFirstToSecond\expandafter{\number\value{rand}}{#1}% }% %======================================================================== % \WriteRandomNumbersLoop{<variable>}{<separator>}<List of numbers>{} \newcommand\WriteRandomNumbersLoop[3]{% \ifx X#3X\expandafter@gobble\else\expandafter@firstofone\fi {% #2$#1=#3$% \WriteRandomNumbersLoop{#1}{; }% I used semicolon instead of comma because comma in many countries is decimal-separator. }% }% %======================================================================== \newcounter{CreatedExpressions} \newcommand\CreateExpression[2]{% % #1 - variable % #2 - amount of random values where to solve the expression for. % As values are in range -50..50, don't request more than 101 values! \global\stepcounter{CreatedExpressions}% @ifundefined{r@CreatedExpression\number\value{CreatedExpressions}}{% @firstoftwo }{% \begingroup \expandafter\expandafter\expandafter \CheckExpressionlabel\csname r@CreatedExpression\number\value{CreatedExpressions}\endcsname \def@tempb{{#1}{#2}}% \ifx@tempa@tempb\expandafter@firstoftwo\else\expandafter@secondoftwo\fi {\endgroup@secondoftwo}{\endgroup@firstoftwo}% }{% \CreateExpressionRandomNumbers{#1}{#2}% }{% \expandafter\expandafter\expandafter \writeexpression\csname r@CreatedExpression\number\value{CreatedExpressions}\endcsname }% }% \newcommand\CheckExpressionlabel[8]{\def@tempa{{#7}{#8}}}% \newcommand\CreateExpressionRandomNumbers[2]{% \CreateListsOfRandomNumbers{\InnerCreateExpressionRandomNumbers}{% {{1}{0}{1}{0}}%<- sign of coefficient {{1}{1}{20}{0}}% <- abs of coefficient {{1}{2}{5}{0}}%<- exponent {{1}{1}{20}{0}}%<- abs of summand {{1}{0}{1}{0}}%<- sign of summand {{#2}{-50}{50}{1}}%<- List with values where the expression to solve for }% {#1}{#2}% }% \newcommand\expressionlist{}% \newcommand\InnerCreateExpressionRandomNumbers[8]{% % #1 - sign of coefficient % #2 - abs of coefficient % #3 - exponent % #4 - abs of summand % #5 - sign of summand % #6 - List with values where the expression to solve for % #7 - variable, usually x % #8 - amount of values where to solve the expression for \begingroup \def@tempa{{#1}{#2}{#3}{#4}{#5}}% \expandafter\CheckExpressionListLoop\expandafter{\expandafter@firstoftwo\expandafter}\expressionlist{}{% \endgroup \CreateExpressionRandomNumbers{#7}{#8}% }{% \endgroup \writeexpression{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}% }% }% \newcommand\writeexpression[8]{% \immediate\write@auxout{% \string\newlabel{CreatedExpression\number\value{CreatedExpressions}}{{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}}% }% \g@addto@macro\expressionlist{{{#1}{#2}{#3}{#4}{#5}}}% $f(#7)=\ifnum#1=0 \else-\fi#2\oddabs{#3}{#7\ifnum#5=0 +\else-\fi#4}^{#3}$% \ifnum#8>0 @firstofone{} for the value\ifnum#8>1 s\fi@firstofone{} \WriteRandomNumbersLoop{#7}{}#6{}\fi.% }% \newcommand\oddabs[2]{% \ifodd\expandafter@firstofone\expandafter{\number#1} % \expandafter@firstoftwo\else\expandafter@secondoftwo\fi {|#2|}{(#2)}% }% \newcommand\CheckExpressionListLoop[2]{% \ifx X#2X\expandafter@firstoftwo\else\expandafter@secondoftwo\fi {#1{@secondoftwo}{@firstoftwo}}% {\def@tempb{#2}% \ifx@tempa@tempb\expandafter@firstoftwo\else\expandafter@secondoftwo\fi {\CheckExpressionListLoop{@secondoftwo}}{\CheckExpressionListLoop{#1}}% }% }% \makeatother

\begin{document}

\section*{Problem 1}

\noindent Provide the output of the function \CreateExpression{t}{7}\

\noindent Provide the output of the function \CreateExpression{x}{3}\

\noindent Provide the output of the function \CreateExpression{y}{1}\

\noindent Provide the output of the function \CreateExpression{z}{0}\

\end{document}

When I compiled the example above, I got a document which looked like this—due to the randomness of numbers the probability is high that you get something different:

enter image description here

Ulrich Diez
  • 28,770
  • The ratio of effort to upvote deserves an infinite increase, which I have now provided. It would be nice to see another 100 votes. – PatrickT Mar 26 '23 at 22:59
1

This "answer" does not provide a solution to the problem.

As in your question the lcg-package is used, let's mention that the lcg package (The lcg package, 2013/08/09 (v1.3), CTAN: https://www.ctan.org/pkg/lcg) produces spurious space tokens.

(I already tried to contact the package author about this via the e-mail-address provided in the package documentation. Neither did the mail bounce nor did I get any reaction. We live in turbulent times. It might be good to put these things in order. But I don't want to hijack/take over the package, because that would probably be unpolite.)

You can easily reproduce this phenomenon:

\documentclass{article}
\usepackage{lcg}
\begin{document}
\noindent X\rand X

\noindent X\chgrand[first=1,last=20,quiet=y]X

\noindent X\rand X \end{document}

\rand and \chgrand and the like should not produce visible output.

Thus I expected the visual output of the minimal example above to be something like this:

XX
XX
XX

But the X are interspersed with spaces and you get something like this:

X X
X  X
XX

The reason is that both the definition-text of the key quiet and the definition-text of the macro \r@nd produce spurious space tokens.

In the following I copied these definitions and marked with <-!!!!! the places where the spurious space tokens come into being:

84 \define@key{Init}{quiet}[y]{ <-!!!!!
85   \def\qui@t{\expandafter\firstletterr@nd #1\delimiter} <-!!!!!
86   \if \qui@t y% nothing to do
87   \else\if\qui@t Y \def\qui@t{y} <-!!!!! (2x)
88   \else\if\qui@t j \def\qui@t{y} <-!!!!! (2x)
89   \else\if\qui@t J \def\qui@t{y} <-!!!!! (2x)
90   \else\if\qui@t n \def\qui@t{n} <-!!!!! (2x)
91   \else\if\qui@t N \def\qui@t{n} <-!!!!! (2x)
92   \else
93     \PackageWarning{lcg}{Value of key <quiet> must be <y> or <n>} <-!!!!!
94     \def\qui@t{y} <-!!!!!
95   \fi\fi\fi\fi\fi\fi
96 }

173 \def\r@nd{% 174 \ifnum \cr@nd < @ne% then ... initialize generator 175 \cr@nd = \the\time 176 \advance \cr@nd \inputlineno 177 \multiply \cr@nd \value{page} <-!!!!! 178 \advance \cr@nd \the\year 179 \multiply \cr@nd \the\month 180 \multiply \cr@nd \the\day 181 \advance \cr@nd \inputlineno 182 \if \qui@t y% 183 \else 184 \typeout{Random number generator initialized to \the\cr@nd}% 185 \fi 186 \r@nd% 187 \else % else ... generate new number 188 @tempcnta = \cr@nd 189 \divide @tempcnta 127773 % @tempcnta = floor(z/q) 190 @tempcntb = @tempcnta % @tempcntb = floor(z/q) 191 \multiply @tempcnta -2836 % @tempcnta = -rfloor(z/q) 192 \multiply @tempcntb -127773 % @tempcntb = -qfloor(z/q) 193 \advance \cr@nd @tempcntb % cr@nd = z mod q 194 \multiply \cr@nd 16807 % cr@nd = a * (z mod q) 195 \advance \cr@nd @tempcnta % cr@nd = az mod m 196 \ifnum \cr@nd < \z@% 197 \advance \cr@nd 2147483647 % cr@nd = (az mod m) > 0 198 \fi 199 \global\cr@nd=\cr@nd % persist the change outside current scope 200 \fi 201 }% end of \r@nd

I suggest the following changes:

\define@key{Init}{quiet}[y]{%
  \def\qui@t{\expandafter\firstletterr@nd #1\delimiter}%
  \if \qui@t y% nothing to do
  \else\if\qui@t Y\def\qui@t{y}%
  \else\if\qui@t j\def\qui@t{y}%
  \else\if\qui@t J\def\qui@t{y}%
  \else\if\qui@t n\def\qui@t{n}%
  \else\if\qui@t N\def\qui@t{n}%
  \else
    \PackageWarning{lcg}{Value of key <quiet> must be <y> or <n>}%
    \def\qui@t{y}%
  \fi\fi\fi\fi\fi\fi
}

 

\def\rand{%
  \r@nd%
  \@tempcnta
  \@tempcntb
  \@tempcnta = \f@rst
  \@tempcntb = \l@st
  \multiply \@tempcnta \m@ne
  \advance \@tempcntb \@tempcnta
  \advance \@tempcntb \@ne %l@st-f@rst+1
  \@tempcnta = 2147483647
  \divide \@tempcnta \@tempcntb
  \multiply \@tempcnta \@tempcntb
  \ifnum \cr@nd > \@tempcnta\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {\rand}%
  {%
    \setcounter{\r@ndcountername}{\cr@nd}%
    \@tempcnta = \cr@nd
    \divide \@tempcnta \@tempcntb
    \multiply \@tempcnta \@tempcntb
    \multiply \@tempcnta \m@ne
    \addtocounter{\r@ndcountername}{\@tempcnta}%
    \addtocounter{\r@ndcountername}{\f@rst}%
  }%
}% end of \rand

 

\def\r@nd{%
  \ifnum \cr@nd < \@ne\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {% then ... initialize generator
    \cr@nd = \the\time
    \advance \cr@nd \inputlineno
    \multiply \cr@nd \value{page}%%%%%%%
    \advance \cr@nd \the\year
    \multiply \cr@nd \the\month
    \multiply \cr@nd \the\day
    \advance \cr@nd \inputlineno
    \if \qui@t y%
    \else
      \typeout{Random number generator initialized to \the\cr@nd}%
    \fi
    \r@nd%
  }{% else ... generate new number
    \@tempcnta = \cr@nd
    \divide \@tempcnta 127773 % \@tempcnta = floor(z/q)
    \@tempcntb = \@tempcnta % \@tempcntb = floor(z/q)
    \multiply \@tempcnta -2836 % \@tempcnta = -r*floor(z/q)
    \multiply \@tempcntb -127773 % \@tempcntb = -q*floor(z/q)
    \advance \cr@nd \@tempcntb % cr@nd = z mod q
    \multiply \cr@nd 16807 % cr@nd = a * (z mod q)
    \advance \cr@nd \@tempcnta % cr@nd = a*z mod m
    \ifnum \cr@nd < \z@%
      \advance \cr@nd 2147483647 % cr@nd = (a*z mod m) > 0
    \fi
    \global\cr@nd=\cr@nd % persist the change outside current scope
  }%
}% end of \r@nd
Ulrich Diez
  • 28,770