/* * call-seq: * GMP::RandState.new() * GMP::RandState.new(:mt) #=> uses gmp_randinit_mt * GMP::RandState.new(:lc_2exp, a, c, m2exp) #=> uses gmp_randinit_lc_2exp * GMP::RandState.new(:lc_2exp_size, size) #=> uses gmp_randinit_lc_2exp_size * * Initializes a new Random State object. Multiple GMP::RandState objects can * be instantiated. They may use different generators and the states * are kept separate. */ VALUE r_gmprandstatesg_new(int argc, VALUE *argv, VALUE klass) { MP_RANDSTATE *rs_val; VALUE rs; VALUE algorithm, arg2, arg3, arg4; ID algorithm_id = rb_intern("default"); MP_INT *a_val; unsigned long c_val, m2exp_val; unsigned long size_val; int free_a_val = 0; ID default_algorithm = rb_intern("default"); ID mt_algorithm = rb_intern("mt"); ID lc_2exp_algorithm = rb_intern("lc_2exp"); ID lc_2exp_size_algorithm = rb_intern("lc_2exp_size"); (void)klass; mprandstate_make_struct(rs, rs_val); rb_scan_args(argc, argv, "04", &algorithm, &arg2, &arg3, &arg4); if (NIL_P(algorithm)) { algorithm_id = rb_intern("default"); } /* default value */ if (SYMBOL_P(algorithm)) { algorithm_id = rb_to_id(algorithm); } if (algorithm_id == default_algorithm || algorithm_id == mt_algorithm) { if (argc > 1) rb_raise(rb_eArgError, "wrong # of arguments (%d for 0 or 1)", argc); gmp_randinit_default(rs_val); } else if (algorithm_id == lc_2exp_algorithm) { if (argc != 4) rb_raise(rb_eArgError, "wrong # of arguments (%d for 4)", argc); if (GMPZ_P(arg2)) { mpz_get_struct(arg2, a_val); } else if (FIXNUM_P(arg2)) { mpz_temp_alloc(a_val); mpz_init_set_ui(a_val, FIX2INT(arg2)); free_a_val = 1; } else if (BIGNUM_P(arg2)) { mpz_temp_from_bignum(a_val, arg2); free_a_val = 1; } else { typeerror_as(ZXB, "b"); } c_val = NUM2LONG(arg3); m2exp_val = NUM2LONG(arg4); gmp_randinit_lc_2exp(rs_val, a_val, c_val, m2exp_val); } else if (algorithm_id == lc_2exp_size_algorithm) { if (argc != 2) rb_raise(rb_eArgError, "wrong # of arguments (%d for 2)", argc); size_val = NUM2LONG(arg2); if (size_val > 128) rb_raise(rb_eArgError, "size must be within [0..128]"); if (gmp_randinit_lc_2exp_size (rs_val, size_val) == 0) rb_raise(rb_eArgError, "could not gmp_randinit_lc_2exp_size with %lu", size_val); } if (free_a_val) { mpz_temp_free(a_val); } rb_obj_call_init(rs, argc, argv); return rs; }
/* Call (*func)() with various random number generators. */ void call_rand_algs (void (*func) (const char *, gmp_randstate_ptr)) { gmp_randstate_t rstate; mpz_t a; mpz_init (a); gmp_randinit_default (rstate); (*func) ("gmp_randinit_default", rstate); gmp_randclear (rstate); gmp_randinit_mt (rstate); (*func) ("gmp_randinit_mt", rstate); gmp_randclear (rstate); gmp_randinit_lc_2exp_size (rstate, 8L); (*func) ("gmp_randinit_lc_2exp_size 8", rstate); gmp_randclear (rstate); gmp_randinit_lc_2exp_size (rstate, 16L); (*func) ("gmp_randinit_lc_2exp_size 16", rstate); gmp_randclear (rstate); gmp_randinit_lc_2exp_size (rstate, 128L); (*func) ("gmp_randinit_lc_2exp_size 128", rstate); gmp_randclear (rstate); /* degenerate always zeros */ mpz_set_ui (a, 0L); gmp_randinit_lc_2exp (rstate, a, 0L, 8L); (*func) ("gmp_randinit_lc_2exp a=0 c=0 m=8", rstate); gmp_randclear (rstate); /* degenerate always FFs */ mpz_set_ui (a, 0L); gmp_randinit_lc_2exp (rstate, a, 0xFFL, 8L); (*func) ("gmp_randinit_lc_2exp a=0 c=0xFF m=8", rstate); gmp_randclear (rstate); mpz_clear (a); }
int gmp_randinit_lc_2exp_size (gmp_randstate_t rstate, unsigned long size) { const struct __gmp_rand_lc_scheme_struct *sp; mpz_t a; /* Pick a scheme. */ for (sp = __gmp_rand_lc_scheme; sp->m2exp != 0; sp++) if (sp->m2exp / 2 >= size) goto found; return 0; found: /* Install scheme. */ mpz_init_set_str (a, sp->astr, 16); gmp_randinit_lc_2exp (rstate, a, sp->c, sp->m2exp); mpz_clear (a); return 1; }
int check_params (void) { gmp_randstate_t r1, r2; mpz_t a, b, m; int i; int result; result = TRUE; mpz_init (a); mpz_init (b); mpz_init (m); if (result) { /* Test the consistency between urandomm and urandomb. */ gmp_randinit_default (r1); gmp_randinit_default (r2); gmp_randseed_ui (r1, 85L); gmp_randseed_ui (r2, 85L); mpz_set_ui (m, 0L); mpz_setbit (m, 80L); for (i = 0; i < 100; i++) { mpz_urandomm (a, r1, m); mpz_urandomb (b, r2, 80L); if (mpz_cmp (a, b) != 0) { result = FALSE; printf ("mpz_urandomm != mpz_urandomb\n"); break; } } gmp_randclear (r1); gmp_randclear (r2); } if (result) { /* Test that mpz_urandomm returns the correct result with a broken LC. */ mpz_set_ui (a, 0L); gmp_randinit_lc_2exp (r1, a, 0xffL, 8L); mpz_set_ui (m, 5L); /* Warning: This code hangs in gmp 4.1 and below */ for (i = 0; i < 100; i++) { mpz_urandomm (a, r1, m); if (mpz_cmp_ui (a, 2L) != 0) { result = FALSE; gmp_printf ("mpz_urandomm returns %Zd instead of 2\n", a); break; } } gmp_randclear (r1); } if (result) { /* Test that the results are always in range for either positive or negative values of m. */ gmp_randinit_default (r1); mpz_set_ui (m, 5L); mpz_set_si (b, -5L); for (i = 0; i < 100; i++) { mpz_urandomm (a, r1, m); if (mpz_cmp_ui (a, 5L) >= 0 || mpz_sgn (a) < 0) { result = FALSE; gmp_printf ("Out-of-range or non-positive value: %Zd\n", a); break; } mpz_urandomm (a, r1, b); if (mpz_cmp_ui (a, 5L) >= 0 || mpz_sgn (a) < 0) { result = FALSE; gmp_printf ("Out-of-range or non-positive value (from negative modulus): %Zd\n", a); break; } } gmp_randclear (r1); } if (result) { /* Test that m=1 forces always result=0. */ gmp_randinit_default (r1); mpz_set_ui (m, 1L); for (i = 0; i < 100; i++) { mpz_urandomm (a, r1, m); if (mpz_sgn (a) != 0) { result = FALSE; gmp_printf ("mpz_urandomm fails with m=1 (result=%Zd)\n", a); break; } } gmp_randclear (r1); } mpz_clear (a); mpz_clear (b); mpz_clear (m); return result; }