From 873f8d7a28e916acd63a0dc7ad923361771f218c Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Thu, 23 Feb 2023 15:30:58 +0100 Subject: [PATCH] Make random numbers external --- .../BaselineOfPolyMath.class.st | 16 +- src/Math-Random/PMBernoulliGenerator.class.st | 71 -------- src/Math-Random/PMBinomialGenerator.class.st | 51 ------ .../PMCombinedRandomGenerator.class.st | 75 -------- src/Math-Random/PMConstantGenerator.class.st | 32 ---- ...nverseCongruentialRandomGenerator.class.st | 96 ---------- .../PMExponentialGenerator.class.st | 63 ------- .../PMFishmanMooreRandomGenerator.class.st | 41 ----- src/Math-Random/PMGaussianGenerator.class.st | 59 ------- .../PMLehmerRandomGenerator.class.st | 40 ----- ...LinearCongruentialRandomGenerator.class.st | 39 ----- .../PMMarsagliaKissRandomGenerator.class.st | 65 ------- .../PMMarsagliaKissRandomKernel.class.st | 97 ----------- .../PMMersenneTwisterRandomGenerator.class.st | 164 ------------------ src/Math-Random/PMNumberGenerator.class.st | 56 ------ ...MParkMillerMinimumRandomGenerator.class.st | 57 ------ src/Math-Random/PMPoissonGenerator.class.st | 61 ------- .../PMPseudoRandomNumberGenerator.class.st | 147 ---------------- src/Math-Random/package.st | 1 - .../PMBernoulliGeneratorTest.class.st | 41 ----- .../PMBinomialGeneratorTest.class.st | 57 ------ .../PMConstantGeneratorTest.class.st | 17 -- .../PMExponentialGeneratorTest.class.st | 41 ----- ...PMFishmanMooreRandomGeneratorTest.class.st | 16 -- .../PMGaussianGeneratorTest.class.st | 41 ----- .../PMLehmerRandomTest.class.st | 28 --- .../PMLinearCongruentialRandomTest.class.st | 28 --- .../PMMersenneTwisterRandomTest.class.st | 42 ----- .../PMNumberGeneratorTest.class.st | 19 -- .../PMPoissonGeneratorTest.class.st | 44 ----- ...PMPseudoRandomNumberGeneratorTest.class.st | 75 -------- src/Math-Tests-Random/PMRandomSample.class.st | 21 --- src/Math-Tests-Random/package.st | 1 - 33 files changed, 10 insertions(+), 1692 deletions(-) delete mode 100644 src/Math-Random/PMBernoulliGenerator.class.st delete mode 100644 src/Math-Random/PMBinomialGenerator.class.st delete mode 100644 src/Math-Random/PMCombinedRandomGenerator.class.st delete mode 100644 src/Math-Random/PMConstantGenerator.class.st delete mode 100644 src/Math-Random/PMExplicitInverseCongruentialRandomGenerator.class.st delete mode 100644 src/Math-Random/PMExponentialGenerator.class.st delete mode 100644 src/Math-Random/PMFishmanMooreRandomGenerator.class.st delete mode 100644 src/Math-Random/PMGaussianGenerator.class.st delete mode 100644 src/Math-Random/PMLehmerRandomGenerator.class.st delete mode 100644 src/Math-Random/PMLinearCongruentialRandomGenerator.class.st delete mode 100644 src/Math-Random/PMMarsagliaKissRandomGenerator.class.st delete mode 100644 src/Math-Random/PMMarsagliaKissRandomKernel.class.st delete mode 100644 src/Math-Random/PMMersenneTwisterRandomGenerator.class.st delete mode 100644 src/Math-Random/PMNumberGenerator.class.st delete mode 100644 src/Math-Random/PMParkMillerMinimumRandomGenerator.class.st delete mode 100644 src/Math-Random/PMPoissonGenerator.class.st delete mode 100644 src/Math-Random/PMPseudoRandomNumberGenerator.class.st delete mode 100644 src/Math-Random/package.st delete mode 100644 src/Math-Tests-Random/PMBernoulliGeneratorTest.class.st delete mode 100644 src/Math-Tests-Random/PMBinomialGeneratorTest.class.st delete mode 100644 src/Math-Tests-Random/PMConstantGeneratorTest.class.st delete mode 100644 src/Math-Tests-Random/PMExponentialGeneratorTest.class.st delete mode 100644 src/Math-Tests-Random/PMFishmanMooreRandomGeneratorTest.class.st delete mode 100644 src/Math-Tests-Random/PMGaussianGeneratorTest.class.st delete mode 100644 src/Math-Tests-Random/PMLehmerRandomTest.class.st delete mode 100644 src/Math-Tests-Random/PMLinearCongruentialRandomTest.class.st delete mode 100644 src/Math-Tests-Random/PMMersenneTwisterRandomTest.class.st delete mode 100644 src/Math-Tests-Random/PMNumberGeneratorTest.class.st delete mode 100644 src/Math-Tests-Random/PMPoissonGeneratorTest.class.st delete mode 100644 src/Math-Tests-Random/PMPseudoRandomNumberGeneratorTest.class.st delete mode 100644 src/Math-Tests-Random/PMRandomSample.class.st delete mode 100644 src/Math-Tests-Random/package.st diff --git a/src/BaselineOfPolyMath/BaselineOfPolyMath.class.st b/src/BaselineOfPolyMath/BaselineOfPolyMath.class.st index 74732584a..edfbb475d 100644 --- a/src/BaselineOfPolyMath/BaselineOfPolyMath.class.st +++ b/src/BaselineOfPolyMath/BaselineOfPolyMath.class.st @@ -25,7 +25,8 @@ BaselineOfPolyMath >> baseline: spec [ self sMark: spec; xmlWriter: spec; - polyMathDataStructures: spec. + polyMathDataStructures: spec; + randomNumbers: spec. spec package: 'ExtendedNumberParser'; @@ -74,7 +75,6 @@ BaselineOfPolyMath >> baseline: spec [ package: 'Math-Quaternion' with: [ spec requires: #('Math-Complex' 'Math-Numerical' 'Math-Polynomials') ]; - package: 'Math-Random'; package: 'Math-Series'; package: 'Math-StatisticalMoments' with: [ spec requires: #('Math-Helpers' 'Math-DistributionForHistogram') ]; package: 'Math-TSNE'; @@ -116,8 +116,6 @@ BaselineOfPolyMath >> baseline: spec [ with: [ spec requires: #('Math-Polynomials') ]; package: 'Math-Tests-Quaternion' with: [ spec requires: #('Math-Quaternion') ]; - package: 'Math-Tests-Random' - with: [ spec requires: #('Math-Random') ]; package: 'Math-Tests-TSNE' with: [ spec requires: #('Math-TSNE') ]; package: 'Math-UtilsDataServer'. @@ -128,13 +126,13 @@ BaselineOfPolyMath >> baseline: spec [ with: #('Math-Benchmarks-ODE' 'Math-Benchmarks-KDTree'); group: 'Core' with: - #('Math-Complex' 'Math-Quaternion' 'Math-Numerical' 'Math-Random' 'Math-KDTree' 'Math-ODE' 'Math-ArbitraryPrecisionFloat' 'Math-FastFourierTransform' 'ExtendedNumberParser' 'Math-Quantile' 'Math-Physics-Constants' 'Math-Polynomials' 'Math-TSNE' 'Math-Core-Process' 'Math-Helpers' 'PolyMathDataStructures' 'Math-Core-Distribution'); + #('Math-Complex' 'Math-Quaternion' 'Math-Numerical' 'MathRandomNumbers' 'Math-KDTree' 'Math-ODE' 'Math-ArbitraryPrecisionFloat' 'Math-FastFourierTransform' 'ExtendedNumberParser' 'Math-Quantile' 'Math-Physics-Constants' 'Math-Polynomials' 'Math-TSNE' 'Math-Core-Process' 'Math-Helpers' 'PolyMathDataStructures' 'Math-Core-Distribution'); group: 'Extensions' with: #('Math-Clustering' 'Math-Number-Extensions' 'Math-Chromosome' 'Math-PrincipalComponentAnalysis' 'Math-FunctionFit' 'Math-AutomaticDifferenciation' 'Math-KernelSmoothing' 'Math-Permutation' 'Math-KolmogorovSmirnov'); group: 'Tests' with: - #('Math-Tests-Clustering' 'Math-Tests-Numerical' 'Math-Tests-Complex' 'Math-Tests-Quaternion' 'Math-Tests-Random' 'Math-Tests-ODE' 'Math-Tests-KDTree' 'Math-Tests-FunctionFit' 'Math-Tests-AutomaticDifferenciation' 'Math-Tests-FastFourierTransform' 'Math-Tests-Accuracy' 'Math-Tests-ArbitraryPrecisionFloat' 'Math-Tests-KolmogorovSmirnov' 'Math-Tests-Quantile' 'Math-Tests-Polynomials' 'Math-Tests-PrincipalComponentAnalysis' 'Math-Tests-KernelSmoothing' 'Math-Tests-Number-Extensions' 'Math-Tests-Permutation' 'Math-Tests-TSNE' 'Math-Tests-Core-Process' 'Math-Tests-Core-Distribution'); + #('Math-Tests-Clustering' 'Math-Tests-Numerical' 'Math-Tests-Complex' 'Math-Tests-Quaternion' 'Math-Tests-ODE' 'Math-Tests-KDTree' 'Math-Tests-FunctionFit' 'Math-Tests-AutomaticDifferenciation' 'Math-Tests-FastFourierTransform' 'Math-Tests-Accuracy' 'Math-Tests-ArbitraryPrecisionFloat' 'Math-Tests-KolmogorovSmirnov' 'Math-Tests-Quantile' 'Math-Tests-Polynomials' 'Math-Tests-PrincipalComponentAnalysis' 'Math-Tests-KernelSmoothing' 'Math-Tests-Number-Extensions' 'Math-Tests-Permutation' 'Math-Tests-TSNE' 'Math-Tests-Core-Process' 'Math-Tests-Core-Distribution'); group: 'default' with: #('Core' 'Extensions' 'Tests' 'Benchmarks' 'Accuracy') ]. @@ -159,6 +157,12 @@ BaselineOfPolyMath >> projectClass [ do: [ super projectClass ] ] +{ #category : #dependencies } +BaselineOfPolyMath >> randomNumbers: spec [ + + spec baseline: 'MathRandomNumbers' with: [ spec repository: 'github://PolyMathOrg/random-numbers:v1.x.x/src' ] +] + { #category : #dependencies } BaselineOfPolyMath >> sMark: spec [ diff --git a/src/Math-Random/PMBernoulliGenerator.class.st b/src/Math-Random/PMBernoulliGenerator.class.st deleted file mode 100644 index 2ca8a0c9e..000000000 --- a/src/Math-Random/PMBernoulliGenerator.class.st +++ /dev/null @@ -1,71 +0,0 @@ -" -A PMBernoulliGenerator is simulates a Bernoulli Process. This is a discrete process, with probability of p for success, and 1-p for failure. - -next - answer 1 if success event, 0 otherwise - -generator: - provide a uniform [0,1] random number generator - -p: - set the probability of success events - -class methods - -withProbability: - create a generator with probability set to p - -defaultGeneratorClass - class used for generator in new instances -" -Class { - #name : #PMBernoulliGenerator, - #superclass : #PMNumberGenerator, - #instVars : [ - 'probability' - ], - #category : #'Math-Random' -} - -{ #category : #'instance creation' } -PMBernoulliGenerator class >> fair [ - ^ self withProbability: 0.5 -] - -{ #category : #private } -PMBernoulliGenerator class >> validProbability: aProbability [ - "reject probabilities outside of [0,1]" - - self assert: [ (aProbability < 0) not and: (aProbability > 1) not ] -] - -{ #category : #'instance creation' } -PMBernoulliGenerator class >> withProbability: p [ - self validProbability: p. - ^ self new probability: p -] - -{ #category : #initialization } -PMBernoulliGenerator >> initialize [ - super initialize. - self generator: self class defaultGeneratorClass new. - self probability: 0.5 -] - -{ #category : #'stream accessing' } -PMBernoulliGenerator >> next [ - ^ randomNumberGenerator next < probability - ifTrue: [ 1 ] - ifFalse: [ 0 ] -] - -{ #category : #accessing } -PMBernoulliGenerator >> probability [ - ^ probability -] - -{ #category : #accessing } -PMBernoulliGenerator >> probability: aProbability [ - self class validProbability: aProbability. - probability := aProbability -] diff --git a/src/Math-Random/PMBinomialGenerator.class.st b/src/Math-Random/PMBinomialGenerator.class.st deleted file mode 100644 index 7bead9d2d..000000000 --- a/src/Math-Random/PMBinomialGenerator.class.st +++ /dev/null @@ -1,51 +0,0 @@ -" -A PMBinomialGenerator yields results from a binomial distribution with probability p and n trials. The generator is the underlying random source. - -If each independent event has probability 0> numberOfTrials: numberOfTrials probabilityOfSuccess: probabilityOfSuccess [ - ^ self new - numberOfTrials: numberOfTrials; - probability: probabilityOfSuccess; - yourself -] - -{ #category : #accessing } -PMBinomialGenerator >> expectedValue [ - ^ numberOfTrials * probability -] - -{ #category : #initialization } -PMBinomialGenerator >> initialize [ - self generator: PMParkMillerMinimumRandomGenerator new. - self numberOfTrials: 10; probability: 0.5 -] - -{ #category : #'stream access' } -PMBinomialGenerator >> next [ - | x | - x := 0. - numberOfTrials timesRepeat: [ randomNumberGenerator next <= probability ifTrue: [ x := x + 1 ] ]. - ^ x -] - -{ #category : #accessing } -PMBinomialGenerator >> numberOfTrials: anInteger [ - numberOfTrials := anInteger -] - -{ #category : #accessing } -PMBinomialGenerator >> probability: aProbability [ - probability := aProbability -] diff --git a/src/Math-Random/PMCombinedRandomGenerator.class.st b/src/Math-Random/PMCombinedRandomGenerator.class.st deleted file mode 100644 index d0b38525a..000000000 --- a/src/Math-Random/PMCombinedRandomGenerator.class.st +++ /dev/null @@ -1,75 +0,0 @@ -" -This Combined Random Number Generator is based on the algorithm described by PIERRE L'ECUYER in ""Efficient and Portable Combined Random Number Generators"" [Communications of the ACM, June 19, Volume 31, Number 6, pp. 742-749, references p.774]. Taking into account its two-dimensional behaviour (from abovementioned article), this generator is suitable to produce the pairs of consecutive numbers. -For the first linear congruential generator (generator A): -m = 2147483563; a = 40014; q = 53668; r = 12211. -For the second linear congruential generator (generator B): -m = 2147483399; a = 40692; q = 52774; r = 3791. - -To produce initial seedA (for the first generator) the method #nextInt: 2147483562 of Random is used; to produce seedB (for the second) - the method #nextInt: 2147483398. Corresponding seeds are represented as Floats. The result of work of two generators (the next seedA and seedB) are combined. - -Developed by Konstantin Nizheradze - -Instance Variables: - random - seedA - seedB -" -Class { - #name : #PMCombinedRandomGenerator, - #superclass : #Random, - #instVars : [ - 'random', - 'seedA', - 'seedB' - ], - #category : 'Math-Random' -} - -{ #category : #initialize } -PMCombinedRandomGenerator >> initialize [ - - super initialize. - random := Random new. - seedA := (random nextInt: 2147483562) asFloat. - seedB := (random nextInt: 2147483398) asFloat -] - -{ #category : #accessing } -PMCombinedRandomGenerator >> next [ - "Combine seedA and seedB to produce new seed. Seed is in the interval [0, 1]. " - - seed := (self nextValueA) - (self nextValueB). - seed < 1 ifTrue: [seed := seed + 2.147483562e9]. - seed := seed * 4.656613057391769e-10. - ^ seed - - -] - -{ #category : #private } -PMCombinedRandomGenerator >> nextValueA [ - "Evaluate next value of seedA using m and a of generatorA" - - | lo hi aLoRHi | - hi := (seedA quo: 53668.0) asFloat. - lo := seedA - (hi * 53668.0). " = seed rem: q" - aLoRHi := ( 40014.0 * lo) - ( 12211.0 * hi). - seedA := (aLoRHi > 0.0) - ifTrue: [aLoRHi] - ifFalse: [aLoRHi + 2.147483563e9]. - ^ seedA -] - -{ #category : #private } -PMCombinedRandomGenerator >> nextValueB [ - "Evaluate next value of seedB using m, a, q and r of generatorB" - - | lo hi aLoRHi | - hi := (seedB quo: 52774.0) asFloat. - lo := seedB - (hi * 52774.0). " = seed rem: q" - aLoRHi := (40692.0 * lo) - (3791.0 * hi). - seedB := (aLoRHi > 0.0) - ifTrue: [aLoRHi] - ifFalse: [aLoRHi + 2.147483399e9]. - ^ seedB -] diff --git a/src/Math-Random/PMConstantGenerator.class.st b/src/Math-Random/PMConstantGenerator.class.st deleted file mode 100644 index 5c004c49b..000000000 --- a/src/Math-Random/PMConstantGenerator.class.st +++ /dev/null @@ -1,32 +0,0 @@ -" -A PMConstantGenerator is still a number generator but a simple one :) -" -Class { - #name : #PMConstantGenerator, - #superclass : #PMNumberGenerator, - #instVars : [ - 'constant' - ], - #category : #'Math-Random' -} - -{ #category : #'instance-creation' } -PMConstantGenerator class >> constant: aNumber [ - ^ self new constant: aNumber ; yourself -] - -{ #category : #accessing } -PMConstantGenerator >> constant: aConstant [ - constant := aConstant -] - -{ #category : #accessing } -PMConstantGenerator >> generator: aRandomGenerator [ - "Do nothing." - ^ self -] - -{ #category : #'stream access' } -PMConstantGenerator >> next [ - ^ constant -] diff --git a/src/Math-Random/PMExplicitInverseCongruentialRandomGenerator.class.st b/src/Math-Random/PMExplicitInverseCongruentialRandomGenerator.class.st deleted file mode 100644 index 0345cda3d..000000000 --- a/src/Math-Random/PMExplicitInverseCongruentialRandomGenerator.class.st +++ /dev/null @@ -1,96 +0,0 @@ -" -A PMExplicitInverseCongruentialGenerator is an explicit inversive congruential generator, constructed according to ""Good random number generators are (not so) easy to find"" by P. Hellekalek (1998) and extended euclidean algorithm. -Developed by Konstantin Nizheradze - -Instance Variables - nextN: - nextValue: - p: - -nextN - - next number of the sequence of random numbers. It is also the parameter at extended euclidean algorythm - -nextValue - - next modulo inverse value, calculated by extended euclidean algorithm - -p - - parameter at extended euclidean algorithm - -" -Class { - #name : #PMExplicitInverseCongruentialRandomGenerator, - #superclass : #Random, - #instVars : [ - 'p', - 'nextN', - 'nextValue', - 'nextModInv' - ], - #category : #'Math-Random' -} - -{ #category : #initialization } -PMExplicitInverseCongruentialRandomGenerator >> initialize [ - "Initialize using Random and define the modulo (p)" - - | random | - super initialize. - p := 16r7FFFFFFF asFloat. - random := Random new. - nextN := random nextValue. - -] - -{ #category : #accessing } -PMExplicitInverseCongruentialRandomGenerator >> next [ - "This method is used by nextInt:, answer a random Float in the interval [0 to 1]" - - nextModInv := self nextRandomValue / p. - ^ nextModInv - - - -] - -{ #category : #private } -PMExplicitInverseCongruentialRandomGenerator >> nextRandomValue [ - "Calculate the next modulo inverse value for n+1" - - | rem newrem inv newinv transrem transinv quotient | - inv := 0. - newinv := 1. - rem := p. - newrem := nextN. - [newrem ~= 0] whileTrue: [quotient := rem // newrem. - transrem := newrem. - newrem := rem \\ newrem. - rem := transrem. - transinv := newinv. - newinv := inv - (quotient * newinv). - inv := transinv]. - (inv < 0) ifTrue: [inv := inv + p]. - nextValue := inv. - nextN := nextN + 1. - ^nextValue - -] - -{ #category : #tests } -PMExplicitInverseCongruentialRandomGenerator >> testNextValue: anInteger [ - "This is to test the principle of modulo inverse" - - | rem newrem inv newinv transrem transinv quotient | - inv := 0. - newinv := 1. - rem := 240. - newrem := anInteger. - [newrem ~= 0] whileTrue: [quotient := rem // newrem. - transrem := newrem. - newrem := rem \\ newrem. - rem := transrem. - transinv := newinv. - newinv := inv - (quotient * newinv). - inv := transinv]. - ^ inv - -] diff --git a/src/Math-Random/PMExponentialGenerator.class.st b/src/Math-Random/PMExponentialGenerator.class.st deleted file mode 100644 index f20112889..000000000 --- a/src/Math-Random/PMExponentialGenerator.class.st +++ /dev/null @@ -1,63 +0,0 @@ -" -A PMExponentialGenerator uses a uniform random variable in [0,1] to sample from an exponential distribution. - -The exponential distribution has a single parameter beta, here denoted as mean. - -The default RandomGenerator is PMRandom, but can be modified. - -The next method uses the formula: - -x= - \beta * ln (1 - u) - -to generate an exponential sample x from a uniform [0,1] sample u. - -(Applied Statistics 3rd ed., Ledolter and Hogg, p. 185) -" -Class { - #name : #PMExponentialGenerator, - #superclass : #PMNumberGenerator, - #instVars : [ - 'mean' - ], - #category : #'Math-Random' -} - -{ #category : #'instance creation' } -PMExponentialGenerator class >> mean: aNumber [ - ^ self basicNew - generator: self defaultGeneratorClass new; - mean: aNumber; - yourself -] - -{ #category : #'instance creation' } -PMExponentialGenerator class >> new [ - ^ self mean: 1 -] - -{ #category : #accessing } -PMExponentialGenerator >> expectedValue [ - "Returns the mean/expectation value" - ^ mean - -] - -{ #category : #accessing } -PMExponentialGenerator >> mean [ - ^ mean -] - -{ #category : #accessing } -PMExponentialGenerator >> mean: aNumber [ - mean := aNumber -] - -{ #category : #'stream access' } -PMExponentialGenerator >> next [ - ^ mean negated * ((1 - randomNumberGenerator next) ln) -] - -{ #category : #'stream access' } -PMExponentialGenerator >> peek [ - ^ mean negated * ((1 - randomNumberGenerator peek) ln) -] diff --git a/src/Math-Random/PMFishmanMooreRandomGenerator.class.st b/src/Math-Random/PMFishmanMooreRandomGenerator.class.st deleted file mode 100644 index 2f14eb55f..000000000 --- a/src/Math-Random/PMFishmanMooreRandomGenerator.class.st +++ /dev/null @@ -1,41 +0,0 @@ -" -I am a simple implementation of Fishman-Moore pseudo-random number generator. - -Onghena, P. A theoretical and empirical comparison of mainframe, microcomputer, and pocket calculator pseudorandom number generators. Behavior Research Methods, Instruments, & Computers 25, 384–395 (1993). https://doi.org/10.3758/BF03204529 -" -Class { - #name : #PMFishmanMooreRandomGenerator, - #superclass : #PMPseudoRandomNumberGenerator, - #category : #'Math-Random' -} - -{ #category : #initialization } -PMFishmanMooreRandomGenerator >> initialize [ - super initialize. - seed := Time millisecondClockValue -] - -{ #category : #accessing } -PMFishmanMooreRandomGenerator >> next [ - ^ (seed := 742938285 * seed \\ 2147483647) / 2147483647.0 -] - -{ #category : #accessing } -PMFishmanMooreRandomGenerator >> nextInt: anInteger [ - ^ (self next * anInteger) truncated + 1 -] - -{ #category : #accessing } -PMFishmanMooreRandomGenerator >> peek [ - ^ 742938285 * seed \\ 2147483647 / 2147483647.0 -] - -{ #category : #accessing } -PMFishmanMooreRandomGenerator >> seed [ - ^ seed -] - -{ #category : #accessing } -PMFishmanMooreRandomGenerator >> seed: anInteger [ - seed := anInteger asInteger -] diff --git a/src/Math-Random/PMGaussianGenerator.class.st b/src/Math-Random/PMGaussianGenerator.class.st deleted file mode 100644 index 41e7e148b..000000000 --- a/src/Math-Random/PMGaussianGenerator.class.st +++ /dev/null @@ -1,59 +0,0 @@ -" -A PMGaussianGenerator uses a Normal Distribution. - -" -Class { - #name : #PMGaussianGenerator, - #superclass : #PMNumberGenerator, - #instVars : [ - 'mean', - 'standardDeviation', - 'nextGaussian' - ], - #category : #'Math-Random' -} - -{ #category : #testing } -PMGaussianGenerator >> hasNextGaussian [ - ^nextGaussian notNil -] - -{ #category : #initialization } -PMGaussianGenerator >> initialize [ - super initialize. - self mean: 0. - self standardDeviation: 1 -] - -{ #category : #accessing } -PMGaussianGenerator >> mean: aMeanValue [ - mean := aMeanValue -] - -{ #category : #'stream access' } -PMGaussianGenerator >> next [ - ^ self nextGaussianNormalized * standardDeviation + mean -] - -{ #category : #'stream access' } -PMGaussianGenerator >> nextGaussianNormalized [ - | x1 x2 w y1 y2 | - self hasNextGaussian - ifTrue: [ - [^ nextGaussian] ensure: [ nextGaussian := nil ] ]. - [ - x1 := 2.0 * randomNumberGenerator nextFloat - 1.0. - x2 := 2.0 * randomNumberGenerator nextFloat - 1.0. - w := x1 * x1 + (x2 * x2). - w >= 1.0 ] whileTrue. - w := (-2.0 * w ln / w) sqrt. - y1 := x1 * w. - y2 := x2 * w. - nextGaussian := y2. - ^ y1 -] - -{ #category : #accessing } -PMGaussianGenerator >> standardDeviation: aStandardDeviation [ - standardDeviation := aStandardDeviation -] diff --git a/src/Math-Random/PMLehmerRandomGenerator.class.st b/src/Math-Random/PMLehmerRandomGenerator.class.st deleted file mode 100644 index 3dc1ba7a6..000000000 --- a/src/Math-Random/PMLehmerRandomGenerator.class.st +++ /dev/null @@ -1,40 +0,0 @@ -" -This generator uses the Lehmer's Linear Congruential method. - -PMLehmerRandomGenerator new next -" -Class { - #name : #PMLehmerRandomGenerator, - #superclass : #PMPseudoRandomNumberGenerator, - #category : #'Math-Random' -} - -{ #category : #'stream access' } -PMLehmerRandomGenerator >> next [ - "Answer a Random Float between 0 and 1. Uses Lehmer's linear congruential method." - - ^ self nextFloat -] - -{ #category : #private } -PMLehmerRandomGenerator >> nextFloat [ - "Private - Answer a Random Float between 0 and 1. Uses Lehmer's linear congruential method." - - seed := self peekSeed. - ^ seed / SmallInteger maxVal asFloat -] - -{ #category : #'stream access' } -PMLehmerRandomGenerator >> peek [ - "Answer a pseudo-Random floating point number between 0 and 1." - - ^ self peekSeed / SmallInteger maxVal asFloat -] - -{ #category : #private } -PMLehmerRandomGenerator >> peekSeed [ - "Private - Answer the next Integer seed calculated using Lehmer's linear congruential - method. The seed is in the range 0..16r3FFFFFFF." - - ^ ( seed * 31415821 ) + 1 bitAnd: SmallInteger maxVal -] diff --git a/src/Math-Random/PMLinearCongruentialRandomGenerator.class.st b/src/Math-Random/PMLinearCongruentialRandomGenerator.class.st deleted file mode 100644 index 1ad21e0f9..000000000 --- a/src/Math-Random/PMLinearCongruentialRandomGenerator.class.st +++ /dev/null @@ -1,39 +0,0 @@ -" -I use a quick and dirty Linear Congruential generator. - -PMLinearCongruentialRandomGenerator new next. -" -Class { - #name : #PMLinearCongruentialRandomGenerator, - #superclass : #PMPseudoRandomNumberGenerator, - #category : #'Math-Random' -} - -{ #category : #'stream access' } -PMLinearCongruentialRandomGenerator >> next [ - "Answer a pseudo-Random floating point number between 0 and 1. Uses a quick and dirty Linear congruential generator" - - ^ self nextFloat -] - -{ #category : #accessing } -PMLinearCongruentialRandomGenerator >> nextFloat [ - "Answer a pseudo-Random floating point number between 0 and 1. Uses a quick and dirty Linear congruential generator." - - seed := self peekSeed. - ^ seed / 120050.0 -] - -{ #category : #'stream access' } -PMLinearCongruentialRandomGenerator >> peek [ - "Answer a pseudo-Random floating point number between 0 and 1. Uses a simple, but fast, Linear Congruential generator." - - ^ self peekSeed / 120050.0 -] - -{ #category : #accessing } -PMLinearCongruentialRandomGenerator >> peekSeed [ - "Answer the next Integer seed calculated using a quick and dirty Linear congruential generator." - - ^ (seed * 2311 + 25367) \\ 120050 -] diff --git a/src/Math-Random/PMMarsagliaKissRandomGenerator.class.st b/src/Math-Random/PMMarsagliaKissRandomGenerator.class.st deleted file mode 100644 index 1660910c9..000000000 --- a/src/Math-Random/PMMarsagliaKissRandomGenerator.class.st +++ /dev/null @@ -1,65 +0,0 @@ -" -A PMMarsagliaKissRandom is a pseudo-random number generator (PRNG) using Marsaglia's Keep it Simple Stupid algorithm. - -It generates Float with uniform distribution in Interval [0,1). -The result divided by 1.0 predecessor will be in [0,1]. - -Instance Variables - kernelRand1: a first generator - kernelRand2: a second generator - -" -Class { - #name : #PMMarsagliaKissRandomGenerator, - #superclass : #PMPseudoRandomNumberGenerator, - #instVars : [ - 'kernelRand1', - 'kernelRand2' - ], - #category : #'Math-Random' -} - -{ #category : #'instance creation' } -PMMarsagliaKissRandomGenerator class >> default [ - ^self seed: #( - 123456789 362436069 521288629 316191069 - 987654321 458629013 582859209 438195021) -] - -{ #category : #'instance creation' } -PMMarsagliaKissRandomGenerator class >> new [ - - ^ self seed: (PMMarsagliaKissRandomKernel new next: 8) -] - -{ #category : #'stream access' } -PMMarsagliaKissRandomGenerator >> next [ - "Answer a Float in interval [0.0,1.0) with uniform distribution. - Note that constant 16rFFFFF800 is computed so as to truncate the 64 bits to Float precision. - It is thus ((1 << 32 - 1 << (64 - Float precision) bitAnd: 1 << 32 - 1)) hex" - ^(kernelRand1 next asFloat timesTwoPower: -32) - + ((kernelRand2 next bitAnd: 16rFFFFF800) asFloat timesTwoPower: -64) -] - -{ #category : #'stream access' } -PMMarsagliaKissRandomGenerator >> peek [ - ^self copy next -] - -{ #category : #copying } -PMMarsagliaKissRandomGenerator >> postCopy [ - kernelRand1 := kernelRand1 copy. - kernelRand2 := kernelRand2 copy -] - -{ #category : #accessing } -PMMarsagliaKissRandomGenerator >> seed [ - ^ kernelRand1 seed , kernelRand2 seed -] - -{ #category : #accessing } -PMMarsagliaKissRandomGenerator >> seed: aWordArray [ - "Initialize with an Array of eight 32-bits Integer" - kernelRand1 := PMMarsagliaKissRandomKernel seed: (aWordArray first: 4). - kernelRand2 := PMMarsagliaKissRandomKernel seed: (aWordArray last: 4) -] diff --git a/src/Math-Random/PMMarsagliaKissRandomKernel.class.st b/src/Math-Random/PMMarsagliaKissRandomKernel.class.st deleted file mode 100644 index 2c94b1338..000000000 --- a/src/Math-Random/PMMarsagliaKissRandomKernel.class.st +++ /dev/null @@ -1,97 +0,0 @@ -" -A PMMarsagliaKissRandomKernel is a private class for generating pseudo-Random numbers. - -It generates 32-bits Integer with uniform distribution in Interval [ 0,16rFFFFFFFF]. - -It holds the states of the pseudo-random generator, and the kernel generation algorithm. -The algorithm is the one used in libgfortran library. -It is based on Marsaglia's Keep It Simple Stupid 2005 version as in ""double precision RNGs"" in sci.math.num-analysis -http://sci.tech-archive.net/Archive/sci.math.num-analysis/2005-11/msg00352.html - -It is a combination of: -1) a linear congruential generator with period 2^32 -2) a 3-shift shift-register generator of period 2^32-1 -3) 2 16-bit multiply with carry generators with a period 597273182964842497 > 2^59 - -Period of this generator is about 2^123 - -Previous 1999 version can be found along with discussions in this sci.stat.math newsgroup archive: -http://www.ciphersbyritter.com/NEWS4/RANDC.HTM#369F6FCA.74C7C041@stat.fsu.edu -The shift-register had a permutation of first two shifts (13 and 17) leading to a reduced period. - -Warning: this pseudo-random generator is not suitable for cryptography as it could be too easily broken (see http://eprint.iacr.org/2011/007.pdf) - -Instance Variables - jcong: state of the linear congruencial generator - jsr: state of the 3-shift register generator - w: state of the first multiply with carry generator - z: state of the second multiply with carry generator - -" -Class { - #name : #PMMarsagliaKissRandomKernel, - #superclass : #Object, - #instVars : [ - 'jcong', - 'jsr', - 'w', - 'z' - ], - #category : #'Math-Random' -} - -{ #category : #'instance creation' } -PMMarsagliaKissRandomKernel class >> new [ - | seedGenerator | - seedGenerator := self seed: ((1 to: 4) collect: [:i | Time millisecondClockValue + i]). - ^self seed: (seedGenerator next: 4) -] - -{ #category : #'instance creation' } -PMMarsagliaKissRandomKernel class >> seed: anArrayWithFourIntegers [ - "Anwer a new Random stream with the initial seed anArrayWithFourIntegers." - - ^ self basicNew seed: anArrayWithFourIntegers; yourself -] - -{ #category : #'stream access' } -PMMarsagliaKissRandomKernel >> next [ - "Anwser a 32 bits positive integer in [0,16rFFFFFFFF]." - jcong := jcong * 69069 + 1327217885 bitAnd: 16rFFFFFFFF. - jsr := (jsr bitAnd: 16r0007FFFF) << 13 bitXor: jsr. - jsr := jsr >> 17 bitXor: jsr. - jsr := (jsr bitAnd: 16r07FFFFFF) << 5 bitXor: jsr. - w := (w bitAnd: 16rFFFF) * 18000 + (w >> 16). - z := (z bitAnd: 16rFFFF) * 30903 + (z >> 16). - ^jcong + jsr + ((w bitAnd: 16rFFFF) << 16) + z bitAnd: 16rFFFFFFFF -] - -{ #category : #accessing } -PMMarsagliaKissRandomKernel >> next: anInteger [ - "Answer an Array of anInteger pseudo-random 32 bits integers between 0 and 16rFFFFFFFF." - - ^ ( 1 to: anInteger ) - collect: [ :i | self next ] -] - -{ #category : #accessing } -PMMarsagliaKissRandomKernel >> peek [ - ^self copy next -] - -{ #category : #accessing } -PMMarsagliaKissRandomKernel >> seed [ - ^(WordArray new: 4) - with: jcong - with: jsr - with: w - with: z -] - -{ #category : #accessing } -PMMarsagliaKissRandomKernel >> seed: seedArray [ - jcong := (seedArray at: 1) bitAnd: 16rFFFFFFFF. - jsr := (seedArray at: 2) bitAnd: 16rFFFFFFFF. - w := (seedArray at: 3) bitAnd: 16rFFFFFFFF. - z := (seedArray at: 4) bitAnd: 16rFFFFFFFF. -] diff --git a/src/Math-Random/PMMersenneTwisterRandomGenerator.class.st b/src/Math-Random/PMMersenneTwisterRandomGenerator.class.st deleted file mode 100644 index 5a3906bd0..000000000 --- a/src/Math-Random/PMMersenneTwisterRandomGenerator.class.st +++ /dev/null @@ -1,164 +0,0 @@ -" -See http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html - -"" To get a pseudo-random float "" -MersenneTwisterRandom new next. - -"" To get a pseudo-random integer "" -MersenneTwisterRandom new nextInteger. - - -" -Class { - #name : #PMMersenneTwisterRandomGenerator, - #superclass : #PMPseudoRandomNumberGenerator, - #instVars : [ - 'states', - 'mti' - ], - #classVars : [ - 'DefaultLengthVector', - 'Mt19937LowerMask', - 'Mt19937Mask', - 'Mt19937MatrixA', - 'Mt19937UpperMask', - 'PeriodParameter', - 'TemperingMaskB', - 'TemperingMaskC' - ], - #category : #'Math-Random' -} - -{ #category : #'class initialization' } -PMMersenneTwisterRandomGenerator class >> initialize [ - " self initialize " - - DefaultLengthVector := 624. - Mt19937LowerMask := 2147483647. - Mt19937Mask := 4294967295. - Mt19937MatrixA := 16r9908B0DF. " 2567483615 " - Mt19937UpperMask := 16r80000000. " 2147483648 " - PeriodParameter := 397. - TemperingMaskB := 16r9D2C5680. " 2636928640 " - TemperingMaskC := 16rEFC60000. " 4022730752 " - - -] - -{ #category : #initialization } -PMMersenneTwisterRandomGenerator >> initialize [ - "Initialize the receiver state vector and multiplier" - - states := Array new: DefaultLengthVector. - mti := 1. - states at: 1 put: ( self seed bitAnd: Mt19937Mask ). - 2 to: DefaultLengthVector - do: [ :multIndex | - states - at: multIndex - put: ( 16r6C078965 * - ( ( states at: multIndex - 1 ) - bitXor: ( ( states at: multIndex - 1 ) bitShift: 30 negated ) ) + multIndex ). - states - at: multIndex - put: ( ( states at: multIndex ) bitAnd: Mt19937Mask ) - ] - -] - -{ #category : #'stream access' } -PMMersenneTwisterRandomGenerator >> next [ - "Private - Answer a pseudo-Random float number - four times faster than rand() ff period 2**19937-1. " - - ^ self nextFloat - -] - -{ #category : #accessing } -PMMersenneTwisterRandomGenerator >> nextFloat [ - "Answer a random float number in the interval [ 0 , 1 ]" - - ^ self nextInteger * ( 1.0 / (4294967295.0 * 2 )) -] - -{ #category : #accessing } -PMMersenneTwisterRandomGenerator >> nextFloat: limit [ - "Answer a random float number in the interval [ 0 , limit ]" - - ^ self nextFloat * limit -] - -{ #category : #accessing } -PMMersenneTwisterRandomGenerator >> nextFloatExcludeUpper [ - "Answer a random float number in the interval [ 0 , 1 )" - - ^ self nextInteger * (1.0 / (4294967296.0 * 2)) -] - -{ #category : #accessing } -PMMersenneTwisterRandomGenerator >> nextFloatExcludeUpper: limit [ - " Answer a random float number in the interval [ 0 , limit ) " - - ^ self nextFloatExcludeUpper * limit -] - -{ #category : #private } -PMMersenneTwisterRandomGenerator >> nextInteger [ - "Answer a random integer on [0,0xffffffff] interval" - - | tempArray y | - tempArray := Array withAll: #(0 16r9908B0DF). - mti >= DefaultLengthVector - ifTrue: [ mti = (DefaultLengthVector + 1) - ifTrue: [ self seed: 5489. - self initialize ]. - 1 to: DefaultLengthVector - PeriodParameter do: [ :kk | - y := ((states at: kk) bitAnd: Mt19937UpperMask) - bitOr: ((states at: kk + 1) bitAnd: Mt19937LowerMask). - states - at: kk - put: - (((states at: kk + PeriodParameter) bitXor: (y bitShift: 1 negated)) - bitXor: (tempArray at: (y bitAnd: 1) + 1)) ]. - DefaultLengthVector - PeriodParameter + 1 to: DefaultLengthVector - 2 - do: [ :kk | - y := ((states at: kk) bitAnd: Mt19937UpperMask) - bitOr: ((states at: kk + 1) bitAnd: Mt19937LowerMask). - states - at: kk - put: - (((states at: kk + PeriodParameter - DefaultLengthVector + 1) - bitXor: (y bitShift: 1 negated)) - bitXor: (tempArray at: (y bitAnd: 1) + 1)) ]. - y := ((states at: DefaultLengthVector) bitAnd: Mt19937UpperMask) - bitOr: ((states at: 1) bitAnd: Mt19937LowerMask). - states - at: DefaultLengthVector - put: - ((states at: PeriodParameter) - bitXor: ((y bitShift: 1) bitXor: (tempArray at: (y bitAnd: 1) + 1))). - mti := 0 ]. - y := self temperAt: mti + 1. - mti := mti + 1. - ^ y -] - -{ #category : #'stream access' } -PMMersenneTwisterRandomGenerator >> peek [ - "Answer the same as next without changing state" - - ^ self copy next - -] - -{ #category : #private } -PMMersenneTwisterRandomGenerator >> temperAt: position [ - | y | - y := states at: position. - y := y bitXor: (y bitShift: 11 negated). - y := y bitXor: ((y bitShift: 7 negated) bitAnd: TemperingMaskB). - y := y bitXor: ((y bitShift: 15 negated) bitAnd: TemperingMaskC). - y := y bitXor: (y bitShift: 18 negated). - ^ y -] diff --git a/src/Math-Random/PMNumberGenerator.class.st b/src/Math-Random/PMNumberGenerator.class.st deleted file mode 100644 index 9352d64fe..000000000 --- a/src/Math-Random/PMNumberGenerator.class.st +++ /dev/null @@ -1,56 +0,0 @@ -" -A PMNumberGenerator is a stream of numbers. All NumberGenerators respond to #next. - -As generator I use a PMRandomGenerator instance as defined by the class message defaultGeneratorClass. -My API is - -- generator: -- next and peek - -By default I use a Park and Miller minimum congruent random number generator. See PMParkMillerMinimumRandomGenerator - - -" -Class { - #name : #PMNumberGenerator, - #superclass : #Object, - #instVars : [ - 'randomNumberGenerator' - ], - #category : #'Math-Random' -} - -{ #category : #factory } -PMNumberGenerator class >> defaultGeneratorClass [ - - ^ PMParkMillerMinimumRandomGenerator -] - -{ #category : #'instance-creation' } -PMNumberGenerator class >> new [ - ^ (self basicNew - generator: self defaultGeneratorClass new) - initialize; - yourself -] - -{ #category : #accessing } -PMNumberGenerator >> generator [ - ^ randomNumberGenerator -] - -{ #category : #accessing } -PMNumberGenerator >> generator: aRandomGenerator [ - randomNumberGenerator := aRandomGenerator -] - -{ #category : #'stream accessing' } -PMNumberGenerator >> next [ - ^ self subclassResponsibility -] - -{ #category : #'stream accessing' } -PMNumberGenerator >> peek [ - "really a subclass responsibility, this may be overriden whenever its more efficient to do so" - ^ (self copy generator: (self generator copy)) next -] diff --git a/src/Math-Random/PMParkMillerMinimumRandomGenerator.class.st b/src/Math-Random/PMParkMillerMinimumRandomGenerator.class.st deleted file mode 100644 index 429b57b8f..000000000 --- a/src/Math-Random/PMParkMillerMinimumRandomGenerator.class.st +++ /dev/null @@ -1,57 +0,0 @@ -" -Uses Park and Miller's 'Minimum Standard' Congruential generator. See 'Numerical Recipes in C', 2nd Edition; Press, Flannery, Teukolsky and Vetterling; Cambridge University Press, 1992. - -PMParkMillerMinimumRandomGenerator new next -" -Class { - #name : #PMParkMillerMinimumRandomGenerator, - #superclass : #PMPseudoRandomNumberGenerator, - #category : #'Math-Random' -} - -{ #category : #'stream access' } -PMParkMillerMinimumRandomGenerator >> next [ - "Answer a pseudo-Random floating point number between 0 and 1. - Uses Park and Miller's 'Minimum Standard' congruential generator - (see 'Numerical Recipes in C', 2nd Edition; Press, Flannery, - Teukolsky and Vetterling; Cambridge University Press, 1992)." - - ^ self nextFloat -] - -{ #category : #accessing } -PMParkMillerMinimumRandomGenerator >> nextFloat [ - "Answer a pseudo-Random floating point number between 0 and 1. - Uses Park and Miller's 'Minimum Standard' congruential generator - (see 'Numerical Recipes in C', 2nd Edition; Press, Flannery, - Teukolsky and Vetterling; Cambridge University Press, 1992)." - - seed := self peekSeed. - ^ seed / 16r7FFFFFFF asFloat -] - -{ #category : #'stream access' } -PMParkMillerMinimumRandomGenerator >> peek [ - "Answer a pseudo-Random floating point number between 0 and 1. - Uses Park and Miller's 'Minimum Standard' congruential generator." - - ^ self peekSeed / 16r7FFFFFFF asFloat - -] - -{ #category : #accessing } -PMParkMillerMinimumRandomGenerator >> peekSeed [ - "Answer the next Integer seed calculated using Park and Miller's 'Minimum Standard' - congruential generator. The seed is in the range 0..16r7FFFFFFF." - - ^ ( seed * ( 7 raisedToInteger: 5 ) ) rem: 16r7FFFFFFF - -] - -{ #category : #accessing } -PMParkMillerMinimumRandomGenerator >> seed: anInteger [ - "Set the seed of the Random stream to anInteger (or 1 if zero)." - - seed := anInteger max: 1 - -] diff --git a/src/Math-Random/PMPoissonGenerator.class.st b/src/Math-Random/PMPoissonGenerator.class.st deleted file mode 100644 index 6ab07568f..000000000 --- a/src/Math-Random/PMPoissonGenerator.class.st +++ /dev/null @@ -1,61 +0,0 @@ -" -A PMPoissonGenerator simulates a Poisson Process with parameter lambda. - -This class is implemented to yield an integer result, corresponding to the number of events in n intervals, with probabilility of an event in each individual interval of p. The parameter lambda is the product of n and p. -" -Class { - #name : #PMPoissonGenerator, - #superclass : #PMNumberGenerator, - #instVars : [ - 'lambda' - ], - #category : #'Math-Random' -} - -{ #category : #'instance creation' } -PMPoissonGenerator class >> lambda: aNumber [ - ^ self basicNew - generator: self defaultGeneratorClass new; - lambda: aNumber; - yourself -] - -{ #category : #'instance creation' } -PMPoissonGenerator class >> new [ - ^ self lambda: 1 -] - -{ #category : #accessing } -PMPoissonGenerator >> expectedValue [ - "Returns the expected value or mean of the distribution" - ^ self lambda -] - -{ #category : #accessing } -PMPoissonGenerator >> lambda [ - ^ lambda -] - -{ #category : #accessing } -PMPoissonGenerator >> lambda: anObject [ - lambda := anObject. - -] - -{ #category : #'stream access' } -PMPoissonGenerator >> next [ - "Generator based on multiplication of uniform random variable. Luc DeVroye, Non-Uniform Random Variate Generation, Section X.3" - - | x prod limit | - limit := self lambda negated exp. - x := 0. - prod := 1. - [ true ] - whileTrue: - [ | u | - u := self generator next. - prod := u * prod. - prod > limit - ifTrue: [ x := x + 1 ] - ifFalse: [ ^ x ] ] -] diff --git a/src/Math-Random/PMPseudoRandomNumberGenerator.class.st b/src/Math-Random/PMPseudoRandomNumberGenerator.class.st deleted file mode 100644 index c6e1c03d2..000000000 --- a/src/Math-Random/PMPseudoRandomNumberGenerator.class.st +++ /dev/null @@ -1,147 +0,0 @@ -" -I'm the top abstract class of the pseudo-random numbers generator. - -The applications of Pseudo-Random Numbers Generators are many ones: -- Simulations -- Sampling -- Cryptography -- Numeric Analysis -- Games -- Aesthetics - -Internally, one can classify Random Number Generator according to several views, so choosing one or another is fully dependent of your requirements: - -From the production view, there is always a tradeoff between: speed and safety - -Another view, based on the seed they use, is: -- Deterministic: They take the seed value from a specific number. These ones are called Pseudo random number generators. -- Non-deterministic: They take the seed value from a physical source non-predictable and outside the human control. These are called true Random number generators. - -Along these terms, deterministic Random Number Generator are divided between: -- Normal PRNG --- Linear Congruential --- Non-Linear Congruential -- Cryptography safe PRNG (CSPRNG) --- DSA --- ECDSA - -And finally, there's a taxonomy more related with the internal implementation, based on how the pseudo-generator make its random variables following a distribution function. - - - -" -Class { - #name : #PMPseudoRandomNumberGenerator, - #superclass : #Object, - #instVars : [ - 'seed' - ], - #category : #'Math-Random' -} - -{ #category : #testing } -PMPseudoRandomNumberGenerator class >> chiSquare: range repeating: anInteger [ - "Run a 'chi-square' test on a random number generator, over a range of integers given by range, repeating anInteger times. - Answer an Array containing the result of the chi-square test (which should be the same as the range), and the upper and lower bounds for 'good' randomness (assuming that anInteger is at least 10 * range)." - - "LCRandom chiSquare: 100 repeating: 4000" - - | array rand ave | - array := Array new: range withAll: 0. - rand := self new. - anInteger - timesRepeat: - [ | temp | - temp := (rand next * range) truncated + 1. - array at: temp put: (array at: temp) + 1 ]. - ave := 0. - array do: [ :each | ave := ave + (each * each) ]. - ^ Array - with: range - (2 * range sqrt) - with: - ave * range / anInteger - anInteger asFloat - with: range + (2 * range sqrt) -] - -{ #category : #'instance creation' } -PMPseudoRandomNumberGenerator class >> new [ - "Answer a new instance of the receiver" - - ^ (self seed: Time millisecondClockValue) initialize -] - -{ #category : #'instance creation' } -PMPseudoRandomNumberGenerator class >> seed: anInteger [ - "Anwer a new Random stream with the initial seed anInteger." - - ^ self basicNew seed: anInteger; yourself -] - -{ #category : #testing } -PMPseudoRandomNumberGenerator >> atEnd [ - "Answer whether the receiver is at its end - never true for a stream of Random numbers" - - ^ false - -] - -{ #category : #accessing } -PMPseudoRandomNumberGenerator >> contents [ - "Answer all of the objects in the collection accessed by the receiver. - Implementation Notes: Random streams are infinite, so there is no implementation possible." - - ^ self shouldNotImplement - -] - -{ #category : #testing } -PMPseudoRandomNumberGenerator >> isReadable [ - "Answer whether the receiver can be read from (i.e. it implements the gettableStream protocol)." - - ^ true - -] - -{ #category : #testing } -PMPseudoRandomNumberGenerator >> isWriteable [ - "Answer whether the receiver can be written to (i.e. it implements the puttableStream protocol)." - - ^ false - -] - -{ #category : #'stream access' } -PMPseudoRandomNumberGenerator >> next [ - "Answer a pseudo-Random number" - - ^ self subclassResponsibility -] - -{ #category : #'stream access' } -PMPseudoRandomNumberGenerator >> next: anInteger [ - "Answer a collection of size anInteger of pseudo-random Floats between 0 and 1. " - - ^ ( 1 to: anInteger ) collect: [ :i | self next ] - -] - -{ #category : #'stream access' } -PMPseudoRandomNumberGenerator >> peek [ - "Answer a pseudo-Random number generated from the next seed, but do not advance down the stream (i.e. self peek = self peek). " - - ^ self subclassResponsibility -] - -{ #category : #accessing } -PMPseudoRandomNumberGenerator >> seed [ - "Returns the instance var of the receiver for external manipulation" - - ^ seed -] - -{ #category : #accessing } -PMPseudoRandomNumberGenerator >> seed: anObject [ - "Sets the instance var of the receiver with anObject. (No checking is done)" - - seed := anObject -] diff --git a/src/Math-Random/package.st b/src/Math-Random/package.st deleted file mode 100644 index 9d6b6042f..000000000 --- a/src/Math-Random/package.st +++ /dev/null @@ -1 +0,0 @@ -Package { #name : #'Math-Random' } diff --git a/src/Math-Tests-Random/PMBernoulliGeneratorTest.class.st b/src/Math-Tests-Random/PMBernoulliGeneratorTest.class.st deleted file mode 100644 index ec209a95a..000000000 --- a/src/Math-Tests-Random/PMBernoulliGeneratorTest.class.st +++ /dev/null @@ -1,41 +0,0 @@ -" -A BernoulliGeneratorTest is a test class for testing the behavior of BernoulliGenerator -" -Class { - #name : #PMBernoulliGeneratorTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #tests } -PMBernoulliGeneratorTest >> testNextYieldsOneOrZero [ - | gen | - gen := PMBernoulliGenerator fair. - self should: [ | x | x := gen next. - (x = 0) or: [x = 1]]. -] - -{ #category : #tests } -PMBernoulliGeneratorTest >> testOneProbabilityGivesOneNext [ - | g | - g := PMBernoulliGenerator withProbability: 1. - self assert: g next equals: 1 -] - -{ #category : #tests } -PMBernoulliGeneratorTest >> testProbabilityIsMutable [ - | g | - g := PMBernoulliGenerator withProbability: 0.0. - self assert: g next equals: 0. - self assert: g probability equals: 0. - g probability: 1. - self assert: g next equals: 1. - self assert: g probability equals: 1 -] - -{ #category : #tests } -PMBernoulliGeneratorTest >> testZeroProbabilityGivesZeroNext [ - | g | - g := PMBernoulliGenerator withProbability: 0.0. - self assert: g next equals: 0 -] diff --git a/src/Math-Tests-Random/PMBinomialGeneratorTest.class.st b/src/Math-Tests-Random/PMBinomialGeneratorTest.class.st deleted file mode 100644 index 07bfb2814..000000000 --- a/src/Math-Tests-Random/PMBinomialGeneratorTest.class.st +++ /dev/null @@ -1,57 +0,0 @@ -Class { - #name : #PMBinomialGeneratorTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #tests } -PMBinomialGeneratorTest >> testBinomialGeneratorWithSuccessProbabilityOfOneAlwaysReturnNumberOfTrials [ - | g numberOfTrials | - g := PMBinomialGenerator new. - numberOfTrials := 10. - g - numberOfTrials: numberOfTrials; - probability: 1.0. - g generator: PMLinearCongruentialRandomGenerator new. - self assert: g next equals: numberOfTrials. - g generator: PMLehmerRandomGenerator new. - self assert: g next equals: numberOfTrials. - g generator: PMMersenneTwisterRandomGenerator new. - self assert: g next equals: numberOfTrials -] - -{ #category : #tests } -PMBinomialGeneratorTest >> testBinomialGeneratorWithSuccessProbabilityOfZeroAlwaysReturnZero [ - | g numberOfTrials | - g := PMBinomialGenerator new. - numberOfTrials := 10. - g - numberOfTrials: numberOfTrials; - probability: 0.0. - g generator: PMLinearCongruentialRandomGenerator new. - self assert: g next equals: 0. - g generator: PMLehmerRandomGenerator new. - self assert: g next equals: 0. - g generator: PMMersenneTwisterRandomGenerator new. - self assert: g next equals: 0 -] - -{ #category : #tests } -PMBinomialGeneratorTest >> testSampleMeanConvergesToExpectedValue [ - "Its purpose is to verify correct convergence of the binomial distribution, - should be Normal (np, np(1-p))" - - | gen sample probabilityOfSuccess numberOfTrials | - probabilityOfSuccess := (Random seed: 0.0) next sqrt. - numberOfTrials := 1000. - gen := PMBinomialGenerator - numberOfTrials: numberOfTrials - probabilityOfSuccess: probabilityOfSuccess. - - sample := PMRandomSample - ofSize: numberOfTrials - usingGenerator: gen. - self assert: sample min > (gen expectedValue * (1 - 0.2)). - self assert: sample max < (gen expectedValue * (1 + 0.2)). - self assert: (sample average - gen expectedValue) abs < 5 -] diff --git a/src/Math-Tests-Random/PMConstantGeneratorTest.class.st b/src/Math-Tests-Random/PMConstantGeneratorTest.class.st deleted file mode 100644 index 668de05cb..000000000 --- a/src/Math-Tests-Random/PMConstantGeneratorTest.class.st +++ /dev/null @@ -1,17 +0,0 @@ -Class { - #name : #PMConstantGeneratorTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #tests } -PMConstantGeneratorTest >> testConstantGenerator [ - | g | - g := PMConstantGenerator new. - g constant: 1. - self assert: g next equals: g next. - self assert: g next equals: g next. - self assert: g next equals: 1. - g := PMConstantGenerator constant: 2. - self assert: g next equals: 2 -] diff --git a/src/Math-Tests-Random/PMExponentialGeneratorTest.class.st b/src/Math-Tests-Random/PMExponentialGeneratorTest.class.st deleted file mode 100644 index 855788f63..000000000 --- a/src/Math-Tests-Random/PMExponentialGeneratorTest.class.st +++ /dev/null @@ -1,41 +0,0 @@ -" -A PMExponentialGeneratorTest is a test class for testing the behavior of PMExponentialGenerator -" -Class { - #name : #PMExponentialGeneratorTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #tests } -PMExponentialGeneratorTest >> testGenerator [ - | eg | - eg := PMExponentialGenerator new. - self - assert: (eg generator isKindOf: PMExponentialGenerator defaultGeneratorClass). - self assert: (eg generator isKindOf: PMPseudoRandomNumberGenerator). - eg generator: PMMersenneTwisterRandomGenerator new. - self assert: (eg generator isKindOf: PMMersenneTwisterRandomGenerator). - self assert: (eg next isKindOf: Number) -] - -{ #category : #tests } -PMExponentialGeneratorTest >> testPeekIsIdempotent [ - | eg | - eg := PMExponentialGenerator new. - self assert: eg peek equals: eg peek. - self assert: eg peek equals: eg next -] - -{ #category : #tests } -PMExponentialGeneratorTest >> testSampleMeanConvergesToExpectedValue [ - "testing a random sample seems suspect. We use a 5% interval here" - - | gen sample | - gen := PMExponentialGenerator mean: 10. - - sample := PMRandomSample ofSize: 10000 usingGenerator: gen. - - self - assert: (sample average between: gen expectedValue * 0.95 and: gen expectedValue * 1.05) -] diff --git a/src/Math-Tests-Random/PMFishmanMooreRandomGeneratorTest.class.st b/src/Math-Tests-Random/PMFishmanMooreRandomGeneratorTest.class.st deleted file mode 100644 index 100862dee..000000000 --- a/src/Math-Tests-Random/PMFishmanMooreRandomGeneratorTest.class.st +++ /dev/null @@ -1,16 +0,0 @@ -Class { - #name : #PMFishmanMooreRandomGeneratorTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #tests } -PMFishmanMooreRandomGeneratorTest >> testNext [ - | random expectedNumbers | - random := PMFishmanMooreRandomGenerator new. - random seed: 2147483646. - expectedNumbers := #(0.6540424017 0.2032902977 0.1634123433 0.0948051145 0.1617738056 0.6769099178 0.4410270808 0.0819611824 0.3259203002 0.9101976547). - (1 to: expectedNumbers size) - with: expectedNumbers - do: [ :i :expected | self assert: random next closeTo: expected ] -] diff --git a/src/Math-Tests-Random/PMGaussianGeneratorTest.class.st b/src/Math-Tests-Random/PMGaussianGeneratorTest.class.st deleted file mode 100644 index e919251f9..000000000 --- a/src/Math-Tests-Random/PMGaussianGeneratorTest.class.st +++ /dev/null @@ -1,41 +0,0 @@ -Class { - #name : #PMGaussianGeneratorTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #utilities } -PMGaussianGeneratorTest >> assertSampleGeneratedBy: aGenerator convergesToExpectedValue: expectedValue andStandardDeviation: stdDeviation [ - | sample | - sample := PMRandomSample ofSize: 10000 usingGenerator: aGenerator. - self assert: (expectedValue - sample average) abs <= 0.2. - self assert: (sample stdev - stdDeviation) abs <= 1 -] - -{ #category : #tests } -PMGaussianGeneratorTest >> testSampleMeanAndStandardDeviationConvergeToDistributionValues [ - | mean standardDeviation g | - mean := 147. - standardDeviation := 17. - g := PMGaussianGenerator new. - g - mean: mean; - standardDeviation: standardDeviation; - generator: PMLinearCongruentialRandomGenerator new. - g generator seed: 42. - - self - assertSampleGeneratedBy: g - convergesToExpectedValue: mean - andStandardDeviation: standardDeviation. - "Replicated test in a different place" - mean := 0. - standardDeviation := 10. - g - mean: mean; - standardDeviation: standardDeviation. - self - assertSampleGeneratedBy: g - convergesToExpectedValue: mean - andStandardDeviation: standardDeviation -] diff --git a/src/Math-Tests-Random/PMLehmerRandomTest.class.st b/src/Math-Tests-Random/PMLehmerRandomTest.class.st deleted file mode 100644 index 55740df49..000000000 --- a/src/Math-Tests-Random/PMLehmerRandomTest.class.st +++ /dev/null @@ -1,28 +0,0 @@ -Class { - #name : #PMLehmerRandomTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #tests } -PMLehmerRandomTest >> testNextBetweenZeroAndOne [ - | g | - g := PMLehmerRandomGenerator new. - 1000 - timesRepeat: [ self assert: g next > 0. - self assert: g next < 1 ] -] - -{ #category : #tests } -PMLehmerRandomTest >> testPeekAnswersSameAsNext [ - | g | - g := PMLehmerRandomGenerator new. - self assert: g peek equals: g next -] - -{ #category : #tests } -PMLehmerRandomTest >> testPeekIsIdempotent [ - | g | - g := PMLehmerRandomGenerator new. - self assert: g peek equals: g peek -] diff --git a/src/Math-Tests-Random/PMLinearCongruentialRandomTest.class.st b/src/Math-Tests-Random/PMLinearCongruentialRandomTest.class.st deleted file mode 100644 index 08ae003cb..000000000 --- a/src/Math-Tests-Random/PMLinearCongruentialRandomTest.class.st +++ /dev/null @@ -1,28 +0,0 @@ -Class { - #name : #PMLinearCongruentialRandomTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #tests } -PMLinearCongruentialRandomTest >> testNextBetweenZeroAndOne [ - | g | - g := PMLinearCongruentialRandomGenerator new. - 1000 - timesRepeat: [ self assert: g next >= 0. - self assert: g next <= 1 ] -] - -{ #category : #tests } -PMLinearCongruentialRandomTest >> testPeekAnswersSameAsNext [ - | g | - g := PMLinearCongruentialRandomGenerator new. - self assert: g peek equals: g next -] - -{ #category : #tests } -PMLinearCongruentialRandomTest >> testPeekIsIdempotent [ - | g | - g := PMLinearCongruentialRandomGenerator new. - self assert: g peek equals: g peek -] diff --git a/src/Math-Tests-Random/PMMersenneTwisterRandomTest.class.st b/src/Math-Tests-Random/PMMersenneTwisterRandomTest.class.st deleted file mode 100644 index 8555b7777..000000000 --- a/src/Math-Tests-Random/PMMersenneTwisterRandomTest.class.st +++ /dev/null @@ -1,42 +0,0 @@ -Class { - #name : #PMMersenneTwisterRandomTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #tests } -PMMersenneTwisterRandomTest >> testNext10BetweenZeroAndTen [ - | g | - g := PMMersenneTwisterRandomGenerator new. - 1000 - timesRepeat: [ | value | - value := g next. - self assert: value > 0. - self assert: value < 10 ] -] - -{ #category : #tests } -PMMersenneTwisterRandomTest >> testNextBetweenZeroAndOne [ - | g | - g := PMMersenneTwisterRandomGenerator new. - 1000 - timesRepeat: [ self assert: g next > 0. - self assert: g next < 1 ] -] - -{ #category : #tests } -PMMersenneTwisterRandomTest >> testNextFloatExcludeUpper [ - "this revealed a bug in early versions, excludeUpper was producing between 0 and 2" - - | g sample1 sample2 | - g := PMMersenneTwisterRandomGenerator new. - sample1 := Array new: 10000. - sample2 := Array new: 10000. - 1 to: 10000 do: [ :i | - sample1 at: i put: g nextFloatExcludeUpper. - sample2 at: i put: (g nextFloatExcludeUpper: 2) ]. - self assert: sample1 max < 1. - self shouldnt: [ sample1 max < 0.8 ]. - self assert: sample2 max < 2. - self shouldnt: [ sample2 max < 1.6 ] -] diff --git a/src/Math-Tests-Random/PMNumberGeneratorTest.class.st b/src/Math-Tests-Random/PMNumberGeneratorTest.class.st deleted file mode 100644 index 82c45070b..000000000 --- a/src/Math-Tests-Random/PMNumberGeneratorTest.class.st +++ /dev/null @@ -1,19 +0,0 @@ -Class { - #name : #PMNumberGeneratorTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #tests } -PMNumberGeneratorTest >> testPeekIsIdempotent [ - "every subclass should implement some basic behavior." - - PMNumberGenerator subclasses - do: [ :ea | - | random numberGenerator | - numberGenerator := ea new. - 10 - timesRepeat: [ random := numberGenerator peek. - self assert: random equals: numberGenerator peek. - self assert: random equals: numberGenerator next ] ] -] diff --git a/src/Math-Tests-Random/PMPoissonGeneratorTest.class.st b/src/Math-Tests-Random/PMPoissonGeneratorTest.class.st deleted file mode 100644 index d4d89644b..000000000 --- a/src/Math-Tests-Random/PMPoissonGeneratorTest.class.st +++ /dev/null @@ -1,44 +0,0 @@ -Class { - #name : #PMPoissonGeneratorTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #tests } -PMPoissonGeneratorTest >> testPeekIsIdempotent [ - | poisson | - poisson := PMPoissonGenerator lambda: 0.1. - self assert: poisson peek equals: poisson peek -] - -{ #category : #tests } -PMPoissonGeneratorTest >> testPeekReturnsSameAsNext [ - | poisson | - poisson := PMPoissonGenerator lambda: 0.1. - self assert: poisson peek equals: poisson next -] - -{ #category : #tests } -PMPoissonGeneratorTest >> testPeekWorksAfterSampling [ - | poisson random | - poisson := PMPoissonGenerator lambda: 0.1. - 1 to: 100 do: [ :ea | poisson next ]. - random := poisson peek. - self assert: random equals: poisson peek. - self assert: random equals: poisson next -] - -{ #category : #tests } -PMPoissonGeneratorTest >> testSampleMeanConvergesToExpectedValue [ - "law of large numbers" - - "made non-random, old random version in comments" - - | gen sample | - gen := PMPoissonGenerator lambda: 5. - "added for non-randomness" - gen generator seed: 42. - - sample := PMRandomSample ofSize: 1000 usingGenerator: gen. - self assert: (sample average between: (gen expectedValue * 0.8) and: (gen expectedValue * 1.2)) -] diff --git a/src/Math-Tests-Random/PMPseudoRandomNumberGeneratorTest.class.st b/src/Math-Tests-Random/PMPseudoRandomNumberGeneratorTest.class.st deleted file mode 100644 index 7145cc0d5..000000000 --- a/src/Math-Tests-Random/PMPseudoRandomNumberGeneratorTest.class.st +++ /dev/null @@ -1,75 +0,0 @@ -Class { - #name : #PMPseudoRandomNumberGeneratorTest, - #superclass : #TestCase, - #category : #'Math-Tests-Random' -} - -{ #category : #private } -PMPseudoRandomNumberGeneratorTest >> pseudoRandomNumberGeneratorsDo: aBlock [ - "Instanciates a pseudo random number generator - to yield to the block" - - PMPseudoRandomNumberGenerator subclasses - do: [ :typeOfGenerator | - | generator | - generator := typeOfGenerator new. - aBlock value: generator ] -] - -{ #category : #tests } -PMPseudoRandomNumberGeneratorTest >> testGeneratorStreamDoesntRespondToContents [ - self - pseudoRandomNumberGeneratorsDo: [ :gen | self should: [ gen contents ] raise: Error ] -] - -{ #category : #tests } -PMPseudoRandomNumberGeneratorTest >> testGeneratorStreamIsReadOnly [ - self - pseudoRandomNumberGeneratorsDo: [ :gen | - self shouldnt: [ gen isWriteable ]. - self assert: gen isReadable ] -] - -{ #category : #tests } -PMPseudoRandomNumberGeneratorTest >> testGeneratorStreamNeverEnds [ - self - pseudoRandomNumberGeneratorsDo: [ :gen | self shouldnt: [ gen atEnd ] ] -] - -{ #category : #tests } -PMPseudoRandomNumberGeneratorTest >> testGeneratorStreamPeekIsNext [ - self - pseudoRandomNumberGeneratorsDo: [ :gen | - | value | - value := gen peek. - self assert: gen peek equals: value. - self assert: gen next equals: value ] -] - -{ #category : #tests } -PMPseudoRandomNumberGeneratorTest >> testGeneratorStreamProducesNumbers [ - self - pseudoRandomNumberGeneratorsDo: [ :gen | - self assert: gen next isNumber. - self assert: gen next isFloat ] -] - -{ #category : #tests } -PMPseudoRandomNumberGeneratorTest >> testGeneratorStreamProducesRandomNumbers [ - self - pseudoRandomNumberGeneratorsDo: [ :gen | - | value | - value := gen next. - self shouldnt: [ gen next = value ] ] -] - -{ #category : #tests } -PMPseudoRandomNumberGeneratorTest >> testNextGivesArrayOfNumbers [ - self - pseudoRandomNumberGeneratorsDo: [ :gen | - | samples | - samples := gen next: 10. - self assert: samples size equals: 10. - self assert: (samples at: 1) isFloat. - self assert: samples asSet size equals: 10 ] -] diff --git a/src/Math-Tests-Random/PMRandomSample.class.st b/src/Math-Tests-Random/PMRandomSample.class.st deleted file mode 100644 index de60a8386..000000000 --- a/src/Math-Tests-Random/PMRandomSample.class.st +++ /dev/null @@ -1,21 +0,0 @@ -" -I generate sample numerical data for the convergence tests given a size and distribution/PRNG - -messages: - - generateASampleOfSize: size usingGenerator:gen -" -Class { - #name : #PMRandomSample, - #superclass : #Object, - #category : #'Math-Tests-Random' -} - -{ #category : #tests } -PMRandomSample class >> ofSize: size usingGenerator: gen [ - "Generates sample data given a distribution" - | sample | - sample := OrderedCollection new. - size timesRepeat: [ sample add: gen next ]. - ^ sample - -] diff --git a/src/Math-Tests-Random/package.st b/src/Math-Tests-Random/package.st deleted file mode 100644 index ccd3a7065..000000000 --- a/src/Math-Tests-Random/package.st +++ /dev/null @@ -1 +0,0 @@ -Package { #name : #'Math-Tests-Random' }