2004-12-06 Zoltan Varga <vargaz@freemail.hu>
[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 //
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 namespace System
36 {
37         [Serializable]
38         public class Random
39         {
40                 const int MBIG = int.MaxValue;
41                 const int MSEED = 161803398;
42                 const int MZ = 0;
43
44                 int inext, inextp;
45                 int [] SeedArray = new int [56];
46                 
47                 public Random ()
48                         : this (Environment.TickCount)
49                 {
50                 }
51
52                 public Random (int Seed)
53                 {
54                         int ii;
55                         int mj, mk;
56
57                         // Numerical Recipes in C online @ http://www.library.cornell.edu/nr/bookcpdf/c7-1.pdf
58                         mj = MSEED - Math.Abs (Seed);
59                         SeedArray [55] = mj;
60                         mk = 1;
61                         for (int i = 1; i < 55; i++) {  //  [1, 55] is special (Knuth)
62                                 ii = (21 * i) % 55;
63                                 SeedArray [ii] = mk;
64                                 mk = mj - mk;
65                                 if (mk < 0)
66                                         mk += MBIG;
67                                 mj = SeedArray [ii];
68                         }
69                         for (int k = 1; k < 5; k++) {
70                                 for (int i = 1; i < 56; i++) {
71                                         SeedArray [i] -= SeedArray [1 + (i + 30) % 55];
72                                         if (SeedArray [i] < 0)
73                                                 SeedArray [i] += MBIG;
74                                 }
75                         }
76                         inext = 0;
77                         inextp = 31;
78                 }
79
80                 protected virtual double Sample ()
81                 {
82                         int retVal;
83
84                         if (++inext  >= 56) inext  = 1;
85                         if (++inextp >= 56) inextp = 1;
86
87                         retVal = SeedArray [inext] - SeedArray [inextp];
88
89                         if (retVal < 0)
90                                 retVal += MBIG;
91
92                         SeedArray [inext] = retVal;
93
94                         return retVal * (1.0 / MBIG);
95                 }
96
97                 public virtual int Next ()
98                 {
99                         return (int)(Sample () * int.MaxValue);
100                 }
101
102                 public virtual int Next (int maxValue)
103                 {
104                         if (maxValue < 0)
105                                 throw new ArgumentOutOfRangeException(Locale.GetText (
106                                         "Max value is less then min value."));
107
108                         return (int)(Sample () * maxValue);
109                 }
110
111                 public virtual int Next (int minValue, int maxValue)
112                 {
113                         if (minValue > maxValue)
114                                 throw new ArgumentOutOfRangeException (Locale.GetText (
115                                         "Min value is greater then max value."));
116
117                         uint diff = (uint)(maxValue - minValue);
118                         if (diff == 0)
119                                 return minValue;
120
121                         int result = (int)(Sample () * diff + minValue);
122                         return ((result != maxValue) ? result : (result - 1));
123                 }
124
125                 public virtual void NextBytes (byte [] buffer)
126                 {
127                         if (buffer == null)
128                                 throw new ArgumentNullException ("buffer");
129
130                         for (int i = 0; i < buffer.Length; i++) {
131                                 buffer [i] = (byte)(Sample () * (byte.MaxValue + 1)); 
132                         }
133                 }
134
135                 public virtual double NextDouble ()
136                 {
137                         return this.Sample ();
138                 }
139         }
140 }