Skip to content

Instantly share code, notes, and snippets.

@jrandom

jrandom/Random.h Secret

Last active March 31, 2018 15:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jrandom/170e00d5ad7b08c71ac708e5137e8867 to your computer and use it in GitHub Desktop.
Save jrandom/170e00d5ad7b08c71ac708e5137e8867 to your computer and use it in GitHub Desktop.
Latest Random Wrapper
//
// 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