#include #include #include #include #include #include #include //#define IMPORT_ONE(NS, NAME) using NAME = NS :: NAME //IMPORT_ONE(std, ssize_t); template static inline To* offset_ptr(T* ptr, ssize_t by) noexcept { return reinterpret_cast(reinterpret_cast(ptr)+by); } /* template offset_ptr(auto* p, std::ssize_t by) -> offset_ptr; template offset_ptr(auto* p, std::ssize_t by) -> offset_ptr; */ #ifdef FT_PT_OPERATORS inline operator RNG*(rng_t ptr) noexcept { if(__builtin_expect(!ptr, false)) return nullptr; #ifdef DEBUG RNG* op = #else return #endif reinterpret_cast(offset_ptr(ptr, -static_cast(offsetof(RNG, _held)))); #ifdef DEBUG if(__builtin_expect(!op, false)) return nullptr; if(__builtin_expect(op->_held, false)) panic("Invalid rng_t -> RNG conversion"); return ptr; #endif } RNG::operator rng_t() const noexcept { return reinterpret_cast(static_cast(this)->_held); } #endif inline unsigned char RNG::byte() { return (unsigned char)next_int(255); } void RNG::bytes(unsigned char* ptr, std::size_t len) { for(std::size_t i=0;i namespace { // C interface using namespace std; [[gnu::always_inline, gnu::gnu_inline]] static inline RNG* extract_ptr(rng_t ptr) { return reinterpret_cast (ptr); } static inline RNG& extract_ref(rng_t rng) { return *extract_ptr(rng); } template T> static inline rng_t wrap_ptr(T* ptr) noexcept { if(__builtin_expect(!ptr, false)) return nullptr; return reinterpret_cast(static_cast(ptr)); } template static inline T* extract_downcast_ptr(rng_t rng) { return dynamic_cast(extract_ptr(rng)); } extern "C" { rng_t rng_new(rng_init_opt opt) { switch(opt.kind) { case RNG_KIND_FRNG: return wrap_ptr( new rng::frng(opt.init.frng.state) ); case RNG_KIND_DRNG: return wrap_ptr( new rng::drng(opt.init.drng.state) ); case RNG_KIND_XORNG: return wrap_ptr( new rng::xoroshiro128plus(opt.init.xorng.state) ); //case RNG_KIND_LORENX: return static_cast( new rng::lorenzAttractor(opt.init.lorenz); ); default: panic("Unknown RNG init opt: %d", opt.kind); __builtin_unreachable(); } return nullptr; } void rng_free(rng_t rng) { RNG* ptr = extract_ptr(rng); delete ptr; } [[gnu::nonnull(1)]] void rng_test_spec(rng_t rng) { auto& ref = extract_ref(rng); cout << "rng_test_spec (" << typeid(ref).name() << ")..." << std::flush; if constexpr(!is_noexcept) { #if EXCEPT try { rng::test_algo(std::move(ref)); } catch(const std::exception& except) { cout << "\r\r\r\tERROR: " << (except.what() ?: typeid(except).name()) << endl; rng_free(rng); throw; } catch(...) { cout << "\r\r\r\tERROR" << endl; rng_free(rng); throw; } #endif } else rng::test_algo(std::move(ref)); cout << "\r\r\r\tOK" << endl; rng_free(rng); } } }