/* rand.c -- rand_r/random_r interface */ /* Copyright (c) 2009-2011 Alex Shinn. All rights reserved. */ /* BSD-style license: http://synthcode.com/license.txt */ #include #include #define SEXP_RANDOM_STATE_SIZE 128 #define ZERO sexp_make_fixnum(0) #define ONE sexp_make_fixnum(1) #define STATE_SIZE sexp_make_fixnum(SEXP_RANDOM_STATE_SIZE) #define sexp_random_source_p(x) sexp_check_tag(x, rs_type_id) #define sexp_random_init(x, seed) \ initstate_r(seed, \ sexp_string_data(sexp_random_state(x)), \ SEXP_RANDOM_STATE_SIZE, \ sexp_random_data(x)) #if SEXP_BSD || defined(__CYGWIN__) typedef unsigned int sexp_random_t; #define sexp_call_random(rs, dst) ((dst) = rand_r(sexp_random_data(rs))) #define sexp_seed_random(n, rs) *sexp_random_data(rs) = (n) #else typedef struct random_data sexp_random_t; #define sexp_call_random(rs, dst) random_r(sexp_random_data(rs), &dst) #define sexp_seed_random(n, rs) srandom_r(n, sexp_random_data(rs)) #endif #define sexp_random_state(x) (sexp_slot_ref((x), 0)) #define sexp_random_data(x) ((sexp_random_t*)(&sexp_slot_ref((x), 1))) #define sexp_sizeof_random (sexp_sizeof_header + sizeof(sexp_random_t) + sizeof(sexp)) static sexp_uint_t rs_type_id = 0; static sexp default_random_source; static sexp sexp_rs_random_integer (sexp ctx, sexp self, sexp_sint_t n, sexp rs, sexp bound) { sexp res; int32_t m; #if SEXP_USE_BIGNUMS int32_t hi, mod, len, i, *data; #endif if (! sexp_random_source_p(rs)) res = sexp_type_exception(ctx, self, rs_type_id, rs); if (sexp_fixnump(bound)) { sexp_call_random(rs, m); res = sexp_make_fixnum(m % sexp_unbox_fixnum(bound)); #if SEXP_USE_BIGNUMS } else if (sexp_bignump(bound)) { hi = sexp_bignum_hi(bound); len = hi * sizeof(sexp_uint_t) / sizeof(int32_t); res = sexp_make_bignum(ctx, hi); data = (int32_t*) sexp_bignum_data(res); for (i=0; i