import std.array, std.range, std.random, std.stdio, std.traits; import mtclass; struct Remainder(RNG) if(isUniformRNG!RNG) { private real _remaining, _u; private size_t _n; private RNG _gen; private bool _first; this(size_t n, RNG gen) { assert(n > 0); _n = n; _remaining = n; _gen = gen; _first = true; } this(typeof(this) source) { this._n = source._n; this._remaining = source._remaining; this._gen = source._gen; this._u = source._u; } bool empty() @property pure nothrow const { return _n == 0; } real front() @property { if(_first) { _first = false; prime(); } return _u; } void popFront() { assert(_n > 0); --_n; if(!empty) { if(_first) { prime(); } _first = true; } } typeof(this) save() @property { auto ret = typeof(this)(this); ret._gen = this._gen.save; return ret; } private void prime() { _u = uniform(0.0L, 1.0L, _gen); _remaining -= _u; } real remaining() @property { if(_first) { _first = false; prime(); } return _remaining; } } auto remainder()(size_t n) { return Remainder!Random(n, rndGen); /* Caution!! Won't really work with current Phobos * as rndGen is value type. This is how you'd do it * with all PRNGs corrected to being reference types. */ } auto remainder(RNG)(size_t n, RNG gen) if(isUniformRNG!RNG) { return Remainder!RNG(n, gen); } void main() { auto gen = new MtClass19937(unpredictableSeed); auto r1 = remainder(5, gen); writeln(" ", r1); writeln(" ", r1); writeln; auto r2 = remainder(5, gen); r2.front; writeln(" ", r2); writeln(" ", r2); writeln; auto r3 = remainder(5, gen); r3.remaining; writeln(" ", r3); writeln(" ", r3); writeln; auto r4 = remainder(5, gen); r4.popFront(); writeln(" ", r4); writeln(" ", r4); }