summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/fp/fp-random.sty
blob: 72bf17f1f10240a6470db0cae910531ccfbb5735 (plain)
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