| 20 | |
| 21 | template <class TIndicesType> |
| 22 | inline void Shuffle(ui64 seed, ui32 blockSize, ui32 sampleCount, TVector<TIndicesType>* orderPtr) { |
| 23 | TRandom rng(seed); |
| 24 | rng.Advance(10); |
| 25 | auto& order = *orderPtr; |
| 26 | order.yresize(sampleCount); |
| 27 | std::iota(order.begin(), order.end(), 0); |
| 28 | |
| 29 | if (blockSize == 1) { |
| 30 | ::Shuffle(order.begin(), order.begin() + sampleCount, rng); |
| 31 | } else { |
| 32 | const auto blocksCount = static_cast<ui32>(::NHelpers::CeilDivide(order.size(), blockSize)); |
| 33 | TVector<ui32> blocks; |
| 34 | blocks.yresize(blocksCount); |
| 35 | std::iota(blocks.begin(), blocks.end(), 0); |
| 36 | ::Shuffle(blocks.begin(), blocks.end(), rng); |
| 37 | |
| 38 | ui32 cursor = 0; |
| 39 | for (ui32 i = 0; i < blocksCount; ++i) { |
| 40 | const ui32 blockStart = blocks[i] * blockSize; |
| 41 | const ui32 blockEnd = Min<ui32>(blockStart + blockSize, order.size()); |
| 42 | for (ui32 j = blockStart; j < blockEnd; ++j) { |
| 43 | order[cursor++] = j; |
| 44 | } |
| 45 | } |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | template <class TIndicesType> |
| 50 | inline void GenerateQueryDocsOrder(ui64 seed, ui32 blockSize, TConstArrayRef<TGroupBounds> groupBounds, TVector<TIndicesType>* orderPtr) { |