@@ -2160,16 +2160,21 @@ struct RandomCover(Range, UniformRNG = void)
21602160 private bool [] _chosen;
21612161 private size_t _current;
21622162 private size_t _alreadyChosen = 0 ;
2163+ private bool _isEmpty = false ;
21632164
21642165 static if (is (UniformRNG == void ))
21652166 {
21662167 this (Range input)
21672168 {
21682169 _input = input;
21692170 _chosen.length = _input.length;
2170- if (_chosen.length == 0 )
2171+ if (_input.empty )
21712172 {
2172- _alreadyChosen = 1 ;
2173+ _isEmpty = true ;
2174+ }
2175+ else
2176+ {
2177+ _current = uniform(0 , _chosen.length);
21732178 }
21742179 }
21752180 }
@@ -2182,9 +2187,13 @@ struct RandomCover(Range, UniformRNG = void)
21822187 _input = input;
21832188 _rng = rng;
21842189 _chosen.length = _input.length;
2185- if (_chosen.length == 0 )
2190+ if (_input.empty)
2191+ {
2192+ _isEmpty = true ;
2193+ }
2194+ else
21862195 {
2187- _alreadyChosen = 1 ;
2196+ _current = uniform( 0 , _chosen.length, rng) ;
21882197 }
21892198 }
21902199
@@ -2198,39 +2207,32 @@ struct RandomCover(Range, UniformRNG = void)
21982207 {
21992208 @property size_t length()
22002209 {
2201- if (_alreadyChosen == 0 )
2202- {
2203- return _input.length;
2204- }
2205- else
2206- {
2207- return (1 + _input.length) - _alreadyChosen;
2208- }
2210+ return _input.length - _alreadyChosen;
22092211 }
22102212 }
22112213
22122214 @property auto ref front()
22132215 {
2214- if (_alreadyChosen == 0 )
2215- {
2216- popFront();
2217- }
2216+ assert (! _isEmpty);
22182217 return _input[_current];
22192218 }
22202219
22212220 void popFront ()
22222221 {
2223- if (_alreadyChosen >= _input.length)
2222+ assert (! _isEmpty);
2223+
2224+ size_t k = _input.length - _alreadyChosen - 1 ;
2225+ if (k == 0 )
22242226 {
2225- // No more elements
2226- ++ _alreadyChosen; // means we're done
2227+ _isEmpty = true ;
2228+ ++ _alreadyChosen;
22272229 return ;
22282230 }
2229- size_t k = _input.length - _alreadyChosen;
2231+
22302232 size_t i;
22312233 foreach (e; _input)
22322234 {
2233- if (_chosen[i]) { ++ i; continue ; }
2235+ if (_chosen[i] || i == _current ) { ++ i; continue ; }
22342236 // Roll a dice with k faces
22352237 static if (is (UniformRNG == void ))
22362238 {
@@ -2243,7 +2245,7 @@ struct RandomCover(Range, UniformRNG = void)
22432245 assert (k > 1 || chooseMe);
22442246 if (chooseMe)
22452247 {
2246- _chosen[i ] = true ;
2248+ _chosen[_current ] = true ;
22472249 _current = i;
22482250 ++ _alreadyChosen;
22492251 return ;
@@ -2264,7 +2266,7 @@ struct RandomCover(Range, UniformRNG = void)
22642266 }
22652267 }
22662268
2267- @property bool empty() { return _alreadyChosen > _input.length ; }
2269+ @property bool empty() { return _isEmpty ; }
22682270}
22692271
22702272// / Ditto
@@ -2286,6 +2288,7 @@ auto randomCover(Range)(Range r)
22862288 import std.algorithm ;
22872289 import std.conv ;
22882290 int [] a = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ];
2291+ int [] c;
22892292 foreach (UniformRNG; std.meta.AliasSeq ! (void , PseudoRngTypes))
22902293 {
22912294 static if (is (UniformRNG == void ))
@@ -2302,6 +2305,8 @@ auto randomCover(Range)(Range r)
23022305 // check for constructor passed a value-type RNG
23032306 auto rc2 = RandomCover! (int [], UniformRNG)(a, UniformRNG(unpredictableSeed));
23042307 static assert (isForwardRange! (typeof (rc2)));
2308+ auto rcEmpty = randomCover(c, rng);
2309+ assert (rcEmpty.length == 0 );
23052310 }
23062311
23072312 int [] b = new int [9 ];
@@ -2323,6 +2328,17 @@ auto randomCover(Range)(Range r)
23232328 auto rc = randomCover(r);
23242329 assert (rc.length == 0 );
23252330 assert (rc.empty);
2331+
2332+ // Bugzilla 16724
2333+ import std.range : iota;
2334+ auto range = iota(10 );
2335+ auto randy = range.randomCover;
2336+
2337+ for (int i=1 ; i<= range.length; i++ )
2338+ {
2339+ randy.popFront;
2340+ assert (randy.length == range.length - i);
2341+ }
23262342}
23272343
23282344// RandomSample
0 commit comments