@@ -30,16 +30,13 @@ sealed abstract class Gen[+T] extends Serializable { self =>
30
30
31
31
import Gen .{R , gen }
32
32
33
- /** Just an alias */
34
- private type P = Gen .Parameters
35
-
36
33
// This is no longer used but preserved here for binary compatibility.
37
34
private [scalacheck] def sieveCopy (x : Any ): Boolean = true
38
35
39
36
// If you implement new Gen[_] directly (instead of using
40
37
// combinators), make sure to use p.initialSeed or p.useInitialSeed
41
38
// in the implementation, instead of using seed directly.
42
- private [scalacheck] def doApply (p : P , seed : Seed ): R [T ]
39
+ private [scalacheck] def doApply (p : Gen . Parameters , seed : Seed ): R [T ]
43
40
44
41
// // Public interface ////
45
42
@@ -106,7 +103,7 @@ sealed abstract class Gen[+T] extends Serializable { self =>
106
103
* This method is identical to [Gen.filter]. */
107
104
def suchThat (f : T => Boolean ): Gen [T ] =
108
105
new Gen [T ] {
109
- def doApply (p : P , seed : Seed ): Gen .R [T ] =
106
+ def doApply (p : Gen . Parameters , seed : Seed ): Gen .R [T ] =
110
107
p.useInitialSeed(seed) { (p0, s0) =>
111
108
val r = self.doApply(p0, s0)
112
109
r.copy(r = r.retrieve.filter(f))
@@ -126,7 +123,7 @@ sealed abstract class Gen[+T] extends Serializable { self =>
126
123
*/
127
124
def retryUntil (p : T => Boolean , maxTries : Int ): Gen [T ] = {
128
125
require(maxTries > 0 )
129
- def loop (params : P , seed : Seed , tries : Int ): R [T ] =
126
+ def loop (params : Gen . Parameters , seed : Seed , tries : Int ): R [T ] =
130
127
if (tries > maxTries) throw RetryUntilException (tries) else {
131
128
val r = self.doApply(params, seed)
132
129
if (r.retrieve.exists(p)) r else loop(params, r.seed, tries + 1 )
@@ -175,7 +172,7 @@ sealed abstract class Gen[+T] extends Serializable { self =>
175
172
176
173
/** Put a label on the generator to make test reports clearer */
177
174
def label (l : String ): Gen [T ] = new Gen [T ] {
178
- def doApply (p : P , seed : Seed ) =
175
+ def doApply (p : Gen . Parameters , seed : Seed ) =
179
176
p.useInitialSeed(seed) { (p0, s0) =>
180
177
val r = self.doApply(p0, s0)
181
178
r.copy(l = r.labels + l)
@@ -240,7 +237,7 @@ object Gen extends GenArities with GenVersionSpecific {
240
237
r(None , seed).copy(l = labels)
241
238
case Some (t) =>
242
239
val r = f(t)
243
- r.copy(l = labels | r.labels, sd = r.seed )
240
+ r.copy(l = labels | r.labels)
244
241
}
245
242
}
246
243
@@ -947,6 +944,158 @@ object Gen extends GenArities with GenVersionSpecific {
947
944
948
945
// // Number Generators ////
949
946
947
+ /**
948
+ * Generate a uniformly-distributed Long.
949
+ *
950
+ * This method has an equally likely method of generating every
951
+ * possible Long value.
952
+ */
953
+ val long : Gen [Long ] =
954
+ gen { (_, s0) =>
955
+ val (n, s1) = s0.long
956
+ r(Some (n), s1)
957
+ }
958
+
959
+ /**
960
+ * Generate a Double uniformly-distributed in [0, 1).
961
+ *
962
+ * This method will generate one of 2^53 distinct Double values in
963
+ * the unit interval.
964
+ */
965
+ val double : Gen [Double ] =
966
+ gen { (_, s0) =>
967
+ val (x, s1) = s0.double
968
+ r(Some (x), s1)
969
+ }
970
+
971
+ /**
972
+ * Generates a Boolean which has the given chance to be true.
973
+ *
974
+ * - prob(1.0) is always true
975
+ * - prob(0.5) is true 50% of the time
976
+ * - prob(0.1) is true 10% of the time
977
+ * - prob(0.0) is never true
978
+ */
979
+ def prob (chance : Double ): Gen [Boolean ] =
980
+ if (chance <= 0.0 ) Gen .const(false )
981
+ else if (chance >= 1.0 ) Gen .const(true )
982
+ else gen { (_, s0) =>
983
+ val (x, s1) = s0.double
984
+ r(Some (x < chance), s1)
985
+ }
986
+
987
+ /**
988
+ * Generates Double values according to the given gaussian
989
+ * distribution, specified by its mean and standard deviation.
990
+ *
991
+ * Gaussian distributions are also called normal distributions.
992
+ *
993
+ * The range of values is theoretically (-∞, ∞) but 99.7% of all
994
+ * values will be contained within (mean ± 3 * stdDev).
995
+ */
996
+ def gaussian (mean : Double , stdDev : Double ): Gen [Double ] = {
997
+ def loop (s0 : Seed ): R [Double ] = {
998
+ val (x0, s1) = s0.double
999
+ val (y0, s2) = s1.double
1000
+ val x = x0 * 2.0 - 1.0
1001
+ val y = y0 * 2.0 - 1.0
1002
+ val s = x * x + y * y
1003
+ if (s >= 1.0 || s == 0.0 ) {
1004
+ loop(s2)
1005
+ } else {
1006
+ val scale = stdDev * Math .sqrt(- 2.0 * Math .log(s) / s)
1007
+ val res = x * scale + mean // dropping y * scale + mean
1008
+ r(Some (res), s2)
1009
+ }
1010
+ }
1011
+ gen((_, seed) => loop(seed))
1012
+ }
1013
+
1014
+ /**
1015
+ * Generates Double values according to the given exponential
1016
+ * distribution, specified by its rate parameter.
1017
+ *
1018
+ * The mean and standard deviation are both equal to 1/rate.
1019
+ *
1020
+ * The range of values is [0, ∞).
1021
+ */
1022
+ def exponential (rate : Double ): Gen [Double ] = {
1023
+ require(rate > 0.0 , s " rate must be positive (got: $rate) " )
1024
+ val mean = 1.0 / rate
1025
+ gen { (_, s0) =>
1026
+ val (x, s1) = s0.double
1027
+ r(Some (- Math .log(x) * mean), s1)
1028
+ }
1029
+ }
1030
+
1031
+ /**
1032
+ * Generates Int values according to the given geometric
1033
+ * distribution, specified by its mean.
1034
+ *
1035
+ * This distribution represents the expected number of failures
1036
+ * before a successful test, where the probability of a successful
1037
+ * test is p = 1 / (mean + 1).
1038
+ *
1039
+ * The ideal range of values is [0, ∞), although the largest value
1040
+ * that can be produced here is 2147483647 (Int.MaxValue).
1041
+ */
1042
+ def geometric (mean : Double ): Gen [Int ] = {
1043
+ require(mean > 0.0 , s " mean must be positive (got: $mean) " )
1044
+ val p = 1.0 / (mean + 1.0 )
1045
+ val lognp = Math .log1p(- p) // log(1 - p)
1046
+ gen { (_, s0) =>
1047
+ val (u, s1) = s0.double
1048
+ r(Some (Math .floor(Math .log(u) / lognp).toInt), s1)
1049
+ }
1050
+ }
1051
+
1052
+ /**
1053
+ * Generates Int values according to the given Poisson distribution,
1054
+ * specified by its rate parameters.
1055
+ *
1056
+ * The mean equals the rate; the standard deviation is sqrt(rate).
1057
+ *
1058
+ * In principle any positive value is a valid rate parameter.
1059
+ * However, our method of generating values cannot handle large
1060
+ * rates, so we require rate <= 745.
1061
+ */
1062
+ def poisson (rate : Double ): Gen [Int ] = {
1063
+ require(0 < rate && rate <= 745.0 , s " rate must be between 0 and 745 (got $rate) " )
1064
+ val L = Math .exp(- rate)
1065
+ def loop (s0 : Seed , k : Int , p : Double ): R [Int ] =
1066
+ if (p <= L ) {
1067
+ r(Some (k - 1 ), s0)
1068
+ } else {
1069
+ val (x, s1) = s0.double
1070
+ loop(s1, k + 1 , p * x)
1071
+ }
1072
+
1073
+ gen((_, s) => loop(s, 0 , 1.0 ))
1074
+ }
1075
+
1076
+ /**
1077
+ * Generates Int values according to the given binomial
1078
+ * distribution, specified by the number of trials to conduct, and
1079
+ * the probability of a true test.
1080
+ *
1081
+ * This distribution counts the number of trials which were
1082
+ * successful according to a given test probability.
1083
+ *
1084
+ * The range of values is [0, trials].
1085
+ */
1086
+ def binomial (test : Gen [Boolean ], trials : Int ): Gen [Int ] = {
1087
+ def loop (ps : Gen .Parameters , s : Seed , i : Int , n : Int ): R [Int ] =
1088
+ if (i >= trials) {
1089
+ r(Some (n), s)
1090
+ } else {
1091
+ val r = test.doPureApply(ps, s)
1092
+ val success = r.retrieve.get
1093
+ loop(ps, r.seed, i + 1 , if (success) n + 1 else n)
1094
+ }
1095
+ gen((ps, s) => loop(ps, s, 0 , 0 ))
1096
+ }
1097
+
1098
+
950
1099
/** Generates positive numbers of uniform distribution, with an
951
1100
* upper bound of the generation size parameter. */
952
1101
def posNum [T ](implicit num : Numeric [T ], c : Choose [T ]): Gen [T ] = {
0 commit comments