RandomParkMiller.st
author Claus Gittinger <cg@exept.de>
Wed, 01 Oct 2014 13:12:17 +0200
changeset 3338 4c5ab3702414
parent 2427 ea26fd4ce3f2
child 3349 7a8dd594971d
permissions -rw-r--r--
class: RandomParkMiller added: #nextBoolean
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
977
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     1
"{ Package: 'stx:libbasic2' }"
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     2
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     3
Object subclass:#RandomParkMiller
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     4
	instanceVariableNames:'seed'
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     5
	classVariableNames:'PMa PMm PMmu1 PMq PMr'
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     6
	poolDictionaries:''
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     7
	category:'Magnitude-Numbers'
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     8
!
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
     9
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    10
!RandomParkMiller class methodsFor:'documentation'!
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    11
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    12
documentation
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    13
"
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    14
    NO WARRANTY
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    15
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    16
    Another pseudo-random number generator
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    17
2427
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
    18
    The ParkMiller random generator (although better than the old Random), is not recommended 
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
    19
    when a high quality random is required (for example, for cryptographic work). 
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
    20
    Applications should use either the OS-random generator or a LaggedFibonacci generator.
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
    21
    This is because the random values provided by the Park-Miller generator are double precision 
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
    22
    floating point numbers which have up to 53 significant bits. Since only the first 31 bits 
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
    23
    of their mantissa are known to have good random properties, the behavior of the remaining 
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
    24
    22 bits is undefined. 
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
    25
    In particular, bit aliasing occurs during the calculation of the next random value, 
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
    26
    and bit 22 of the mantissa is always 1.
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
    27
998
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    28
    Please read:
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    29
        Standard reference by Park and Miller in 
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    30
            'Random Number Generators: Good Ones Are Hard to Find',
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    31
        Comm. ACM, 31:1192-1201, 1988.
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    32
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    33
    [see also:]
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    34
        Random  - fast, but generates less quality random numbers
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    35
        RandomTT800 - another random generator
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    36
"
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    37
!
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    38
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    39
testing
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    40
"
5f66a2dd6b7d documentation
Claus Gittinger <cg@exept.de>
parents: 977
diff changeset
    41
977
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    42
    |r|
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    43
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    44
    r := self new.
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    45
    (1 to:10) collect:[:i | r next]
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    46
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    47
    -> should be
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    48
        #(
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    49
            0.1492432697 
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    50
            0.3316330217 
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    51
            0.7561964480 
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    52
            0.3937015400 
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    53
            0.9417831814 
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    54
            0.5499291939 
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    55
            0.6599625962 
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    56
            0.9913545591 
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    57
            0.6960744326 
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    58
            0.9229878997
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    59
        #)
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    60
"
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    61
! !
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    62
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    63
!RandomParkMiller class methodsFor:'initialization'!
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    64
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    65
initialize
2073
7cb0248742e3 comments
Claus Gittinger <cg@exept.de>
parents: 998
diff changeset
    66
    PMa := 16807.         " magic constant "
7cb0248742e3 comments
Claus Gittinger <cg@exept.de>
parents: 998
diff changeset
    67
    PMm := 2147483647.    " magic constant "
7cb0248742e3 comments
Claus Gittinger <cg@exept.de>
parents: 998
diff changeset
    68
    PMq := 127773.        " quotient (m quo: a) = 44488 "
7cb0248742e3 comments
Claus Gittinger <cg@exept.de>
parents: 998
diff changeset
    69
    PMr := 2836.          " remainder (m \\ a). = 2836 "
7cb0248742e3 comments
Claus Gittinger <cg@exept.de>
parents: 998
diff changeset
    70
    PMmu1 := 4.65661E-10  
977
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    71
! !
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    72
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    73
!RandomParkMiller class methodsFor:'instance creation'!
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    74
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    75
new
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    76
    self initialize.
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    77
    ^ super new initialize
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    78
! !
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    79
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    80
!RandomParkMiller methodsFor:'accessing-reading'!
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    81
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    82
next
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    83
    " This method generates random instances of Float in the interval 0.0 to 1.0 "
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    84
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    85
    seed := self nextInteger.
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    86
    ^ seed * PMmu1
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    87
!
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    88
3338
4c5ab3702414 class: RandomParkMiller
Claus Gittinger <cg@exept.de>
parents: 2427
diff changeset
    89
