Add seed(InputRange) overload to MersenneTwisterEngine #627

Merged
merged 1 commit into from Jun 17, 2012

Projects

None yet

3 participants

@jpf91
jpf91 commented Jun 12, 2012

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

@klickverbot
Member

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

@klickverbot
Member

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

@jpf91
jpf91 commented Jun 12, 2012

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
klickverbot Jun 12, 2012 D Programming Language member

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

@jpf91
jpf91 commented Jun 13, 2012

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
jmdavis Jun 17, 2012 D Programming Language member

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

@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
jmdavis Jun 17, 2012 D Programming Language member

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

@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
jmdavis Jun 17, 2012 D Programming Language member

Please use assertThrown.

@jpf91
jpf91 commented Jun 17, 2012

@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
jpf91 commented Jun 17, 2012

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
jpf91 commented Jun 17, 2012

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
Member
jmdavis commented Jun 17, 2012

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
jpf91 commented Jun 17, 2012

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
Member
jmdavis commented Jun 17, 2012

Merged.

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