14#include "internal/compar.h"
15#include "internal/enum.h"
16#include "internal/hash.h"
17#include "internal/imemo.h"
18#include "internal/numeric.h"
19#include "internal/object.h"
20#include "internal/proc.h"
21#include "internal/rational.h"
22#include "internal/re.h"
23#include "internal/set.h"
25#include "ruby_assert.h"
32static ID id__separator;
33static ID id_chunk_categorize;
34static ID id_chunk_enumerable;
35static ID id_sliceafter_enum;
36static ID id_sliceafter_pat;
37static ID id_sliceafter_pred;
38static ID id_slicebefore_enumerable;
39static ID id_slicebefore_sep_pat;
40static ID id_slicebefore_sep_pred;
41static ID id_slicewhen_enum;
42static ID id_slicewhen_inverted;
43static ID id_slicewhen_pred;
49#define id_lshift idLTLT
54rb_enum_values_pack(
int argc,
const VALUE *argv)
56 if (argc == 0)
return Qnil;
57 if (argc == 1)
return argv[0];
61#define ENUM_WANT_SVALUE() do { \
62 i = rb_enum_values_pack(argc, argv); \
66enum_yield(
int argc,
VALUE ary)
69 return rb_yield_force_blockarg(ary);
76enum_yield_array(
VALUE ary)
81 return rb_yield_force_blockarg(ary);
90 struct MEMO *memo = MEMO_CAST(args);
102 struct MEMO *memo = MEMO_CAST(args);
103 VALUE converted_element, match;
108 match =
NIL_P(converted_element) ?
Qfalse : rb_reg_match_p(memo->v1, i, 0);
109 if (match == memo->u3.value) {
118 struct MEMO *memo = MEMO_CAST(args);
131 struct MEMO *memo = rb_imemo_memo_new_value(pat, ary, test);
176 return enum_grep0(obj, pat,
Qtrue);
208 return enum_grep0(obj, pat,
Qfalse);
215 m->flags |= MEMO_U3_IS_VALUE;
219imemo_count_up(
struct MEMO *memo)
221 if (memo->flags & MEMO_U3_IS_VALUE) {
223 MEMO_V3_SET(memo, rb_int_succ(memo->u3.value));
225 else if (++memo->u3.cnt == 0) {
227 unsigned long buf[2] = {0, 1};
228 MEMO_V3_SET(memo, rb_big_unpack(buf, 2));
233imemo_count_value(
struct MEMO *memo)
235 if (memo->flags & MEMO_U3_IS_VALUE) {
237 return memo->u3.value;
247 struct MEMO *memo = MEMO_CAST(memop);
252 imemo_count_up(memo);
260 struct MEMO *memo = MEMO_CAST(memop);
263 imemo_count_up(memo);
271 struct MEMO *memo = MEMO_CAST(memop);
273 imemo_count_up(memo);
321 rb_warn(
"given block not used");
326 memo = rb_imemo_memo_new(item, 0, 0);
328 return imemo_count_value(memo);
331NORETURN(
static void found(
VALUE i,
VALUE memop));
335 struct MEMO *memo = MEMO_CAST(memop);
336 MEMO_V1_SET(memo, i);
356 if (
RTEST(enum_yield(argc, i))) {
391 memo = rb_imemo_memo_new(
Qundef, 0, 0);
392 if (rb_block_pair_yield_optimizable())
393 rb_block_call2(obj, id_each, 0, 0, find_i_fast, (
VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS);
395 rb_block_call2(obj, id_each, 0, 0, find_i, (
VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS);
399 if (!
NIL_P(if_none)) {
408 struct MEMO *memo = MEMO_CAST(memop);
413 MEMO_V1_SET(memo, imemo_count_value(memo));
416 imemo_count_up(memo);
423 struct MEMO *memo = MEMO_CAST(memop);
426 MEMO_V1_SET(memo, imemo_count_value(memo));
429 imemo_count_up(memo);
458enum_find_index(
int argc,
VALUE *argv,
VALUE obj)
466 func = find_index_iter_i;
471 rb_warn(
"given block not used");
476 memo = rb_imemo_memo_new(
Qnil, condition_value, 0);
486 if (
RTEST(enum_yield(argc, i))) {
495 return rb_check_funcall_default(self, id_size, 0, 0,
Qnil);
499limit_by_enum_size(
VALUE obj,
long n)
505 return ((
unsigned long)n > limit) ? (long)limit : n;
509enum_size_over_p(
VALUE obj,
long n)
513 return ((
unsigned long)n >
FIX2ULONG(size));
535enum_find_all(
VALUE obj)
576enum_filter_map(
VALUE obj)
594 if (!
RTEST(enum_yield(argc, i))) {
619enum_reject(
VALUE obj)
664enum_collect(
VALUE obj)
667 int min_argc, max_argc;
672 min_argc = rb_block_min_max_arity(&max_argc);
673 rb_lambda_call(obj, id_each, 0, 0, collect_i, min_argc, max_argc, ary);
715enum_flat_map(
VALUE obj)
756 return enum_hashify_into(obj, argc, argv, iter, rb_hash_new());
763 return rb_hash_set_pair(hash, i);
797 return enum_hashify(obj, argc, argv, iter);
803 struct MEMO *memo = MEMO_CAST(p);
807 if (UNDEF_P(memo->v1)) {
808 MEMO_V1_SET(memo, i);
819 struct MEMO *memo = MEMO_CAST(p);
824 if (UNDEF_P(memo->v1)) {
825 MEMO_V1_SET(memo, i);
827 else if (
SYMBOL_P(name = memo->u3.value)) {
835 MEMO_V1_SET(memo, rb_f_send(numberof(args), args, memo->v1));
848 return UNDEF_P(init) ?
Qnil : init;
876 else if (RB_BIGNUM_TYPE_P(e))
877 v = rb_big_plus(e, v);
1072 op =
id ?
ID2SYM(
id) : init;
1086 if (iter == inject_op_i &&
1090 return ary_inject_op(obj, init, op);
1093 memo = rb_imemo_memo_new_value(init,
Qnil, op);
1095 if (UNDEF_P(memo->v1))
return Qnil;
1102 struct MEMO *memo = MEMO_CAST(arys);
1106 if (
RTEST(enum_yield(argc, i))) {
1145enum_partition(
VALUE obj)
1165 group = enum_yield(argc, i);
1166 values = rb_hash_aref(hash, group);
1169 rb_hash_aset(hash, group, values);
1200enum_group_by(
VALUE obj)
1204 return enum_hashify(obj, 0, 0, group_by_i);
1208tally_up(st_data_t *group, st_data_t *value, st_data_t arg,
int existing)
1216 tally +=
INT2FIX(1) & ~FIXNUM_FLAG;
1220 tally = rb_big_plus(tally,
INT2FIX(1));
1223 *value = (st_data_t)tally;
1230 if (!rb_hash_stlike_update(hash, group, tally_up, (st_data_t)hash)) {
1240 rb_enum_tally_up(hash, i);
1295 hash = rb_to_hash_type(argv[0]);
1296 rb_check_frozen(hash);
1299 hash = rb_hash_new();
1302 return enum_hashify_into(obj, 0, 0, tally_i, hash);
1309 struct MEMO *memo = MEMO_CAST(params);
1312 MEMO_V1_SET(memo, i);
1351 return enum_take(obj, argv[0]);
1354 memo = rb_imemo_memo_new(
Qnil, 0, 0);
1398#define SORT_BY_BUFSIZE 16
1399#define SORT_BY_UNIFORMED(num, flo, fix) (((num&1)<<2)|((flo&1)<<1)|fix)
1404 uint8_t primitive_uniformed;
1411 VALUE ary = data->ary;
1416 v = enum_yield(argc, i);
1418 if (
RBASIC(ary)->klass) {
1421 if (
RARRAY_LEN(data->buf) != SORT_BY_BUFSIZE*2) {
1425 if (data->primitive_uniformed) {
1433 if (data->n == SORT_BY_BUFSIZE) {
1441sort_by_cmp(
const void *ap,
const void *bp,
void *data)
1447 if (
RBASIC(ary)->klass) {
1454 return OPTIMIZED_CMP(a, b);
1462#define uless rb_uniform_is_less
1463#define UNIFORM_SWAP(a,b)\
1464 do{struct rb_uniform_sort_data tmp = a; a = b; b = tmp;} while(0)
1480 return rb_float_cmp(b, a) > 0;
1484 return rb_float_cmp(a, b) < 0;
1497 return rb_float_cmp(b, a) < 0;
1501 return rb_float_cmp(a, b) > 0;
1505#define med3_val(a,b,c) (uless(a,b)?(uless(b,c)?b:uless(c,a)?a:c):(uless(c,b)?b:uless(a,c)?a:c))
1511 if ((ptr_end - ptr_begin) < 2)
return;
1513 *index = ptr_begin+1;
1514 for (; index < ptr_end; index++) {
1517 if (uless(tmp.v, ptr_begin->v)) {
1518 while (ptr_begin < j) {
1524 while (uless(tmp.v, (--k)->v)) {
1535 size_t offset,
size_t len)
1539 while ((c = (offset<<1)+1) <=
len) {
1540 if (c <
len && uless(ptr_begin[c].v, ptr_begin[c+1].v)) {
1543 if (!uless(tmp.v, ptr_begin[c].v))
break;
1544 ptr_begin[offset] = ptr_begin[c];
1547 ptr_begin[offset] = tmp;
1554 size_t n = ptr_end - ptr_begin;
1557 for (
size_t offset = n>>1; offset > 0;) {
1558 rb_uniform_heap_down_2(ptr_begin, --offset, n-1);
1560 for (
size_t offset = n-1; offset > 0;) {
1561 UNIFORM_SWAP(*ptr_begin, ptr_begin[offset]);
1562 rb_uniform_heap_down_2(ptr_begin, 0, --offset);
1572 if (ptr_end - ptr_begin <= 16) {
1573 rb_uniform_insertionsort_2(ptr_begin, ptr_end);
1577 rb_uniform_heapsort_2(ptr_begin, ptr_end);
1581 VALUE x = med3_val(ptr_begin->v,
1582 ptr_begin[(ptr_end - ptr_begin)>>1].v,
1588 while (uless(i->v, x)) i++;
1589 while (uless(x, j->v)) j--;
1591 UNIFORM_SWAP(*i, *j);
1597 if (ptr_end - j > 1) rb_uniform_quicksort_intro_2(j, ptr_end, d-1);
1598 if (i - ptr_begin > 1) rb_uniform_quicksort_intro_2(ptr_begin, i, d-1);
1610 size_t n = ptr_end - ptr_begin;
1611 size_t d = CHAR_BIT *
sizeof(n) - nlz_intptr(n) - 1;
1612 bool sorted_flag =
true;
1615 if (rb_uniform_is_larger((ptr-1)->v, (ptr)->v)) {
1616 sorted_flag =
false;
1624 rb_uniform_quicksort_intro_2(ptr_begin, ptr_end, d<<1);
1713enum_sort_by(
VALUE obj)
1728 RBASIC_CLEAR_CLASS(ary);
1731 memo = rb_imemo_memo_new(0, 0, 0);
1736 data->primitive_uniformed = SORT_BY_UNIFORMED((CMP_OPTIMIZABLE(FLOAT) && CMP_OPTIMIZABLE(INTEGER)),
1737 CMP_OPTIMIZABLE(FLOAT),
1738 CMP_OPTIMIZABLE(INTEGER));
1747 if (data->primitive_uniformed) {
1755 sort_by_cmp, (
void *)ary));
1758 if (
RBASIC(ary)->klass) {
1770#define ENUMFUNC(name) argc ? name##_eqq : rb_block_given_p() ? name##_iter_i : name##_i
1772#define ENUM_BLOCK_CALL(name) \
1773 rb_block_call2(obj, id_each, 0, 0, ENUMFUNC(name), (VALUE)memo, rb_block_given_p() && rb_block_pair_yield_optimizable() ? RB_BLOCK_NO_USE_PACKED_ARGS : 0);
1775#define MEMO_ENUM_NEW(v1) (rb_check_arity(argc, 0, 1), rb_imemo_memo_new((v1), (argc ? *argv : 0), 0))
1777#define DEFINE_ENUMFUNCS(name) \
1778static VALUE enum_##name##_func(VALUE result, struct MEMO *memo); \
1781name##_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1783 return enum_##name##_func(rb_enum_values_pack(argc, argv), MEMO_CAST(memo)); \
1787name##_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1789 return enum_##name##_func(rb_yield_values2(argc, argv), MEMO_CAST(memo)); \
1793name##_eqq(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1795 ENUM_WANT_SVALUE(); \
1796 return enum_##name##_func(rb_funcallv(MEMO_CAST(memo)->v2, id_eqq, 1, &i), MEMO_CAST(memo)); \
1800enum_##name##_func(VALUE result, struct MEMO *memo)
1802#define WARN_UNUSED_BLOCK(argc) do { \
1803 if ((argc) > 0 && rb_block_given_p()) { \
1804 rb_warn("given block not used"); \
1808DEFINE_ENUMFUNCS(all)
1810 if (!
RTEST(result)) {
1811 MEMO_V1_SET(memo,
Qfalse);
1866 struct MEMO *memo = MEMO_ENUM_NEW(
Qtrue);
1867 WARN_UNUSED_BLOCK(argc);
1868 ENUM_BLOCK_CALL(all);
1872DEFINE_ENUMFUNCS(any)
1874 if (
RTEST(result)) {
1875 MEMO_V1_SET(memo,
Qtrue);
1929 WARN_UNUSED_BLOCK(argc);
1930 ENUM_BLOCK_CALL(any);
1934DEFINE_ENUMFUNCS(one)
1936 if (
RTEST(result)) {
1937 if (UNDEF_P(memo->v1)) {
1938 MEMO_V1_SET(memo,
Qtrue);
1940 else if (memo->v1 ==
Qtrue) {
1941 MEMO_V1_SET(memo,
Qfalse);
1954 int (*cmpfunc)(
const void *,
const void *,
void *);
1962 if (
RBASIC(data->buf)->klass) {
1964 data->rev ?
"max" :
"min",
1965 data->by ?
"_by" :
"");
1971nmin_cmp(
const void *ap,
const void *bp,
void *_data)
1975#define rb_cmpint(cmp, a, b) rb_cmpint(cmpint_reenter_check(data, (cmp)), a, b)
1976 return OPTIMIZED_CMP(a, b);
1981nmin_block_cmp(
const void *ap,
const void *bp,
void *_data)
1986 cmpint_reenter_check(data, cmp);
1987 return rb_cmpint(cmp, a, b);
2003 if (data->curlen <= data->n)
2008 eltsize = data->by ? 2 : 1;
2009 numelts = data->curlen;
2014#define GETPTR(i) (beg+(i)*eltsize)
2016#define SWAP(i, j) do { \
2018 memcpy(tmp, GETPTR(i), sizeof(VALUE)*eltsize); \
2019 memcpy(GETPTR(i), GETPTR(j), sizeof(VALUE)*eltsize); \
2020 memcpy(GETPTR(j), tmp, sizeof(VALUE)*eltsize); \
2024 long pivot_index = left + (right-left)/2;
2025 long num_pivots = 1;
2027 SWAP(pivot_index, right);
2028 pivot_index = right;
2032 while (i <= right-num_pivots) {
2033 int c = data->cmpfunc(GETPTR(i), GETPTR(pivot_index), data);
2037 SWAP(i, right-num_pivots);
2042 SWAP(i, store_index);
2048 for (i = right; right-num_pivots < i; i--) {
2055 if (store_index <= n && n <= store_index+num_pivots)
2058 if (n < store_index) {
2059 right = store_index-1;
2062 left = store_index+num_pivots;
2068 data->limit =
RARRAY_AREF(data->buf, store_index*eltsize);
2069 data->curlen = data->n;
2082 cmpv = enum_yield(argc, i);
2086 if (!UNDEF_P(data->limit)) {
2087 int c = data->cmpfunc(&cmpv, &data->limit, data);
2100 if (data->curlen == data->bufmax) {
2108rb_nmin_run(
VALUE obj,
VALUE num,
int by,
int rev,
int ary)
2115 rb_raise(rb_eArgError,
"negative size (%ld)", data.n);
2118 if (LONG_MAX/4/(by ? 2 : 1) < data.n)
2119 rb_raise(rb_eArgError,
"too big size");
2120 data.bufmax = data.n * 4;
2124 data.cmpfunc = by ? nmin_cmp :
2148 data.cmpfunc, (
void *)&data);
2158 data.cmpfunc, (
void *)&data);
2218 WARN_UNUSED_BLOCK(argc);
2219 ENUM_BLOCK_CALL(one);
2221 if (UNDEF_P(result))
return Qfalse;
2225DEFINE_ENUMFUNCS(none)
2227 if (
RTEST(result)) {
2228 MEMO_V1_SET(memo,
Qfalse);
2277 struct MEMO *memo = MEMO_ENUM_NEW(
Qtrue);
2279 WARN_UNUSED_BLOCK(argc);
2280 ENUM_BLOCK_CALL(none);
2291 struct min_t *memo = MEMO_FOR(
struct min_t, args);
2295 if (UNDEF_P(memo->min)) {
2299 if (OPTIMIZED_CMP(i, memo->min) < 0) {
2310 struct min_t *memo = MEMO_FOR(
struct min_t, args);
2314 if (UNDEF_P(memo->min)) {
2319 if (rb_cmpint(cmp, i, memo->min) < 0) {
2388 struct min_t *m = NEW_MEMO_FOR(
struct min_t, memo);
2393 return rb_nmin_run(obj, num, 0, 0, 0);
2403 if (UNDEF_P(result))
return Qnil;
2414 struct max_t *memo = MEMO_FOR(
struct max_t, args);
2418 if (UNDEF_P(memo->max)) {
2422 if (OPTIMIZED_CMP(i, memo->max) > 0) {
2432 struct max_t *memo = MEMO_FOR(
struct max_t, args);
2437 if (UNDEF_P(memo->max)) {
2442 if (rb_cmpint(cmp, i, memo->max) > 0) {
2510 struct max_t *m = NEW_MEMO_FOR(
struct max_t, memo);
2515 return rb_nmin_run(obj, num, 0, 1, 0);
2525 if (UNDEF_P(result))
return Qnil;
2540 if (UNDEF_P(memo->min)) {
2545 n = OPTIMIZED_CMP(i, memo->min);
2549 n = OPTIMIZED_CMP(j, memo->max);
2565 if (UNDEF_P(memo->last)) {
2572 n = OPTIMIZED_CMP(j, i);
2582 minmax_i_update(i, j, memo);
2592 if (UNDEF_P(memo->min)) {
2617 if (UNDEF_P(memo->last)) {
2634 minmax_ii_update(i, j, memo);
2671enum_minmax(
VALUE obj)
2680 if (!UNDEF_P(m->last))
2681 minmax_ii_update(m->last, m->last, m);
2685 if (!UNDEF_P(m->last))
2686 minmax_i_update(m->last, m->last, m);
2688 if (!UNDEF_P(m->min)) {
2697 struct MEMO *memo = MEMO_CAST(args);
2702 v = enum_yield(argc, i);
2703 if (UNDEF_P(memo->v1)) {
2704 MEMO_V1_SET(memo, v);
2705 MEMO_V2_SET(memo, i);
2707 else if (OPTIMIZED_CMP(v, memo->v1) < 0) {
2708 MEMO_V1_SET(memo, v);
2709 MEMO_V2_SET(memo, i);
2760 if (argc && !
NIL_P(num = argv[0]))
2761 return rb_nmin_run(obj, num, 1, 0, 0);
2771 struct MEMO *memo = MEMO_CAST(args);
2776 v = enum_yield(argc, i);
2777 if (UNDEF_P(memo->v1)) {
2778 MEMO_V1_SET(memo, v);
2779 MEMO_V2_SET(memo, i);
2781 else if (OPTIMIZED_CMP(v, memo->v1) > 0) {
2782 MEMO_V1_SET(memo, v);
2783 MEMO_V2_SET(memo, i);
2834 if (argc && !
NIL_P(num = argv[0]))
2835 return rb_nmin_run(obj, num, 1, 1, 0);
2854 if (UNDEF_P(memo->min_bv)) {
2861 if (OPTIMIZED_CMP(v1, memo->min_bv) < 0) {
2865 if (OPTIMIZED_CMP(v2, memo->max_bv) > 0) {
2881 vi = enum_yield(argc, i);
2883 if (UNDEF_P(memo->last_bv)) {
2892 n = OPTIMIZED_CMP(vj, vi);
2907 minmax_by_i_update(vi, vj, i, j, memo);
2936enum_minmax_by(
VALUE obj)
2950 if (!UNDEF_P(m->last_bv))
2951 minmax_by_i_update(m->last_bv, m->last_bv, m->last, m->last, m);
2959 struct MEMO *memo = MEMO_CAST(args);
2961 if (
rb_equal(rb_enum_values_pack(argc, argv), memo->v1)) {
2962 MEMO_V2_SET(memo,
Qtrue);
2988 struct MEMO *memo = rb_imemo_memo_new(val,
Qfalse, 0);
2997 struct vm_ifunc *ifunc = rb_current_ifunc();
2998 ifunc->data = (
const void *)rb_int_succ(index);
3032enum_each_with_index(
int argc,
VALUE *argv,
VALUE obj)
3068enum_reverse_each(
int argc,
VALUE *argv,
VALUE obj)
3075 ary = enum_to_a(argc, argv, obj);
3095 enum_yield(argc, i);
3138enum_each_entry(
int argc,
VALUE *argv,
VALUE obj)
3146add_int(
VALUE x,
long n)
3154div_int(
VALUE x,
long n)
3161#define dont_recycle_block_arg(arity) ((arity) == 1 || (arity) < 0)
3166 struct MEMO *memo = MEMO_CAST(m);
3167 VALUE ary = memo->v1;
3169 long size = memo->u3.cnt;
3195 if (slice_size <= 0) rb_raise(rb_eArgError,
"invalid slice size");
3197 size = enum_size(obj, 0, 0);
3203 n = add_int(size, slice_size-1);
3204 return div_int(n, slice_size);
3235 if (size <= 0) rb_raise(rb_eArgError,
"invalid slice size");
3237 size = limit_by_enum_size(obj, size);
3239 arity = rb_block_arity();
3240 memo = rb_imemo_memo_new(ary, dont_recycle_block_arg(arity), size);
3251 struct MEMO *memo = MEMO_CAST(args);
3252 VALUE ary = memo->v1;
3254 long size = memo->u3.cnt;
3276 if (cons_size <= 0) rb_raise(rb_eArgError,
"invalid size");
3278 size = enum_size(obj, 0, 0);
3281 n = add_int(size, 1 - cons_size);
3282 return (OPTIMIZED_CMP(n, zero) == -1) ? zero : n;
3312 if (size <= 0) rb_raise(rb_eArgError,
"invalid size");
3314 arity = rb_block_arity();
3315 if (enum_size_over_p(obj, size))
return obj;
3316 memo = rb_imemo_memo_new(
rb_ary_new2(size), dont_recycle_block_arg(arity), size);
3351 rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
3359 struct MEMO *memo = (
struct MEMO *)memoval;
3360 VALUE result = memo->v1;
3361 VALUE args = memo->v2;
3362 long n = memo->u3.cnt++;
3378 if (
NIL_P(result)) {
3379 enum_yield_array(tmp);
3407 struct MEMO *memo = (
struct MEMO *)memoval;
3408 VALUE result = memo->v1;
3409 VALUE args = memo->v2;
3424 if (UNDEF_P(v[0])) {
3431 if (
NIL_P(result)) {
3432 enum_yield_array(tmp);
3521 for (i=0; i<argc; i++) {
3530 static const VALUE sym_each = STATIC_ID2SYM(id_each);
3532 for (i=0; i<argc; i++) {
3534 rb_raise(
rb_eTypeError,
"wrong argument type %"PRIsVALUE
" (must respond to :each)",
3537 argv[i] =
rb_funcallv(argv[i], conv, 1, &sym_each);
3545 memo = rb_imemo_memo_new(result, args, 0);
3554 struct MEMO *memo = MEMO_CAST(args);
3555 rb_ary_push(memo->v1, rb_enum_values_pack(argc, argv));
3583 rb_raise(rb_eArgError,
"attempt to take negative size");
3588 memo = rb_imemo_memo_new(result, 0,
len);
3598 rb_ary_push(ary, rb_enum_values_pack(argc, argv));
3622enum_take_while(
VALUE obj)
3635 struct MEMO *memo = MEMO_CAST(args);
3636 if (memo->u3.cnt == 0) {
3637 rb_ary_push(memo->v1, rb_enum_values_pack(argc, argv));
3672 rb_raise(rb_eArgError,
"attempt to drop negative size");
3676 memo = rb_imemo_memo_new(result, 0,
len);
3685 struct MEMO *memo = MEMO_CAST(args);
3688 if (!memo->u3.state && !
RTEST(enum_yield(argc, i))) {
3689 memo->u3.state = TRUE;
3691 if (memo->u3.state) {
3728enum_drop_while(
VALUE obj)
3735 memo = rb_imemo_memo_new(result, 0, FALSE);
3746 enum_yield(argc, i);
3762 size = enum_size(self, args, 0);
3763 if (
NIL_P(size) || FIXNUM_ZERO_P(size))
return size;
3766 if (mul <= 0)
return INT2FIX(0);
3808 if (!argc ||
NIL_P(nv = argv[0])) {
3813 if (n <= 0)
return Qnil;
3816 RBASIC_CLEAR_CLASS(ary);
3820 while (n < 0 || 0 < --n) {
3821 for (i=0; i<
len; i++) {
3845 v =
rb_funcallv(argp->categorize, id_call, 1, &i);
3848 if (!
NIL_P(argp->prev_value)) {
3851 argp->prev_value = argp->prev_elts =
Qnil;
3856 else if (
NIL_P(v) || v == separator) {
3857 if (!
NIL_P(argp->prev_value)) {
3860 argp->prev_value = argp->prev_elts =
Qnil;
3864 rb_raise(
rb_eRuntimeError,
"symbols beginning with an underscore are reserved");
3867 if (
NIL_P(argp->prev_value)) {
3868 argp->prev_value = v;
3872 if (
rb_equal(argp->prev_value, v)) {
3878 argp->prev_value = v;
3895 memo->prev_value =
Qnil;
3896 memo->prev_elts =
Qnil;
3901 if (!
NIL_P(memo->prev_elts)) {
4013enum_chunk(
VALUE enumerable)
4042 if (!
NIL_P(argp->sep_pat))
4043 header_p =
rb_funcallv(argp->sep_pat, id_eqq, 1, &i);
4045 header_p =
rb_funcallv(argp->sep_pred, id_call, 1, &i);
4046 if (
RTEST(header_p)) {
4047 if (!
NIL_P(argp->prev_elts))
4048 rb_funcallv(argp->yielder, id_lshift, 1, &argp->prev_elts);
4052 if (
NIL_P(argp->prev_elts))
4069 memo->sep_pred = rb_attr_get(
enumerator, id_slicebefore_sep_pred);
4071 memo->prev_elts =
Qnil;
4074 rb_block_call(enumerable, id_each, 0, 0, slicebefore_ii, arg);
4076 if (!
NIL_P(memo->prev_elts))
4077 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4242enum_slice_before(
int argc,
VALUE *argv,
VALUE enumerable)
4248 rb_error_arity(argc, 0, 0);
4274#define UPDATE_MEMO ((void)(memo = MEMO_FOR(struct sliceafter_arg, _memo)))
4281 if (
NIL_P(memo->prev_elts)) {
4288 if (
NIL_P(memo->pred)) {
4298 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4300 memo->prev_elts =
Qnil;
4316 memo->pred = rb_attr_get(
enumerator, id_sliceafter_pred);
4317 memo->prev_elts =
Qnil;
4320 rb_block_call(enumerable, id_each, 0, 0, sliceafter_ii, arg);
4322 if (!
NIL_P(memo->prev_elts))
4323 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4364enum_slice_after(
int argc,
VALUE *argv,
VALUE enumerable)
4371 rb_raise(rb_eArgError,
"both pattern and block are given");
4398#define UPDATE_MEMO ((void)(memo = MEMO_FOR(struct slicewhen_arg, _memo)))
4405 if (UNDEF_P(memo->prev_elt)) {
4412 args[0] = memo->prev_elt;
4421 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4445 memo->pred = rb_attr_get(
enumerator, id_slicewhen_pred);
4447 memo->prev_elts =
Qnil;
4449 memo->inverted =
RTEST(rb_attr_get(
enumerator, id_slicewhen_inverted));
4451 rb_block_call(enumerable, id_each, 0, 0, slicewhen_ii, arg);
4453 if (!
NIL_P(memo->prev_elts))
4454 rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4521enum_slice_when(
VALUE enumerable)
4587enum_chunk_while(
VALUE enumerable)
4615 memo->v = rb_fix_plus(
LONG2FIX(memo->n), memo->v);
4618 switch (
TYPE(memo->r)) {
4619 case T_RATIONAL: memo->v = rb_rational_plus(memo->r, memo->v);
break;
4631 memo->v = rb_big_plus(
LONG2NUM(memo->n), memo->v);
4639 memo->v = rb_big_plus(i, memo->v);
4645 if (UNDEF_P(memo->r)) {
4649 memo->r = rb_rational_plus(memo->r, i);
4671 case T_BIGNUM: x = rb_big2dbl(i);
break;
4675 memo->float_value = 0;
4676 sum_iter_some_value(i, memo);
4685 else if (! isfinite(x)) {
4686 if (isinf(x) && isinf(f) && signbit(x) != signbit(f)) {
4694 else if (isinf(f)) {
4701 if (fabs(f) >= fabs(x)) {
4717 if (memo->block_given) {
4721 if (memo->float_value) {
4722 sum_iter_Kahan_Babuska(i, memo);
4724 else switch (
TYPE(memo->v)) {
4725 default: sum_iter_some_value(i, memo);
return;
4731 case T_FIXNUM: sum_iter_fixnum(i, memo);
return;
4732 case T_BIGNUM: sum_iter_bignum(i, memo);
return;
4733 case T_RATIONAL: sum_iter_rational(i, memo);
return;
4735 sum_iter_normalize_memo(memo);
4738 memo->float_value = 1;
4739 sum_iter_Kahan_Babuska(i, memo);
4742 sum_iter_normalize_memo(memo);
4743 sum_iter_some_value(i, memo);
4780 end = rb_big_minus(end,
LONG2FIX(1));
4783 if (rb_int_ge(end, beg)) {
4785 a = rb_int_plus(rb_int_minus(end, beg),
LONG2FIX(1));
4786 a = rb_int_mul(a, rb_int_plus(end, beg));
4788 return rb_int_plus(init, a);
4847 if (!memo.block_given && !memo.float_value &&
4848 (
FIXNUM_P(beg) || RB_BIGNUM_TYPE_P(beg)) &&
4849 (
FIXNUM_P(end) || RB_BIGNUM_TYPE_P(end))) {
4850 return int_range_sum(beg, end, excl, memo.v);
4856 hash_sum(obj, &memo);
4860 if (memo.float_value) {
4861 return DBL2NUM(memo.f + memo.c);
4865 memo.v = rb_fix_plus(
LONG2FIX(memo.n), memo.v);
4866 if (!UNDEF_P(memo.r)) {
4867 memo.v = rb_rational_plus(memo.r, memo.v);
4877 rb_set_add_no_check(set, i);
4917 ret = rb_hash_values(hash);
4918 rb_hash_clear(hash);
4923 ret = rb_set_to_a(set);
4952enum_compact(
VALUE obj)
5213Init_Enumerable(
void)
5285 id_slicebefore_enumerable =
rb_intern_const(
"slicebefore_enumerable");
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
int rb_block_given_p(void)
Determines if the current method is given a block.
#define TYPE(_)
Old name of rb_type.
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
#define T_FLOAT
Old name of RUBY_T_FLOAT.
#define ID2SYM
Old name of RB_ID2SYM.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define ULONG2NUM
Old name of RB_ULONG2NUM.
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define SYM2ID
Old name of RB_SYM2ID.
#define CLASS_OF
Old name of rb_class_of.
#define rb_ary_new4
Old name of rb_ary_new_from_values.
#define FIXABLE
Old name of RB_FIXABLE.
#define LONG2FIX
Old name of RB_INT2FIX.
#define FIX2ULONG
Old name of RB_FIX2ULONG.
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
#define T_HASH
Old name of RUBY_T_HASH.
#define NUM2DBL
Old name of rb_num2dbl.
#define rb_ary_new3
Old name of rb_ary_new_from_args.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define T_UNDEF
Old name of RUBY_T_UNDEF.
#define Qtrue
Old name of RUBY_Qtrue.
#define FIXNUM_MAX
Old name of RUBY_FIXNUM_MAX.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define NIL_P
Old name of RB_NIL_P.
#define DBL2NUM
Old name of rb_float_new.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define CONST_ID
Old name of RUBY_CONST_ID.
#define rb_ary_new2
Old name of rb_ary_new_capa.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
#define T_REGEXP
Old name of RUBY_T_REGEXP.
void rb_iter_break(void)
Breaks from a block.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eRuntimeError
RuntimeError exception.
VALUE rb_eStopIteration
StopIteration exception.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
void rb_warning(const char *fmt,...)
Issues a warning.
VALUE rb_cArray
Array class.
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
VALUE rb_mEnumerable
Enumerable module.
VALUE rb_cEnumerator
Enumerator class.
VALUE rb_cInteger
Module class.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
double rb_num2dbl(VALUE num)
Converts an instance of rb_cNumeric into C's double.
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it only takes public methods into account.
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Identical to rb_ary_new_from_args(), except how objects are passed.
VALUE rb_ary_concat(VALUE lhs, VALUE rhs)
Destructively appends the contents of latter into the end of former.
VALUE rb_ary_reverse(VALUE ary)
Destructively reverses the passed array in-place.
VALUE rb_ary_shift(VALUE ary)
Destructively deletes an element from the beginning of the passed array and returns what was deleted.
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_resize(VALUE ary, long len)
Expands or shrinks the passed array to the passed length.
VALUE rb_ary_hidden_new(long capa)
Allocates a hidden (no class) empty array.
VALUE rb_ary_clear(VALUE ary)
Destructively removes everything form an array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_sort_bang(VALUE ary)
Destructively sorts the passed array in-place, according to each elements' <=> result.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
VALUE rb_block_proc(void)
Constructs a Proc object from implicitly passed components.
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Deconstructs a range into its components.
VALUE rb_set_clear(VALUE set)
Removes all entries from set.
VALUE rb_set_new(void)
Creates a new, empty set object.
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well... Let us hesitate from describing what a "basic definition" is.
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
int rb_obj_respond_to(VALUE obj, ID mid, int private_p)
Identical to rb_respond_to(), except it additionally takes the visibility parameter.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
VALUE rb_sym2str(VALUE symbol)
Obtain a frozen string representation of a symbol (not including the leading colon).
int len
Length of the buffer.
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
Reentrant implementation of quick sort.
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
VALUE rb_yield(VALUE val)
Yields the block.
rb_block_call_func * rb_block_call_func_t
Shorthand type that represents an iterator-written-in-C function pointer.
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
This is the type of a function that the interpreter expect for C-backended blocks.
VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2, int kw_splat)
Identical to rb_funcallv_kw(), except it additionally passes a function as a block.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
void rb_hash_foreach(VALUE q, int_type *w, VALUE e)
Iteration over the given hash.
VALUE rb_rescue2(type *q, VALUE w, type *e, VALUE r,...)
An equivalent of rescue clause.
#define RARRAY_LEN
Just another name of rb_array_len.
static void RARRAY_ASET(VALUE ary, long i, VALUE v)
Assigns an object in an array.
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Declares a section of code where raw pointers are used.
static VALUE * RARRAY_PTR(VALUE ary)
Wild use of a C pointer.
#define RARRAY_AREF(a, i)
#define RBASIC(obj)
Convenient casting macro.
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
IFUNC (Internal FUNCtion)
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.