/** * Perform a uniform shuffle of a vector. * * @tparam random_t Type of the random number generator * @tparam Vector Type of the vector. Must implement size() and operator[]. * For example: std::vector of std::deque * @param [in,out] gen the rng * @param [in,out] vec the vector * * @return An uint32. **/ template<class Vector, class random_t> inline void randomShuffle(Vector & vec, random_t & gen) { const size_t l = vec.size(); if (l < 2) return; for (size_t i = l - 1; i > 0; --i) { size_t j = (size_t)(Unif(gen)*(i + 1)); typename std::remove_reference<decltype(vec[0])>::type temp(vec[i]); vec[i] = vec[j]; vec[j] = temp; } }
/************************************************************** * * Perform the walk until the range increases by nb * ***************************************************************/ void makeWalk(int64 nb,bool displayProgress = true) { ProgressBar<uint64> * PB = nullptr; if (displayProgress) { PB = new ProgressBar<uint64>(nb, "Simulating..."); } nb += N; auto startN = N; int64 lastb = 0; char v = G(pos); // current site while (N < nb) { if (isFull(v)) { // the four edge around the site are set, do simple rw if (lastb < 100) { // boundary not a long time ago, just one step SRW_Z2_1step(pos, gen); lastb++; } else { int64 d; do { iBox2 fullR; G.findFullBoxCentered(pos, fullR); // find a full box fullR.min[0]--; fullR.max[0]++; fullR.min[1]--; fullR.max[1]++; d = SRW_Z2_MoveInRect(pos, fullR, 8, gen); // move in the rectangle } while (d > 0); } v = G(pos); } else { // not all egdes are set, do ERRW lastb = 0; // reset the last visit to boundary const double up = ((v & maskup) ? delta : 1.0); const double right = ((v & maskright) ? delta : 1.0); const double down = ((v & maskdown) ? delta : 1.0); const double left = ((v & maskleft) ? delta : 1.0); const double a = Unif(gen)*(up + right + down + left); if (a < up + right) { if (a < up) { if ((v & maskup) == 0) { G.set(pos, v | maskup); pos.Y()++; v = G(pos); if (isEmpty(v)) { N++; if (PB != nullptr) { PB->update(N - startN); } } v |= maskdown; G.set(pos, v); } else { pos.Y()++; v = G(pos); } } else { if ((v & maskright) == 0) { G.set(pos, v | maskright); pos.X()++; v = G(pos); if (isEmpty(v)) { N++; if (PB != nullptr) { PB->update(N - startN); } } v |= maskleft; G.set(pos, v); } else { pos.X()++; v = G(pos); } } } else { if (a < up + right + down) { if ((v & maskdown) == 0) { G.set(pos, v | maskdown); pos.Y()--; v = G(pos); if (isEmpty(v)) { N++; if (PB != nullptr) { PB->update(N - startN); } } v |= maskup; G.set(pos, v); } else { pos.Y()--; v = G(pos); } } else { if ((v & maskleft) == 0) { G.set(pos, v | maskleft); pos.X()--; v = G(pos); if (isEmpty(v)) { N++; if (PB != nullptr) { PB->update(N - startN); } } v |= maskright; G.set(pos, v); } else { pos.X()--; v = G(pos); } } } } } delete PB; }