You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
245 lines
7.6 KiB
245 lines
7.6 KiB
% Copyright 2007 by Mark Wibrow
|
|
%
|
|
% This file may be distributed and/or modified
|
|
%
|
|
% 1. under the LaTeX Project Public License and/or
|
|
% 2. under the GNU Public License.
|
|
%
|
|
% See the file doc/generic/pgf/licenses/LICENSE for more details.
|
|
|
|
% This file defines the pseudorandom numbers.
|
|
%
|
|
% Version 1.414213 29/9/2007
|
|
|
|
% Pseudo-random number generation.
|
|
%
|
|
% See:
|
|
% \book@{pressetal1992,
|
|
% author = {William H. Press and Brian P. Flannery and Saul A.
|
|
% Teukolsky and William T. Vetterling},
|
|
% title = {Numerical Recipies in C},
|
|
% edition = {Second},
|
|
% publisher = {Cambridge University Press}
|
|
% }
|
|
%
|
|
% See also, the documentation for the lcg package by Erich Janka:
|
|
% (http://www.ctan.org/tex-archive/macros/latex/contrib/lcg/lcg.pdf)
|
|
%
|
|
\def\pgfmath@rnd@m{2147483647}% LaTeX Maximum.
|
|
|
|
\begingroup
|
|
\c@pgfmath@counta=\time%
|
|
\multiply\c@pgfmath@counta by\year%
|
|
\ifnum\c@pgfmath@counta=0
|
|
\c@pgfmath@counta=1
|
|
\fi
|
|
\xdef\pgfmath@rnd@z{\the\c@pgfmath@counta}% The seed.
|
|
\endgroup
|
|
|
|
% \pgfmathsetseed
|
|
%
|
|
% Explicitly set the seed for the generator
|
|
%
|
|
% #1 -> the new seed.
|
|
%
|
|
\def\pgfmathsetseed#1{%
|
|
% Attention pgflibraryluamath.code.tex relies on the fact that
|
|
% this method also modifies \pgfmathresult:
|
|
\pgfmathparse{#1}\expandafter\pgfmath@setseed\pgfmathresult.0\pgfmath@stop
|
|
}%
|
|
\def\pgfmath@setseed#1.#2\pgfmath@stop{\def\pgfmath@rnd@z{#1}}%
|
|
|
|
% Alternative parameters - see Press et al (1992) p278-279,
|
|
% for discussion.
|
|
%
|
|
% a=16807 q=127773 r=2836
|
|
% a=48271 q=4488 r=3399
|
|
%
|
|
\def\pgfmath@rnd@a{69621}
|
|
\def\pgfmath@rnd@r{23902}
|
|
\def\pgfmath@rnd@q{30845}
|
|
|
|
% \pgfmathgeneratepseudorandomnumber
|
|
%
|
|
% A linear congruency generator for generating
|
|
% pseudo-random numbers. Generates numbers in
|
|
% the range 1 - 2^31-1.
|
|
%
|
|
\def\pgfmathgeneratepseudorandomnumber{%
|
|
\begingroup%
|
|
\c@pgfmath@counta=\pgfmath@rnd@z%
|
|
\c@pgfmath@countb=\pgfmath@rnd@z%
|
|
\c@pgfmath@countc=\pgfmath@rnd@q%
|
|
\divide\c@pgfmath@counta by\c@pgfmath@countc%
|
|
\multiply\c@pgfmath@counta by-\c@pgfmath@countc%
|
|
\advance\c@pgfmath@counta by\c@pgfmath@countb
|
|
\c@pgfmath@countc=\pgfmath@rnd@a%
|
|
\multiply\c@pgfmath@counta by\c@pgfmath@countc%
|
|
\c@pgfmath@countc=\pgfmath@rnd@q%
|
|
\divide\c@pgfmath@countb by\c@pgfmath@countc%
|
|
\c@pgfmath@countc=\pgfmath@rnd@r%
|
|
\multiply\c@pgfmath@countb by\c@pgfmath@countc%
|
|
\advance\c@pgfmath@counta by-\c@pgfmath@countb%
|
|
\ifnum\c@pgfmath@counta<0\relax%
|
|
\c@pgfmath@countb=\pgfmath@rnd@m%
|
|
\advance\c@pgfmath@counta by\c@pgfmath@countb%
|
|
\fi%
|
|
\xdef\pgfmath@rnd@z{\the\c@pgfmath@counta}%
|
|
\endgroup%
|
|
\edef\pgfmathresult{\pgfmath@rnd@z}%
|
|
}
|
|
|
|
% \pgfmathrnd
|
|
%
|
|
% Generates a pseudo-random number between 0 and 1.
|
|
%
|
|
\pgfmathdeclarefunction{rnd}{0}{%
|
|
\begingroup%
|
|
\pgfmathgeneratepseudorandomnumber%
|
|
\c@pgfmath@counta\pgfmathresult%
|
|
\c@pgfmath@countb\c@pgfmath@counta%
|
|
\divide\c@pgfmath@countb100001\relax% To get one.
|
|
\multiply\c@pgfmath@countb-100001\relax%
|
|
\advance\c@pgfmath@countb\c@pgfmath@counta%
|
|
\advance\c@pgfmath@countb1000000\relax%
|
|
\expandafter\pgfmathrnd@@\the\c@pgfmath@countb\pgfmath@%
|
|
\pgfmath@returnone\pgfmath@x%
|
|
\endgroup%
|
|
}%
|
|
|
|
\def\pgfmathrnd@@#1#2#3\pgfmath@{%
|
|
\edef\pgfmath@temp{#2.#3}%
|
|
\pgfmath@x=\pgfmath@temp pt\relax%
|
|
}%
|
|
|
|
% \pgfmathrand
|
|
%
|
|
% Generates a pseudo-random number between -1 and 1.
|
|
%
|
|
\pgfmathdeclarefunction{rand}{0}{%
|
|
\begingroup%
|
|
\pgfmathgeneratepseudorandomnumber%
|
|
\c@pgfmath@counta\pgfmathresult%
|
|
\c@pgfmath@countb\c@pgfmath@counta%
|
|
\divide\c@pgfmath@countb200001\relax%
|
|
\multiply\c@pgfmath@countb-200001\relax%
|
|
\advance\c@pgfmath@countb\c@pgfmath@counta%
|
|
\advance\c@pgfmath@countb-100000\relax%
|
|
\ifnum\c@pgfmath@countb<0\relax%
|
|
\advance\c@pgfmath@countb-1000000\relax%
|
|
\else%
|
|
\advance\c@pgfmath@countb1000000\relax%
|
|
\fi%
|
|
\expandafter\pgfmathrand@@\the\c@pgfmath@countb\pgfmath@%
|
|
\pgfmath@returnone\pgfmath@x%
|
|
\endgroup%
|
|
}%
|
|
|
|
\def\pgfmathrand@@#1#2#3#4\pgfmath@{%
|
|
\ifx#1-%
|
|
\edef\pgfmath@temp{-#3.#4}%
|
|
\else%
|
|
\edef\pgfmath@temp{#2.#3#4}%
|
|
\fi%
|
|
\pgfmath@x=\pgfmath@temp pt\relax%
|
|
}%
|
|
|
|
\pgfmathdeclarefunction{random}{...}{%
|
|
\begingroup%
|
|
\def\pgfmath@temp{#1}%
|
|
\ifx\pgfmath@temp\pgfmath@empty%
|
|
\pgfmathrnd@%
|
|
\else%
|
|
\expandafter\pgfmathrandom@@#1\pgfmath@stop%
|
|
\fi%
|
|
\pgfmath@smuggleone\pgfmathresult%
|
|
\endgroup}
|
|
|
|
\def\pgfmathrandom@@{\futurelet\pgfmath@token\pgfmathrandom@@@}
|
|
\def\pgfmathrandom@@@{%
|
|
\ifx\pgfmath@token\bgroup%
|
|
\expandafter\pgfmath@random@@@@%
|
|
\else%
|
|
\expandafter\pgfmath@random@@@@@%
|
|
\fi%
|
|
}
|
|
\def\pgfmath@random@@@@@#1\pgfmath@stop{%
|
|
\pgfmathrandominteger\pgfmathresult{1}{#1}%
|
|
}
|
|
\def\pgfmath@random@@@@#1#2\pgfmath@stop{%
|
|
\pgfmathrandominteger\pgfmathresult{#1}{#2}%
|
|
}
|
|
|
|
% \pgfmathrandominteger
|
|
%
|
|
% Return a 'randomly' selected integer in the range #2 - #3 (inclusive).
|
|
%
|
|
% #1 - a macro to store the integer (not a count register).
|
|
% #2 - the lower limit of the range.
|
|
% #3 - the upper limit of the range.
|
|
%
|
|
\def\pgfmathrandominteger#1#2#3{%
|
|
\begingroup%
|
|
\pgfmathsetcount\c@pgfmath@counta{#2}%
|
|
\pgfmathsetcount\c@pgfmath@countb{#3}%
|
|
\c@pgfmath@countc\c@pgfmath@countb%
|
|
% OK. Maybe #2 > #3.
|
|
\ifnum\c@pgfmath@counta>\c@pgfmath@countb\relax%
|
|
\c@pgfmath@countc\c@pgfmath@countb%
|
|
\c@pgfmath@countb\c@pgfmath@counta%
|
|
\c@pgfmath@counta\c@pgfmath@countc%
|
|
\fi%
|
|
\advance\c@pgfmath@countc1\relax%
|
|
\advance\c@pgfmath@countc-\c@pgfmath@counta%
|
|
\pgfmathgeneratepseudorandomnumber%
|
|
\c@pgfmath@counta\pgfmathresult\relax%
|
|
\c@pgfmath@countb\c@pgfmath@counta%
|
|
\divide\c@pgfmath@countb\c@pgfmath@countc%
|
|
\multiply\c@pgfmath@countb-\c@pgfmath@countc%
|
|
\advance\c@pgfmath@counta\c@pgfmath@countb%
|
|
\pgfmathaddtocount\c@pgfmath@counta{#2}%
|
|
\edef\pgfmathresult{\the\c@pgfmath@counta}%
|
|
\pgfmath@smuggleone{\pgfmathresult}%
|
|
\endgroup%
|
|
\edef#1{\pgfmathresult}%
|
|
}
|
|
|
|
% \pgfmathdeclarerandomlist
|
|
%
|
|
% Create a list to be used with \pgfmathrandomelement.
|
|
%
|
|
% #1 - the name of the list
|
|
% #2 - a list of comma separated elements.
|
|
%
|
|
\def\pgfmathdeclarerandomlist#1#2{%
|
|
\def\pgfmath@randomlistname{#1}%
|
|
\begingroup%
|
|
\c@pgfmath@counta=1\relax%
|
|
% {} is a possible random element so (locally)
|
|
% redefine \pgfmath@empty.
|
|
\def\pgfmath@empty{pgfmath@empty}%
|
|
\expandafter\pgfmath@scanrandomlist#2{pgfmath@empty}}
|
|
\def\pgfmath@scanrandomlist#1{%
|
|
\def\pgfmath@scanneditem{#1}%
|
|
\ifx\pgfmath@scanneditem\pgfmath@empty%
|
|
\advance\c@pgfmath@counta-1\relax%
|
|
\expandafter\xdef\csname pgfmath@randomlist@\pgfmath@randomlistname\endcsname{\the\c@pgfmath@counta}%
|
|
\endgroup%
|
|
\else%
|
|
\expandafter\gdef\csname pgfmath@randomlist@\pgfmath@randomlistname @\the\c@pgfmath@counta\endcsname{#1}%
|
|
\advance\c@pgfmath@counta1\relax%
|
|
\expandafter\pgfmath@scanrandomlist%
|
|
\fi}
|
|
|
|
% \pgfmathrandomitem
|
|
%
|
|
% Return a 'randomly' selected element from a list.
|
|
%
|
|
% #1 - a macro to store the item.
|
|
% #2 - the name of the list.
|
|
%
|
|
\def\pgfmathrandomitem#1#2{%
|
|
\pgfmath@ifundefined{pgfmath@randomlist@#2}{\pgfmath@error{Unknown random list `#2'}}{%
|
|
\edef\pgfmath@randomlistlength{\csname pgfmath@randomlist@#2\endcsname}%
|
|
\pgfmathrandominteger{\pgfmath@randomtemp}{1}{\pgfmath@randomlistlength}%
|
|
\def#1{\csname pgfmath@randomlist@#2@\pgfmath@randomtemp\endcsname}}}
|
|
|