RandomGenerator.st
changeset 2439 8ef4ad63fb9b
parent 2438 3601d0065aff
child 2440 1460919397a4
--- a/RandomGenerator.st	Tue Mar 30 14:32:10 2010 +0200
+++ b/RandomGenerator.st	Tue Mar 30 15:39:21 2010 +0200
@@ -91,18 +91,31 @@
      a cryptographic secure PRNG (part of the extra libcrypt package). 
      As last resort fallback to the cryptographic insecure linear builtin PRNG"
 
+    |result|
+
     SharedGenerator notNil ifTrue:[
         "each time, we do an new, add some entropy to the SharedGenerator"
         SharedGenerator addEntropy:OperatingSystem getMicrosecondTime.
         ^ SharedGenerator.
     ].
 
-    RandFile isNil ifTrue:[
-        self openRandFile.
-    ].
-    RandFile isStream ifTrue:[
+    [
+        result := OperatingSystem randomBytesInto:(ByteArray new:1).
+    ] on:PrimitiveFailure do:[:ex| ].
+
+    result notNil ifTrue:[
+        "OperatingSystem knows how to get random bytes"
+        RandFile := true.
         SharedGenerator := self basicNew.
         ^ SharedGenerator.
+    ] ifFalse:[
+        RandFile isNil ifTrue:[
+            self openRandFile.
+        ].
+        RandFile isStream ifTrue:[
+            SharedGenerator := self basicNew.
+            ^ SharedGenerator.
+        ].
     ].
 
     Rc4Cipher notNil ifTrue:[
@@ -157,6 +170,80 @@
     ^ self
 ! !
 
+!RandomGenerator methodsFor:'basic reading'!
+
+nextByte
+    "get the next random byte"
+
+    RandFile == true ifTrue:[
+        ^ OperatingSystem randomBytesInto:1.
+    ].
+
+    ^ RandFile nextByte
+
+    "
+      RandomGenerator new nextByte
+    "
+
+    "
+     Distribution should be equal:
+
+     |r bag|
+     r := RandomGenerator new.
+     bag := Bag new.
+     1000000 timesRepeat:[
+         bag add:(r nextByte).
+     ].
+     bag.
+     Transcript showCR:bag contents
+    "
+
+    "Created: / 11.11.1999 / 09:25:39 / stefan"
+!
+
+nextBytes:cnt
+    "get the next cnt random bytes"
+
+    RandFile == true ifTrue:[
+        ^ OperatingSystem randomBytesInto:(ByteArray new:cnt).
+    ].
+    ^ RandFile nextBytes:cnt.
+
+    "
+      RandomGenerator new nextBytes:4
+    "
+
+    "Created: / 11.11.1999 / 09:25:39 / stefan"
+    "Modified: / 11.11.1999 / 09:52:26 / stefan"
+!
+
+nextInteger
+    "return the next integral random number,
+     in the range 0 .. 16r3FFFFFFF."
+
+    |res|
+
+    RandFile == true ifTrue:[
+        ^ OperatingSystem randomBytesInto:4.
+    ].
+
+    res := self nextBytes:4.
+    ^ ((((((res at:1) bitAnd:16r3F) * 256) + (res at:2)) * 256) + (res at:3)) * 256 + (res at:4)
+
+
+
+    "
+     |r|
+     r := RandomGenerator new.
+     Transcript showCR:r nextInteger.
+     Transcript showCR:r nextInteger.
+     Transcript showCR:r nextInteger.
+     Transcript showCR:r nextInteger.
+    "
+
+    "Modified: / 11.11.1999 / 10:08:10 / stefan"
+! !
+
 !RandomGenerator methodsFor:'reading'!
 
 next
@@ -213,6 +300,8 @@
     "
 
     "
+     Distribution should approach 50/50:
+
      |r bag|
      r := RandomGenerator new.
      bag := Bag new.
@@ -226,31 +315,6 @@
     "Modified: / 12.11.1999 / 17:22:01 / stefan"
 !
 
-nextByte
-    "get the next random byte"
-
-    ^ RandFile nextByte
-
-    "
-      RandomGenerator new nextByte
-    "
-
-    "Created: / 11.11.1999 / 09:25:39 / stefan"
-!
-
-nextBytes:cnt
-    "get the next cnt random bytes"
-
-    ^ RandFile nextBytes:cnt.
-
-    "
-      RandomGenerator new nextBytes:4
-    "
-
-    "Created: / 11.11.1999 / 09:25:39 / stefan"
-    "Modified: / 11.11.1999 / 09:52:26 / stefan"
-!
-
 nextCharacters:cnt
     "get the next cnt printable characters.
      We answer characters in the ascii range (codepoints 32 - 127)"
@@ -272,29 +336,6 @@
     "
 !
 
-nextInteger
-    "return the next integral random number,
-     in the range 0 .. 16r3FFFFFFF."
-
-    |res|
-
-    res := self nextBytes:4.
-    ^ ((((((res at:1) bitAnd:16r3F) * 256) + (res at:2)) * 256) + (res at:3)) * 256 + (res at:4)
-
-
-
-    "
-     |r|
-     r := RandomGenerator new.
-     Transcript showCR:r nextInteger.
-     Transcript showCR:r nextInteger.
-     Transcript showCR:r nextInteger.
-     Transcript showCR:r nextInteger.
-    "
-
-    "Modified: / 11.11.1999 / 10:08:10 / stefan"
-!
-
 nextIntegerBetween:start and:stop
     "return an integral random number between start and stop"
 
@@ -355,11 +396,11 @@
 !RandomGenerator class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic2/RandomGenerator.st,v 1.6 2010-03-30 12:32:10 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic2/RandomGenerator.st,v 1.7 2010-03-30 13:39:21 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic2/RandomGenerator.st,v 1.6 2010-03-30 12:32:10 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic2/RandomGenerator.st,v 1.7 2010-03-30 13:39:21 stefan Exp $'
 ! !
 
 RandomGenerator initialize!