@@ -1433,16 +1433,17 @@ random_usize_limited(VALUE rnd, size_t max)
14331433}
14341434#endif
14351435
1436- struct sample_single_memo {
1436+ struct enum_sample_memo {
14371437 size_t k ;
1438+ long n ;
14381439 VALUE sample ;
14391440 VALUE random ;
14401441};
14411442
14421443static VALUE
14431444enum_sample_single_i (RB_BLOCK_CALL_FUNC_ARGLIST (e , data ))
14441445{
1445- struct sample_single_memo * memo = (struct sample_single_memo * )data ;
1446+ struct enum_sample_memo * memo = (struct enum_sample_memo * )data ;
14461447 ENUM_WANT_SVALUE ();
14471448
14481449 if (++ memo -> k <= 1 ) {
@@ -1461,9 +1462,10 @@ enum_sample_single_i(RB_BLOCK_CALL_FUNC_ARGLIST(e, data))
14611462static VALUE
14621463enum_sample_single (VALUE obj , VALUE random )
14631464{
1464- struct sample_single_memo memo ;
1465+ struct enum_sample_memo memo ;
14651466
14661467 memo .k = 0 ;
1468+ memo .n = 1 ;
14671469 memo .sample = Qundef ;
14681470 memo .random = random ;
14691471
@@ -1473,13 +1475,46 @@ enum_sample_single(VALUE obj, VALUE random)
14731475}
14741476
14751477static VALUE
1476- enum_sample_multiple_unweighted ( VALUE obj , long size , int replace_p )
1478+ enum_sample_multiple_without_replace_unweighted_i ( RB_BLOCK_CALL_FUNC_ARGLIST ( e , data ) )
14771479{
1478- assert (size > 1 );
1480+ struct enum_sample_memo * memo = (struct enum_sample_memo * )data ;
1481+ ENUM_WANT_SVALUE ();
1482+
1483+ if (++ memo -> k <= memo -> n ) {
1484+ rb_ary_push (memo -> sample , e );
1485+ }
1486+ else {
1487+ size_t j = random_usize_limited (memo -> random , memo -> k - 1 );
1488+ if (j <= memo -> n ) {
1489+ rb_ary_store (memo -> sample , (long )(j - 1 ), e );
1490+ }
1491+ }
14791492
14801493 return Qnil ;
14811494}
14821495
1496+ static VALUE
1497+ enum_sample_multiple_unweighted (VALUE obj , long size , VALUE random , int replace_p )
1498+ {
1499+ struct enum_sample_memo memo ;
1500+
1501+ assert (size > 1 );
1502+
1503+ memo .k = 0 ;
1504+ memo .n = size ;
1505+ memo .sample = rb_ary_new_capa (size );
1506+ memo .random = random ;
1507+
1508+ if (replace_p ) {
1509+ return Qnil ;
1510+ }
1511+ else {
1512+ rb_block_call (obj , id_each , 0 , 0 , enum_sample_multiple_without_replace_unweighted_i , (VALUE )& memo );
1513+ }
1514+
1515+ return memo .sample ;
1516+ }
1517+
14831518/* call-seq:
14841519 * enum.sample(n=1, random: Random, replace: false)
14851520 */
@@ -1516,6 +1551,7 @@ enum_sample(int argc, VALUE *argv, VALUE obj)
15161551 replace_v = kwargs [1 ];
15171552 /* weights_v = kwargs[2]; */
15181553 }
1554+
15191555 if (random_v == Qundef ) {
15201556 random_v = rb_cRandom ;
15211557 }
@@ -1525,9 +1561,9 @@ enum_sample(int argc, VALUE *argv, VALUE obj)
15251561 return enum_sample_single (obj , random_v );
15261562 }
15271563
1528- replace_p = (replace_v == Qundef ) ? 1 : RTEST (replace_v );
1564+ replace_p = (replace_v == Qundef ) ? 0 : RTEST (replace_v );
15291565
1530- return enum_sample_unweighted (obj , NUM2LONG ( size ) , replace_p );
1566+ return enum_sample_multiple_unweighted (obj , size , random_v , replace_p );
15311567}
15321568
15331569
0 commit comments