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.

72 lines
1.3KB

  1. #include <atomic>
  2. #include <time.h>
  3. #include <sys/time.h>
  4. #include <random.hpp>
  5. #include <math.hpp>
  6. namespace rack {
  7. namespace random {
  8. thread_local Xoroshiro128Plus rng;
  9. static std::atomic<uint64_t> threadCounter {0};
  10. void init() {
  11. // Don't reset state if already seeded
  12. if (rng.isSeeded())
  13. return;
  14. struct timeval tv;
  15. gettimeofday(&tv, NULL);
  16. rng.seed(uint64_t(tv.tv_sec) * 1000 * 1000 + tv.tv_usec, threadCounter++);
  17. // Shift state a few times due to low seed entropy
  18. for (int i = 0; i < 4; i++) {
  19. rng();
  20. }
  21. }
  22. float normal() {
  23. // Box-Muller transform
  24. float radius = std::sqrt(-2.f * std::log(1.f - uniform()));
  25. float theta = 2.f * M_PI * uniform();
  26. return radius * std::sin(theta);
  27. // // Central Limit Theorem
  28. // const int n = 8;
  29. // float sum = 0.0;
  30. // for (int i = 0; i < n; i++) {
  31. // sum += uniform();
  32. // }
  33. // return (sum - n / 2.f) / std::sqrt(n / 12.f);
  34. }
  35. void buffer(uint8_t* out, size_t len) {
  36. for (size_t i = 0; i < len; i += 4) {
  37. uint64_t r = u64();
  38. out[i] = r;
  39. if (i + 1 < len)
  40. out[i + 1] = r >> 8;
  41. if (i + 2 < len)
  42. out[i + 2] = r >> 16;
  43. if (i + 3 < len)
  44. out[i + 3] = r >> 24;
  45. }
  46. }
  47. std::vector<uint8_t> vector(size_t len) {
  48. std::vector<uint8_t> v(len);
  49. buffer(v.data(), len);
  50. return v;
  51. }
  52. } // namespace random
  53. } // namespace rack