diff --git a/array.c b/array.c index a19e7bb..00a6d37 100755 --- a/array.c +++ b/array.c @@ -4797,6 +4797,7 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary) VALUE opts, randgen = rb_cRandom; long n, len, i, j, k, idx[10]; long rnds[numberof(idx)]; + long memo_threshold; if (OPTHASH_GIVEN_P(opts)) { VALUE rnd; @@ -4856,6 +4857,7 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary) } return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k)); } + memo_threshold = len < 2560 ? len / 128 : len < 5120 ? len / 64 : len < 10240 ? len / 32 : len / 16; if (n <= numberof(idx)) { long sorted[numberof(idx)]; sorted[0] = idx[0] = rnds[0]; @@ -4875,6 +4877,25 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary) } }); } + else if (n <= memo_threshold) { + st_table *table = st_init_numtable_with_size(n); + long i2, j2; + st_data_t value; + result = rb_ary_new_capa(n); + RARRAY_PTR_USE(ary, ptr_ary, { + RARRAY_PTR_USE(result, ptr_result, { + for (i=0; i