| 311 | } |
| 312 | |
| 313 | std::string shuffle_samples( |
| 314 | const std::string & rng_state, |
| 315 | size_t * shuffled_offs, |
| 316 | size_t * shuffled_begins, |
| 317 | size_t * shuffled_sizes, |
| 318 | const size_t * begins, |
| 319 | const size_t * sizes, |
| 320 | size_t count) { |
| 321 | if (count == 0) return rng_state; |
| 322 | |
| 323 | std::mt19937 rng; |
| 324 | mt19937_set_state(rng, rng_state); |
| 325 | |
| 326 | // sort indices by random value for each index |
| 327 | std::vector<size_t> idcs; |
| 328 | { |
| 329 | std::vector<unsigned> rnd; |
| 330 | idcs.resize(count); |
| 331 | rnd.resize(count); |
| 332 | for (unsigned i=0; i<count; ++i) { |
| 333 | idcs[i] = i; |
| 334 | rnd[i] = rng(); |
| 335 | } |
| 336 | |
| 337 | std::sort(idcs.begin(), idcs.end(), [&rnd](size_t a, size_t b){ |
| 338 | // stable sort for reproducibility |
| 339 | return (rnd[a] == rnd[b]) ? (a < b) : (rnd[a] < rnd[b]); |
| 340 | }); |
| 341 | } |
| 342 | |
| 343 | // create random offsets |
| 344 | for (unsigned i=0; i<count; ++i) { |
| 345 | shuffled_offs[i] = (size_t) ((sizes[idcs[i]] - 1) * ((double) rng() / (double) (rng.max()-1))); |
| 346 | } |
| 347 | |
| 348 | // reorder begins and sizes by sorted indices |
| 349 | for (unsigned i=0; i<count; ++i) { |
| 350 | shuffled_begins[i] = begins[idcs[i]]; |
| 351 | } |
| 352 | |
| 353 | for (unsigned i=0; i<count; ++i) { |
| 354 | shuffled_sizes[i] = sizes[idcs[i]]; |
| 355 | } |
| 356 | |
| 357 | return mt19937_get_state(rng); |
| 358 | } |
| 359 | |
| 360 | size_t hash_combine(size_t h1, size_t h2) { |
| 361 | return h1 ^ (h2 << 1); |
no test coverage detected