static mrb_value mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) { mrb_int i; mt_state *random = NULL; if (RARRAY_LEN(ary) > 1) { mrb_get_args(mrb, "|d", &random, &mt_state_type); if (random == NULL) { random = get_random_state(mrb); } mrb_random_rand_seed(mrb, random); mrb_ary_modify(mrb, mrb_ary_ptr(ary)); for (i = RARRAY_LEN(ary) - 1; i > 0; i--) { mrb_int j; mrb_value tmp; j = mrb_fixnum(mrb_random_mt_rand(mrb, random, mrb_fixnum_value(RARRAY_LEN(ary)))); tmp = RARRAY_PTR(ary)[i]; mrb_ary_ptr(ary)->ptr[i] = RARRAY_PTR(ary)[j]; mrb_ary_ptr(ary)->ptr[j] = tmp; } } return ary; }
static mrb_value mrb_ary_sample(mrb_state *mrb, mrb_value ary) { mrb_int n = 0; mrb_bool given; mt_state *random = NULL; mrb_int len = RARRAY_LEN(ary); mrb_get_args(mrb, "|i?d", &n, &given, &random, &mt_state_type); if (random == NULL) { random = get_random_state(mrb); } mrb_random_rand_seed(mrb, random); mt_rand(random); if (!given) { /* pick one element */ switch (len) { case 0: return mrb_nil_value(); case 1: return RARRAY_PTR(ary)[0]; default: return RARRAY_PTR(ary)[mt_rand(random) % len]; } } else { mrb_value result; mrb_int i, j; if (n < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "negative sample number"); if (n > len) n = len; result = mrb_ary_new_capa(mrb, n); for (i=0; i<n; i++) { mrb_int r; for (;;) { retry: r = mt_rand(random) % len; for (j=0; j<i; j++) { if (mrb_fixnum(RARRAY_PTR(result)[j]) == r) { goto retry; /* retry if duplicate */ } } break; } RARRAY_PTR(result)[i] = mrb_fixnum_value(r); RARRAY_LEN(result)++; } for (i=0; i<n; i++) { RARRAY_PTR(result)[i] = RARRAY_PTR(ary)[mrb_fixnum(RARRAY_PTR(result)[i])]; } return result; } }