1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-01-19 03:57:14 +01:00
Sandu Liviu Catalin 4a6bfc086c Major plugin refactor and cleanup.
Switched to POCO library for unified platform/library interface.
Deprecated the external module API. It was creating more problems than solving.
Removed most built-in libraries in favor of system libraries for easier maintenance.
Cleaned and secured code with help from static analyzers.
2021-01-30 08:51:39 +02:00

438 lines
15 KiB
C++

// ------------------------------------------------------------------------------------------------
#include "Library/Numeric/Random.hpp"
#include "Core/Common.hpp"
#include "Core/Buffer.hpp"
// ------------------------------------------------------------------------------------------------
#include <ctime>
#include <memory>
#include <random>
// ------------------------------------------------------------------------------------------------
#ifdef SQMOD_OS_WINDOWS
#include <process.h>
#else
#include <sys/types.h>
#include <unistd.h>
#endif
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
static std::unique_ptr< std::mt19937 > RG32_MT19937 = // NOLINT(cert-err58-cpp)
std::make_unique< std::mt19937 >(GenerateSeed());
static std::unique_ptr< std::mt19937_64 > RG64_MT19937 = // NOLINT(cert-err58-cpp)
std::make_unique< std::mt19937_64 >(GenerateSeed());
// ------------------------------------------------------------------------------------------------
static std::uniform_int_distribution< int8_t > Int8_Dist(std::numeric_limits< int8_t >::min(), // NOLINT(cert-err58-cpp)
std::numeric_limits< int8_t >::max());
static std::uniform_int_distribution< uint8_t > uint8_t_Dist(std::numeric_limits< uint8_t >::min(), // NOLINT(cert-err58-cpp)
std::numeric_limits< uint8_t >::max());
static std::uniform_int_distribution< int16_t > Int16_Dist(std::numeric_limits< int16_t >::min(), // NOLINT(cert-err58-cpp)
std::numeric_limits< int16_t >::max());
static std::uniform_int_distribution< uint16_t > Uint16_Dist(std::numeric_limits< uint16_t >::min(), // NOLINT(cert-err58-cpp)
std::numeric_limits< uint16_t >::max());
static std::uniform_int_distribution< int32_t > Int32_Dist(std::numeric_limits< int32_t >::min(), // NOLINT(cert-err58-cpp)
std::numeric_limits< int32_t >::max());
static std::uniform_int_distribution< uint32_t > Uint32_Dist(std::numeric_limits< uint32_t >::min(), // NOLINT(cert-err58-cpp)
std::numeric_limits< uint32_t >::max());
static std::uniform_int_distribution< int64_t > Int64_Dist(std::numeric_limits< int64_t >::min(), // NOLINT(cert-err58-cpp)
std::numeric_limits< int64_t >::max());
static std::uniform_int_distribution< uint64_t > Uint64_Dist(std::numeric_limits< uint64_t >::min(), // NOLINT(cert-err58-cpp)
std::numeric_limits< uint64_t >::max());
static std::uniform_real_distribution<float> Float32_Dist(std::numeric_limits< float >::min(), // NOLINT(cert-err58-cpp)
std::numeric_limits< float >::max());
static std::uniform_real_distribution<double> Float64_Dist(std::numeric_limits< double >::min(), // NOLINT(cert-err58-cpp)
std::numeric_limits< double >::max());
// ------------------------------------------------------------------------------------------------
static std::uniform_int_distribution< String::value_type >
String_Dist(std::numeric_limits< String::value_type >::min(), // NOLINT(cert-err58-cpp)
std::numeric_limits< String::value_type >::max());
// ------------------------------------------------------------------------------------------------
uint32_t GenerateSeed()
{
unsigned long a = clock();
unsigned long b = time(nullptr);
#ifdef SQMOD_OS_WINDOWS
unsigned long c = _getpid();
#else
unsigned long c = getpid();
#endif
// Mangle
a=a-b; a=a-c; a=a^(c >> 13);
b=b-c; b=b-a; b=b^(a << 8);
c=c-a; c=c-b; c=c^(b >> 13);
a=a-b; a=a-c; a=a^(c >> 12);
b=b-c; b=b-a; b=b^(a << 16);
c=c-a; c=c-b; c=c^(b >> 5);
a=a-b; a=a-c; a=a^(c >> 3);
b=b-c; b=b-a; b=b^(a << 10);
c=c-a; c=c-b; c=c^(b >> 15);
// Return result
return c;
}
// ------------------------------------------------------------------------------------------------
size_t GenerateSeed2()
{
struct { // NOLINT(cppcoreguidelines-pro-type-member-init)
std::clock_t c;
std::time_t t;
#ifdef SQMOD_OS_WINDOWS
int p;
#else
pid_t p;
#endif
} data;
data.c = std::clock();
data.t = std::time(nullptr);
#ifdef SQMOD_OS_WINDOWS
data.p = _getpid();
#else
data.p = getpid();
#endif
// Mangle and return result
return FnvHash(reinterpret_cast< const uint8_t * >(&data), sizeof(data));
}
// ------------------------------------------------------------------------------------------------
void ReseedRandom()
{
RG32_MT19937 = std::make_unique<std::mt19937>(GenerateSeed());
RG64_MT19937 = std::make_unique<std::mt19937_64>(GenerateSeed());
}
void ReseedRandom(uint32_t n)
{
RG32_MT19937 = std::make_unique<std::mt19937>(n);
RG64_MT19937 = std::make_unique<std::mt19937_64>(n);
}
// ------------------------------------------------------------------------------------------------
void ReseedRandom32()
{
RG32_MT19937 = std::make_unique<std::mt19937>(GenerateSeed());
}
void ReseedRandom32(uint32_t n)
{
RG32_MT19937 = std::make_unique<std::mt19937>(n);
}
// ------------------------------------------------------------------------------------------------
void ReseedRandom64()
{
RG64_MT19937 = std::make_unique<std::mt19937_64>(GenerateSeed());
}
void ReseedRandom64(uint32_t n)
{
RG64_MT19937 = std::make_unique<std::mt19937_64>(n);
}
// ------------------------------------------------------------------------------------------------
int8_t GetRandomInt8()
{
return Int8_Dist(*RG32_MT19937);
}
int8_t GetRandomInt8(int8_t n)
{
return std::uniform_int_distribution< int8_t >(0, n)(*RG32_MT19937);
}
int8_t GetRandomInt8(int8_t m, int8_t n)
{
return std::uniform_int_distribution< int8_t >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
uint8_t GetRandomUint8()
{
return uint8_t_Dist(*RG32_MT19937);
}
uint8_t GetRandomUint8(uint8_t n)
{
return std::uniform_int_distribution< uint8_t >(0, n)(*RG32_MT19937);
}
uint8_t GetRandomUint8(uint8_t m, uint8_t n)
{
return std::uniform_int_distribution< uint8_t >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
int16_t GetRandomInt16()
{
return Int16_Dist(*RG32_MT19937);
}
int16_t GetRandomInt16(int16_t n)
{
return std::uniform_int_distribution< int16_t >(0, n)(*RG32_MT19937);
}
int16_t GetRandomInt16(int16_t m, int16_t n)
{
return std::uniform_int_distribution< int16_t >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
uint16_t GetRandomUint16()
{
return Uint16_Dist(*RG32_MT19937);
}
uint16_t GetRandomUint16(uint16_t n)
{
return std::uniform_int_distribution< uint16_t >(0, n)(*RG32_MT19937);
}
uint16_t GetRandomUint16(uint16_t m, uint16_t n)
{
return std::uniform_int_distribution< uint16_t >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
int32_t GetRandomInt32()
{
return Int32_Dist(*RG32_MT19937);
}
int32_t GetRandomInt32(int32_t n)
{
return std::uniform_int_distribution< int32_t >(0, n)(*RG32_MT19937);
}
int32_t GetRandomInt32(int32_t m, int32_t n)
{
return std::uniform_int_distribution< int32_t >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
uint32_t GetRandomUint32()
{
return Uint32_Dist(*RG32_MT19937);
}
uint32_t GetRandomUint32(uint32_t n)
{
return std::uniform_int_distribution< uint32_t >(0, n)(*RG32_MT19937);
}
uint32_t GetRandomUint32(uint32_t m, uint32_t n)
{
return std::uniform_int_distribution< uint32_t >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
int64_t GetRandomInt64()
{
return Int64_Dist(*RG64_MT19937);
}
int64_t GetRandomInt64(int64_t n)
{
return std::uniform_int_distribution< int64_t >(0, n)(*RG64_MT19937);
}
int64_t GetRandomInt64(int64_t m, int64_t n)
{
return std::uniform_int_distribution< int64_t >(m, n)(*RG64_MT19937);
}
// ------------------------------------------------------------------------------------------------
uint64_t GetRandomUint64()
{
return Uint64_Dist(*RG64_MT19937);
}
uint64_t GetRandomUint64(uint64_t n)
{
return std::uniform_int_distribution< uint64_t >(0, n)(*RG64_MT19937);
}
uint64_t GetRandomUint64(uint64_t m, uint64_t n)
{
return std::uniform_int_distribution< uint64_t >(m, n)(*RG64_MT19937);
}
// ------------------------------------------------------------------------------------------------
float GetRandomFloat32()
{
return Float32_Dist(*RG32_MT19937);
}
float GetRandomFloat32(float n)
{
return std::uniform_real_distribution< float >(0, n)(*RG32_MT19937);
}
float GetRandomFloat32(float m, float n)
{
return std::uniform_real_distribution< float >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
double GetRandomFloat64()
{
return Float64_Dist(*RG64_MT19937);
}
double GetRandomFloat64(double n)
{
return std::uniform_real_distribution< double >(0, n)(*RG64_MT19937);
}
double GetRandomFloat64(double m, double n)
{
return std::uniform_real_distribution< double >(m, n)(*RG64_MT19937);
}
// ------------------------------------------------------------------------------------------------
void GetRandomString(String & str, String::size_type len)
{
// Resize to the requested size and fill with 0
str.resize(len);
// Generate the requested amount of characters
for (auto & c : str)
{
c = String_Dist(*RG32_MT19937);
}
}
void GetRandomString(String & str, String::size_type len, String::value_type n)
{
// Resize to the requested size and fill with 0
str.resize(len);
// Create the custom distribution
std::uniform_int_distribution< String::value_type > dist(1, n);
// Generate the requested amount of characters
for (auto & c : str)
{
c = dist(*RG32_MT19937);
}
}
void GetRandomString(String & str, String::size_type len, String::value_type m, String::value_type n)
{
// Resize to the requested size and fill with 0
str.resize(len);
// Create the custom distribution
std::uniform_int_distribution< String::value_type > dist(m, n);
// Generate the requested amount of characters
for (auto & c : str)
{
c = dist(*RG32_MT19937);
}
}
// ------------------------------------------------------------------------------------------------
bool GetRandomBool()
{
return std::bernoulli_distribution()(*RG32_MT19937);
}
bool GetRandomBool(SQFloat p)
{
return std::bernoulli_distribution(p)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
static String RandomString(int32_t len)
{
// Is there anything to generate?
if (len <= 0)
return _SC("");
// Prepare the string buffer
String str;
// Request the random fill
GetRandomString(str, len);
// Return ownership of the string
return str;
}
// ------------------------------------------------------------------------------------------------
static String RandomString(int32_t len, SQChar n)
{
// Is there anything to generate?
if (len <= 0)
return _SC("");
// Prepare the string buffer
String str;
// Request the random fill
GetRandomString(str, len, n);
// Return ownership of the string
return str;
}
// ------------------------------------------------------------------------------------------------
static String RandomString(int32_t len, SQChar m, SQChar n)
{
// Is there anything to generate?
if (len <= 0)
return _SC("");
// Prepare the string buffer
String str;
// Request the random fill
GetRandomString(str, len, m, n);
// Return ownership of the string
return str;
}
// ------------------------------------------------------------------------------------------------
void Register_Random(HSQUIRRELVM vm)
{
RootTable(vm).Bind(_SC("SqRand"), Table(vm)
.Func(_SC("GenSeed"), &GenerateSeed)
.Func(_SC("GenSeed2"), &GenerateSeed2)
.Overload< void (*)(void) >(_SC("Reseed"), &ReseedRandom)
.Overload< void (*)(uint32_t) >(_SC("Reseed"), &ReseedRandom)
.Overload< void (*)(void) >(_SC("Reseed32"), &ReseedRandom32)
.Overload< void (*)(uint32_t) >(_SC("Reseed32"), &ReseedRandom32)
.Overload< void (*)(void) >(_SC("Reseed64"), &ReseedRandom64)
.Overload< void (*)(uint32_t) >(_SC("Reseed64"), &ReseedRandom64)
#ifdef _SQ64
.Overload< SQInteger (*)(void) >(_SC("Integer"), &GetRandomInt64)
.Overload< SQInteger (*)(SQInteger) >(_SC("Integer"), &GetRandomInt64)
.Overload< SQInteger (*)(SQInteger, SQInteger) >(_SC("Integer"), &GetRandomInt64)
#else
.Overload< SQInteger (*)(void) >(_SC("Integer"), &GetRandomInt32)
.Overload< SQInteger (*)(SQInteger) >(_SC("Integer"), &GetRandomInt32)
.Overload< SQInteger (*)(SQInteger, SQInteger) >(_SC("Integer"), &GetRandomInt32)
#endif // _SQ64
#ifdef SQUSEDOUBLE
.Overload< SQFloat (*)(void) >(_SC("Float"), &GetRandomFloat64)
.Overload< SQFloat (*)(SQFloat) >(_SC("Float"), &GetRandomFloat64)
.Overload< SQFloat (*)(SQFloat, SQFloat) >(_SC("Float"), &GetRandomFloat64)
#else
.Overload< SQFloat (*)(void) >(_SC("Float"), &GetRandomFloat32)
.Overload< SQFloat (*)(SQFloat) >(_SC("Float"), &GetRandomFloat32)
.Overload< SQFloat (*)(SQFloat, SQFloat) >(_SC("Float"), &GetRandomFloat32)
#endif // SQUSEDOUBLE
.Overload< String (*)(int32_t) >(_SC("String"), &RandomString)
.Overload< String (*)(int32_t, SQChar) >(_SC("String"), &RandomString)
.Overload< String (*)(int32_t, SQChar, SQChar) >(_SC("String"), &RandomString)
.Overload< bool (*)(void) >(_SC("Bool"), &GetRandomBool)
.Overload< bool (*)(SQFloat) >(_SC("Bool"), &GetRandomBool)
);
}
} // Namespace:: SqMod