nextBoolean
4c5ab3702414 class: RandomParkMiller
Claus Gittinger <cg@exept.de>
parents: 2427
diff changeset
    90
    " This method generates a boolean "
4c5ab3702414 class: RandomParkMiller
Claus Gittinger <cg@exept.de>
parents: 2427
diff changeset
    91
4c5ab3702414 class: RandomParkMiller
Claus Gittinger <cg@exept.de>
parents: 2427
diff changeset
    92
    ^ self next > 0.5
4c5ab3702414 class: RandomParkMiller
Claus Gittinger <cg@exept.de>
parents: 2427
diff changeset
    93
!
4c5ab3702414 class: RandomParkMiller
Claus Gittinger <cg@exept.de>
parents: 2427
diff changeset
    94
977
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    95
nextInteger
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    96
    " This method generates random instances of Integer in the interval 0 to 16r7FFFFFFF. "
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    97
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    98
    seed := self peekInteger.
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
    99
    ^ seed
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   100
! !
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   101
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   102
!RandomParkMiller methodsFor:'initialization'!
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   103
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   104
initialize
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   105
    " Set a reasonable Park-Miller starting seed "
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   106
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   107
    seed := 2345678901
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   108
!
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   109
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   110
seed:anInteger 
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   111
    seed := anInteger
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   112
! !
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   113
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   114
!RandomParkMiller methodsFor:'private'!
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   115
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   116
peek
2073
7cb0248742e3 comments
Claus Gittinger <cg@exept.de>
parents: 998
diff changeset
   117
    " This method answers the next random number that will be generated as a Float in the range [0..1). 
7cb0248742e3 comments
Claus Gittinger <cg@exept.de>
parents: 998
diff changeset
   118
      It answers the same value for all successive message sends. "
977
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   119
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   120
    ^ self peekInteger * PMmu1
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   121
!
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   122
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   123
peekInteger
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   124
    " This method generates random instances of Integer in the interval 0 to 16r7FFFFFFF. This method does NOT update the seed; repeated sends answer the same value. The algorithm is described in detail in 'Random Number Generators: Good Ones Are Hard to Find' by Stephen K. Park and Keith W. Miller, (Comm. Asso. Comp. Mach., 31(10):1192--1201, 1988). "
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   125
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   126
    |lo hi aLoRHi answer|
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   127
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   128
    hi := seed quo:PMq.
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   129
    lo := seed rem:PMq.
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   130
    aLoRHi := (PMa * lo) - (PMr * hi).
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   131
    (aLoRHi > 0) ifTrue:[ ^ aLoRHi ].
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   132
    ^ aLoRHi + PMm
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   133
! !
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   134
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   135
!RandomParkMiller class methodsFor:'documentation'!
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   136
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   137
version
3338
4c5ab3702414 class: RandomParkMiller
Claus Gittinger <cg@exept.de>
parents: 2427
diff changeset
   138
    ^ '$Header: /cvs/stx/stx/libbasic2/RandomParkMiller.st,v 1.5 2014-10-01 11:12:17 cg Exp $'
2427
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
   139
!
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
   140
ea26fd4ce3f2 changed: #documentation
Claus Gittinger <cg@exept.de>
parents: 2073
diff changeset
   141
version_CVS
3338
4c5ab3702414 class: RandomParkMiller
Claus Gittinger <cg@exept.de>
parents: 2427
diff changeset
   142
    ^ '$Header: /cvs/stx/stx/libbasic2/RandomParkMiller.st,v 1.5 2014-10-01 11:12:17 cg Exp $'
977
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   143
! !
2073
7cb0248742e3 comments
Claus Gittinger <cg@exept.de>
parents: 998
diff changeset
   144
3338
4c5ab3702414 class: RandomParkMiller
Claus Gittinger <cg@exept.de>
parents: 2427
diff changeset
   145
977
a7e2a422bfdb initial checkin
Claus Gittinger <cg@exept.de>
parents:
diff changeset
   146
RandomParkMiller initialize!