From f365f19054cefe6b95041d3111edc37117f3e2cb Mon Sep 17 00:00:00 2001 From: drbrain Date: Wed, 5 Oct 2011 23:54:33 +0000 Subject: [PATCH] * random.c: Improve documentation of Random. Patch by Gregory Parkhurst. [Ruby 1.9 - Bug #5410] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33413 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 ++ random.c | 201 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 134 insertions(+), 72 deletions(-) diff --git a/ChangeLog b/ChangeLog index 14f6791541..f425cf1bb3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu Oct 6 08:54:05 2011 Eric Hodel + + * random.c: Improve documentation of Random. Patch by Gregory + Parkhurst. [Ruby 1.9 - Bug #5410] + Thu Oct 6 01:44:51 2011 CHIKANAGA Tomoyuki * cont.c (cont_mark): mark original Thread object from saved_thread. diff --git a/random.c b/random.c index 0f7a379756..5b5ae7f273 100644 --- a/random.c +++ b/random.c @@ -450,20 +450,14 @@ rand_init(struct MT *mt, VALUE vseed) } /* - * call-seq: Random.new([seed]) -> prng + * call-seq: + * Random.new() -> prng + * Random.new(seed) -> prng * - * Creates new Mersenne Twister based pseudorandom number generator with - * seed. When the argument seed is omitted, the generator is initialized - * with Random.new_seed. + * Creates a new PRNG using +seed+ to set the initial state. If +seed+ is + * omitted, the generator is initialized with Random.new_seed. * - * The argument seed is used to ensure repeatable sequences of random numbers - * between different runs of the program. - * - * prng = Random.new(1234) - * [ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832] - * [ prng.integer(10), prng.integer(1000) ] #=> [4, 664] - * prng = Random.new(1234) - * [ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832] + * See Random.srand for more information on the use of seed values. */ static VALUE random_init(int argc, VALUE *argv, VALUE obj) @@ -569,7 +563,10 @@ make_seed_value(const void *ptr) /* * call-seq: Random.new_seed -> integer * - * Returns arbitrary value for seed. + * Returns an arbitrary seed value. This is used by Random.new + * when no seed value is specified as an argument. + * + * Random.new_seed #=> 115032730400174366788466674494640623225 */ static VALUE random_seed(void) @@ -582,7 +579,16 @@ random_seed(void) /* * call-seq: prng.seed -> integer * - * Returns the seed of the generator. + * Returns the seed value used to initialize the generator. This may be used to + * initialize another generator with the same state at a later time, causing it + * to produce the same sequence of numbers. + * + * prng1 = Random.new(1234) + * prng1.seed #=> 1234 + * prng1.rand(100) #=> 47 + * + * prng2 = Random.new(prng1.seed) + * prng2.rand(100) #=> 47 */ static VALUE random_get_seed(VALUE obj) @@ -758,17 +764,26 @@ random_load(VALUE obj, VALUE dump) } /* - * call-seq: - * srand(number=0) -> old_seed + * call-seq: + * srand(number=0) -> old_seed * - * Seeds the pseudorandom number generator to the value of - * number. If number is omitted, - * seeds the generator using a combination of the time, the - * process id, and a sequence number. (This is also the behavior if - * Kernel::rand is called without previously calling - * srand, but without the sequence.) By setting the seed - * to a known value, scripts can be made deterministic during testing. - * The previous seed value is returned. Also see Kernel::rand. + * Seeds the system pseudo-random number generator, Random::DEFAULT, with + * +number+. The previous seed value is returned. + * + * If +number+ is omitted, seeds the generator using a source of entropy + * provided by the operating system, if available (/dev/urandom on Unix systems + * or the RSA cryptographic provider on Windows), which is then combined with + * the time, the process id, and a sequence number. + * + * srand may be used to ensure repeatable sequences of pseudo-random numbers + * between different runs of the program. By setting the seed to a known value, + * programs can be made deterministic during testing. + * + * srand 1234 # => 268519324636777531569100071560086917274 + * [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319] + * [ rand(10), rand(1000) ] # => [4, 664] + * srand 1234 # => 1234 + * [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319] */ static VALUE @@ -878,9 +893,9 @@ limited_big_rand(struct MT *mt, struct RBignum *limit) } /* - * Returns random unsigned long value in [0, _limit_]. + * Returns random unsigned long value in [0, +limit+]. * - * Note that _limit_ is included, and the range of the argument and the + * Note that +limit+ is included, and the range of the argument and the * return value depends on environments. */ unsigned long @@ -924,8 +939,10 @@ rb_random_real(VALUE obj) /* * call-seq: prng.bytes(size) -> a_string * - * Returns a random binary string. The argument size specified the length of - * the result string. + * Returns a random binary string containing +size+ bytes. + * + * random_string = Random.new.bytes(10) # => "\xD7:R\xAB?\x83\xCE\xFAkO" + * random_string.size # => 10 */ static VALUE random_bytes(VALUE obj, VALUE len) @@ -1111,27 +1128,32 @@ rand_range(struct MT* mt, VALUE range) /* * call-seq: - * prng.rand -> float - * prng.rand(limit) -> number + * prng.rand -> float + * prng.rand(max) -> number * - * When the argument is an +Integer+ or a +Bignum+, it returns a - * random integer greater than or equal to zero and less than the - * argument. Unlike Random.rand, when the argument is a negative - * integer or zero, it raises an ArgumentError. + * When +max+ is an Integer, +rand+ returns a random integer greater than + * or equal to zero and less than +max+. Unlike Kernel.rand, when +max+ + * is a negative integer or zero, +rand+ raises an ArgumentError. * - * When the argument is a +Float+, it returns a random floating point - * number between 0.0 and _max_, including 0.0 and excluding _max_. + * prng = Random.new + * prng.rand(100) # => 42 * - * When the argument _limit_ is a +Range+, it returns a random - * number where range.member?(number) == true. - * prng.rand(5..9) #=> one of [5, 6, 7, 8, 9] - * prng.rand(5...9) #=> one of [5, 6, 7, 8] - * prng.rand(5.0..9.0) #=> between 5.0 and 9.0, including 9.0 - * prng.rand(5.0...9.0) #=> between 5.0 and 9.0, excluding 9.0 + * When +max+ is a Float, +rand+ returns a random floating point number + * between 0.0 and +max+, including 0.0 and excluding +max+. * - * +begin+/+end+ of the range have to have subtract and add methods. + * prng.rand(1.5) # => 1.4600282860034115 * - * Otherwise, it raises an ArgumentError. + * When +max+ is a Range, +rand+ returns a random number where + * range.member?(number) == true. + * + * prng.rand(5..9) # => one of [5, 6, 7, 8, 9] + * prng.rand(5...9) # => one of [5, 6, 7, 8] + * prng.rand(5.0..9.0) # => between 5.0 and 9.0, including 9.0 + * prng.rand(5.0...9.0) # => between 5.0 and 9.0, excluding 9.0 + * + * Both the beginning and ending values of the range must respond to subtract + * (-) and add (+)methods, or rand will raise an + * ArgumentError. */ static VALUE random_rand(int argc, VALUE *argv, VALUE obj) @@ -1177,9 +1199,27 @@ random_rand(int argc, VALUE *argv, VALUE obj) /* * call-seq: - * prng1 == prng2 -> true or false + * prng1 == prng2 -> true or false * - * Returns true if the generators' states equal. + * Returns true if the two generators have the same internal state, otherwise + * false. Equivalent generators will return the same sequence of + * pseudo-random numbers. Two generators will generally have the same state + * only if they were initialized with the same seed + * + * Random.new == Random.new # => false + * Random.new(1234) == Random.new(1234) # => true + * + * and have the same invocation history. + * + * prng1 = Random.new(1234) + * prng2 = Random.new(1234) + * prng1 == prng2 # => true + * + * prng1.rand # => 0.1915194503788923 + * prng1 == prng2 # => false + * + * prng2.rand # => 0.1915194503788923 + * prng1 == prng2 # => true */ static VALUE random_equal(VALUE self, VALUE other) @@ -1196,31 +1236,32 @@ random_equal(VALUE self, VALUE other) } /* - * call-seq: - * rand(max=0) -> number + * call-seq: + * rand(max=0) -> number * + * If called without an argument, or if max.to_i.abs == 0, rand + * returns a pseudo-random floating point number between 0.0 and 1.0, + * including 0.0 and excluding 1.0. * - * If max is +Range+, returns a pseudorandom number where - * range.member(number) == true. + * rand #=> 0.2725926052826416 * - * Or else converts _max_ to an integer using max1 = - * max.to_i.abs. + * When max.abs is greater than or equal to 1, +rand+ returns a + * pseudo-random integer greater than or equal to 0 and less than + * max.to_i.abs. * - * Then if _max_ is +nil+ the result is zero, returns a pseudorandom floating - * point number greater than or equal to 0.0 and less than 1.0. + * rand(100) #=> 12 * - * Otherwise, returns a pseudorandom integer greater than or equal to zero and - * less than max1. + * Negative or floating point values for +max+ are allowed, but may give + * surprising results. * - * Kernel::srand may be used to ensure repeatable sequences of - * random numbers between different runs of the program. Ruby currently uses - * a modified Mersenne Twister with a period of 2**19937-1. + * rand(-100) # => 87 + * rand(-0.5) # => 0.8130921818028143 + * rand(1.9) # equivalent to rand(1), which is always 0 * - * srand 1234 #=> 0 - * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136] - * [ rand(10), rand(1000) ] #=> [6, 817] - * srand 1234 #=> 1234 - * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136] + * Kernel.srand may be used to ensure that sequences of random numbers are + * reproducible between different runs of a program. + * + * See also Random.rand. */ static VALUE @@ -1244,12 +1285,11 @@ rb_f_rand(int argc, VALUE *argv, VALUE obj) } /* - * call-seq: - * Random.rand -> float - * Random.rand(limit) -> number - * - * Alias of _Random::DEFAULT.rand_. + * call-seq: + * Random.rand -> float + * Random.rand(max) -> number * + * Alias of Random::DEFAULT.rand. */ static VALUE @@ -1322,10 +1362,27 @@ rb_reset_random_seed(void) } /* - * Document-class: Random + * Document-class: Random * - * The Random module contains module functions for producing pseudo-random - * numbers that meet certain requirements for randomness. + * Random provides an interface to Ruby's pseudo-random number generator, or + * PRNG. The PRNG produces a deterministic sequence of bits which approximate + * true randomness. The sequence may be represented by integers, floats, or + * binary strings. + * + * The generator may be initialized with either a system-generated or + * user-supplied seed value by using Random.srand. + * + * The class method Random.rand provides the base functionality of Kernel.rand + * along with better handling of floating point values. These are both + * interfaces to Random::DEFAULT, the Ruby system PRNG. + * + * Random.new will create a new PRNG with a state independent of + * Random::DEFAULT, allowing multiple generators with different seed values or + * sequence positions to exist simultaneously. Random objects can be + * marshaled, allowing sequences to be saved and resumed. + * + * PRNGs are currently implemented as a modified Mersenne Twister with a period + * of 2**19937-1. */ void