31 #define ARY_DEFAULT_SIZE 16 32 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE)) 33 #define SMALL_ARRAY_LEN 16 35 # define ARY_SHARED_P(ary) \ 36 (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \ 37 FL_TEST((ary),ELTS_SHARED)!=0) 38 # define ARY_EMBED_P(ary) \ 39 (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \ 40 FL_TEST((ary), RARRAY_EMBED_FLAG)!=0) 42 #define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr) 43 #define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len) 44 #define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary) 45 #define ARY_EMBED_LEN(a) \ 46 (assert(ARY_EMBED_P(a)), \ 47 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \ 48 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT))) 49 #define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), RARRAY(a)->as.heap.aux.capa * sizeof(VALUE)) 51 #define ARY_OWNS_HEAP_P(a) (!FL_TEST((a), ELTS_SHARED|RARRAY_EMBED_FLAG)) 52 #define FL_SET_EMBED(a) do { \ 53 assert(!ARY_SHARED_P(a)); \ 54 FL_SET((a), RARRAY_EMBED_FLAG); \ 56 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK) 57 #define FL_SET_SHARED(ary) do { \ 58 assert(!ARY_EMBED_P(ary)); \ 59 FL_SET((ary), ELTS_SHARED); \ 61 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED) 63 #define ARY_SET_PTR(ary, p) do { \ 64 assert(!ARY_EMBED_P(ary)); \ 65 assert(!OBJ_FROZEN(ary)); \ 66 RARRAY(ary)->as.heap.ptr = (p); \ 68 #define ARY_SET_EMBED_LEN(ary, n) do { \ 70 assert(ARY_EMBED_P(ary)); \ 71 assert(!OBJ_FROZEN(ary)); \ 72 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \ 73 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \ 75 #define ARY_SET_HEAP_LEN(ary, n) do { \ 76 assert(!ARY_EMBED_P(ary)); \ 77 RARRAY(ary)->as.heap.len = (n); \ 79 #define ARY_SET_LEN(ary, n) do { \ 80 if (ARY_EMBED_P(ary)) { \ 81 ARY_SET_EMBED_LEN((ary), (n)); \ 84 ARY_SET_HEAP_LEN((ary), (n)); \ 86 assert(RARRAY_LEN(ary) == (n)); \ 88 #define ARY_INCREASE_PTR(ary, n) do { \ 89 assert(!ARY_EMBED_P(ary)); \ 90 assert(!OBJ_FROZEN(ary)); \ 91 RARRAY(ary)->as.heap.ptr += (n); \ 93 #define ARY_INCREASE_LEN(ary, n) do { \ 94 assert(!OBJ_FROZEN(ary)); \ 95 if (ARY_EMBED_P(ary)) { \ 96 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \ 99 RARRAY(ary)->as.heap.len += (n); \ 103 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \ 104 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : RARRAY(ary)->as.heap.aux.capa) 105 #define ARY_SET_CAPA(ary, n) do { \ 106 assert(!ARY_EMBED_P(ary)); \ 107 assert(!ARY_SHARED_P(ary)); \ 108 assert(!OBJ_FROZEN(ary)); \ 109 RARRAY(ary)->as.heap.aux.capa = (n); \ 112 #define ARY_SHARED(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared) 113 #define ARY_SET_SHARED(ary, value) do { \ 114 const VALUE _ary_ = (ary); \ 115 const VALUE _value_ = (value); \ 116 assert(!ARY_EMBED_P(_ary_)); \ 117 assert(ARY_SHARED_P(_ary_)); \ 118 assert(ARY_SHARED_ROOT_P(_value_)); \ 119 RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared, _value_); \ 121 #define RARRAY_SHARED_ROOT_FLAG FL_USER5 122 #define ARY_SHARED_ROOT_P(ary) (FL_TEST((ary), RARRAY_SHARED_ROOT_FLAG)) 123 #define ARY_SHARED_NUM(ary) \ 124 (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa) 125 #define ARY_SHARED_OCCUPIED(ary) (ARY_SHARED_NUM(ary) == 1) 126 #define ARY_SET_SHARED_NUM(ary, value) do { \ 127 assert(ARY_SHARED_ROOT_P(ary)); \ 128 RARRAY(ary)->as.heap.aux.capa = (value); \ 130 #define FL_SET_SHARED_ROOT(ary) do { \ 131 assert(!ARY_EMBED_P(ary)); \ 132 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \ 135 #define ARY_SET(a, i, v) RARRAY_ASET((assert(!ARY_SHARED_P(a)), (a)), (i), (v)) 146 ary_mem_clear(
VALUE ary,
long beg,
long size)
165 memfill(ptr + beg,
size, val);
185 for (i=0; i<
argc; i++) {
200 ary_memcpy0(ary, beg,
argc, argv, ary);
204 ary_resize_capa(
VALUE ary,
long capacity)
228 if (len > capacity) len = capacity;
238 ary_shrink_capa(
VALUE ary)
241 long old_capa =
RARRAY(ary)->as.heap.aux.capa;
243 assert(old_capa >= capacity);
244 if (old_capa > capacity)
249 ary_double_capa(
VALUE ary,
long min)
260 ary_resize_capa(ary, new_capa);
264 rb_ary_decrement_share(
VALUE shared)
279 rb_ary_unshare(
VALUE ary)
282 rb_ary_decrement_share(shared);
287 rb_ary_unshare_safe(
VALUE ary)
295 rb_ary_increment_share(
VALUE shared)
307 rb_ary_increment_share(shared);
313 rb_ary_modify_check(
VALUE ary)
321 rb_ary_modify_check(ary);
330 rb_ary_decrement_share(shared);
342 rb_ary_decrement_share(shared);
357 ary_ensure_room_for_push(
VALUE ary,
long add_len)
360 long new_len = old_len + add_len;
371 rb_ary_modify_check(ary);
378 if (new_len > capa - (capa >> 6)) {
379 ary_double_capa(ary, new_len);
388 rb_ary_modify_check(ary);
391 if (new_len > capa) {
392 ary_double_capa(ary, new_len);
423 rb_ary_frozen_p(
VALUE ary)
441 RARRAY(ary1)->as.heap.aux.shared ==
RARRAY(ary2)->as.heap.aux.shared &&
442 RARRAY(ary1)->as.heap.len ==
RARRAY(ary2)->as.heap.len) {
449 ary_alloc(
VALUE klass)
460 empty_ary_alloc(
VALUE klass)
463 return ary_alloc(klass);
467 ary_new(
VALUE klass,
long capa)
480 ary = ary_alloc(klass);
514 for (i=0; i<n; i++) {
528 ary = ary_new(klass, n);
530 ary_memcpy(ary, 0, n, elts);
546 return ary_new(0, capa);
552 VALUE ary = ary_new(0, capa);
553 ary_memfill(ary, 0, capa,
Qnil);
582 ary_discard(
VALUE ary)
590 ary_make_shared(
VALUE ary)
600 ary_shrink_capa(ary);
618 return (
VALUE)shared;
623 ary_make_substitution(
VALUE ary)
634 return rb_ary_increment_share(ary_make_shared(ary));
748 rb_ary_unshare_safe(ary);
775 ary_resize_capa(ary, len);
780 rb_warn(
"block supersedes default value argument");
782 for (i=0; i<
len; i++) {
788 ary_memfill(ary, 0, len, val);
803 rb_ary_s_create(
int argc,
VALUE *argv,
VALUE klass)
805 VALUE ary = ary_new(klass, argc);
806 if (argc > 0 && argv) {
807 ary_memcpy(ary, 0, argc, argv);
832 ary_double_capa(ary, idx);
835 ary_mem_clear(ary, len, idx - len + 1);
845 ary_make_partial(
VALUE ary,
VALUE klass,
long offset,
long len)
852 VALUE result = ary_alloc(klass);
858 VALUE shared, result = ary_alloc(klass);
861 shared = ary_make_shared(ary);
864 rb_ary_set_shared(result, shared);
873 ary_make_shared_copy(
VALUE ary)
904 return ary_make_partial(ary,
rb_cArray, offset, n);
927 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
939 VALUE target_ary = ary_ensure_room_for_push(ary, len);
940 ary_memcpy0(ary, oldlen, len, argv, target_ary);
962 rb_ary_push_m(
int argc,
VALUE *argv,
VALUE ary)
971 rb_ary_modify_check(ary);
973 if (n == 0)
return Qnil;
978 ary_resize_capa(ary, n * 2);
1004 rb_ary_pop_m(
int argc,
VALUE *argv,
VALUE ary)
1012 rb_ary_modify_check(ary);
1013 result = ary_take_first_or_last(argc, argv, ary,
ARY_TAKE_LAST);
1024 rb_ary_modify_check(ary);
1025 if (len == 0)
return Qnil;
1038 ary_make_shared(ary);
1073 rb_ary_shift_m(
int argc,
VALUE *argv,
VALUE ary)
1082 rb_ary_modify_check(ary);
1083 result = ary_take_first_or_last(argc, argv, ary,
ARY_TAKE_FIRST);
1087 setup_occupied_shared:
1088 ary_mem_clear(ary, 0, n);
1099 ary_make_shared(ary);
1100 goto setup_occupied_shared;
1109 ary_ensure_room_for_unshift(
VALUE ary,
int argc)
1112 long new_len = len +
argc;
1114 const VALUE *head, *sharedp;
1126 goto makeroom_if_need;
1132 if (capa - (capa >> 6) <= new_len) {
1133 ary_double_capa(ary, new_len);
1140 ary_make_shared(ary);
1145 if (head - sharedp < argc) {
1148 room = capa - new_len;
1151 head = sharedp + argc + room;
1180 rb_ary_unshift_m(
int argc,
VALUE *argv,
VALUE ary)
1186 rb_ary_modify_check(ary);
1190 target_ary = ary_ensure_room_for_unshift(ary, argc);
1191 ary_memcpy0(ary, 0, argc, argv, target_ary);
1199 return rb_ary_unshift_m(1,&item,ary);
1204 rb_ary_elt(
VALUE ary,
long offset)
1207 if (len == 0)
return Qnil;
1208 if (offset < 0 || len <= offset) {
1219 if (len == 0)
return Qnil;
1222 if (offset < 0)
return Qnil;
1224 else if (len <= offset) {
1236 if (beg > alen)
return Qnil;
1237 if (beg < 0 || len < 0)
return Qnil;
1239 if (alen < len || alen < beg + len) {
1243 if (len == 0)
return ary_new(klass, 0);
1245 return ary_make_partial(ary, klass, beg, len);
1353 rb_ary_first(
int argc,
VALUE *argv,
VALUE ary)
1384 if (len == 0)
return Qnil;
1388 return ary_take_first_or_last(argc, argv, ary,
ARY_TAKE_LAST);
1417 rb_ary_fetch(
int argc,
VALUE *argv,
VALUE ary)
1425 if (block_given && argc == 2) {
1426 rb_warn(
"block supersedes default value argument");
1434 if (block_given)
return rb_yield(pos);
1471 rb_ary_index(
int argc,
VALUE *argv,
VALUE ary)
1488 rb_warn(
"given block not used");
1523 rb_ary_rindex(
int argc,
VALUE *argv,
VALUE ary)
1542 rb_warn(
"given block not used");
1557 if (!
NIL_P(tmp))
return tmp;
1562 rb_ary_splice(
VALUE ary,
long beg,
long len,
const VALUE *rptr,
long rlen)
1576 if (olen < len || olen < beg + len) {
1582 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
1590 target_ary = ary_ensure_room_for_push(ary, rlen-len);
1592 ary_mem_clear(ary, olen, beg - olen);
1595 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
1606 alen = olen + rlen -
len;
1608 ary_double_capa(ary, alen);
1613 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
1614 VALUE, olen - (beg + len)));
1629 rb_ary_modify_check(ary);
1633 if (len > (capa = (
long)
ARY_CAPA(ary))) {
1634 rb_bug(
"probable buffer overflow: %ld for %ld", len, capa);
1654 if (len == olen)
return ary;
1660 ary_double_capa(ary, len);
1662 ary_mem_clear(ary, olen, len - olen);
1721 rb_ary_aset(
int argc,
VALUE *argv,
VALUE ary)
1723 long offset, beg,
len;
1727 rb_ary_modify_check(ary);
1733 rb_ary_modify_check(ary);
1744 return argv[argc-1];
1770 rb_ary_insert(
int argc,
VALUE *argv,
VALUE ary)
1775 rb_ary_modify_check(ary);
1777 if (argc == 1)
return ary;
1789 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
1794 rb_ary_length(
VALUE ary);
1799 return rb_ary_length(ary);
1851 rb_ary_each_index(
VALUE ary)
1878 rb_ary_reverse_each(
VALUE ary)
1906 rb_ary_length(
VALUE ary)
1922 rb_ary_empty_p(
VALUE ary)
1955 VALUE result = arg[2];
1956 int *first = (
int *)arg[3];
1962 ary_join_1(obj, ary, sep, 0, result, first);
1974 for (i=0; i<max; i++) {
1976 if (i > 0 && !
NIL_P(sep))
1989 if (i > 0 && !
NIL_P(sep))
2014 args[3] = (
VALUE)first;
2054 if (
NIL_P(tmp) || tmp != val) {
2059 ary_join_0(ary, sep, i, result);
2061 ary_join_1(ary, ary, sep, i, result, &first);
2070 ary_join_0(ary, sep,
RARRAY_LEN(ary), result);
2094 rb_ary_join_m(
int argc,
VALUE *argv,
VALUE ary)
2105 inspect_ary(
VALUE ary,
VALUE dummy,
int recur)
2136 rb_ary_inspect(
VALUE ary)
2145 return rb_ary_inspect(ary);
2158 rb_ary_to_a(
VALUE ary)
2180 rb_ary_to_h(
VALUE ary)
2185 const VALUE elt = rb_ary_elt(ary, i);
2187 if (
NIL_P(key_value_pair)) {
2208 rb_ary_to_ary_m(
VALUE ary)
2233 ary_reverse(p1, p2);
2251 rb_ary_reverse_bang(
VALUE ary)
2267 rb_ary_reverse_m(
VALUE ary)
2275 do *p2-- = *p1++;
while (--len > 0);
2282 rotate_count(
long cnt,
long len)
2284 return (cnt < 0) ? (len - (~cnt %
len) - 1) : (cnt %
len);
2296 if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
2298 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
2299 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
2300 if (len > 0) ary_reverse(ptr, ptr + len);
2326 rb_ary_rotate_bang(
int argc,
VALUE *argv,
VALUE ary)
2357 rb_ary_rotate_m(
int argc,
VALUE *argv,
VALUE ary)
2372 cnt = rotate_count(cnt, len);
2375 ary_memcpy(rotated, 0, len, ptr + cnt);
2376 ary_memcpy(rotated, len, cnt, ptr);
2388 sort_reentered(
VALUE ary)
2390 if (
RBASIC(ary)->klass) {
2397 sort_1(
const void *ap,
const void *
bp,
void *dummy)
2400 VALUE retval = sort_reentered(data->
ary);
2409 sort_reentered(data->
ary);
2414 sort_2(
const void *ap,
const void *bp,
void *dummy)
2417 VALUE retval = sort_reentered(data->
ary);
2422 if ((
long)a > (long)b)
return 1;
2423 if ((
long)a < (long)b)
return -1;
2435 sort_reentered(data->
ary);
2470 VALUE tmp = ary_make_substitution(ary);
2485 rb_ary_unshare(ary);
2503 rb_ary_unshare(ary);
2556 static VALUE rb_ary_bsearch_index(
VALUE ary);
2612 rb_ary_bsearch(
VALUE ary)
2614 VALUE index_result = rb_ary_bsearch_index(ary);
2619 return index_result;
2636 rb_ary_bsearch_index(
VALUE ary)
2639 int smaller = 0, satisfied = 0;
2643 while (low < high) {
2644 mid = low + ((high - low) / 2);
2651 else if (v ==
Qtrue) {
2662 case 1: smaller = 1;
break;
2663 case -1: smaller = 0;
2668 " (must be numeric, true, false or nil)",
2678 if (!satisfied)
return Qnil;
2706 rb_ary_sort_by_bang(
VALUE ary)
2740 rb_ary_collect(
VALUE ary)
2776 rb_ary_collect_bang(
VALUE ary)
2792 long beg,
len, i, j;
2794 for (i=0; i<
argc; i++) {
2801 long end = olen < beg+len ? olen : beg+
len;
2802 for (j = beg; j < end; j++) {
2833 rb_ary_values_at(
int argc,
VALUE *argv,
VALUE ary)
2858 rb_ary_select(
VALUE ary)
2879 select_bang_i(
VALUE a)
2885 for (i1 = i2 = 0; i1 <
RARRAY_LEN(ary); arg->
len[0] = ++i1) {
2893 return (i1 == i2) ?
Qnil :
ary;
2897 select_bang_ensure(
VALUE a)
2902 long i1 = arg->
len[0], i2 = arg->
len[1];
2904 if (i2 < len && i2 < i1) {
2936 rb_ary_select_bang(
VALUE ary)
2944 args.
len[0] = args.
len[1] = 0;
2965 rb_ary_keep_if(
VALUE ary)
2968 rb_ary_select_bang(ary);
2973 ary_resize_smaller(
VALUE ary,
long len)
2980 ary_resize_capa(ary, len * 2);
3011 for (i1 = i2 = 0; i1 <
RARRAY_LEN(ary); i1++) {
3030 ary_resize_smaller(ary, i2);
3040 for (i1 = i2 = 0; i1 <
RARRAY_LEN(ary); i1++) {
3055 ary_resize_smaller(ary, i2);
3064 if (pos >= len)
return Qnil;
3067 if (pos < 0)
return Qnil;
3123 rb_ary_slice_bang(
int argc,
VALUE *argv,
VALUE ary)
3126 long pos,
len, orig_len;
3128 rb_ary_modify_check(ary);
3133 if (len < 0)
return Qnil;
3137 if (pos < 0)
return Qnil;
3139 else if (orig_len < pos)
return Qnil;
3140 if (orig_len < pos + len) {
3141 len = orig_len - pos;
3146 rb_ary_splice(ary, pos, len, 0, 0);
3160 goto delete_pos_len;
3188 reject_bang_i(
VALUE a)
3194 for (i1 = i2 = 0; i1 <
RARRAY_LEN(ary); arg->
len[0] = ++i1) {
3202 return (i1 == i2) ?
Qnil :
ary;
3206 ary_reject_bang(
VALUE ary)
3210 rb_ary_modify_check(ary);
3212 args.
len[0] = args.
len[1] = 0;
3232 rb_ary_reject_bang(
VALUE ary)
3235 return ary_reject_bang(ary);
3252 rb_ary_reject(
VALUE ary)
3258 ary_reject(ary, rejected_ary);
3259 return rejected_ary;
3281 rb_ary_delete_if(
VALUE ary)
3284 ary_reject_bang(ary);
3299 take_items(
VALUE obj,
long n)
3306 args[0] = result; args[1] = (
VALUE)n;
3345 for (i=0; i<
argc; i++) {
3346 argv[i] = take_items(argv[i], len);
3359 for (j=0; j<
argc; j++) {
3360 tmp[j+1] = rb_ary_elt(argv[j], i);
3372 for (j=0; j<
argc; j++) {
3382 for (i=0; i<
len; i++) {
3386 for (j=0; j<
argc; j++) {
3410 rb_ary_transpose(
VALUE ary)
3412 long elen = -1, alen, i, j;
3413 VALUE tmp, result = 0;
3417 for (i=0; i<alen; i++) {
3418 tmp = to_ary(rb_ary_elt(ary, i));
3422 for (j=0; j<elen; j++) {
3430 for (j=0; j<elen; j++) {
3431 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
3453 rb_ary_modify_check(copy);
3454 orig = to_ary(orig);
3455 if (copy == orig)
return copy;
3470 rb_ary_decrement_share(shared);
3475 VALUE shared = ary_make_shared(orig);
3480 rb_ary_unshare_safe(copy);
3485 rb_ary_set_shared(copy, shared);
3503 rb_ary_modify_check(ary);
3507 rb_ary_unshare(ary);
3548 rb_ary_fill(
int argc,
VALUE *argv,
VALUE ary)
3551 long beg = 0, end = 0, len = 0;
3574 if (beg < 0) beg = 0;
3589 ary_resize_capa(ary, end);
3599 for (i=beg; i<end; i++) {
3606 ary_memfill(ary, beg, len, item);
3638 long len, xlen, ylen;
3683 rb_ary_concat_multi(
int argc,
VALUE *argv,
VALUE ary)
3685 rb_ary_modify_check(ary);
3690 else if (argc > 1) {
3693 for (i = 0; i <
argc; i++) {
3696 ary_append(ary, args);
3705 return ary_append(x, to_ary(y));
3756 ary_memcpy(ary2, 0, t, ptr);
3757 while (t <= len/2) {
3841 recursive_equal(
VALUE ary1,
VALUE ary2,
int recur)
3844 const VALUE *p1, *p2;
3846 if (recur)
return Qtrue;
3852 for (i = 0; i < len1; i++) {
3890 if (ary1 == ary2)
return Qtrue;
3903 recursive_eql(
VALUE ary1,
VALUE ary2,
int recur)
3907 if (recur)
return Qtrue;
3909 if (!
rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
3926 if (ary1 == ary2)
return Qtrue;
3946 rb_ary_hash(
VALUE ary)
3990 rb_ary_includes_by_eql(
VALUE ary,
VALUE item)
4005 recursive_cmp(
VALUE ary1,
VALUE ary2,
int recur)
4009 if (recur)
return Qundef;
4014 for (i=0; i<
len; i++) {
4015 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
4062 if (ary1 == ary2)
return INT2FIX(0);
4064 if (v !=
Qundef)
return v;
4066 if (len == 0)
return INT2FIX(0);
4067 if (len > 0)
return INT2FIX(1);
4084 ary_tmp_hash_new(
VALUE ary)
4094 ary_make_hash(
VALUE ary)
4096 VALUE hash = ary_tmp_hash_new(ary);
4097 return ary_add_hash(hash, ary);
4113 ary_make_hash_by(
VALUE ary)
4115 VALUE hash = ary_tmp_hash_new(ary);
4116 return ary_add_hash_by(hash, ary);
4120 ary_recycle_hash(
VALUE hash)
4123 if (
RHASH(hash)->ntbl) {
4154 ary2 = to_ary(ary2);
4159 VALUE elt = rb_ary_elt(ary1, i);
4160 if (rb_ary_includes_by_eql(ary2, elt))
continue;
4166 hash = ary_make_hash(ary2);
4171 ary_recycle_hash(hash);
4194 VALUE hash, ary3, v;
4199 ary2 = to_ary(ary2);
4206 if (!rb_ary_includes_by_eql(ary2, v))
continue;
4207 if (rb_ary_includes_by_eql(ary3, v))
continue;
4213 hash = ary_make_hash(ary2);
4223 ary_recycle_hash(hash);
4232 *key = *value = (
VALUE)arg;
4257 ary2 = to_ary(ary2);
4261 VALUE elt = rb_ary_elt(ary1, i);
4262 if (rb_ary_includes_by_eql(ary3, elt))
continue;
4266 VALUE elt = rb_ary_elt(ary2, i);
4267 if (rb_ary_includes_by_eql(ary3, elt))
continue;
4273 hash = ary_make_hash(ary1);
4281 ary_recycle_hash(hash);
4430 rb_ary_uniq_bang(
VALUE ary)
4435 rb_ary_modify_check(ary);
4439 hash = ary_make_hash_by(ary);
4441 hash = ary_make_hash(ary);
4447 rb_ary_modify_check(ary);
4450 rb_ary_unshare(ary);
4453 ary_resize_capa(ary, hash_size);
4455 ary_recycle_hash(hash);
4482 rb_ary_uniq(
VALUE ary)
4489 hash = ary_make_hash_by(ary);
4493 hash = ary_make_hash(ary);
4497 ary_recycle_hash(hash);
4515 rb_ary_compact_bang(
VALUE ary)
4532 ary_resize_smaller(ary, n);
4548 rb_ary_compact(
VALUE ary)
4551 rb_ary_compact_bang(ary);
4577 rb_ary_count(
int argc,
VALUE *argv,
VALUE ary)
4597 rb_warn(
"given block not used");
4611 VALUE stack, result, tmp, elt;
4624 if (level >= 0 &&
RARRAY_LEN(stack) / 2 >= level) {
4629 if (
RBASIC(result)->klass) {
4686 rb_ary_flatten_bang(
int argc,
VALUE *argv,
VALUE ary)
4688 int mod = 0, level = -1;
4692 rb_ary_modify_check(ary);
4694 if (level == 0)
return Qnil;
4696 result = flatten(ary, level, &mod);
4698 ary_discard(result);
4731 rb_ary_flatten(
int argc,
VALUE *argv,
VALUE ary)
4733 int mod = 0, level = -1;
4738 if (level == 0)
return ary_make_shared_copy(ary);
4740 result = flatten(ary, level, &mod);
4746 #define OPTHASH_GIVEN_P(opts) \ 4747 (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1)) 4748 static ID id_random;
4750 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1) 4769 rb_ary_shuffle_bang(
int argc,
VALUE *argv,
VALUE ary)
4778 keyword_ids[0] = id_random;
4820 rb_ary_shuffle(
int argc,
VALUE *argv,
VALUE ary)
4823 rb_ary_shuffle_bang(argc, argv, ary);
4853 rb_ary_sample(
int argc,
VALUE *argv,
VALUE ary)
4857 long n,
len, i, j, k, idx[10];
4859 long memo_threshold;
4865 keyword_ids[0] = id_random;
4878 return rb_ary_elt(ary, i);
4883 if (n > len) n =
len;
4885 for (i = 0; i < n; ++i) {
4891 if (len < k && n <=
numberof(idx)) {
4892 for (i = 0; i < n; ++i) {
4896 if (n > len) n =
len;
4914 if (j >= i) l = i, g = ++j;
4915 if (k >= l && (++k >= g)) ++k;
4920 len < 2560 ? len / 128 :
4921 len < 5120 ? len / 64 :
4922 len < 10240 ? len / 32 :
4926 sorted[0] = idx[0] = rnds[0];
4927 for (i=1; i<n; i++) {
4929 for (j = 0; j < i; ++j) {
4930 if (k < sorted[j])
break;
4933 memmove(&sorted[j+1], &sorted[j],
sizeof(sorted[0])*(i-j));
4934 sorted[j] = idx[i] = k;
4938 for (i=0; i<n; i++) {
4943 else if (n <= memo_threshold / 2) {
4945 #undef RUBY_UNTYPED_DATA_WARNING 4946 #define RUBY_UNTYPED_DATA_WARNING 0 4952 for (i=0; i<n; i++) {
4955 if (r > max_idx) max_idx = r;
4958 if (len <= max_idx) n = 0;
4959 else if (n > len) n =
len;
4961 for (i=0; i<n; i++) {
4962 long j2 = j = ptr_result[i];
4968 ptr_result[i] = ptr_ary[j2];
4980 for (i=0; i<n; i++) {
4983 ptr_result[j] = ptr_result[i];
5005 if (mul <= 0)
return INT2FIX(0);
5007 return rb_fix_mul_fix(rb_ary_length(
self), n);
5031 rb_ary_cycle(
int argc,
VALUE *argv,
VALUE ary)
5044 if (n <= 0)
return Qnil;
5047 while (
RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
5055 #define tmpbuf(n, size) rb_str_tmp_new((n)*(size)) 5056 #define tmpbuf_discard(s) (rb_str_resize((s), 0L), RBASIC_SET_CLASS_RAW(s, rb_cString)) 5057 #define tmpary(n) rb_ary_tmp_new(n) 5058 #define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray)) 5066 yield_indexed_values(
const VALUE values,
const long r,
const long *
const p)
5073 for (i = 0; i < r; i++) result_array[i] = values_array[p[i]];
5076 return !
RBASIC(values)->klass;
5092 permute0(
const long n,
const long r,
long *
const p,
char *
const used,
const VALUE values)
5094 long i = 0, index = 0;
5097 const char *
const unused = memchr(&used[i], 0, n-i);
5112 for (i = 0; i < n; ++i) {
5113 if (used[i])
continue;
5115 if (!yield_indexed_values(values, r, p)) {
5131 descending_factorial(
long from,
long how_many)
5136 while (--how_many > 0) {
5148 binomial_coefficient(
long comb,
long size)
5152 if (comb > size-comb) {
5158 else if (comb == 0) {
5162 for (i = 1; i < comb; ++i) {
5175 return descending_factorial(n, k);
5207 rb_ary_permutation(
int argc,
VALUE *argv,
VALUE ary)
5217 if (r < 0 || n < r) {
5231 char *used = (
char*)(p + r);
5232 VALUE ary0 = ary_make_shared_copy(ary);
5237 permute0(n, r, p, used, ary0);
5245 combinate0(
const long len,
const long n,
long *
const stack,
const VALUE values)
5252 for (lev++; lev < n; lev++) {
5253 stack[lev+1] = stack[lev]+1;
5255 if (!yield_indexed_values(values, n, stack+1)) {
5259 if (lev == 0)
return;
5261 }
while (stack[lev+1]+n == len+lev+1);
5271 return binomial_coefficient(k, n);
5307 if (n < 0 || len < n) {
5319 VALUE ary0 = ary_make_shared_copy(ary);
5321 long *stack =
ALLOCV_N(
long, t0, n+1);
5324 combinate0(len, n, stack, ary0);
5344 rpermute0(
const long n,
const long r,
long *
const p,
const VALUE values)
5346 long i = 0, index = 0;
5350 if (++index < r-1) {
5354 for (i = 0; i < n; ++i) {
5356 if (!yield_indexed_values(values, r, p)) {
5361 if (index <= 0)
return;
5362 }
while ((i = ++p[--index]) >= n);
5405 rb_ary_repeated_permutation(
VALUE ary,
VALUE num)
5427 VALUE ary0 = ary_make_shared_copy(ary);
5430 rpermute0(n, r, p, ary0);
5438 rcombinate0(
const long n,
const long r,
long *
const p,
const long rest,
const VALUE values)
5440 long i = 0, index = 0;
5444 if (++index < r-1) {
5448 for (; i < n; ++i) {
5450 if (!yield_indexed_values(values, r, p)) {
5455 if (index <= 0)
return;
5456 }
while ((i = ++p[--index]) >= n);
5468 return binomial_coefficient(k, n + k - 1);
5499 rb_ary_repeated_combination(
VALUE ary,
VALUE num)
5517 else if (len == 0) {
5523 VALUE ary0 = ary_make_shared_copy(ary);
5526 rcombinate0(len, n, p, n, ary0);
5555 rb_ary_product(
int argc,
VALUE *argv,
VALUE ary)
5572 for (i = 1; i < n; i++) arrays[i] =
Qnil;
5573 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
5576 for (i = 0; i < n; i++) counters[i] = 0;
5581 for (i = 0; i < n; i++) {
5583 arrays[i] = ary_make_shared_copy(arrays[i]);
5588 for (i = 0; i < n; i++) {
5604 for (j = 0; j < n; j++) {
5609 if (
NIL_P(result)) {
5629 while (counters[m] ==
RARRAY_LEN(arrays[m])) {
5632 if (--m < 0)
goto done;
5640 return NIL_P(result) ?
ary : result;
5686 rb_ary_take_while(
VALUE ary)
5694 return rb_ary_take(ary,
LONG2FIX(i));
5746 rb_ary_drop_while(
VALUE ary)
5754 return rb_ary_drop(ary,
LONG2FIX(i));
5765 rb_ary_any_p(
VALUE ary)
5803 if (!--argc)
return self;
5809 finish_exact_sum(
long n,
VALUE r,
VALUE v,
int z)
5909 v = finish_exact_sum(n, r, v, argc!=0);
5913 v = finish_exact_sum(n, r, v, i!=0);
5924 goto has_float_value;
5943 if (fabs(f) >= fabs(x))
5956 goto has_some_value;
6209 #define rb_intern(str) rb_intern_const(str) #define RBASIC_CLEAR_CLASS(obj)
VALUE rb_ary_unshift(VALUE ary, VALUE item)
VALUE rb_ary_last(int argc, const VALUE *argv, VALUE ary)
void rb_warn(const char *fmt,...)
VALUE rb_ary_pop(VALUE ary)
void rb_bug(const char *fmt,...)
VALUE rb_ary_entry(VALUE ary, long offset)
VALUE rb_ary_new_capa(long capa)
void rb_enc_copy(VALUE obj1, VALUE obj2)
VALUE rb_ary_freeze(VALUE ary)
#define ARY_SET_EMBED_LEN(ary, n)
VALUE rb_yield_values(int n,...)
VALUE rb_check_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
#define RB_OBJ_WRITTEN(a, oldv, b)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
int rb_block_given_p(void)
Determines if the current method is given a block.
VALUE rb_ary_sort(VALUE ary)
int rb_float_cmp(VALUE x, VALUE y)
#define rb_usascii_str_new2
VALUE rb_ary_subseq(VALUE ary, long beg, long len)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_ary_delete_at(VALUE ary, long pos)
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
st_index_t rb_hash_end(st_index_t)
VALUE rb_ary_shift(VALUE ary)
int rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val)
#define FL_UNSET_SHARED(ary)
VALUE rb_big_plus(VALUE x, VALUE y)
RUBY_EXTERN VALUE rb_cRandom
VALUE rb_ary_each(VALUE ary)
#define ARY_SET_CAPA(ary, n)
void rb_mem_clear(register VALUE *mem, register long size)
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_ary_push(VALUE ary, VALUE item)
#define SIZED_REALLOC_N(var, type, n, old_n)
VALUE rb_str_buf_new2(const char *)
#define ARY_OWNS_HEAP_P(a)
VALUE rb_ary_rassoc(VALUE ary, VALUE value)
struct st_table * rb_hash_tbl_raw(VALUE hash)
VALUE rb_ary_tmp_new(long capa)
VALUE rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
void ruby_sized_xfree(void *x, size_t size)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
#define RBASIC_SET_CLASS(obj, cls)
VALUE rb_int_mul(VALUE x, VALUE y)
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
VALUE rb_ary_clear(VALUE ary)
#define FL_SET_SHARED_ROOT(ary)
#define MUL_OVERFLOW_LONG_P(a, b)
#define OPTIMIZED_CMP(a, b, data)
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
void rb_include_module(VALUE klass, VALUE module)
#define ARY_SHARED_ROOT_P(ary)
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
#define ARY_SHARED_NUM(ary)
VALUE rb_range_beg_len(VALUE, long *, long *, long, int)
double rb_big2dbl(VALUE x)
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
int rb_str_cmp(VALUE, VALUE)
VALUE rb_ary_rotate(VALUE ary, long cnt)
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
An equivalent to ensure clause.
void rb_gc_force_recycle(VALUE obj)
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
VALUE rb_hash_new_with_size(st_index_t size)
#define ARY_SHARED_P(ary)
VALUE rb_ary_cat(VALUE ary, const VALUE *argv, long len)
VALUE rb_str_buf_append(VALUE, VALUE)
#define st_init_numtable_with_size
RUBY_EXTERN void * memmove(void *, const void *, size_t)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
#define NEWOBJ_OF(obj, type, klass, flags)
#define Data_Wrap_Struct(klass, mark, free, sval)
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
#define OPTHASH_GIVEN_P(opts)
#define RBASIC_SET_CLASS_RAW(obj, cls)
VALUE rb_obj_class(VALUE)
call-seq: obj.class -> class
#define RB_TYPE_P(obj, type)
VALUE rb_ary_assoc(VALUE ary, VALUE key)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
call-seq: obj.is_a?(class) -> true or false obj.kind_of?(class) -> true or false
#define MEMZERO(p, type, n)
VALUE rb_int_idiv(VALUE x, VALUE y)
VALUE rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE(*func)(VALUE, long))
#define tmpbuf_discard(s)
void rb_ary_free(VALUE ary)
VALUE rb_equal(VALUE, VALUE)
call-seq: obj === other -> true or false
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
RUBY_EXTERN VALUE rb_cObject
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound)
VALUE rb_ary_at(VALUE ary, VALUE pos)
#define RGENGC_WB_PROTECTED_ARRAY
#define tmpary_discard(a)
VALUE rb_ary_replace(VALUE copy, VALUE orig)
VALUE rb_obj_as_string(VALUE)
VALUE rb_str_buf_cat2(VALUE, const char *)
VALUE rb_ary_to_s(VALUE ary)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
#define FL_SET_SHARED(ary)
void rb_ary_store(VALUE ary, long idx, VALUE val)
VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
rb_atomic_t cnt[RUBY_NSIG]
#define ALLOCV_N(type, v, n)
#define range(low, item, hi)
#define RUBY_FUNC_EXPORTED
#define MEMCPY(p1, p2, type, n)
VALUE rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary)
RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y)
#define RUBY_DTRACE_CREATE_HOOK(name, arg)
VALUE rb_ary_to_ary(VALUE obj)
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
#define CMP_OPTIMIZABLE(data, type)
#define RARRAY_CONST_PTR(a)
#define REALLOC_N(var, type, n)
VALUE rb_obj_freeze(VALUE)
call-seq: obj.freeze -> obj
VALUE rb_ary_dig(int argc, VALUE *argv, VALUE self)
#define RARRAY_PTR_USE(ary, ptr_name, expr)
void rb_ary_modify(VALUE ary)
VALUE rb_ary_delete(VALUE ary, VALUE item)
#define MEMMOVE(p1, p2, type, n)
VALUE rb_hash_values(VALUE hash)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
VALUE rb_fix_plus(VALUE x, VALUE y)
rb_encoding * rb_usascii_encoding(void)
#define ARY_SET_LEN(ary, n)
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
#define ARY_SET_PTR(ary, p)
#define FL_UNSET_EMBED(ary)
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
RUBY_FUNC_EXPORTED size_t rb_ary_memsize(VALUE ary)
#define rb_cmpint(cmp, a, b)
RUBY_EXTERN VALUE rb_cNumeric
#define RB_FLOAT_TYPE_P(obj)
int rb_respond_to(VALUE, ID)
register unsigned int len
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
VALUE rb_rational_plus(VALUE self, VALUE other)
#define RB_OBJ_WRITE(a, slot, b)
VALUE rb_ary_resize(VALUE ary, long len)
expands or shrinks ary to len elements.
#define ARY_SET_HEAP_LEN(ary, n)
VALUE rb_yield_values2(int n, const VALUE *argv)
#define UNLIMITED_ARGUMENTS
#define RARRAY_AREF(a, i)
VALUE rb_ary_plus(VALUE x, VALUE y)
#define RBASIC_CLASS(obj)
VALUE rb_check_array_type(VALUE ary)
VALUE rb_check_string_type(VALUE)
VALUE rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
VALUE rb_ary_includes(VALUE ary, VALUE item)
#define ARY_INCREASE_PTR(ary, n)
void rb_warning(const char *fmt,...)
st_index_t rb_hash_uint(st_index_t, st_index_t)
#define ARY_INCREASE_LEN(ary, n)
VALUE rb_ary_sort_bang(VALUE ary)
VALUE rb_ary_dup(VALUE ary)
VALUE rb_ary_concat(VALUE x, VALUE y)
void rb_gc_writebarrier_remember(VALUE obj)
#define RETURN_ENUMERATOR(obj, argc, argv)
VALUE rb_ary_join(VALUE ary, VALUE sep)
VALUE rb_ary_tmp_new_fill(long capa)
struct cmp_opt_data cmp_opt
double rb_num2dbl(VALUE)
Converts a Numeric object to double.
#define ARY_SET_SHARED_NUM(ary, value)
#define ARY_SET_SHARED(ary, value)
#define RB_DEBUG_COUNTER_INC(type)
int rb_eql(VALUE, VALUE)
Determines if obj1 and obj2 are equal in terms of Object::eql?.
VALUE rb_ary_reverse(VALUE ary)
VALUE() rb_ary_new_from_args(long n,...)
#define rb_check_frozen(obj)
VALUE rb_ary_cmp(VALUE ary1, VALUE ary2)
VALUE rb_ary_resurrect(VALUE ary)
VALUE rb_str_buf_new(long)
VALUE rb_usascii_str_new(const char *, long)
#define ARY_SHARED_OCCUPIED(ary)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
void rb_ary_delete_same(VALUE ary, VALUE item)
st_index_t rb_hash_start(st_index_t)
VALUE rb_usascii_str_new_cstr(const char *)
void rb_ary_set_len(VALUE ary, long len)