2004-04-24 Andreas Nahr <ClassDevelopment@A-SoftTech.com>
[mono.git] / mcs / class / corlib / System / Random.cs
1 //
2 // System.Random.cs
3 //
4 // Authors:
5 //   Bob Smith (bob@thestuff.net)
6 //   Ben Maurer (bmaurer@users.sourceforge.net)
7 //
8 // (C) 2001 Bob Smith.  http://www.thestuff.net
9 // (C) 2003 Ben Maurer
10 //
11
12 namespace System
13 {
14         [Serializable]
15         public class Random
16         {
17                 const int MBIG = int.MaxValue;
18                 const int MSEED = 161803398;
19                 const int MZ = 0;
20
21                 int inext, inextp;
22                 int [] ma = new int [56];
23                 
24                 public Random ()
25                         : this (Environment.TickCount)
26                 {
27                 }
28
29                 public Random (int Seed)
30                 {
31                         int ii;
32                         int mj, mk;
33
34                         // Numerical Recipes in C online @ http://www.library.cornell.edu/nr/bookcpdf/c7-1.pdf
35                         mj = MSEED - Math.Abs (Seed);
36                         ma [55] = mj;
37                         mk = 1;
38                         for (int i = 1; i < 55; i++) {  //  [1, 55] is special (Knuth)
39                                 ii = (21 * i) % 55;
40                                 ma [ii] = mk;
41                                 mk = mj - mk;
42                                 if (mk < 0)
43                                         mk += MBIG;
44                                 mj = ma[ii];
45                         }
46                         for (int k = 1; k < 5; k++) {
47                                 for (int i = 1; i < 56; i++) {
48                                         ma [i] -= ma [1 + (i + 30) % 55];
49                                         if (ma [i] < 0)
50                                                 ma [i] += MBIG;
51                                 }
52                         }
53                         inext = 0;
54                         inextp = 21;
55                 }
56
57                 protected virtual double Sample ()
58                 {
59                         int retVal;
60
61                         if (++inext  >= 56) inext  = 1;
62                         if (++inextp >= 56) inextp = 1;
63
64                         retVal = ma [inext] - ma [inextp];
65
66                         if (retVal < 0)
67                                 retVal += MBIG;
68
69                         ma [inext] = retVal;
70
71                         return retVal * (1.0 / MBIG);
72                 }
73
74                 public virtual int Next ()
75                 {
76                         return (int)(Sample () * int.MaxValue);
77                 }
78
79                 public virtual int Next (int maxValue)
80                 {
81                         if (maxValue < 0)
82                                 throw new ArgumentOutOfRangeException(Locale.GetText (
83                                         "Max value is less then min value."));
84
85                         return (int)(Sample () * maxValue);
86                 }
87
88                 public virtual int Next (int minValue, int maxValue)
89                 {
90                         if (minValue > maxValue)
91                                 throw new ArgumentOutOfRangeException (Locale.GetText (
92                                         "Min value is greater then max value."));
93
94                         uint diff = (uint)(maxValue - minValue);
95                         if (diff == 0)
96                                 return minValue;
97
98                         int result = (int)(Sample () * diff + minValue);
99                         return ((result != maxValue) ? result : (result - 1));
100                 }
101
102                 public virtual void NextBytes (byte [] buffer)
103                 {
104                         if (buffer == null)
105                                 throw new ArgumentNullException ("buffer");
106
107                         for (int i = 0; i < buffer.Length; i++) {
108                                 buffer [i] = (byte)(Sample () * (byte.MaxValue + 1)); 
109                         }
110                 }
111
112                 public virtual double NextDouble ()
113                 {
114                         return this.Sample ();
115                 }
116         }
117 }