Added `nexta[m]` array handling functions.

Fixed C-C++ bool interop sizing bug.

Fortune for rngxx's current commit: Small curse − 小凶
iter
Avril 3 years ago
parent 5a4b68ab3f
commit b071cbb1ad
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -68,7 +68,7 @@ struct rng_next_opt {
uint32_t _padding : 24; uint32_t _padding : 24;
} ty; // 32 bits :/ } ty; // 32 bits :/
union { union {
uint32_t array_size; //TODO: Implement next for arrays uint32_t array_size;
} ex; // 32 bits. fills hole } ex; // 32 bits. fills hole
}; };
@ -90,6 +90,8 @@ 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_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_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); 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_dyn_ctor_ref rng_ctor_ref(const char* name);
@ -112,6 +114,14 @@ _rng__always_inline T rng_next_ ## name (rng_t* engine, const T* min, const T* m
T output; \ T output; \
rng_next_tyb(engine, &output, RNG_TY_ ## N, RNG_TYQ_ ## S, min, max); \ rng_next_tyb(engine, &output, RNG_TY_ ## N, RNG_TYQ_ ## S, min, max); \
return output; \ 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(T, N, S) _NEXT_TYPED_(T, T, N, S)
@ -133,6 +143,14 @@ _rng__always_inline rng_bool_t rng_next_bool(rng_t* engine)
rng_next_tyb(engine, &output, RNG_TY_BOOL, 0, NULL, NULL); rng_next_tyb(engine, &output, RNG_TY_BOOL, 0, NULL, NULL);
return output & 1; 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_INT
#undef _NEXT_TYPED #undef _NEXT_TYPED

@ -29,11 +29,27 @@ namespace bridge _export(internal)
return engine.next<T>(); return engine.next<T>();
} }
template<typename T>
inline void rep_ptr(void* vptr, size_t n, auto lambda)
{
T* ptr = reinterpret_cast<T*>(vptr);
if(!n) lambda(ptr);
else while( n --> 0 ) lambda(ptr++);
}
template<typename T> template<typename T>
inline void next_typed_into(Random& engine, void* restrict output, const void* minp = nullptr, const void* maxp = nullptr) inline void next_typed_into(Random& engine, void* restrict output, const void* minp = nullptr, const void* maxp = nullptr)
{ {
*reinterpret_cast<T* restrict>(output) = next_typed<T>(engine, minp, maxp); *reinterpret_cast<T* restrict>(output) = next_typed<T>(engine, minp, maxp);
} }
template<typename T>
inline void next_typed_into_n(Random& engine, void* restrict output, size_t rep = 0, const void* minp = nullptr, const void* maxp = nullptr)
{
if(!rep) return next_typed_into<T>(engine, output, minp, maxp);
T* restrict ro = reinterpret_cast<T*>(output);
while( rep --> 0 )
next_typed_into<T>(engine, reinterpret_cast<void*>(ro++), minp, maxp);
}
inline void nblob(Random& engine, unsigned char* restrict output, size_t es, size_t l) inline void nblob(Random& engine, unsigned char* restrict output, size_t es, size_t l)
{ {
@ -47,7 +63,7 @@ namespace bridge _export(internal)
{ {
switch(ty) switch(ty)
{ {
case RNG_TY_BOOL: return alignof(bool); case RNG_TY_BOOL: return alignof(rng_bool_t);
case RNG_TY_INT8: return alignof(i8); case RNG_TY_INT8: return alignof(i8);
case RNG_TY_INT16: return alignof(i16); case RNG_TY_INT16: return alignof(i16);
@ -64,7 +80,7 @@ namespace bridge _export(internal)
{ {
switch(ty) switch(ty)
{ {
case RNG_TY_BOOL: return sizeof(bool); case RNG_TY_BOOL: return sizeof(rng_bool_t);
case RNG_TY_INT8: return sizeof(i8); case RNG_TY_INT8: return sizeof(i8);
case RNG_TY_INT16: return sizeof(i16); case RNG_TY_INT16: return sizeof(i16);
@ -81,11 +97,14 @@ namespace bridge _export(internal)
constexpr inline bool ty_signed(rng_next_flag f) { return ! (f & RNG_TYQ_UNSIGNED); } constexpr inline bool ty_signed(rng_next_flag f) { return ! (f & RNG_TYQ_UNSIGNED); }
constexpr inline bool ty_signed(const rng_next_tyq& qt) { return ty_signed(qt.mod); } constexpr inline bool ty_signed(const rng_next_tyq& qt) { return ty_signed(qt.mod); }
constexpr inline bool ty_hasflag(rng_next_flag hay, rng_next_flag nee) { return !!(hay & nee); }
constexpr inline bool ty_hasflag(const rng_next_tyq& q, rng_next_flag nee) { return ty_hasflag(q.mod, nee); }
template<typename S, typename U> template<typename S, typename U>
inline auto next_fun_of(const rng_next_tyq& ty) inline auto next_fun_of(const rng_next_tyq& ty)
{ {
if(ty_signed(ty)) return &next_typed_into<S>; if(ty_signed(ty)) return &next_typed_into_n<S>; //ty.hasflag(ty, RNG_TYQ_ARRAY) ? &next_typed_into_n<S> : &next_typed_into<S>;
else return &next_typed_into<U>; else return &next_typed_into_n<U>; //ty.hasflag(ty, RNG_TYQ_ARRAY) ? &next_typed_into_n<U> : &next_typed_into<U>;
} }
auto dc_lookup(const char* name) auto dc_lookup(const char* name)
@ -126,25 +145,30 @@ extern "C" {
return 1; return 1;
} }
const size_t array = bridge::ty_hasflag(opt->ty, RNG_TYQ_ARRAY)
? static_cast<size_t>(opt->ex.array_size)
: 0;
switch(opt->ty.type) switch(opt->ty.type)
{ {
case RNG_TY_BLOB: bridge::nblob(*engine, reinterpret_cast<unsigned char*>(output), opt->bound.len); break; case RNG_TY_BLOB: bridge::nblob(*engine, reinterpret_cast<unsigned char*>(output), opt->bound.len); break;
#define INTTY(bits) case RNG_TY_INT ## bits: \ #define INTTY(bits) case RNG_TY_INT ## bits: \
bridge::next_fun_of<i ## bits, u ## bits>(opt->ty)(*engine, output, opt->bound.range.pmin, opt->bound.range.pmax); break bridge::next_fun_of<i ## bits, u ## bits>(opt->ty)(*engine, output, array, opt->bound.range.pmin, opt->bound.range.pmax); break
INTTY(8); INTTY(8);
INTTY(16); INTTY(16);
INTTY(32); INTTY(32);
INTTY(64); INTTY(64);
#undef INTTY #undef INTTY
case RNG_TY_F32: case RNG_TY_F32:
bridge::next_typed_into<f32>(*engine, output, opt->bound.range.pmin, opt->bound.range.pmax); bridge::next_typed_into_n<f32>(*engine, output, array, opt->bound.range.pmin, opt->bound.range.pmax);
break; break;
case RNG_TY_F64: case RNG_TY_F64:
bridge::next_typed_into<f64>(*engine, output, opt->bound.range.pmin, opt->bound.range.pmax); bridge::next_typed_into_n<f64>(*engine, output, array, opt->bound.range.pmin, opt->bound.range.pmax);
break; break;
case RNG_TY_BOOL: case RNG_TY_BOOL:
*reinterpret_cast<rng_bool_t*>(output) = bridge::next_typed<bool>(*engine, output) ? 1 : 0; bridge::rep_ptr<rng_bool_t>(output, array, [&](rng_bool_t* restrict output) {
*output = bridge::next_typed<bool>(*engine) ? 1 : 0;
});
break; break;
default: return 0; default: return 0;
} }

@ -45,6 +45,37 @@ static void* m_alloc_for(enum rng_next_type ty)
return NULL; return NULL;
} }
static void* m_alloc_array(enum rng_next_type ty, size_t ars)
{
size_t s, a;
switch( RNG_IMPL(m_allocsz_for)(ty, &s, &a) )
{
case 2: // size 0, align nonzero
case 0: break;
case 1: return calloc(ars, s);
case 3: return aligned_alloc(a, s * ars);
}
return NULL;
}
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)
{
if(!sz) return output;
if(! (output = output ?: m_alloc_array(ty, (size_t)sz)) ) return NULL;
RNG_IMPL(mnext)(engine, output, &(struct rng_next_opt){
.bound.range = { pmin, pmax },
.ty = {
.type = ty,
.mod = flags | (sz > 1 ? RNG_TYQ_ARRAY : 0 ),
},
.ex = {
.array_size = sz,
},
});
return output;
}
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) 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)
{ {
if(! ( output = output ?: m_alloc_for(ty)) ) return NULL; if(! ( output = output ?: m_alloc_for(ty)) ) return NULL;
@ -58,6 +89,7 @@ void* rng_next_tyb(rng_t* engine, void* restrict output, enum rng_next_type ty,
.type = ty, .type = ty,
.mod = flags, .mod = flags,
}, },
.ex = {0},
}); });
return output; return output;
@ -68,6 +100,12 @@ void* rng_next_ty(rng_t* engine, void* restrict output, enum rng_next_type ty, e
return rng_next_tyb(engine, output, ty, flags, NULL, NULL); return rng_next_tyb(engine, output, ty, flags, NULL, NULL);
} }
void* rng_next_tya(rng_t* engine, void* restrict output, enum rng_next_type ty, enum rng_next_flag flags, uint32_t sz)
{
if(!sz) return output;
return rng_next_tyab(engine, output, ty, flags, sz, NULL, NULL);
}
rng_t* rng_new_named(const char* name, const void* seed) rng_t* rng_new_named(const char* name, const void* seed)
{ {
return RNG_IMPL(dynctor_trycall)(name, seed); return RNG_IMPL(dynctor_trycall)(name, seed);

@ -46,6 +46,27 @@ int main()
printf("%ld\n", rng_next_i64(engine, NULL, NULL)); printf("%ld\n", rng_next_i64(engine, NULL, NULL));
printf("%lf\n", rng_next_f64(engine, TREF(1.0), TREF(100.0))); printf("%lf\n", rng_next_f64(engine, TREF(1.0), TREF(100.0)));
printf("%d\n", rng_next_bool(engine)); printf("%d\n", rng_next_bool(engine));
rng_bool_t* array = rng_nextam_bool(engine, 100);
if(!array) {
fprintf(stderr, "failed to allocate for array\n");
return 1;
}
for(int i=0;i<100;i++)
printf("%d ", array[i]);
printf("\n"); free(array);
int ints[100];
if(!rng_nexta_i32(engine, ints, 100, NULL, TREF(100))) {
fprintf(stderr, "failed to compute int array\n");
return 1;
}
for(size_t i=0;i<sizeof(ints)/sizeof(ints[0]);i++)
printf("%d ", ints[i]);
printf("\n");
rng_free(engine); rng_free(engine);
return 0; return 0;
} }

Loading…
Cancel
Save