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.

206 lines
4.3KB

  1. #include "util.hpp"
  2. #include <stdarg.h>
  3. #include <string.h>
  4. #include <random>
  5. #include <algorithm>
  6. #include <libgen.h> // for dirname and basename
  7. #include <sys/time.h>
  8. #if ARCH_WIN
  9. #include <windows.h>
  10. #include <shellapi.h>
  11. #endif
  12. namespace rack {
  13. ////////////////////
  14. // RNG
  15. ////////////////////
  16. // xoroshiro128+
  17. // from http://xoroshiro.di.unimi.it/xoroshiro128plus.c
  18. static uint64_t xoroshiro128plus_state[2];
  19. static uint64_t rotl(const uint64_t x, int k) {
  20. return (x << k) | (x >> (64 - k));
  21. }
  22. static uint64_t xoroshiro128plus_next(void) {
  23. const uint64_t s0 = xoroshiro128plus_state[0];
  24. uint64_t s1 = xoroshiro128plus_state[1];
  25. const uint64_t result = s0 + s1;
  26. s1 ^= s0;
  27. xoroshiro128plus_state[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
  28. xoroshiro128plus_state[1] = rotl(s1, 36); // c
  29. return result;
  30. }
  31. void randomSeedTime() {
  32. struct timeval tv;
  33. gettimeofday(&tv, NULL);
  34. xoroshiro128plus_state[0] = tv.tv_sec;
  35. xoroshiro128plus_state[1] = tv.tv_usec;
  36. // Generate a few times to fix the fact that the time is not a uniform u64
  37. for (int i = 0; i < 10; i++) {
  38. xoroshiro128plus_next();
  39. }
  40. }
  41. uint32_t randomu32() {
  42. return xoroshiro128plus_next() >> 32;
  43. }
  44. uint64_t randomu64() {
  45. return xoroshiro128plus_next();
  46. }
  47. float randomf() {
  48. // 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).
  49. return (xoroshiro128plus_next() >> (64 - 24)) / powf(2, 24);
  50. }
  51. float randomNormal() {
  52. // Box-Muller transform
  53. float radius = sqrtf(-2.f * logf(1.f - randomf()));
  54. float theta = 2.f * M_PI * randomf();
  55. return radius * sinf(theta);
  56. // // Central Limit Theorem
  57. // const int n = 8;
  58. // float sum = 0.0;
  59. // for (int i = 0; i < n; i++) {
  60. // sum += randomf();
  61. // }
  62. // return (sum - n / 2.f) / sqrtf(n / 12.f);
  63. }
  64. ////////////////////
  65. // String functions
  66. ////////////////////
  67. std::string stringf(const char *format, ...) {
  68. va_list args;
  69. va_start(args, format);
  70. // Compute size of required buffer
  71. int size = vsnprintf(NULL, 0, format, args);
  72. va_end(args);
  73. if (size < 0)
  74. return "";
  75. // Create buffer
  76. std::string s;
  77. s.resize(size);
  78. va_start(args, format);
  79. vsnprintf(&s[0], size + 1, format, args);
  80. va_end(args);
  81. return s;
  82. }
  83. std::string tolower(std::string s) {
  84. std::transform(s.begin(), s.end(), s.begin(), ::tolower);
  85. return s;
  86. }
  87. std::string toupper(std::string s) {
  88. std::transform(s.begin(), s.end(), s.begin(), ::toupper);
  89. return s;
  90. }
  91. std::string ellipsize(std::string s, size_t len) {
  92. if (s.size() <= len)
  93. return s;
  94. else
  95. return s.substr(0, len - 3) + "...";
  96. }
  97. std::string extractDirectory(std::string path) {
  98. char *pathDup = strdup(path.c_str());
  99. std::string directory = dirname(pathDup);
  100. free(pathDup);
  101. return directory;
  102. }
  103. std::string extractFilename(std::string path) {
  104. char *pathDup = strdup(path.c_str());
  105. std::string filename = basename(pathDup);
  106. free(pathDup);
  107. return filename;
  108. }
  109. std::string extractExtension(std::string path) {
  110. const char *ext = strrchr(path.c_str(), '.');
  111. if (!ext)
  112. return "";
  113. return ext + 1;
  114. }
  115. ////////////////////
  116. // Operating system functions
  117. ////////////////////
  118. void openBrowser(std::string url) {
  119. #if ARCH_LIN
  120. std::string command = "xdg-open " + url;
  121. (void)system(command.c_str());
  122. #endif
  123. #if ARCH_MAC
  124. std::string command = "open " + url;
  125. system(command.c_str());
  126. #endif
  127. #if ARCH_WIN
  128. ShellExecute(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
  129. #endif
  130. }
  131. ////////////////////
  132. // logger
  133. ////////////////////
  134. FILE *gLogFile = stderr;
  135. void debug(const char *format, ...) {
  136. va_list args;
  137. va_start(args, format);
  138. fprintf(gLogFile, "[debug] ");
  139. vfprintf(gLogFile, format, args);
  140. fprintf(gLogFile, "\n");
  141. fflush(gLogFile);
  142. va_end(args);
  143. }
  144. void info(const char *format, ...) {
  145. va_list args;
  146. va_start(args, format);
  147. fprintf(gLogFile, "[info] ");
  148. vfprintf(gLogFile, format, args);
  149. fprintf(gLogFile, "\n");
  150. fflush(gLogFile);
  151. va_end(args);
  152. }
  153. void warn(const char *format, ...) {
  154. va_list args;
  155. va_start(args, format);
  156. fprintf(gLogFile, "[warning] ");
  157. vfprintf(gLogFile, format, args);
  158. fprintf(gLogFile, "\n");
  159. fflush(gLogFile);
  160. va_end(args);
  161. }
  162. void fatal(const char *format, ...) {
  163. va_list args;
  164. va_start(args, format);
  165. fprintf(gLogFile, "[fatal] ");
  166. vfprintf(gLogFile, format, args);
  167. fprintf(gLogFile, "\n");
  168. fflush(gLogFile);
  169. va_end(args);
  170. }
  171. } // namespace rack