// C api for rngxx
# ifndef _RNGXX_H
# define _RNGXX_H
# ifndef _RNGXX_IMPL
# define _RNGXX_COMMON_MINIMAL
# endif
# include "rngxx/internal/common.h"
# ifndef _RNGXX_IMPL
# undef _RNGXX_COMMON_MINIMAL
# endif
# ifdef __cplusplus
# ifndef _RNGXX_IMPL_ONLY_TYPES
# warning "C++ compilers might not like this header file. Please use the C++ interface for C++ TUs"
# endif
extern " C " {
# endif
// -- C API types -- (C++ compat)
typedef struct Random rng_t ;
enum rng_kind {
RNG_KIND_CRAND ,
RNG_KIND_SM64 ,
} ;
enum rng_next_flag {
RNG_TYQ_SIGNED = 0 , // Binary with `unsigned`.
RNG_TYQ_UNSIGNED = 1 < < 0 ,
RNG_TYQ_CHAOS = 1 < < 1 ,
RNG_TYQ_ARRAY = 1 < < 2 ,
} ; // 3 bits
typedef int rng_bool_t ;
enum rng_next_type {
RNG_TY_BLOB = 0 ,
RNG_TY_BOOL , // Expects type `rng_bool_t`.
RNG_TY_INT8 ,
RNG_TY_INT16 ,
RNG_TY_INT32 ,
RNG_TY_INT64 ,
RNG_TY_F32 ,
RNG_TY_F64 ,
} ; // 4 bits
struct rng_next_opt {
union {
// Bounded types
struct {
const void * restrict pmin ;
const void * restrict pmax ;
} range ;
// Blob types
size_t len ;
} bound ;
struct {
enum rng_next_type type : 4 ;
enum rng_next_flag mod : 3 ;
uint8_t _unused0 : 1 ;
//first byte
uint32_t _padding : 24 ;
} ty ; // 32 bits :/
union {
uint32_t array_size ;
} ex ; // 32 bits. fills hole
} ;
typedef __typeof ( ( ( struct rng_next_opt * ) NULL ) - > ty ) rng_next_tyq ; // Qualified type
typedef rng_t * ( * rng_ctor_fn ) ( const void * ) ;
typedef struct rng_dyn_ctor * rng_dyn_ctor_ref ;
// -- // --
# ifndef _RNGXX_IMPL_ONLY_TYPES
_Static_assert ( sizeof ( rng_next_tyq ) = = sizeof ( uint32_t ) ) ;
_Static_assert ( sizeof ( ( ( struct rng_next_opt * ) NULL ) - > ex ) = = sizeof ( uint32_t ) ) ;
// -- C API functions -- (C++ NO compat)
int rng_raw ( rng_t * engine , void * restrict output , struct rng_next_opt opt ) ;
void rng_next_bin ( rng_t * engine , unsigned char * restrict output , size_t n ) ;
void * rng_next_ty ( rng_t * engine , void * restrict output , enum rng_next_type ty , enum rng_next_flag flags ) ;
void * rng_next_tya ( rng_t * engine , void * restrict output , enum rng_next_type ty , enum rng_next_flag flags , uint32_t sz ) ;
void * rng_next_tyab ( rng_t * engine , void * restrict output , enum rng_next_type ty , enum rng_next_flag flags , uint32_t sz , const void * pmin , const void * pmax ) ;
void * rng_next_tyb ( rng_t * engine , void * restrict output , enum rng_next_type ty , enum rng_next_flag flags , const void * pmin , const void * pmax ) ;
rng_dyn_ctor_ref rng_ctor_ref ( const char * name ) ;
rng_ctor_fn rng_ctor ( const char * name ) __attribute__ ( ( deprecated ( " many dynamic ctors will have state that cannot be expressed through a raw function pointer, and so this method will not work for them. use `rng_ctor_ref` and `rng_ctor_call` instead where possible, unless you know that the dynamic ctor is a bare function pointer. " ) ) ) ; // Get a dynamic ctor that is a raw funciton pointer. If the ctor for this name is not a raw function pointer (if it has state), then NULL is returned.
rng_t * rng_ctor_call ( rng_dyn_ctor_ref ctor , const void * seed ) ;
rng_t * rng_new_named ( const char * name , const void * seed ) ;
rng_t * rng_new ( enum rng_kind kind , const u64 seed [ static restrict 1 ] ) ;
void rng_free ( rng_t * rng ) ;
# ifdef _RNGXX_INLINE_ONLY
# define _rng__always_inline __attribute__((gnu_inline)) inline extern
# else
# define _rng__always_inline __attribute__((gnu_inline)) inline static
# endif
# define _NEXT_TYPED_(name, T, N, S) \
_rng__always_inline T rng_next_ # # name ( rng_t * engine , const T * min , const T * max ) \
{ \
T output ; \
rng_next_tyb ( engine , & output , RNG_TY_ # # N , RNG_TYQ_ # # S , min , max ) ; \
return output ; \
} \
_rng__always_inline T * rng_nexta_ # # name ( uint32_t len ; rng_t * engine , T output [ restrict len ] , uint32_t len , const T * min , const T * max ) \
{ \
return rng_next_tyab ( engine , output , RNG_TY_ # # N , RNG_TYQ_ # # S , len , min , max ) ; \
} \
_rng__always_inline T * rng_nextam_ # # name ( rng_t * engine , uint32_t len , const T * min , const T * max ) \
{ \
return rng_next_tyab ( engine , NULL , RNG_TY_ # # N , RNG_TYQ_ # # S , len , min , max ) ; \
}
# define _NEXT_TYPED(T, N, S) _NEXT_TYPED_(T, T, N, S)
# define NEXT_TYPED_INT(n) _NEXT_TYPED(i ## n, INT ## n, SIGNED) \
_NEXT_TYPED ( u # # n , INT # # n , UNSIGNED )
NEXT_TYPED_INT ( 8 )
NEXT_TYPED_INT ( 16 )
NEXT_TYPED_INT ( 32 )
NEXT_TYPED_INT ( 64 )
_NEXT_TYPED ( f32 , F32 , SIGNED )
_NEXT_TYPED ( f64 , F64 , SIGNED )
_rng__always_inline rng_bool_t rng_next_bool ( rng_t * engine )
{
rng_bool_t output ;
rng_next_tyb ( engine , & output , RNG_TY_BOOL , 0 , NULL , NULL ) ;
return output & 1 ;
}
_rng__always_inline rng_bool_t * rng_nexta_bool ( uint32_t len ; rng_t * engine , rng_bool_t output [ restrict len ] , uint32_t len )
{
return rng_next_tyab ( engine , output , RNG_TY_BOOL , 0 , len , NULL , NULL ) ;
}
_rng__always_inline rng_bool_t * rng_nextam_bool ( rng_t * engine , uint32_t len )
{
return rng_next_tyab ( engine , NULL , RNG_TY_BOOL , 0 , len , NULL , NULL ) ;
}
# undef NEXT_TYPED_INT
# undef _NEXT_TYPED
# undef _NEXT_TYPED_
# undef _rng__always_inline
// -- // --
# endif
# ifdef __cplusplus
}
# endif
# endif /* _RNGXX_H */