Random.cpp 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #include "core/Random.hpp"
  2. #include <cstring>
  3. using Core::Random;
  4. Random::Random(u32 seed) : data(), index(0) {
  5. for(u32& u : data) {
  6. u = seed;
  7. seed = seed * 7 + 31;
  8. }
  9. }
  10. void Random::update() {
  11. constexpr int M = 7;
  12. static const u32 map[2] = {0, 0x8EBF'D028};
  13. for(size_t i = 0; i < data.getLength() - M; i++) {
  14. data[i] = data[i + M] ^ (data[i] >> 1) ^ map[data[i] & 1];
  15. }
  16. for(size_t i = data.getLength() - M; i < data.getLength(); i++) {
  17. data[i] = data[i + (M - data.getLength())] ^ (data[i] >> 1) ^
  18. map[data[i] & 1];
  19. }
  20. index = 0;
  21. }
  22. u32 Random::nextU32() {
  23. if(index >= data.getLength()) {
  24. update();
  25. }
  26. u32 u = data[index++];
  27. u ^= (u << 7) & 0x2B5B'2500;
  28. u ^= (u << 15) & 0xDB8B'0000;
  29. u ^= (u >> 16);
  30. return u;
  31. }
  32. template<typename T>
  33. T limit(T value, T min, T exclusiveMax) {
  34. return min + value % (exclusiveMax - min);
  35. }
  36. u32 Random::nextU32(u32 min, u32 exclusiveMax) {
  37. return limit(nextU32(), min, exclusiveMax);
  38. }
  39. i32 Random::nextI32(i32 min, i32 exclusiveMax) {
  40. return limit(static_cast<i32>(nextU32() >> 1), min, exclusiveMax);
  41. }
  42. size_t Core::Random::nextSize(size_t min, size_t exclusiveMax) {
  43. return limit<size_t>(nextU32(), min, exclusiveMax);
  44. }
  45. bool Core::Random::nextBool() {
  46. return nextU32() & 1;
  47. }
  48. float Core::Random::nextFloat() {
  49. float f = static_cast<float>(nextU32()) / static_cast<float>(0xFFFF'FFFFu);
  50. return f >= 1.0f ? nextFloat() : f;
  51. }