% 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 pesudorandom numbers.
%
% Version 0.0 08/03/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%
\xdef\pgfmath@rnd@z{\the\c@pgfmath@counta}% The seed. 
\endgroup

% \pgfmathsetseed
%
% Explictly set the seed for the generator
%   
% #1 -> the new seed.
%

\def\pgfmathsetseed#1{\pgfmathparse{#1}\expandafter\pgfmath@setseed\pgfmathresult\relax}%
\def\pgfmath@setseed#1.#2\relax{\def\pgfmath@rnd@z{#1}}%  

% Alternative paramaters - 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.
%
\def\pgfmathrnd{%
	\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.
%
\def\pgfmathrand{%
	\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%
}%

% \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%
		\pgfmathgeneratepseudorandomnumber%
		\c@pgfmath@counta#2\relax%
		\c@pgfmath@countb#3\relax%
		\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%
		\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%
		\advance\c@pgfmath@counta#2\relax%
		\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}}}