Add seed(InputRange) overload to MersenneTwisterEngine #627

Merged
merged 1 commit into from Jun 17, 2012

3 participants

@jpf91

Adds a new seed overload as discussed here: http://forum.dlang.org/thread/jr0luj$1ctj$1@digitalmars.com

@klickverbot
D Programming Language member

Maybe add the number of elements required to the error message and documentation?

@klickverbot
D Programming Language member

Also, you might want to add a note to the single integer overload, describing its limitations.

@jpf91

The the number of elements required is not fixed. It's 624 for Mt19937 but it seems it can be any value for MersenneTwisterEngine. But I added a basic description to the docs.

@klickverbot klickverbot commented on an outdated diff Jun 12, 2012
std/random.d
@@ -559,8 +559,11 @@ Parameter for the generator.
/**
Seeds a MersenneTwisterEngine object.
+ Note:
+ This seed function gives 2^32 starting points. To allow the RNG to be started in any one of its
+ 2^19,937 internal states use the seed overload taking an InputRange.
@klickverbot
D Programming Language member
klickverbot added a line comment Jun 12, 2012

2^19937 (-1) is only the period for Mt19937, not for MersenneTwisterEngine in general, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jpf91

Yes, you're right. Removed the 2^19937 note.

@jmdavis jmdavis commented on an outdated diff Jun 17, 2012
std/random.d
@@ -587,6 +590,37 @@ Parameter for the generator.
}
/**
+ Seeds a MersenneTwisterEngine object using an InputRange.
+
+ Throws:
+ $(D Exception) if the InputRange didn't provide enough elements to seed the generator.
+ The number of elements required is the 'n' template parameter of the MersenneTwisterEngine struct.
+
+ Examples:
+ ----------------
+ Mt19937 gen;
+ gen.seed(map!((a) => unpredictableSeed)(repeat(0)));
+ ----------------
+ */
+ void seed(T)(T range) if(isInputRange!T && is(Unqual!(ElementType!T) == UIntType))
+ {
+ int j;
@jmdavis
D Programming Language member
jmdavis added a line comment Jun 17, 2012

j is used for indexing mt and comparing against n (which is a size_t), so it should be size_t, not int.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jmdavis jmdavis commented on an outdated diff Jun 17, 2012
std/random.d
+ gen.seed(map!((a) => unpredictableSeed)(repeat(0)));
+ ----------------
+ */
+ void seed(T)(T range) if(isInputRange!T && is(Unqual!(ElementType!T) == UIntType))
+ {
+ int j;
+ for(j = 0; j < n && !range.empty; ++j, range.popFront())
+ {
+ mt[j] = range.front;
+ }
+
+ mti = n;
+ if(range.empty && j < n)
+ {
+ throw new Exception("MersenneTwisterEngine.seed: Input range didn't provide enough"
+ " elements: Need " ~ to!string(n) ~ " elements.");
@jmdavis
D Programming Language member
jmdavis added a line comment Jun 17, 2012

This should use format. It's cleaner and shorter that way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jmdavis jmdavis commented on an outdated diff Jun 17, 2012
std/random.d
@@ -698,6 +732,23 @@ unittest
unittest
{
+ Mt19937 gen;
+
+ bool thrown = false;
+ try
+ gen.seed(map!((a) => unpredictableSeed)(repeat(0, 623)));
+ catch(Exception)
+ thrown = true;
+
+ assert(thrown);
@jmdavis
D Programming Language member
jmdavis added a line comment Jun 17, 2012

Please use assertThrown.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jpf91

@jmdavis OK, implemented your suggested changes. rndGen is also using the new seed overload now. However, I had to slightly change isSeedable as well. Without that change, it's not possible to use isSeedable for the new seed overload.

@jpf91

Yes I should probably do that. Although adding the guarantee about Rng.front was wrong in the first place, but I didn't know that RNGs could be seeded with other types (I implemented isSeedable).

@jpf91

map doesn't work in CTFE yet. I think we can just leave that as is, as long as rndGen uses the new seed method and we document the problems with the old seed overload.

@jmdavis
D Programming Language member

If there's really no relation between the type of front and the type that's used to seed the range, then there should be no check for whether the type of front and the seed type are the same. I objected, because it was checking that, and you changed it so that it wasn't. Now, it's half-and-half. In one case it checks, and the other doesn't, which seems a bit off to me. So, if you're sure that there's not really any relation between front and the seed type (and the more I think about it, the more it seems like there wouldn't be), then isSeedable shouldn't be checking the type of front at all.

@jpf91

OK, I removed the check again. It doesn't really make sense and user code should always check isRandomRNG(Type, frontType) and isSeedable(SeedType).

@jmdavis jmdavis merged commit d6ffd58 into dlang:master Jun 17, 2012
@jmdavis
D Programming Language member

Merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment