<div dir="ltr"><div><div>About instance variables, this could have been used to have several different instantiations of the same algorithm with different constants...<br></div>But given the fact that there isn't even an accessor for that purpose, we can effectively get rid of them.<br>
</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">2013/9/23 Levente Uzonyi <span dir="ltr"><<a href="mailto:leves@elte.hu" target="_blank">leves@elte.hu</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I put this to the Inbox, because the Trunk is unstable.<span class="HOEnZb"><font color="#888888"><br>
<br>
<br>
Levente</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
On Mon, 23 Sep 2013, <a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a> wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
A new version of Kernel was added to project The Inbox:<br>
<a href="http://source.squeak.org/inbox/Kernel-ul.811.mcz" target="_blank">http://source.squeak.org/<u></u>inbox/Kernel-ul.811.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Kernel-ul.811<br>
Author: ul<br>
Time: 23 September 2013, 6:48:32.356 pm<br>
UUID: b32f1827-e63d-46dd-b6b9-<u></u>0a15355aac6a<br>
Ancestors: Kernel-nice.810<br>
<br>
Changed Random for faster instance creation and better randomness:<br>
- moved constants q, r, a and m to class variables. There's no need to calculate and store them in all instances. Haven't inlined them, so they are documented and defined in one place.<br>
- try to use #primUTCMicrosecondClock for seed generation<br>
- don't calculate seed, when the user provides it<br>
- updated constants in #bucketTest:, because machines are faster nowadays<br>
<br>
=============== Diff against Kernel-nice.810 ===============<br>
<br>
Item was changed:<br>
Object subclass: #Random<br>
+ instanceVariableNames: 'seed'<br>
+ classVariableNames: 'A M Q R'<br>
- instanceVariableNames: 'seed a m q r'<br>
- classVariableNames: ''<br>
poolDictionaries: ''<br>
category: 'Kernel-Numbers'!<br>
<br>
!Random commentStamp: 'nice 3/24/2010 07:38' prior: 0!<br>
This Random Number Generator graciously contributed by David N. Smith. It is an adaptation of the Park-Miller RNG which uses Floats to avoid the need for LargeInteger arithmetic.<br>
<br>
If you just want a quick random integer, use:<br>
10 atRandom<br>
Every integer interval can give a random number:<br>
(6 to: 12) atRandom<br>
SequenceableCollections can give randomly selected elements:<br>
'pick one of these letters randomly' atRandom<br>
SequenceableCollections also respond to shuffled, as in:<br>
($A to: $Z) shuffled<br>
<br>
The correct way to use class Random is to store one in an instance or class variable:<br>
myGenerator := Random new.<br>
Then use it every time you need another number between 0.0 and 1.0 (excluding)<br>
myGenerator next<br>
You can also generate a positive integer<br>
myGenerator nextInt: 10!<br>
<br>
Item was changed:<br>
----- Method: Random class>>bucketTest: (in category 'testing') -----<br>
bucketTest: randy<br>
"Execute this: Random bucketTest: Random new"<br>
" A quick-and-dirty bucket test. Prints nbuckets values on the<br>
Transcript.<br>
Each should be 'near' the value of ntries. Any run with any value<br>
'far' from ntries<br>
indicates something is very wrong. Each run generates different<br>
values.<br>
For a slightly better test, try values of nbuckets of 200-1000 or<br>
more; go get coffee.<br>
This is a poor test; see Knuth. Some 'OK' runs:<br>
1000 1023 998 969 997 1018 1030 1019 1054 985 1003<br>
1011 987 982 980 982 974 968 1044 976<br>
1029 1011 1025 1016 997 1019 991 954 968 999 991<br>
978 1035 995 988 1038 1009 988 993 976<br>
"<br>
| nbuckets buckets ntrys |<br>
+ nbuckets := 200.<br>
- nbuckets := 20.<br>
buckets := Array new: nbuckets.<br>
buckets atAllPut: 0.<br>
+ ntrys := 1000.<br>
- ntrys := 100.<br>
ntrys*nbuckets timesRepeat: [ | slot |<br>
slot := (randy next * nbuckets) floor + 1.<br>
buckets at: slot put: (buckets at: slot) + 1 ].<br>
Transcript cr.<br>
1 to: nbuckets do: [ :nb |<br>
Transcript show: (buckets at: nb) printString, ' ' ]!<br>
<br>
Item was added:<br>
+ ----- Method: Random class>>initialize (in category 'class initialization') -----<br>
+ initialize<br>
+ "Initialize the magic constants. All instances share these values. Use floats to avoid LargeInteger computations (it still gives about 3-4x speedup)."<br>
+<br>
+ A := 16807.0. " magic constant = 16807 "<br>
+ M := 2147483647.0. " magic constant = <a href="tel:2147483647" value="+12147483647" target="_blank">2147483647</a> "<br>
+ Q := 127773.0. "(m quo: a) asFloat."<br>
+ R := 2836.0 "(m \\ a) asFloat."!<br>
<br>
Item was changed:<br>
----- Method: Random class>>seed: (in category 'instance creation') -----<br>
seed: anInteger<br>
+ ^self basicNew seed: anInteger!<br>
- ^self new seed: anInteger!<br>
<br>
Item was changed:<br>
----- Method: Random>>initialize (in category 'initialization') -----<br>
initialize<br>
+<br>
+ | hash |<br>
+ hash := self hash.<br>
+ "Set a reasonable Park-Miller starting seed"<br>
+ seed := Time primUTCMicrosecondClock.<br>
+ seed = 0 ifFalse: [ "Use the microsecond clock if possible."<br>
+ seed := (seed bitAnd: 16r3FFFFFFF) bitXor: hash ].<br>
+ [ seed = 0 ] whileTrue: [ "Try again if ever get a seed = 0, or there's no microsecond clock."<br>
+ seed := (Time millisecondClockValue bitAnd: 16r3FFFFFFF) bitXor: hash ]!<br>
- " Set a reasonable Park-Miller starting seed "<br>
- [seed := (Time millisecondClockValue bitAnd: 16r3FFFFFFF) bitXor: self hash.<br>
- seed = 0] whileTrue: ["Try again if ever get a seed = 0"].<br>
-<br>
- a := 16r000041A7 asFloat. " magic constant = 16807 "<br>
- m := 16r7FFFFFFF asFloat. " magic constant = <a href="tel:2147483647" value="+12147483647" target="_blank">2147483647</a> "<br>
- q := (m quo: a) asFloat.<br>
- r := (m \\ a) asFloat.<br>
- !<br>
<br>
Item was changed:<br>
----- Method: Random>>next (in category 'accessing') -----<br>
next<br>
"Answer a random Float in the interval [0 to 1)."<br>
<br>
+ ^ (seed := self nextValue) / M!<br>
- ^ (seed := self nextValue) / m!<br>
<br>
Item was changed:<br>
----- Method: Random>>nextValue (in category 'private') -----<br>
nextValue<br>
"This method generates random instances of Integer in the interval<br>
0 to 16r7FFFFFFF. This method does NOT update the seed; repeated sends<br>
answer the same value.<br>
The algorithm is described in detail in 'Random Number Generators:<br>
Good Ones Are Hard to Find' by Stephen K. Park and Keith W. Miller<br>
(Comm. Asso. Comp. Mach., 31(10):1192--1201, 1988)."<br>
<br>
| lo hi aLoRHi answer |<br>
+ hi := (seed quo: Q) asFloat.<br>
+ lo := seed - (hi * Q). " = seed rem: q"<br>
+ aLoRHi := (A * lo) - (R * hi).<br>
- hi := (seed quo: q) asFloat.<br>
- lo := seed - (hi * q). " = seed rem: q"<br>
- aLoRHi := (a * lo) - (r * hi).<br>
answer := (aLoRHi > 0.0)<br>
ifTrue: [aLoRHi]<br>
+ ifFalse: [aLoRHi + M].<br>
- ifFalse: [aLoRHi + m].<br>
^ answer!<br>
<br>
<br>
<br>
</blockquote>
<br>
</div></div></blockquote></div><br></div>