@ -1,3 +1,5 @@
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
# include <bit>
# include <climits>
@ -16,7 +18,14 @@ constexpr const i64 _J_RANGE_MAX = (i64)INT32_MAX;
static_assert ( _J_RANGE_MIN = = rng : : crand : : RANGE_MIN ) ;
static_assert ( _J_RANGE_MAX = = rng : : crand : : RANGE_MAX ) ;
namespace {
template < typename T >
inline void setinc ( u8 * & ptr , auto val )
{
* reinterpret_cast < T * > ( ptr ) = T ( val ) ;
ptr + = sizeof ( T ) ;
}
}
namespace rng
{
void crand : : _deleter : : delete_object ( _opaque * * state ) { _jr_free ( reinterpret_cast < jr_state * > ( * state ) ) ; * state = nullptr ; }
@ -35,7 +44,30 @@ namespace rng
i32 crand : : next_i32 ( ) { return ( i32 ) next_i64 ( ) ; }
u32 crand : : next_u32 ( ) { return std : : bit_cast < u32 > ( ( i32 ) _sample_int ( ) ) ; } // I think keeping the sign bit in the transmute here doesn't violate the distribution, since it's between int32's min and max value...
//TODO: next_bytes(), next_v*()
// next_bytes(), next_v*()
void crand : : next_bytes ( u8 * b , usize n )
{
while ( n )
switch ( n % 4 ) // this is soo dogy...
{
case 0 : setinc < u32 > ( b , std : : bit_cast < u64 > ( _sample_int ( ) & _J_RANGE_MAX ) ) ; n - = 4 ; break ;
case 3 : setinc < u8 > ( b , std : : bit_cast < u64 > ( _sample_int ( ) ) & 0xff ) ; n - = 1 ;
case 2 : setinc < u16 > ( b , std : : bit_cast < u64 > ( _sample_int ( ) ) & 0xffff ) ; n - = 2 ;
break ;
case 1 : * b + + = u8 ( _sample_int ( ) & 0xff ) ; n - = 1 ; break ;
}
}
void crand : : next_v32 ( u32 * p , usize n )
{
while ( n - - > 0 ) * p + + = ( u32 ) ( _sample_int ( ) & INT32_MAX ) ;
}
void crand : : next_v64 ( u64 * p , usize n )
{
while ( n - - > 0 ) * p + + = u64 ( _sample_int ( ) & INT32_MAX ) + ( u64 ( _sample_int ( ) & INT32_MAX ) < < 32 ) ;
}
}
void rng_test ( )
@ -46,6 +78,15 @@ void rng_test()
printf ( " %d %d %d \n " , r . next_i32 ( ) , r . next_i32 ( ) , r . next_i32 ( ) ) ;
printf ( " %u %u %u \n " , r . next_u32 ( ) , r . next_u32 ( ) , r . next_u32 ( ) ) ;
union {
volatile u64 u ;
u8 b [ sizeof ( u64 ) ] ;
std : : array < u8 , sizeof ( u64 ) > a ;
} thing = { 0 } ;
r . next_bytes ( thing . b , sizeof ( u64 ) ) ;
printf ( " chaos: %lu, %lu, %lu \n " , thing . u , ( r . next_bytes ( thing . a ) , thing . u ) , ( r . next_bytes ( thing . b ) , thing . u ) ) ;
// TODO: these aren't implemented yet in the base Random huh...
printf ( " --- \n %u %d %d %u \n " , r . next_u32 ( 10 , 20 ) , r . next_i32 ( 10 , 20 ) , r . next_i32 ( 10 ) , r . next_u32 ( 10 ) ) ;
}