// Deterministic shuffled list iterator using an XORSHIFT RNG // Each step is O(1), iterator is OSPACE(1) // This iterator doesn't have a seed parameter and is completely // deterministic with respect to a given list size. // If you want to pass a seed, use WeightlessShuffledIteratorWithSeed. sclass WeightlessShuffledIterator extends ItIt { final L list; final int n; int i; TripletLSFR lsfr; // initialize only with a length (and a pseudo-list) // if you are going to be calling nextIndex() instead of next() *(int n) { this((L) virtualNullList(n)); } // initialize with a list to shuffle *(L *list) { n = l(list); if (n == 0) ret; int bits = numberOfBitsNeededToRepresentNOptions(n+1); lsfr = new TripletLSFR(bits); } public bool hasNext() { ret i < n; } public A next() { ret list.get(nextIndex()); } public int nextIndex() { if (i++ >= n) throw new NoSuchElementException; int raw; do { ifdef WeightlessShuffledIterator_SafetyChecks if (lsfr.cycleComplete()) fail("Internal error"); endifdef raw = postProcessLSFRValue(lsfr.next()-1); printVars ifdef WeightlessShuffledIterator_debug(+i, +raw, step := lsfr.step); } while (raw >= n); ret raw; }; int bits() { ret lsfr == null ? 0 : lsfr.n; } // overridable in subclasses int postProcessLSFRValue(int i) { ret i; } }