You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

73 lines
1.7KB

  1. #include "util/util.hpp"
  2. #include <time.h>
  3. #include <sys/time.h>
  4. namespace rack {
  5. // xoroshiro128+
  6. // from http://xoroshiro.di.unimi.it/xoroshiro128plus.c
  7. static uint64_t xoroshiro128plus_state[2] = {};
  8. static uint64_t rotl(const uint64_t x, int k) {
  9. return (x << k) | (x >> (64 - k));
  10. }
  11. static uint64_t xoroshiro128plus_next(void) {
  12. const uint64_t s0 = xoroshiro128plus_state[0];
  13. uint64_t s1 = xoroshiro128plus_state[1];
  14. const uint64_t result = s0 + s1;
  15. s1 ^= s0;
  16. xoroshiro128plus_state[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
  17. xoroshiro128plus_state[1] = rotl(s1, 36); // c
  18. return result;
  19. }
  20. void randomInit() {
  21. // Only allow the seed to be initialized once during the lifetime of the program.
  22. assert(xoroshiro128plus_state[0] == 0 && xoroshiro128plus_state[1] == 0);
  23. struct timeval tv;
  24. gettimeofday(&tv, NULL);
  25. xoroshiro128plus_state[0] = tv.tv_sec;
  26. xoroshiro128plus_state[1] = tv.tv_usec;
  27. // Generate a few times to fix the fact that the time is not a uniform u64
  28. for (int i = 0; i < 10; i++) {
  29. xoroshiro128plus_next();
  30. }
  31. }
  32. uint32_t randomu32() {
  33. return xoroshiro128plus_next() >> 32;
  34. }
  35. uint64_t randomu64() {
  36. return xoroshiro128plus_next();
  37. }
  38. float randomf() {
  39. // 24 bits of granularity is the best that can be done with floats while ensuring that the return value lies in [0.0, 1.0).
  40. return (xoroshiro128plus_next() >> (64 - 24)) / powf(2, 24);
  41. }
  42. float randomNormal() {
  43. // Box-Muller transform
  44. float radius = sqrtf(-2.f * logf(1.f - randomf()));
  45. float theta = 2.f * M_PI * randomf();
  46. return radius * sinf(theta);
  47. // // Central Limit Theorem
  48. // const int n = 8;
  49. // float sum = 0.0;
  50. // for (int i = 0; i < n; i++) {
  51. // sum += randomf();
  52. // }
  53. // return (sum - n / 2.f) / sqrtf(n / 12.f);
  54. }
  55. } // namespace rack