--- a/Random.st Fri Mar 02 16:15:00 2018 +0100
+++ b/Random.st Fri Mar 02 17:05:37 2018 +0100
@@ -1,37 +1,23 @@
"{ Encoding: utf8 }"
"
-======================================================================
-|
-| Copyright (C) 1988, 1989 Free Software Foundation, Inc.
-| Written by Steve Byrne.
-|
-| This file is part of GNU Smalltalk.
-|
-| GNU Smalltalk is free software; you can redistribute it and/or modify it
-| under the terms of the GNU General Public License as published by the Free
-| Software Foundation; either version 1, or (at your option) any later version.
-|
-| GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
-| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-| FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-| details.
-|
-| You should have received a copy of the GNU General Public License along with
-| GNU Smalltalk; see the file LICENSE. If not, write to the Free Software
-| Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-|
-======================================================================
+ COPYRIGHT (c) 1989 by Claus Gittinger
+ All Rights Reserved
-see notice in (Random>>documentation)
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
"
"{ Package: 'stx:libbasic2' }"
"{ NameSpace: Smalltalk }"
Stream subclass:#Random
- instanceVariableNames:'seed increment multiplier modulus'
- classVariableNames:'SharedGenerator RandomSalt'
+ instanceVariableNames:'seed'
+ classVariableNames:'RandomSalt SharedGenerator'
poolDictionaries:''
category:'Magnitude-Numbers-Random'
!
@@ -40,62 +26,31 @@
copyright
"
-======================================================================
-|
-| Copyright (C) 1988, 1989 Free Software Foundation, Inc.
-| Written by Steve Byrne.
-|
-| This file is part of GNU Smalltalk.
-|
-| GNU Smalltalk is free software; you can redistribute it and/or modify it
-| under the terms of the GNU General Public License as published by the Free
-| Software Foundation; either version 1, or (at your option) any later version.
-|
-| GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
-| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-| FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-| details.
-|
-| You should have received a copy of the GNU General Public License along with
-| GNU Smalltalk; see the file LICENSE. If not, write to the Free Software
-| Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-|
-======================================================================
+ COPYRIGHT (c) 1989 by Claus Gittinger
+ All Rights Reserved
-see notice in (Random>>documentation)
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
"
!
documentation
"
- WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
- =======================================================================================
- DO NOT USE THIS GENERATOR FOR CRYPTOGRAPHY OR OTHER SECURITY RELATED WORK,
- because linear congruential generators are predictable and can be broken easily!!
-
- Smalltalk/X includes a better generator named RandomGenerator, which uses the best
- available generator of the system (either OS-random, /dev/random or as a less dangerous
- fallback, an RC4-based random generator).
- Please use that one.
- =======================================================================================
-
- A simple random numbers - thanks to Steves GNU Smalltalk
+ A facade to the actual RandomGenerator.
+ In previous versions, Random was a very bad fallback random generator,
+ with an included warning, to not use it.
- This implements a linear congruential maximum period random number generator
- which passes the spectral test for randomness for dimensions 2 3 4 5 6.
+ Now this old generator was renamed to RandomGNUSmalltalk,
+ and the default generator used is the one provided by the much
+ better RandomGenerator class.
- Notice: although being included here,
- this file is NOT covered by the ST/X license, but by
- the FSF copyLeft (see copyright method).
-
- You can redistribute it under the terms stated there ...
- Also, the price you pay for ST/X does not include a charge for
- this file - it has to be considered as a separate piece of
- software, which can be copied and given away without any
- restriction from my (CG) side.
+ Random new next:10
[author:]
- Steve Byrne
Claus Gittinger
[see also:]
@@ -131,24 +86,30 @@
!Random class methodsFor:'instance creation'!
new
- "return a new random generator"
+ "return a new random generator.
+ Here, this instance creation message is forwarded to the standardGenerator"
- ^ self basicNew initialize
+ ^ self standard
+
+ "
+ Random new
+ "
!
random
"return a new random generator.
Defined here for compatibility with StreamCipher"
- ^ self new
+ ^ self standard
"Created: / 12.11.1999 / 17:52:08 / stefan"
!
seed:seedValue
- "return a new random generator with initial seed"
+ "return a new random generator with initial seed.
+ Here, this instance creation message is forwarded to the standardGenerator"
- ^self basicNew setSeed:seedValue
+ ^ self standardGeneratorClass basicNew setSeed:seedValue
"Created: / 26-05-2007 / 21:27:18 / cg"
!
@@ -157,7 +118,7 @@
"return a shared random generator."
SharedGenerator isNil ifTrue:[
- SharedGenerator := self new.
+ SharedGenerator := self standard.
].
^ SharedGenerator
!
@@ -165,7 +126,13 @@
standard
"return the 'standard' generator"
- ^ self new
+ ^ self standardGeneratorClass new
+!
+
+standardGeneratorClass
+ "return the class used for the 'standard' generator"
+
+ ^ RandomGenerator
! !
!Random class methodsFor:'random numbers'!
@@ -445,8 +412,7 @@
next
"return the next random number in the range ]0..1["
- self step.
- ^ seed / modulus asFloat
+ self subclassResponsibility.
"
|r|
@@ -486,8 +452,7 @@
nextBoolean
"return true or false by random"
- self step.
- ^ seed < (modulus // 2)
+ ^ self next bitAnd:16r10.
"
|r|
@@ -514,8 +479,7 @@
nextByte
"return the next integral random number byte in the range 0 .. 16rFF"
- self step.
- ^ seed bitAnd:16rFF
+ ^ self next bitAnd:16rFF
"
|r|
@@ -532,20 +496,10 @@
nextBytes:count
"return count random bytes (0..16rFF each)"
- |res cnt "{Class: SmallInteger}"|
-
- cnt := count.
- res := ByteArray uninitializedNew:cnt.
-
- 1 to:cnt do:[:i|
- self step.
- res at:i put:(seed bitAnd:16rFF).
- ].
-
- ^ res
+ ^ (1 to:count) collect:[:i | self nextByte] as:ByteArray
"
- Transcript showCR:(Random new nextBytes:20).
+ Transcript showCR:(RandomGenerator new nextBytes:20).
"
"Modified: 1.4.1997 / 22:42:53 / cg"
@@ -582,32 +536,18 @@
"get the next cnt printable characters.
We answer printable characters in the ascii range (codepoints 32 - 126)"
- |res cnt "{ Class:SmallInteger }"|
-
- cnt := count.
- res := String uninitializedNew:cnt.
-
- 1 to:cnt do:[:i|
- self step.
- res at:i put:(Character value:(seed \\ 94 + 32)).
- ].
-
- ^ res
+ ^ (1 to:count) collect:[:i | Character value:(self next \\ 94 + 32) ] as:String
"
- Random new nextCharacters:8
+ RandomGenerator new nextCharacters:8
"
!
nextInteger
"return the next integral random number,
- in the range 0 .. modulus (which is less than 16r3FFFFFFF).
- From Sedgewick's 'Algorithms', based on Lehmer's method.
+ in the range 0 .. self maxInteger"
- Take care, this returns an even number after each odd number!!"
-
- self step.
- ^ seed
+ self subclassResponsibility
"
|r|
@@ -622,22 +562,53 @@
!
nextIntegerBetween:start and:stop
- "return an integral random number between start and stop"
+ "return an integral random number in [start..stop] (inclusive)"
|rnd range bytesNeeded|
range := stop - start + 1.
-
- range < modulus ifTrue:[
- "we need the float computation in order to not return alternate even and odd numbers"
- rnd := (self next * range) truncated.
- ^ rnd + start.
+ "Fetch at least 2 bytes, otherwise we get some unbalanced distributions for small ranges"
+ bytesNeeded := (range highBit + 15) // 8.
+ bytesNeeded < 4 ifTrue:[
+ rnd := (((self nextByte bitShift:8) + self nextByte) bitShift:8) + self nextByte.
+ rnd := rnd \\ range.
] ifFalse:[
- bytesNeeded := (range highBit + 7) // 8.
- rnd := LargeInteger digitBytes:(self nextBytes:bytesNeeded).
- rnd := rnd bitXor:(seed < (modulus//2) ifTrue:[0] ifFalse:[1]). "do not alternately return even and odd numbers"
- ^ start + (rnd \\ range).
+ rnd := (LargeInteger digitBytes:(self nextBytes:bytesNeeded)) compressed.
+ rnd := rnd \\ range.
].
+ ^ rnd + start
+
+ "shows pair-combination counts
+
+ |r v prev this counts|
+
+ v := TextView new .
+ v extent:500@250.
+ v list:#('xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx'
+ 'xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx'
+ 'xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx'
+ 'xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx'
+ 'xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx'
+ 'xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx'
+ 'xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx'
+ 'xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx'
+ 'xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx'
+ 'xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx').
+ v openAndWait.
+ counts := (1 to:10) collect:[:row | Array new:10 withAll:0].
+
+ r := self new.
+ prev := r nextIntegerBetween:1 and:10.
+ 10000 timesRepeat:[
+ 100 timesRepeat:[
+ this := r nextIntegerBetween:1 and:10.
+ (counts at:this) at:prev put:((counts at:this) at:prev)+1.
+ ].
+ v list:(counts collect:[:row |
+ '%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d'printf:row ]).
+ prev := this.
+ ].
+ "
"
|r|
@@ -711,7 +682,7 @@
!
nextLettersOrDigits:count
- "get the next count printable letters or digits [0-9A-Za-z]."
+ "get a random string consisting of count printable letters or digits [0-9A-Za-z]."
|res cnt "{ Class:SmallInteger }"|
@@ -728,7 +699,7 @@
^ res
"
- Random new nextLettersOrDigits:40
+ Random new nextLettersOrDigits:40
"
! !
@@ -787,20 +758,9 @@
!
setSeed:seedValue
- "set the initial seed and intialite the PRNG parameters.
- These numbers implement a maximum period generator which passes
- the spectral test for randomness for dimensions 2 3 4 5 6 and
- the product does not overflow 2 raisedTo:29.
+ "set the initial seed and intialize the PRNG parameters."
- These numbers are carefully choosen, so don't change them,
- unless you know what you are doing!!"
-
- modulus := 244944 " 244957 " .
- multiplier := 1597.
- increment := 51749.
- seed := seedValue \\ modulus.
-
- self step.
+ self subclassResponsibility.
"Modified: / 12-11-1999 / 17:50:52 / stefan"
"Created: / 26-05-2007 / 21:25:10 / cg"
@@ -809,10 +769,7 @@
step
"compute the next random integer"
- seed := (seed * multiplier + increment) \\ modulus
-
- "Created: 1.4.1997 / 22:40:45 / cg"
- "Modified: 1.4.1997 / 22:43:01 / cg"
+ self subclassResponsibility
! !
!Random methodsFor:'testing'!
@@ -834,6 +791,12 @@
^ false
"Created: 1.4.1997 / 22:38:27 / cg"
+!
+
+maxInteger
+ "the max value returned by self nextInteger"
+
+ self subclassResponsibility
! !
!Random class methodsFor:'documentation'!