// // Lol Engine // // Copyright © 2010—2020 Sam Hocevar // // Lol Engine is free software. It comes without any warranty, to // the extent permitted by applicable law. You can redistribute it // and/or modify it under the terms of the Do What the Fuck You Want // to Public License, Version 2, as published by the WTFPL Task Force. // See http://www.wtfpl.net/ for more details. // #pragma once // // The Random number generators // ———————————————————————————— // #include #include #include #include namespace lol { /* Random number generators */ template lol_attr_nodiscard static inline T rand(); template lol_attr_nodiscard static inline T rand(T a); template lol_attr_nodiscard static inline T rand(T a, T b); /* One-value random number generators */ template lol_attr_nodiscard static inline T rand(T a) { return a ? rand() % a : T(0); } #if 0 template<> lol_attr_nodiscard inline half rand(half a) { float f = (float)std::rand() / (float)RAND_MAX; return (half)(a * f); } #endif template<> lol_attr_nodiscard inline float rand(float a) { auto f = (float)std::rand() / (float)RAND_MAX; return a * f; } template<> lol_attr_nodiscard inline double rand(double a) { auto f = (double)std::rand() / (double)RAND_MAX; return a * f; } template<> lol_attr_nodiscard inline long double rand(long double a) { auto f = (long double)std::rand() / (long double)RAND_MAX; return a * f; } /* Two-value random number generator -- no need for specialisation */ template lol_attr_nodiscard static inline T rand(T a, T b) { return a + rand(b - a); } /* Default random number generator */ template lol_attr_nodiscard static inline T rand() { switch (sizeof(T)) { case 1: return static_cast(std::rand() & 0x7f); case 2: { uint16_t ret = std::rand(); if (RAND_MAX < 0x7fff) ret = (ret << 7) ^ std::rand(); return static_cast(ret & 0x7fffu); } case 4: { uint32_t ret = std::rand(); if (RAND_MAX >= 0xffff) ret = (ret << 16) ^ std::rand(); else { ret = (ret << 8) ^ std::rand(); ret = (ret << 8) ^ std::rand(); ret = (ret << 8) ^ std::rand(); } return static_cast(ret & 0x7fffffffu); } case 8: { uint64_t ret = std::rand(); if (RAND_MAX >= 0xffff) { ret = (ret << 16) ^ std::rand(); ret = (ret << 16) ^ std::rand(); ret = (ret << 16) ^ std::rand(); } else { ret = (ret << 8) ^ std::rand(); ret = (ret << 8) ^ std::rand(); ret = (ret << 8) ^ std::rand(); ret = (ret << 8) ^ std::rand(); ret = (ret << 8) ^ std::rand(); ret = (ret << 8) ^ std::rand(); ret = (ret << 8) ^ std::rand(); } return static_cast(ret & (~(uint64_t)0 >> 1)); } default: assert(false); return 0; } } #if 0 template<> lol_attr_nodiscard inline half rand() { return rand(1.f); } #endif template<> lol_attr_nodiscard inline float rand() { return rand(1.f); } template<> lol_attr_nodiscard inline double rand() { return rand(1.0); } template<> lol_attr_nodiscard inline long double rand() { return rand(1.0); } } /* namespace lol */