#include "util.hpp" #include #include #include #include #include // for dirname and basename #include #if ARCH_WIN #include #include #endif namespace rack { //////////////////// // RNG //////////////////// // xoroshiro128+ // from http://xoroshiro.di.unimi.it/xoroshiro128plus.c static uint64_t xoroshiro128plus_state[2]; static uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); } static uint64_t xoroshiro128plus_next(void) { const uint64_t s0 = xoroshiro128plus_state[0]; uint64_t s1 = xoroshiro128plus_state[1]; const uint64_t result = s0 + s1; s1 ^= s0; xoroshiro128plus_state[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b xoroshiro128plus_state[1] = rotl(s1, 36); // c return result; } void randomSeedTime() { struct timeval tv; gettimeofday(&tv, NULL); xoroshiro128plus_state[0] = tv.tv_sec; xoroshiro128plus_state[1] = tv.tv_usec; // Generate a few times to fix the fact that the time is not a uniform u64 for (int i = 0; i < 10; i++) { xoroshiro128plus_next(); } } uint32_t randomu32() { return xoroshiro128plus_next() >> 32; } uint64_t randomu64() { return xoroshiro128plus_next(); } float randomf() { // 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). return (xoroshiro128plus_next() >> (64 - 24)) / powf(2, 24); } float randomNormal() { // Box-Muller transform float radius = sqrtf(-2.f * logf(1.f - randomf())); float theta = 2.f * M_PI * randomf(); return radius * sinf(theta); // // Central Limit Theorem // const int n = 8; // float sum = 0.0; // for (int i = 0; i < n; i++) { // sum += randomf(); // } // return (sum - n / 2.f) / sqrtf(n / 12.f); } //////////////////// // String functions //////////////////// std::string stringf(const char *format, ...) { va_list args; va_start(args, format); // Compute size of required buffer int size = vsnprintf(NULL, 0, format, args); va_end(args); if (size < 0) return ""; // Create buffer std::string s; s.resize(size); va_start(args, format); vsnprintf(&s[0], size + 1, format, args); va_end(args); return s; } std::string tolower(std::string s) { std::transform(s.begin(), s.end(), s.begin(), ::tolower); return s; } std::string toupper(std::string s) { std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s; } std::string ellipsize(std::string s, size_t len) { if (s.size() <= len) return s; else return s.substr(0, len - 3) + "..."; } std::string extractDirectory(std::string path) { char *pathDup = strdup(path.c_str()); std::string directory = dirname(pathDup); free(pathDup); return directory; } std::string extractFilename(std::string path) { char *pathDup = strdup(path.c_str()); std::string filename = basename(pathDup); free(pathDup); return filename; } std::string extractExtension(std::string path) { const char *ext = strrchr(path.c_str(), '.'); if (!ext) return ""; return ext + 1; } //////////////////// // Operating system functions //////////////////// void openBrowser(std::string url) { #if ARCH_LIN std::string command = "xdg-open " + url; (void)system(command.c_str()); #endif #if ARCH_MAC std::string command = "open " + url; system(command.c_str()); #endif #if ARCH_WIN ShellExecute(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL); #endif } //////////////////// // logger //////////////////// FILE *gLogFile = stderr; void debug(const char *format, ...) { va_list args; va_start(args, format); fprintf(gLogFile, "[debug] "); vfprintf(gLogFile, format, args); fprintf(gLogFile, "\n"); fflush(gLogFile); va_end(args); } void info(const char *format, ...) { va_list args; va_start(args, format); fprintf(gLogFile, "[info] "); vfprintf(gLogFile, format, args); fprintf(gLogFile, "\n"); fflush(gLogFile); va_end(args); } void warn(const char *format, ...) { va_list args; va_start(args, format); fprintf(gLogFile, "[warning] "); vfprintf(gLogFile, format, args); fprintf(gLogFile, "\n"); fflush(gLogFile); va_end(args); } void fatal(const char *format, ...) { va_list args; va_start(args, format); fprintf(gLogFile, "[fatal] "); vfprintf(gLogFile, format, args); fprintf(gLogFile, "\n"); fflush(gLogFile); va_end(args); } } // namespace rack