lcg_engine.cpp 983 B

123456789101112131415161718192021222324252627282930
  1. #include "lcg_engine.h"
  2. namespace NPrivate {
  3. template <typename T>
  4. T LcgAdvance(T seed, T lcgBase, T lcgAddend, T delta) noexcept {
  5. // seed[n+1] = A * seed[n] + B, A = lcgBase, B = lcgAddend
  6. // seed[n] = A**n * seed[0] + (A**n - 1) / (A - 1) * B
  7. // (initial value of n) = m * 2**k + (lower bits of n)
  8. T mask = 1;
  9. while (mask != (1ULL << (8 * sizeof(T) - 1)) && (mask << 1) <= delta) {
  10. mask <<= 1;
  11. }
  12. T apow = 1; // A**m
  13. T adiv = 0; // (A**m-1)/(A-1)
  14. for (; mask; mask >>= 1) {
  15. // m *= 2
  16. adiv *= apow + 1;
  17. apow *= apow;
  18. if (delta & mask) {
  19. // m++
  20. adiv += apow;
  21. apow *= lcgBase;
  22. }
  23. }
  24. return seed * apow + lcgAddend * adiv;
  25. }
  26. template ui32 LcgAdvance<ui32>(ui32, ui32, ui32, ui32) noexcept;
  27. template ui64 LcgAdvance<ui64>(ui64, ui64, ui64, ui64) noexcept;
  28. }