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.

77 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. Xoroshiro128Plus& get() {
  23. return rng;
  24. }
  25. float normal() {
  26. // Box-Muller transform
  27. float radius = std::sqrt(-2.f * std::log(1.f - uniform()));
  28. float theta = 2.f * M_PI * uniform();
  29. return radius * std::sin(theta);
  30. // // Central Limit Theorem
  31. // const int n = 8;
  32. // float sum = 0.0;
  33. // for (int i = 0; i < n; i++) {
  34. // sum += uniform();
  35. // }
  36. // return (sum - n / 2.f) / std::sqrt(n / 12.f);
  37. }
  38. void buffer(uint8_t* out, size_t len) {
  39. for (size_t i = 0; i < len; i += 4) {
  40. uint64_t r = u64();
  41. out[i] = r;
  42. if (i + 1 < len)
  43. out[i + 1] = r >> 8;
  44. if (i + 2 < len)
  45. out[i + 2] = r >> 16;
  46. if (i + 3 < len)
  47. out[i + 3] = r >> 24;
  48. }
  49. }
  50. std::vector<uint8_t> vector(size_t len) {
  51. std::vector<uint8_t> v(len);
  52. buffer(v.data(), len);
  53. return v;
  54. }
  55. } // namespace random
  56. } // namespace rack