# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
# include <bit>
# include <climits>
# include <cmath>
# include <rngxx.hpp>
# include <mem.h>
# include <rngxx/crand.h>
# include "crand.h"
// Note: the output of drand48 is uniform between INT32_MIN..=INT32_MAX (inclusive)
constexpr const i64 _J_RANGE_MIN = ( i64 ) INT32_MIN ;
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 ; }
crand : : crand ( _opaque * raw ) : Random ( ) , _state ( mem : : aligned_ptr < _opaque , _deleter > ( raw ) ) { }
crand : : crand ( u64 seed ) : crand ( reinterpret_cast < _opaque * > ( _jr_new ( seed ) ) ) { }
crand : : crand ( ) : crand ( 0xabad1dea ) { }
i64 crand : : _sample_int ( ) { return _jr_proc ( reinterpret_cast < jr_state * > ( & _state ) ) ; } //RANGE_MIN..=RANGE_MAX
f64 crand : : _sample ( ) { return _jr_procf ( reinterpret_cast < jr_state * > ( & _state ) ) ; } //0..1
// Overrides //
u64 crand : : next_u64 ( ) { return std : : bit_cast < u64 > ( std : : abs ( _sample_int ( ) ) & INT32_MAX ) ; }
// next_i/u64(max) overrides not nessicary, the impl would be same as base. same with array next_*(p, n) overrides
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...
// 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 ) ;
}
}