1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{fp-random}[1995/02/23]
% Version information
\def\FP@randomversion{1.0a}
\message{%
`Fixed Point Random,%
\space\space\space\space\space\space%
\space\space\space\space\space\space\space%
Version \FP@randomversion%
\space(C) Denis Girou (CNRS/IDRIS)%
\space\space\space%
}
% Resolve dependencies
\RequirePackage{fp-basic}
% Uniform random value
\newcount\FPseed % Seed value
\def\FPrandom#1{%
% #1 macro, which gets the result
%
% Uniform random number generator (numbers between 0 and 1)
%
% Algorithm reproduce from a very old Fortran program (unknown origin!)
%
% double precision function RANF()
%
% integer SEED
% common /COMSEED/SEED
% *
% integer A,M,Q,R
% parameter(A=16807,M=2147483647,Q=127773,R=2836)
% *
% integer LO,HI,TEST
% *
% HI = SEED/Q
% LO = SEED-HI*Q
% TEST = A*LO-R*HI
% if(TEST.gt.0) then
% SEED = TEST
% else
% SEED = TEST+M
% endif
% *
% RANF = DFLOAT(SEED)/DFLOAT(M)
% *
% end
%
% The macro used a seed value, defined by the counter \FPseed.
% If it's unknown at first call, we used an arbitrary value.
%
% We verify that we obtain the same results as in Fortran
%
% The algorithm seems fairly good. With the Fortran version, we obtain
% typically something like 49954 numbers between 0 and 0.5 and 50046 between
% 0.5 and 1 for 100000 random numbers, depending of the seed value used.
%
% To generate a "pseudo-random" seed, you can consider to use the \time
% macro, to intialize the random numbers generator according to the time.
% Something like:
% \FPseed=\the\time
% \multiply\FPseed\the\day
% \multiply\FPseed\the\month
% \multiply\FPseed\the\year
%
% Of course, it is very slow comparing to "standard" programming
% languages. On a RS 6000 370, it's take 51s to generate 100 numbers,
% loading time of the test program included (and 0.2s for the Fortran
% version ... for 100000 numbers!)
% But you must also notice that Hans van der Meer published in TUGboat
% Vol. 15, 1, March 1994, pages 57-58, an article on "Random bit generator
% in TeX". In fact, he doesn't give a complete solution to generate uniform
% random numbers, but at least give some interesting ideas, and also the
% code of a simple but powerful macro \SRtest{choice 1}{choice 2}, which
% allow to execute the instructions of "choice 1" or those of "choice 2"
% with a probability of 1/2 each. As his method is based on shifts of bits
% with almost no computations, it's very fast (around 1000 faster than to do
% the same thing that \SRtest with \FPrandom.)
%
{\FP@beginmessage{RANDOM}%
%
\ifnum\FPseed=0%
\FPseed=123456789%
\FP@debug{random: seed value undefined! We will used \the\FPseed.^^J%
Define it if you want to generate a different sequence of random%
numbers.}%
\else%
\FP@debug{random: seed value used: \the\FPseed}%
\fi%
%
\FP@xia=\FPseed%
\divide\FP@xia by 127773%
\FP@xib=\FP@xia%
\multiply\FP@xib by 127773%
\advance\FP@xib by -\FPseed%
\FP@xib=-\FP@xib%
\multiply\FP@xia by 2836%
\FPseed=\FP@xib%
\multiply\FPseed by 16807%
\advance\FPseed by -\FP@xia%
%
\ifnum\FPseed>0%
\else%
\advance\FPseed by 2147483647%
\fi%
\FPdiv\FP@tmpa{\the\FPseed}{2147483647}%
\global\let\FP@tmp\FP@tmpa%
\global\FPseed=\FPseed%
\FP@debug{random: random number: \FP@tmp\space%
(new seed value: \the\FPseed)}%
%
\FP@endmessage{}%
}%
\let#1\FP@tmp%
}
\endinput
|