// 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 */