-
-
Save jrandom/170e00d5ad7b08c71ac708e5137e8867 to your computer and use it in GitHub Desktop.
Latest Random Wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Random.h | |
// Tools/Core | |
// | |
#ifndef Tools_Core_Random_h | |
#define Tools_Core_Random_h | |
// ================================================================================ Tools Includes | |
// Tools Includes | |
// -------------------------------------------------------------------------------- | |
#include "Types.h" | |
#include "Utility.h" | |
// ================================================================================ Standard Includes | |
// Standard Includes | |
// -------------------------------------------------------------------------------- | |
#include <random> | |
#include <memory> | |
#include <complex> | |
#include <algorithm> | |
// Stupid windows workaround | |
#include <time.h> | |
namespace Random | |
{ | |
// ============================================================================ Generator | |
// Generator | |
// | |
// Heavyweight random number generator | |
// ---------------------------------------------------------------------------- | |
class Generator final | |
{ | |
public: | |
// -------------------------------------------------------------------- Types | |
using SharedPtr_t = std::shared_ptr< Generator >; | |
private: | |
// -------------------------------------------------------------------- Types | |
using Dist_float_t = std::uniform_real_distribution< float >; | |
using Dist_double_t = std::uniform_real_distribution< double >; | |
using Dist_quadruple_t = std::uniform_real_distribution< long double >; | |
using Dist_i16_t = std::uniform_int_distribution < int16_t >; | |
using Dist_i32_t = std::uniform_int_distribution < int32_t >; | |
using Dist_i64_t = std::uniform_int_distribution < int64_t >; | |
using Dist_u16_t = std::uniform_int_distribution < uint16_t >; | |
using Dist_u32_t = std::uniform_int_distribution < uint32_t >; | |
using Dist_u64_t = std::uniform_int_distribution < uint64_t >; | |
using Dist_SizeT_t = std::uniform_int_distribution < std::size_t >; | |
// -------------------------------------------------------------------- Engine State | |
std::mt19937_64 _engine; | |
Dist_float_t _float_01_distribution; | |
Dist_double_t _double_01_distribution; | |
Dist_quadruple_t _quadruple_01_distribution; | |
Dist_float_t _float_distribution; | |
Dist_double_t _double_distribution; | |
Dist_quadruple_t _quadruple_distribution; | |
Dist_i16_t _int16_distribution; | |
Dist_i32_t _int32_distribution; | |
Dist_i64_t _int64_distribution; | |
Dist_u16_t _uint16_distribution; | |
Dist_u32_t _uint32_distribution; | |
Dist_u64_t _uint64_distribution; | |
Dist_SizeT_t _sizeT_distribution; | |
public: | |
// ==================================================================== Construct / Destruct | |
// Construct / Destruct | |
// -------------------------------------------------------------------- Construct (seed) | |
explicit Generator( uint_fast64_t seed ) | |
: _engine ( seed ), | |
_float_01_distribution ( 0.0f, 1.0f ), | |
_double_01_distribution ( 0.0, 1.0 ), | |
_quadruple_01_distribution( (long double)0.0, (long double)1.0 ) {} | |
// -------------------------------------------------------------------- Construct (random seed) | |
Generator() | |
: Generator( uint64_t(std::random_device{}()) << 32 | |
| uint64_t(std::random_device{}()) ) {} | |
/* | |
// MSYS2 / gcc on Windows is giving me the same fukcing numbers from std::random_device() | |
// every goddamned time. This is a temp workaround until I get better seeding tech in here. | |
Generator() | |
: Generator( time(NULL) ) | |
{} | |
*/ | |
// -------------------------------------------------------------------- Construct ( move ) | |
Generator( Generator && source ) | |
: _engine ( std::move( source._engine ) ), | |
_float_01_distribution ( std::move( source._float_01_distribution ) ), | |
_double_01_distribution ( std::move( source._double_01_distribution ) ), | |
_quadruple_01_distribution ( std::move( source._quadruple_01_distribution ) ) | |
{} | |
public: | |
// ==================================================================== Public API | |
// Public API | |
// -------------------------------------------------------------------- Engine | |
decltype(_engine) & Engine() { return _engine; } | |
// ==================================================================== Public API - Random Number Generation | |
// Public API - Random Number Generation | |
// -------------------------------------------------------------------- Bits | |
uint8_t Bits_8 () noexcept { return (uint8_t)_uint16_distribution( _engine, Dist_u16_t::param_type(0, std::numeric_limits< uint8_t >::max())); } | |
uint16_t Bits_16() noexcept { return _uint16_distribution( _engine, Dist_u16_t::param_type(0, std::numeric_limits< uint16_t >::max())); } | |
uint32_t Bits_32() noexcept { return _uint32_distribution( _engine, Dist_u32_t::param_type(0, std::numeric_limits< uint32_t >::max())); } | |
uint64_t Bits_64() noexcept { return _uint64_distribution( _engine, Dist_u64_t::param_type(0, std::numeric_limits< uint64_t >::max())); } | |
// -------------------------------------------------------------------- Bits (templated) | |
template< typename int_type_t > | |
int_type_t Bits() noexcept | |
{ | |
if constexpr( sizeof(int_type_t) == 1 ) return Bits_8 (); | |
if constexpr( sizeof(int_type_t) == 2 ) return Bits_16(); | |
if constexpr( sizeof(int_type_t) == 4 ) return Bits_32(); | |
if constexpr( sizeof(int_type_t) == 8 ) return Bits_64(); | |
} | |
// -------------------------------------------------------------------- Integers | |
int8_t Int_8 ( int8_t low, int8_t high ) noexcept { return _int16_distribution ( _engine, Dist_i16_t::param_type(low, high)); } | |
int16_t Int_16 ( int16_t low, int16_t high ) noexcept { return _int16_distribution ( _engine, Dist_i16_t::param_type(low, high)); } | |
int32_t Int_32 ( int32_t low, int32_t high ) noexcept { return _int32_distribution ( _engine, Dist_i32_t::param_type(low, high)); } | |
int64_t Int_64 ( int64_t low, int64_t high ) noexcept { return _int64_distribution ( _engine, Dist_i64_t::param_type(low, high)); } | |
uint8_t Uint_8 ( uint8_t low, uint8_t high ) noexcept { return _uint16_distribution( _engine, Dist_u16_t::param_type(low, high)); } | |
uint16_t Uint_16 ( uint16_t low, uint16_t high ) noexcept { return _uint16_distribution( _engine, Dist_u16_t::param_type(low, high)); } | |
uint32_t Uint_32 ( uint32_t low, uint32_t high ) noexcept { return _uint32_distribution( _engine, Dist_u32_t::param_type(low, high)); } | |
uint64_t Uint_64 ( uint64_t low, uint64_t high ) noexcept { return _uint64_distribution( _engine, Dist_u64_t::param_type(low, high)); } | |
std::size_t Size_T ( std::size_t low, std::size_t high ) noexcept { return _sizeT_distribution ( _engine, Dist_SizeT_t::param_type(low, high)); } | |
// -------------------------------------------------------------------- Integers (pairs) | |
int8_t Int_8 ( const int8_pair_t range ) noexcept { return Int_8 ( range.first, range.second ); } | |
int16_t Int_16 ( const int16_pair_t range ) noexcept { return Int_16 ( range.first, range.second ); } | |
int32_t Int_32 ( const int32_pair_t range ) noexcept { return Int_32 ( range.first, range.second ); } | |
int64_t Int_64 ( const int64_pair_t range ) noexcept { return Int_64 ( range.first, range.second ); } | |
uint8_t Uint_8 ( const uint8_pair_t range ) noexcept { return Uint_8 ( range.first, range.second ); } | |
uint16_t Uint_16 ( const uint16_pair_t range ) noexcept { return Uint_16( range.first, range.second ); } | |
uint32_t Uint_32 ( const uint32_pair_t range ) noexcept { return Uint_32( range.first, range.second ); } | |
uint64_t Uint_64 ( const uint64_pair_t range ) noexcept { return Uint_64( range.first, range.second ); } | |
std::size_t Size_T ( const size_t_pair_t range ) noexcept { return Size_T ( range.first, range.second ); } | |
// -------------------------------------------------------------------- Reals | |
float Float_01 () noexcept { return _float_01_distribution(_engine); } | |
double Double_01 () noexcept { return _double_01_distribution(_engine); } | |
long double Quadruple_01() noexcept { return _quadruple_01_distribution(_engine); } | |
float Float ( float low, float high ) noexcept { return _float_distribution( _engine, Dist_float_t::param_type(low, high)); } | |
double Double ( double low, double high ) noexcept { return _double_distribution( _engine, Dist_double_t::param_type(low, high)); } | |
long double Quadruple ( long double low, long double high ) noexcept { return _quadruple_01_distribution( _engine, Dist_quadruple_t::param_type(low, high)); } | |
// -------------------------------------------------------------------- Reals (pairs) | |
float Float ( const float_pair_t range ) noexcept { return Float ( range.first, range.second ); } | |
double Double ( const double_pair_t range ) noexcept { return Double ( range.first, range.second ); } | |
long double Quadruple( const quadruple_pair_t range ) noexcept { return Quadruple( range.first, range.second ); } | |
// -------------------------------------------------------------------- Overloaded | |
int_fast8_t Number ( int8_t low, int8_t high ) noexcept { return Int_8 (low, high); } | |
int_fast16_t Number ( int16_t low, int16_t high ) noexcept { return Int_16 (low, high); } | |
int_fast32_t Number ( int32_t low, int32_t high ) noexcept { return Int_32 (low, high); } | |
int_fast64_t Number ( int64_t low, int64_t high ) noexcept { return Int_64 (low, high); } | |
uint_fast8_t Number ( uint8_t low, uint8_t high ) noexcept { return Uint_8 (low, high); } | |
uint_fast16_t Number ( uint16_t low, uint16_t high ) noexcept { return Uint_16 (low, high); } | |
uint_fast32_t Number ( uint32_t low, uint32_t high ) noexcept { return Uint_32 (low, high); } | |
uint_fast64_t Number ( uint64_t low, uint64_t high ) noexcept { return Uint_64 (low, high); } | |
float Number ( float low, float high ) noexcept { return Float (low, high); } | |
double Number ( double low, double high ) noexcept { return Double (low, high); } | |
long double Number ( long double low, long double high ) noexcept { return Quadruple(low, high); } | |
// -------------------------------------------------------------------- Templated | |
template < typename value_t > | |
value_t Number( std::pair<value_t, value_t> range ) noexcept { return Number(range.first, range.second); } | |
// -------------------------------------------------------------------- Complex | |
template < typename value_t > | |
std::complex< value_t > Number( std::complex< value_t > low, | |
std::complex< value_t > high ) noexcept | |
{ | |
return { Number( low.real(), high.real() ), | |
Number( low.imag(), high.imag() ) }; | |
} | |
// -------------------------------------------------------------------- Complex( range ) | |
template < typename value_t > | |
std::complex< value_t > Number( std::pair< std::complex< value_t >, std::complex< value_t > > range ) | |
{ | |
return Number( range.first, range.second ); | |
} | |
// -------------------------------------------------------------------- Enum | |
template < typename enum_t > enum_t Enum( enum_t first, enum_t last ) noexcept { return enum_t( Number( Enum::as_Integer( first ), Enum::as_Integer( last ) ) ); } | |
template < typename enum_t > enum_t Enum( std::pair< enum_t, enum_t > range ) noexcept { return Enum( range.first, range.second ); } | |
// -------------------------------------------------------------------- Chance() | |
bool Chance ( float probability ) noexcept | |
{ | |
return Float_01() < probability; | |
} | |
// -------------------------------------------------------------------- Shuffle() | |
template < typename random_iter_t > | |
void Shuffle( random_iter_t begin, random_iter_t end ) | |
{ | |
std::shuffle( begin, end, _engine ); | |
} | |
}; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment