* 2022-01-18 [ci skip]
[ruby-80x24.org.git] / array.c
blob8becdbbc9193a543e73ff7865c000603260fdc07
1 /**********************************************************************
3 array.c -
5 $Author$
6 created at: Fri Aug 6 09:46:12 JST 1993
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
12 **********************************************************************/
14 #include "debug_counter.h"
15 #include "id.h"
16 #include "internal.h"
17 #include "internal/array.h"
18 #include "internal/compar.h"
19 #include "internal/enum.h"
20 #include "internal/gc.h"
21 #include "internal/hash.h"
22 #include "internal/numeric.h"
23 #include "internal/object.h"
24 #include "internal/proc.h"
25 #include "internal/rational.h"
26 #include "internal/vm.h"
27 #include "probes.h"
28 #include "ruby/encoding.h"
29 #include "ruby/st.h"
30 #include "ruby/util.h"
31 #include "transient_heap.h"
32 #include "builtin.h"
34 #if !ARRAY_DEBUG
35 # undef NDEBUG
36 # define NDEBUG
37 #endif
38 #include "ruby_assert.h"
40 VALUE rb_cArray;
42 /* for OPTIMIZED_CMP: */
43 #define id_cmp idCmp
45 #define ARY_DEFAULT_SIZE 16
46 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
47 #define SMALL_ARRAY_LEN 16
49 RBIMPL_ATTR_MAYBE_UNUSED()
50 static int
51 should_be_T_ARRAY(VALUE ary)
53 return RB_TYPE_P(ary, T_ARRAY);
56 RBIMPL_ATTR_MAYBE_UNUSED()
57 static int
58 should_not_be_shared_and_embedded(VALUE ary)
60 return !FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG);
63 #define ARY_SHARED_P(ary) \
64 (assert(should_be_T_ARRAY((VALUE)(ary))), \
65 assert(should_not_be_shared_and_embedded((VALUE)ary)), \
66 FL_TEST_RAW((ary),ELTS_SHARED)!=0)
68 #define ARY_EMBED_P(ary) \
69 (assert(should_be_T_ARRAY((VALUE)(ary))), \
70 assert(should_not_be_shared_and_embedded((VALUE)ary)), \
71 FL_TEST_RAW((ary), RARRAY_EMBED_FLAG) != 0)
73 #define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
74 #define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
75 #define ARY_HEAP_CAPA(a) (assert(!ARY_EMBED_P(a)), assert(!ARY_SHARED_ROOT_P(a)), \
76 RARRAY(a)->as.heap.aux.capa)
78 #define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
79 #define ARY_EMBED_LEN(a) \
80 (assert(ARY_EMBED_P(a)), \
81 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
82 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
83 #define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
85 #define ARY_OWNS_HEAP_P(a) (assert(should_be_T_ARRAY((VALUE)(a))), \
86 !FL_TEST_RAW((a), ELTS_SHARED|RARRAY_EMBED_FLAG))
88 #define FL_SET_EMBED(a) do { \
89 assert(!ARY_SHARED_P(a)); \
90 FL_SET((a), RARRAY_EMBED_FLAG); \
91 RARY_TRANSIENT_UNSET(a); \
92 ary_verify(a); \
93 } while (0)
95 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
96 #define FL_SET_SHARED(ary) do { \
97 assert(!ARY_EMBED_P(ary)); \
98 FL_SET((ary), ELTS_SHARED); \
99 } while (0)
100 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED)
102 #define ARY_SET_PTR(ary, p) do { \
103 assert(!ARY_EMBED_P(ary)); \
104 assert(!OBJ_FROZEN(ary)); \
105 RARRAY(ary)->as.heap.ptr = (p); \
106 } while (0)
107 #define ARY_SET_EMBED_LEN(ary, n) do { \
108 long tmp_n = (n); \
109 assert(ARY_EMBED_P(ary)); \
110 assert(!OBJ_FROZEN(ary)); \
111 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
112 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
113 } while (0)
114 #define ARY_SET_HEAP_LEN(ary, n) do { \
115 assert(!ARY_EMBED_P(ary)); \
116 RARRAY(ary)->as.heap.len = (n); \
117 } while (0)
118 #define ARY_SET_LEN(ary, n) do { \
119 if (ARY_EMBED_P(ary)) { \
120 ARY_SET_EMBED_LEN((ary), (n)); \
122 else { \
123 ARY_SET_HEAP_LEN((ary), (n)); \
125 assert(RARRAY_LEN(ary) == (n)); \
126 } while (0)
127 #define ARY_INCREASE_PTR(ary, n) do { \
128 assert(!ARY_EMBED_P(ary)); \
129 assert(!OBJ_FROZEN(ary)); \
130 RARRAY(ary)->as.heap.ptr += (n); \
131 } while (0)
132 #define ARY_INCREASE_LEN(ary, n) do { \
133 assert(!OBJ_FROZEN(ary)); \
134 if (ARY_EMBED_P(ary)) { \
135 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
137 else { \
138 RARRAY(ary)->as.heap.len += (n); \
140 } while (0)
142 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
143 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
144 #define ARY_SET_CAPA(ary, n) do { \
145 assert(!ARY_EMBED_P(ary)); \
146 assert(!ARY_SHARED_P(ary)); \
147 assert(!OBJ_FROZEN(ary)); \
148 RARRAY(ary)->as.heap.aux.capa = (n); \
149 } while (0)
151 #define ARY_SHARED_ROOT(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared_root)
152 #define ARY_SET_SHARED(ary, value) do { \
153 const VALUE _ary_ = (ary); \
154 const VALUE _value_ = (value); \
155 assert(!ARY_EMBED_P(_ary_)); \
156 assert(ARY_SHARED_P(_ary_)); \
157 assert(ARY_SHARED_ROOT_P(_value_)); \
158 RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared_root, _value_); \
159 } while (0)
160 #define RARRAY_SHARED_ROOT_FLAG FL_USER5
161 #define ARY_SHARED_ROOT_P(ary) (assert(should_be_T_ARRAY((VALUE)(ary))), \
162 FL_TEST_RAW((ary), RARRAY_SHARED_ROOT_FLAG))
163 #define ARY_SHARED_ROOT_REFCNT(ary) \
164 (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
165 #define ARY_SHARED_ROOT_OCCUPIED(ary) (ARY_SHARED_ROOT_REFCNT(ary) == 1)
166 #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
167 assert(ARY_SHARED_ROOT_P(ary)); \
168 RARRAY(ary)->as.heap.aux.capa = (value); \
169 } while (0)
170 #define FL_SET_SHARED_ROOT(ary) do { \
171 assert(!ARY_EMBED_P(ary)); \
172 assert(!RARRAY_TRANSIENT_P(ary)); \
173 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
174 } while (0)
176 static inline void
177 ARY_SET(VALUE a, long i, VALUE v)
179 assert(!ARY_SHARED_P(a));
180 assert(!OBJ_FROZEN(a));
182 RARRAY_ASET(a, i, v);
184 #undef RARRAY_ASET
187 #if ARRAY_DEBUG
188 #define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
190 static VALUE
191 ary_verify_(VALUE ary, const char *file, int line)
193 assert(RB_TYPE_P(ary, T_ARRAY));
195 if (FL_TEST(ary, ELTS_SHARED)) {
196 VALUE root = RARRAY(ary)->as.heap.aux.shared_root;
197 const VALUE *ptr = ARY_HEAP_PTR(ary);
198 const VALUE *root_ptr = RARRAY_CONST_PTR_TRANSIENT(root);
199 long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
200 assert(FL_TEST(root, RARRAY_SHARED_ROOT_FLAG));
201 assert(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
202 ary_verify(root);
204 else if (ARY_EMBED_P(ary)) {
205 assert(!RARRAY_TRANSIENT_P(ary));
206 assert(!ARY_SHARED_P(ary));
207 assert(RARRAY_LEN(ary) <= RARRAY_EMBED_LEN_MAX);
209 else {
210 #if 1
211 const VALUE *ptr = RARRAY_CONST_PTR_TRANSIENT(ary);
212 long i, len = RARRAY_LEN(ary);
213 volatile VALUE v;
214 if (len > 1) len = 1; /* check only HEAD */
215 for (i=0; i<len; i++) {
216 v = ptr[i]; /* access check */
218 v = v;
219 #endif
222 #if USE_TRANSIENT_HEAP
223 if (RARRAY_TRANSIENT_P(ary)) {
224 assert(rb_transient_heap_managed_ptr_p(RARRAY_CONST_PTR_TRANSIENT(ary)));
226 #endif
228 rb_transient_heap_verify();
230 return ary;
233 void
234 rb_ary_verify(VALUE ary)
236 ary_verify(ary);
238 #else
239 #define ary_verify(ary) ((void)0)
240 #endif
242 VALUE *
243 rb_ary_ptr_use_start(VALUE ary)
245 #if ARRAY_DEBUG
246 FL_SET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
247 #endif
248 return (VALUE *)RARRAY_CONST_PTR_TRANSIENT(ary);
251 void
252 rb_ary_ptr_use_end(VALUE ary)
254 #if ARRAY_DEBUG
255 FL_UNSET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
256 #endif
259 void
260 rb_mem_clear(VALUE *mem, long size)
262 while (size--) {
263 *mem++ = Qnil;
267 static void
268 ary_mem_clear(VALUE ary, long beg, long size)
270 RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
271 rb_mem_clear(ptr + beg, size);
275 static inline void
276 memfill(register VALUE *mem, register long size, register VALUE val)
278 while (size--) {
279 *mem++ = val;
283 static void
284 ary_memfill(VALUE ary, long beg, long size, VALUE val)
286 RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
287 memfill(ptr + beg, size, val);
288 RB_OBJ_WRITTEN(ary, Qundef, val);
292 static void
293 ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary)
295 assert(!ARY_SHARED_P(buff_owner_ary));
297 if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
298 rb_gc_writebarrier_remember(buff_owner_ary);
299 RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
300 MEMCPY(ptr+beg, argv, VALUE, argc);
303 else {
304 int i;
305 RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
306 for (i=0; i<argc; i++) {
307 RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
313 static void
314 ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
316 ary_memcpy0(ary, beg, argc, argv, ary);
319 static VALUE *
320 ary_heap_alloc(VALUE ary, size_t capa)
322 VALUE *ptr = rb_transient_heap_alloc(ary, sizeof(VALUE) * capa);
324 if (ptr != NULL) {
325 RARY_TRANSIENT_SET(ary);
327 else {
328 RARY_TRANSIENT_UNSET(ary);
329 ptr = ALLOC_N(VALUE, capa);
332 return ptr;
335 static void
336 ary_heap_free_ptr(VALUE ary, const VALUE *ptr, long size)
338 if (RARRAY_TRANSIENT_P(ary)) {
339 /* ignore it */
341 else {
342 ruby_sized_xfree((void *)ptr, size);
346 static void
347 ary_heap_free(VALUE ary)
349 if (RARRAY_TRANSIENT_P(ary)) {
350 RARY_TRANSIENT_UNSET(ary);
352 else {
353 ary_heap_free_ptr(ary, ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
357 static size_t
358 ary_heap_realloc(VALUE ary, size_t new_capa)
360 size_t alloc_capa = new_capa;
361 size_t old_capa = ARY_HEAP_CAPA(ary);
363 if (RARRAY_TRANSIENT_P(ary)) {
364 if (new_capa <= old_capa) {
365 /* do nothing */
366 alloc_capa = old_capa;
368 else {
369 VALUE *new_ptr = rb_transient_heap_alloc(ary, sizeof(VALUE) * new_capa);
371 if (new_ptr == NULL) {
372 new_ptr = ALLOC_N(VALUE, new_capa);
373 RARY_TRANSIENT_UNSET(ary);
376 MEMCPY(new_ptr, ARY_HEAP_PTR(ary), VALUE, old_capa);
377 ARY_SET_PTR(ary, new_ptr);
380 else {
381 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, old_capa);
383 ary_verify(ary);
385 return alloc_capa;
388 #if USE_TRANSIENT_HEAP
389 static inline void
390 rb_ary_transient_heap_evacuate_(VALUE ary, int transient, int promote)
392 if (transient) {
393 VALUE *new_ptr;
394 const VALUE *old_ptr = ARY_HEAP_PTR(ary);
395 long capa = ARY_HEAP_CAPA(ary);
396 long len = ARY_HEAP_LEN(ary);
398 if (ARY_SHARED_ROOT_P(ary)) {
399 capa = len;
402 assert(ARY_OWNS_HEAP_P(ary));
403 assert(RARRAY_TRANSIENT_P(ary));
404 assert(!ARY_PTR_USING_P(ary));
406 if (promote) {
407 new_ptr = ALLOC_N(VALUE, capa);
408 RARY_TRANSIENT_UNSET(ary);
410 else {
411 new_ptr = ary_heap_alloc(ary, capa);
414 MEMCPY(new_ptr, old_ptr, VALUE, capa);
415 /* do not use ARY_SET_PTR() because they assert !frozen */
416 RARRAY(ary)->as.heap.ptr = new_ptr;
419 ary_verify(ary);
422 void
423 rb_ary_transient_heap_evacuate(VALUE ary, int promote)
425 rb_ary_transient_heap_evacuate_(ary, RARRAY_TRANSIENT_P(ary), promote);
428 void
429 rb_ary_detransient(VALUE ary)
431 assert(RARRAY_TRANSIENT_P(ary));
432 rb_ary_transient_heap_evacuate_(ary, TRUE, TRUE);
434 #else
435 void
436 rb_ary_detransient(VALUE ary)
438 /* do nothing */
440 #endif
442 static void
443 ary_resize_capa(VALUE ary, long capacity)
445 assert(RARRAY_LEN(ary) <= capacity);
446 assert(!OBJ_FROZEN(ary));
447 assert(!ARY_SHARED_P(ary));
449 if (capacity > RARRAY_EMBED_LEN_MAX) {
450 size_t new_capa = capacity;
451 if (ARY_EMBED_P(ary)) {
452 long len = ARY_EMBED_LEN(ary);
453 VALUE *ptr = ary_heap_alloc(ary, capacity);
455 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
456 FL_UNSET_EMBED(ary);
457 ARY_SET_PTR(ary, ptr);
458 ARY_SET_HEAP_LEN(ary, len);
460 else {
461 new_capa = ary_heap_realloc(ary, capacity);
463 ARY_SET_CAPA(ary, new_capa);
465 else {
466 if (!ARY_EMBED_P(ary)) {
467 long len = ARY_HEAP_LEN(ary);
468 long old_capa = ARY_HEAP_CAPA(ary);
469 const VALUE *ptr = ARY_HEAP_PTR(ary);
471 if (len > capacity) len = capacity;
472 MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
473 ary_heap_free_ptr(ary, ptr, old_capa);
475 FL_SET_EMBED(ary);
476 ARY_SET_LEN(ary, len);
480 ary_verify(ary);
483 static inline void
484 ary_shrink_capa(VALUE ary)
486 long capacity = ARY_HEAP_LEN(ary);
487 long old_capa = ARY_HEAP_CAPA(ary);
488 assert(!ARY_SHARED_P(ary));
489 assert(old_capa >= capacity);
490 if (old_capa > capacity) ary_heap_realloc(ary, capacity);
492 ary_verify(ary);
495 static void
496 ary_double_capa(VALUE ary, long min)
498 long new_capa = ARY_CAPA(ary) / 2;
500 if (new_capa < ARY_DEFAULT_SIZE) {
501 new_capa = ARY_DEFAULT_SIZE;
503 if (new_capa >= ARY_MAX_SIZE - min) {
504 new_capa = (ARY_MAX_SIZE - min) / 2;
506 new_capa += min;
507 ary_resize_capa(ary, new_capa);
509 ary_verify(ary);
512 static void
513 rb_ary_decrement_share(VALUE shared_root)
515 if (shared_root) {
516 long num = ARY_SHARED_ROOT_REFCNT(shared_root) - 1;
517 if (num > 0) {
518 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num);
523 static void
524 rb_ary_unshare(VALUE ary)
526 VALUE shared_root = RARRAY(ary)->as.heap.aux.shared_root;
527 rb_ary_decrement_share(shared_root);
528 FL_UNSET_SHARED(ary);
531 static inline void
532 rb_ary_unshare_safe(VALUE ary)
534 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
535 rb_ary_unshare(ary);
539 static VALUE
540 rb_ary_increment_share(VALUE shared_root)
542 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
543 if (num >= 0) {
544 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
546 return shared_root;
549 static void
550 rb_ary_set_shared(VALUE ary, VALUE shared_root)
552 rb_ary_increment_share(shared_root);
553 FL_SET_SHARED(ary);
554 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
555 ARY_SET_SHARED(ary, shared_root);
558 static inline void
559 rb_ary_modify_check(VALUE ary)
561 rb_check_frozen(ary);
562 ary_verify(ary);
565 void
566 rb_ary_cancel_sharing(VALUE ary)
568 if (ARY_SHARED_P(ary)) {
569 long shared_len, len = RARRAY_LEN(ary);
570 VALUE shared_root = ARY_SHARED_ROOT(ary);
572 ary_verify(shared_root);
574 if (len <= RARRAY_EMBED_LEN_MAX) {
575 const VALUE *ptr = ARY_HEAP_PTR(ary);
576 FL_UNSET_SHARED(ary);
577 FL_SET_EMBED(ary);
578 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
579 rb_ary_decrement_share(shared_root);
580 ARY_SET_EMBED_LEN(ary, len);
582 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) {
583 long shift = RARRAY_CONST_PTR_TRANSIENT(ary) - RARRAY_CONST_PTR_TRANSIENT(shared_root);
584 FL_UNSET_SHARED(ary);
585 ARY_SET_PTR(ary, RARRAY_CONST_PTR_TRANSIENT(shared_root));
586 ARY_SET_CAPA(ary, shared_len);
587 RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
588 MEMMOVE(ptr, ptr+shift, VALUE, len);
590 FL_SET_EMBED(shared_root);
591 rb_ary_decrement_share(shared_root);
593 else {
594 VALUE *ptr = ary_heap_alloc(ary, len);
595 MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len);
596 rb_ary_unshare(ary);
597 ARY_SET_CAPA(ary, len);
598 ARY_SET_PTR(ary, ptr);
601 rb_gc_writebarrier_remember(ary);
603 ary_verify(ary);
606 void
607 rb_ary_modify(VALUE ary)
609 rb_ary_modify_check(ary);
610 rb_ary_cancel_sharing(ary);
613 static VALUE
614 ary_ensure_room_for_push(VALUE ary, long add_len)
616 long old_len = RARRAY_LEN(ary);
617 long new_len = old_len + add_len;
618 long capa;
620 if (old_len > ARY_MAX_SIZE - add_len) {
621 rb_raise(rb_eIndexError, "index %ld too big", new_len);
623 if (ARY_SHARED_P(ary)) {
624 if (new_len > RARRAY_EMBED_LEN_MAX) {
625 VALUE shared_root = ARY_SHARED_ROOT(ary);
626 if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
627 if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR_TRANSIENT(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
628 rb_ary_modify_check(ary);
630 ary_verify(ary);
631 ary_verify(shared_root);
632 return shared_root;
634 else {
635 /* if array is shared, then it is likely it participate in push/shift pattern */
636 rb_ary_modify(ary);
637 capa = ARY_CAPA(ary);
638 if (new_len > capa - (capa >> 6)) {
639 ary_double_capa(ary, new_len);
641 ary_verify(ary);
642 return ary;
646 ary_verify(ary);
647 rb_ary_modify(ary);
649 else {
650 rb_ary_modify_check(ary);
652 capa = ARY_CAPA(ary);
653 if (new_len > capa) {
654 ary_double_capa(ary, new_len);
657 ary_verify(ary);
658 return ary;
662 * call-seq:
663 * array.freeze -> self
665 * Freezes +self+; returns +self+:
666 * a = []
667 * a.frozen? # => false
668 * a.freeze
669 * a.frozen? # => true
671 * An attempt to modify a frozen \Array raises FrozenError.
674 VALUE
675 rb_ary_freeze(VALUE ary)
677 return rb_obj_freeze(ary);
680 /* This can be used to take a snapshot of an array (with
681 e.g. rb_ary_replace) and check later whether the array has been
682 modified from the snapshot. The snapshot is cheap, though if
683 something does modify the array it will pay the cost of copying
684 it. If Array#pop or Array#shift has been called, the array will
685 be still shared with the snapshot, but the array length will
686 differ. */
687 VALUE
688 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
690 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
691 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
692 RARRAY(ary1)->as.heap.aux.shared_root == RARRAY(ary2)->as.heap.aux.shared_root &&
693 RARRAY(ary1)->as.heap.len == RARRAY(ary2)->as.heap.len) {
694 return Qtrue;
696 return Qfalse;
699 static VALUE
700 ary_alloc(VALUE klass)
702 NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
703 /* Created array is:
704 * FL_SET_EMBED((VALUE)ary);
705 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
707 return (VALUE)ary;
710 static VALUE
711 empty_ary_alloc(VALUE klass)
713 RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
714 return ary_alloc(klass);
717 static VALUE
718 ary_new(VALUE klass, long capa)
720 VALUE ary,*ptr;
722 if (capa < 0) {
723 rb_raise(rb_eArgError, "negative array size (or size too big)");
725 if (capa > ARY_MAX_SIZE) {
726 rb_raise(rb_eArgError, "array size too big");
729 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
731 ary = ary_alloc(klass);
732 if (capa > RARRAY_EMBED_LEN_MAX) {
733 ptr = ary_heap_alloc(ary, capa);
734 FL_UNSET_EMBED(ary);
735 ARY_SET_PTR(ary, ptr);
736 ARY_SET_CAPA(ary, capa);
737 ARY_SET_HEAP_LEN(ary, 0);
740 return ary;
743 VALUE
744 rb_ary_new_capa(long capa)
746 return ary_new(rb_cArray, capa);
749 VALUE
750 rb_ary_new(void)
752 return rb_ary_new2(RARRAY_EMBED_LEN_MAX);
755 VALUE
756 (rb_ary_new_from_args)(long n, ...)
758 va_list ar;
759 VALUE ary;
760 long i;
762 ary = rb_ary_new2(n);
764 va_start(ar, n);
765 for (i=0; i<n; i++) {
766 ARY_SET(ary, i, va_arg(ar, VALUE));
768 va_end(ar);
770 ARY_SET_LEN(ary, n);
771 return ary;
774 MJIT_FUNC_EXPORTED VALUE
775 rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
777 VALUE ary;
779 ary = ary_new(klass, n);
780 if (n > 0 && elts) {
781 ary_memcpy(ary, 0, n, elts);
782 ARY_SET_LEN(ary, n);
785 return ary;
788 VALUE
789 rb_ary_new_from_values(long n, const VALUE *elts)
791 return rb_ary_tmp_new_from_values(rb_cArray, n, elts);
794 static VALUE
795 ec_ary_alloc(rb_execution_context_t *ec, VALUE klass)
797 RB_EC_NEWOBJ_OF(ec, ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
798 /* Created array is:
799 * FL_SET_EMBED((VALUE)ary);
800 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
802 return (VALUE)ary;
805 static VALUE
806 ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
808 VALUE ary,*ptr;
810 if (capa < 0) {
811 rb_raise(rb_eArgError, "negative array size (or size too big)");
813 if (capa > ARY_MAX_SIZE) {
814 rb_raise(rb_eArgError, "array size too big");
817 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
819 ary = ec_ary_alloc(ec, klass);
821 if (capa > RARRAY_EMBED_LEN_MAX) {
822 ptr = ary_heap_alloc(ary, capa);
823 FL_UNSET_EMBED(ary);
824 ARY_SET_PTR(ary, ptr);
825 ARY_SET_CAPA(ary, capa);
826 ARY_SET_HEAP_LEN(ary, 0);
829 return ary;
832 VALUE
833 rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
835 VALUE ary;
837 ary = ec_ary_new(ec, rb_cArray, n);
838 if (n > 0 && elts) {
839 ary_memcpy(ary, 0, n, elts);
840 ARY_SET_LEN(ary, n);
843 return ary;
846 VALUE
847 rb_ary_tmp_new(long capa)
849 VALUE ary = ary_new(0, capa);
850 rb_ary_transient_heap_evacuate(ary, TRUE);
851 return ary;
854 VALUE
855 rb_ary_tmp_new_fill(long capa)
857 VALUE ary = ary_new(0, capa);
858 ary_memfill(ary, 0, capa, Qnil);
859 ARY_SET_LEN(ary, capa);
860 rb_ary_transient_heap_evacuate(ary, TRUE);
861 return ary;
864 void
865 rb_ary_free(VALUE ary)
867 if (ARY_OWNS_HEAP_P(ary)) {
868 if (USE_DEBUG_COUNTER &&
869 !ARY_SHARED_ROOT_P(ary) &&
870 ARY_HEAP_CAPA(ary) > RARRAY_LEN(ary)) {
871 RB_DEBUG_COUNTER_INC(obj_ary_extracapa);
874 if (RARRAY_TRANSIENT_P(ary)) {
875 RB_DEBUG_COUNTER_INC(obj_ary_transient);
877 else {
878 RB_DEBUG_COUNTER_INC(obj_ary_ptr);
879 ary_heap_free(ary);
882 else {
883 RB_DEBUG_COUNTER_INC(obj_ary_embed);
886 if (ARY_SHARED_P(ary)) {
887 RB_DEBUG_COUNTER_INC(obj_ary_shared);
889 if (ARY_SHARED_ROOT_P(ary) && ARY_SHARED_ROOT_OCCUPIED(ary)) {
890 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
894 RUBY_FUNC_EXPORTED size_t
895 rb_ary_memsize(VALUE ary)
897 if (ARY_OWNS_HEAP_P(ary)) {
898 return ARY_CAPA(ary) * sizeof(VALUE);
900 else {
901 return 0;
905 static inline void
906 ary_discard(VALUE ary)
908 rb_ary_free(ary);
909 RBASIC(ary)->flags |= RARRAY_EMBED_FLAG;
910 RBASIC(ary)->flags &= ~(RARRAY_EMBED_LEN_MASK | RARRAY_TRANSIENT_FLAG);
913 static VALUE
914 ary_make_shared(VALUE ary)
916 assert(!ARY_EMBED_P(ary));
917 ary_verify(ary);
919 if (ARY_SHARED_P(ary)) {
920 return ARY_SHARED_ROOT(ary);
922 else if (ARY_SHARED_ROOT_P(ary)) {
923 return ary;
925 else if (OBJ_FROZEN(ary)) {
926 rb_ary_transient_heap_evacuate(ary, TRUE);
927 ary_shrink_capa(ary);
928 FL_SET_SHARED_ROOT(ary);
929 ARY_SET_SHARED_ROOT_REFCNT(ary, 1);
930 return ary;
932 else {
933 long capa = ARY_CAPA(ary), len = RARRAY_LEN(ary);
934 const VALUE *ptr;
935 NEWOBJ_OF(shared, struct RArray, 0, T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
936 VALUE vshared = (VALUE)shared;
938 rb_ary_transient_heap_evacuate(ary, TRUE);
939 ptr = ARY_HEAP_PTR(ary);
941 FL_UNSET_EMBED(vshared);
942 ARY_SET_LEN(vshared, capa);
943 ARY_SET_PTR(vshared, ptr);
944 ary_mem_clear(vshared, len, capa - len);
945 FL_SET_SHARED_ROOT(vshared);
946 ARY_SET_SHARED_ROOT_REFCNT(vshared, 1);
947 FL_SET_SHARED(ary);
948 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
949 ARY_SET_SHARED(ary, vshared);
950 OBJ_FREEZE(vshared);
952 ary_verify(vshared);
953 ary_verify(ary);
955 return vshared;
959 static VALUE
960 ary_make_substitution(VALUE ary)
962 long len = RARRAY_LEN(ary);
964 if (len <= RARRAY_EMBED_LEN_MAX) {
965 VALUE subst = rb_ary_new2(len);
966 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR_TRANSIENT(ary));
967 ARY_SET_EMBED_LEN(subst, len);
968 return subst;
970 else {
971 return rb_ary_increment_share(ary_make_shared(ary));
975 VALUE
976 rb_assoc_new(VALUE car, VALUE cdr)
978 return rb_ary_new3(2, car, cdr);
981 VALUE
982 rb_to_array_type(VALUE ary)
984 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
986 #define to_ary rb_to_array_type
988 VALUE
989 rb_check_array_type(VALUE ary)
991 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
994 MJIT_FUNC_EXPORTED VALUE
995 rb_check_to_array(VALUE ary)
997 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1000 VALUE
1001 rb_to_array(VALUE ary)
1003 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1007 * call-seq:
1008 * Array.try_convert(object) -> object, new_array, or nil
1010 * If +object+ is an \Array object, returns +object+.
1012 * Otherwise if +object+ responds to <tt>:to_ary</tt>,
1013 * calls <tt>object.to_ary</tt> and returns the result.
1015 * Returns +nil+ if +object+ does not respond to <tt>:to_ary</tt>
1017 * Raises an exception unless <tt>object.to_ary</tt> returns an \Array object.
1020 static VALUE
1021 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
1023 return rb_check_array_type(ary);
1027 * call-seq:
1028 * Array.new -> new_empty_array
1029 * Array.new(array) -> new_array
1030 * Array.new(size) -> new_array
1031 * Array.new(size, default_value) -> new_array
1032 * Array.new(size) {|index| ... } -> new_array
1034 * Returns a new \Array.
1036 * With no block and no arguments, returns a new empty \Array object.
1038 * With no block and a single \Array argument +array+,
1039 * returns a new \Array formed from +array+:
1040 * a = Array.new([:foo, 'bar', 2])
1041 * a.class # => Array
1042 * a # => [:foo, "bar", 2]
1044 * With no block and a single \Integer argument +size+,
1045 * returns a new \Array of the given size
1046 * whose elements are all +nil+:
1047 * a = Array.new(3)
1048 * a # => [nil, nil, nil]
1050 * With no block and arguments +size+ and +default_value+,
1051 * returns an \Array of the given size;
1052 * each element is that same +default_value+:
1053 * a = Array.new(3, 'x')
1054 * a # => ['x', 'x', 'x']
1056 * With a block and argument +size+,
1057 * returns an \Array of the given size;
1058 * the block is called with each successive integer +index+;
1059 * the element for that +index+ is the return value from the block:
1060 * a = Array.new(3) {|index| "Element #{index}" }
1061 * a # => ["Element 0", "Element 1", "Element 2"]
1063 * Raises ArgumentError if +size+ is negative.
1065 * With a block and no argument,
1066 * or a single argument +0+,
1067 * ignores the block and returns a new empty \Array.
1070 static VALUE
1071 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
1073 long len;
1074 VALUE size, val;
1076 rb_ary_modify(ary);
1077 if (argc == 0) {
1078 if (ARY_OWNS_HEAP_P(ary) && ARY_HEAP_PTR(ary) != NULL) {
1079 ary_heap_free(ary);
1081 rb_ary_unshare_safe(ary);
1082 FL_SET_EMBED(ary);
1083 ARY_SET_EMBED_LEN(ary, 0);
1084 if (rb_block_given_p()) {
1085 rb_warning("given block not used");
1087 return ary;
1089 rb_scan_args(argc, argv, "02", &size, &val);
1090 if (argc == 1 && !FIXNUM_P(size)) {
1091 val = rb_check_array_type(size);
1092 if (!NIL_P(val)) {
1093 rb_ary_replace(ary, val);
1094 return ary;
1098 len = NUM2LONG(size);
1099 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1100 if (len < 0) {
1101 rb_raise(rb_eArgError, "negative array size");
1103 if (len > ARY_MAX_SIZE) {
1104 rb_raise(rb_eArgError, "array size too big");
1106 /* recheck after argument conversion */
1107 rb_ary_modify(ary);
1108 ary_resize_capa(ary, len);
1109 if (rb_block_given_p()) {
1110 long i;
1112 if (argc == 2) {
1113 rb_warn("block supersedes default value argument");
1115 for (i=0; i<len; i++) {
1116 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
1117 ARY_SET_LEN(ary, i + 1);
1120 else {
1121 ary_memfill(ary, 0, len, val);
1122 ARY_SET_LEN(ary, len);
1124 return ary;
1128 * Returns a new array populated with the given objects.
1130 * Array.[]( 1, 'a', /^A/) # => [1, "a", /^A/]
1131 * Array[ 1, 'a', /^A/ ] # => [1, "a", /^A/]
1132 * [ 1, 'a', /^A/ ] # => [1, "a", /^A/]
1135 static VALUE
1136 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
1138 VALUE ary = ary_new(klass, argc);
1139 if (argc > 0 && argv) {
1140 ary_memcpy(ary, 0, argc, argv);
1141 ARY_SET_LEN(ary, argc);
1144 return ary;
1147 void
1148 rb_ary_store(VALUE ary, long idx, VALUE val)
1150 long len = RARRAY_LEN(ary);
1152 if (idx < 0) {
1153 idx += len;
1154 if (idx < 0) {
1155 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1156 idx - len, -len);
1159 else if (idx >= ARY_MAX_SIZE) {
1160 rb_raise(rb_eIndexError, "index %ld too big", idx);
1163 rb_ary_modify(ary);
1164 if (idx >= ARY_CAPA(ary)) {
1165 ary_double_capa(ary, idx);
1167 if (idx > len) {
1168 ary_mem_clear(ary, len, idx - len + 1);
1171 if (idx >= len) {
1172 ARY_SET_LEN(ary, idx + 1);
1174 ARY_SET(ary, idx, val);
1177 static VALUE
1178 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
1180 assert(offset >= 0);
1181 assert(len >= 0);
1182 assert(offset+len <= RARRAY_LEN(ary));
1184 if (len <= RARRAY_EMBED_LEN_MAX) {
1185 VALUE result = ary_alloc(klass);
1186 ary_memcpy(result, 0, len, RARRAY_CONST_PTR_TRANSIENT(ary) + offset);
1187 ARY_SET_EMBED_LEN(result, len);
1188 return result;
1190 else {
1191 VALUE shared, result = ary_alloc(klass);
1192 FL_UNSET_EMBED(result);
1194 shared = ary_make_shared(ary);
1195 ARY_SET_PTR(result, RARRAY_CONST_PTR_TRANSIENT(ary));
1196 ARY_SET_LEN(result, RARRAY_LEN(ary));
1197 rb_ary_set_shared(result, shared);
1199 ARY_INCREASE_PTR(result, offset);
1200 ARY_SET_LEN(result, len);
1202 ary_verify(shared);
1203 ary_verify(result);
1204 return result;
1208 static VALUE
1209 ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
1211 assert(offset >= 0);
1212 assert(len >= 0);
1213 assert(offset+len <= RARRAY_LEN(ary));
1214 assert(step != 0);
1216 const VALUE *values = RARRAY_CONST_PTR_TRANSIENT(ary);
1217 const long orig_len = len;
1219 if ((step > 0 && step >= len) || (step < 0 && (step < -len))) {
1220 VALUE result = ary_new(klass, 1);
1221 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1222 RB_OBJ_WRITE(result, ptr, values[offset]);
1223 ARY_SET_EMBED_LEN(result, 1);
1224 return result;
1227 long ustep = (step < 0) ? -step : step;
1228 len = (len + ustep - 1) / ustep;
1230 long i;
1231 long j = offset + ((step > 0) ? 0 : (orig_len - 1));
1232 VALUE result = ary_new(klass, len);
1233 if (len <= RARRAY_EMBED_LEN_MAX) {
1234 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1235 for (i = 0; i < len; ++i) {
1236 RB_OBJ_WRITE(result, ptr+i, values[j]);
1237 j += step;
1239 ARY_SET_EMBED_LEN(result, len);
1241 else {
1242 RARRAY_PTR_USE_TRANSIENT(result, ptr, {
1243 for (i = 0; i < len; ++i) {
1244 RB_OBJ_WRITE(result, ptr+i, values[j]);
1245 j += step;
1248 ARY_SET_LEN(result, len);
1251 return result;
1254 static VALUE
1255 ary_make_shared_copy(VALUE ary)
1257 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
1260 enum ary_take_pos_flags
1262 ARY_TAKE_FIRST = 0,
1263 ARY_TAKE_LAST = 1
1266 static VALUE
1267 ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1269 long n;
1270 long len;
1271 long offset = 0;
1273 argc = rb_check_arity(argc, 0, 1);
1274 /* the case optional argument is omitted should be handled in
1275 * callers of this function. if another arity case is added,
1276 * this arity check needs to rewrite. */
1277 RUBY_ASSERT_ALWAYS(argc == 1);
1279 n = NUM2LONG(argv[0]);
1280 len = RARRAY_LEN(ary);
1281 if (n > len) {
1282 n = len;
1284 else if (n < 0) {
1285 rb_raise(rb_eArgError, "negative array size");
1287 if (last) {
1288 offset = len - n;
1290 return ary_make_partial(ary, rb_cArray, offset, n);
1294 * call-seq:
1295 * array << object -> self
1297 * Appends +object+ to +self+; returns +self+:
1298 * a = [:foo, 'bar', 2]
1299 * a << :baz # => [:foo, "bar", 2, :baz]
1301 * Appends +object+ as one element, even if it is another \Array:
1302 * a = [:foo, 'bar', 2]
1303 * a1 = a << [3, 4]
1304 * a1 # => [:foo, "bar", 2, [3, 4]]
1307 VALUE
1308 rb_ary_push(VALUE ary, VALUE item)
1310 long idx = RARRAY_LEN((ary_verify(ary), ary));
1311 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
1312 RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
1313 RB_OBJ_WRITE(target_ary, &ptr[idx], item);
1315 ARY_SET_LEN(ary, idx + 1);
1316 ary_verify(ary);
1317 return ary;
1320 VALUE
1321 rb_ary_cat(VALUE ary, const VALUE *argv, long len)
1323 long oldlen = RARRAY_LEN(ary);
1324 VALUE target_ary = ary_ensure_room_for_push(ary, len);
1325 ary_memcpy0(ary, oldlen, len, argv, target_ary);
1326 ARY_SET_LEN(ary, oldlen + len);
1327 return ary;
1331 * call-seq:
1332 * array.push(*objects) -> self
1334 * Appends trailing elements.
1336 * Appends each argument in +objects+ to +self+; returns +self+:
1337 * a = [:foo, 'bar', 2]
1338 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1340 * Appends each argument as one element, even if it is another \Array:
1341 * a = [:foo, 'bar', 2]
1342 * a1 = a.push([:baz, :bat], [:bam, :bad])
1343 * a1 # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1345 * Array#append is an alias for \Array#push.
1347 * Related: #pop, #shift, #unshift.
1350 static VALUE
1351 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
1353 return rb_ary_cat(ary, argv, argc);
1356 VALUE
1357 rb_ary_pop(VALUE ary)
1359 long n;
1360 rb_ary_modify_check(ary);
1361 n = RARRAY_LEN(ary);
1362 if (n == 0) return Qnil;
1363 if (ARY_OWNS_HEAP_P(ary) &&
1364 n * 3 < ARY_CAPA(ary) &&
1365 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
1367 ary_resize_capa(ary, n * 2);
1369 --n;
1370 ARY_SET_LEN(ary, n);
1371 ary_verify(ary);
1372 return RARRAY_AREF(ary, n);
1376 * call-seq:
1377 * array.pop -> object or nil
1378 * array.pop(n) -> new_array
1380 * Removes and returns trailing elements.
1382 * When no argument is given and +self+ is not empty,
1383 * removes and returns the last element:
1384 * a = [:foo, 'bar', 2]
1385 * a.pop # => 2
1386 * a # => [:foo, "bar"]
1388 * Returns +nil+ if the array is empty.
1390 * When a non-negative \Integer argument +n+ is given and is in range,
1391 * removes and returns the last +n+ elements in a new \Array:
1392 * a = [:foo, 'bar', 2]
1393 * a.pop(2) # => ["bar", 2]
1395 * If +n+ is positive and out of range,
1396 * removes and returns all elements:
1397 * a = [:foo, 'bar', 2]
1398 * a.pop(50) # => [:foo, "bar", 2]
1400 * Related: #push, #shift, #unshift.
1403 static VALUE
1404 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
1406 VALUE result;
1408 if (argc == 0) {
1409 return rb_ary_pop(ary);
1412 rb_ary_modify_check(ary);
1413 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1414 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
1415 ary_verify(ary);
1416 return result;
1419 VALUE
1420 rb_ary_shift(VALUE ary)
1422 VALUE top;
1423 long len = RARRAY_LEN(ary);
1425 rb_ary_modify_check(ary);
1426 if (len == 0) return Qnil;
1427 top = RARRAY_AREF(ary, 0);
1428 if (!ARY_SHARED_P(ary)) {
1429 if (len < ARY_DEFAULT_SIZE) {
1430 RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
1431 MEMMOVE(ptr, ptr+1, VALUE, len-1);
1432 }); /* WB: no new reference */
1433 ARY_INCREASE_LEN(ary, -1);
1434 ary_verify(ary);
1435 return top;
1437 assert(!ARY_EMBED_P(ary)); /* ARY_EMBED_LEN_MAX < ARY_DEFAULT_SIZE */
1439 ARY_SET(ary, 0, Qnil);
1440 ary_make_shared(ary);
1442 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1443 RARRAY_PTR_USE_TRANSIENT(ary, ptr, ptr[0] = Qnil);
1445 ARY_INCREASE_PTR(ary, 1); /* shift ptr */
1446 ARY_INCREASE_LEN(ary, -1);
1448 ary_verify(ary);
1450 return top;
1454 * call-seq:
1455 * array.shift -> object or nil
1456 * array.shift(n) -> new_array
1458 * Removes and returns leading elements.
1460 * When no argument is given, removes and returns the first element:
1461 * a = [:foo, 'bar', 2]
1462 * a.shift # => :foo
1463 * a # => ['bar', 2]
1465 * Returns +nil+ if +self+ is empty.
1467 * When positive \Integer argument +n+ is given, removes the first +n+ elements;
1468 * returns those elements in a new \Array:
1469 * a = [:foo, 'bar', 2]
1470 * a.shift(2) # => [:foo, 'bar']
1471 * a # => [2]
1473 * If +n+ is as large as or larger than <tt>self.length</tt>,
1474 * removes all elements; returns those elements in a new \Array:
1475 * a = [:foo, 'bar', 2]
1476 * a.shift(3) # => [:foo, 'bar', 2]
1478 * If +n+ is zero, returns a new empty \Array; +self+ is unmodified.
1480 * Related: #push, #pop, #unshift.
1483 static VALUE
1484 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
1486 VALUE result;
1487 long n;
1489 if (argc == 0) {
1490 return rb_ary_shift(ary);
1493 rb_ary_modify_check(ary);
1494 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1495 n = RARRAY_LEN(result);
1496 rb_ary_behead(ary,n);
1498 return result;
1501 static VALUE
1502 behead_shared(VALUE ary, long n)
1504 assert(ARY_SHARED_P(ary));
1505 rb_ary_modify_check(ary);
1506 if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1507 ary_mem_clear(ary, 0, n);
1509 ARY_INCREASE_PTR(ary, n);
1510 ARY_INCREASE_LEN(ary, -n);
1511 ary_verify(ary);
1512 return ary;
1515 static VALUE
1516 behead_transient(VALUE ary, long n)
1518 rb_ary_modify_check(ary);
1519 RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
1520 MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n);
1521 }); /* WB: no new reference */
1522 ARY_INCREASE_LEN(ary, -n);
1523 ary_verify(ary);
1524 return ary;
1527 MJIT_FUNC_EXPORTED VALUE
1528 rb_ary_behead(VALUE ary, long n)
1530 if (n <= 0) {
1531 return ary;
1533 else if (ARY_SHARED_P(ary)) {
1534 return behead_shared(ary, n);
1536 else if (RARRAY_LEN(ary) >= ARY_DEFAULT_SIZE) {
1537 ary_make_shared(ary);
1538 return behead_shared(ary, n);
1540 else {
1541 return behead_transient(ary, n);
1545 static VALUE
1546 make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, long capa, long len)
1548 if (head - sharedp < argc) {
1549 long room = capa - len - argc;
1551 room -= room >> 4;
1552 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
1553 head = sharedp + argc + room;
1555 ARY_SET_PTR(ary, head - argc);
1556 assert(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
1558 ary_verify(ary);
1559 return ARY_SHARED_ROOT(ary);
1562 static VALUE
1563 ary_modify_for_unshift(VALUE ary, int argc)
1565 long len = RARRAY_LEN(ary);
1566 long new_len = len + argc;
1567 long capa;
1568 const VALUE *head, *sharedp;
1570 rb_ary_modify(ary);
1571 capa = ARY_CAPA(ary);
1572 if (capa - (capa >> 6) <= new_len) {
1573 ary_double_capa(ary, new_len);
1576 /* use shared array for big "queues" */
1577 if (new_len > ARY_DEFAULT_SIZE * 4) {
1578 ary_verify(ary);
1580 /* make a room for unshifted items */
1581 capa = ARY_CAPA(ary);
1582 ary_make_shared(ary);
1584 head = sharedp = RARRAY_CONST_PTR_TRANSIENT(ary);
1585 return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
1587 else {
1588 /* sliding items */
1589 RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
1590 MEMMOVE(ptr + argc, ptr, VALUE, len);
1593 ary_verify(ary);
1594 return ary;
1598 static VALUE
1599 ary_ensure_room_for_unshift(VALUE ary, int argc)
1601 long len = RARRAY_LEN(ary);
1602 long new_len = len + argc;
1604 if (len > ARY_MAX_SIZE - argc) {
1605 rb_raise(rb_eIndexError, "index %ld too big", new_len);
1607 else if (! ARY_SHARED_P(ary)) {
1608 return ary_modify_for_unshift(ary, argc);
1610 else {
1611 VALUE shared_root = ARY_SHARED_ROOT(ary);
1612 long capa = RARRAY_LEN(shared_root);
1614 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
1615 return ary_modify_for_unshift(ary, argc);
1617 else if (new_len > capa) {
1618 return ary_modify_for_unshift(ary, argc);
1620 else {
1621 const VALUE * head = RARRAY_CONST_PTR_TRANSIENT(ary);
1622 void *sharedp = (void *)RARRAY_CONST_PTR_TRANSIENT(shared_root);
1624 rb_ary_modify_check(ary);
1625 return make_room_for_unshift(ary, head, sharedp, argc, capa, len);
1631 * call-seq:
1632 * array.unshift(*objects) -> self
1634 * Prepends the given +objects+ to +self+:
1635 * a = [:foo, 'bar', 2]
1636 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1638 * Array#prepend is an alias for Array#unshift.
1640 * Related: #push, #pop, #shift.
1643 static VALUE
1644 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1646 long len = RARRAY_LEN(ary);
1647 VALUE target_ary;
1649 if (argc == 0) {
1650 rb_ary_modify_check(ary);
1651 return ary;
1654 target_ary = ary_ensure_room_for_unshift(ary, argc);
1655 ary_memcpy0(ary, 0, argc, argv, target_ary);
1656 ARY_SET_LEN(ary, len + argc);
1657 return ary;
1660 VALUE
1661 rb_ary_unshift(VALUE ary, VALUE item)
1663 return rb_ary_unshift_m(1,&item,ary);
1666 /* faster version - use this if you don't need to treat negative offset */
1667 static inline VALUE
1668 rb_ary_elt(VALUE ary, long offset)
1670 long len = RARRAY_LEN(ary);
1671 if (len == 0) return Qnil;
1672 if (offset < 0 || len <= offset) {
1673 return Qnil;
1675 return RARRAY_AREF(ary, offset);
1678 VALUE
1679 rb_ary_entry(VALUE ary, long offset)
1681 return rb_ary_entry_internal(ary, offset);
1684 VALUE
1685 rb_ary_subseq_step(VALUE ary, long beg, long len, long step)
1687 VALUE klass;
1688 long alen = RARRAY_LEN(ary);
1690 if (beg > alen) return Qnil;
1691 if (beg < 0 || len < 0) return Qnil;
1693 if (alen < len || alen < beg + len) {
1694 len = alen - beg;
1696 klass = rb_cArray;
1697 if (len == 0) return ary_new(klass, 0);
1698 if (step == 0)
1699 rb_raise(rb_eArgError, "slice step cannot be zero");
1700 if (step == 1)
1701 return ary_make_partial(ary, klass, beg, len);
1702 else
1703 return ary_make_partial_step(ary, klass, beg, len, step);
1706 VALUE
1707 rb_ary_subseq(VALUE ary, long beg, long len)
1709 return rb_ary_subseq_step(ary, beg, len, 1);
1712 static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
1715 * call-seq:
1716 * array[index] -> object or nil
1717 * array[start, length] -> object or nil
1718 * array[range] -> object or nil
1719 * array[aseq] -> object or nil
1720 * array.slice(index) -> object or nil
1721 * array.slice(start, length) -> object or nil
1722 * array.slice(range) -> object or nil
1723 * array.slice(aseq) -> object or nil
1725 * Returns elements from +self+; does not modify +self+.
1727 * When a single \Integer argument +index+ is given, returns the element at offset +index+:
1728 * a = [:foo, 'bar', 2]
1729 * a[0] # => :foo
1730 * a[2] # => 2
1731 * a # => [:foo, "bar", 2]
1733 * If +index+ is negative, counts relative to the end of +self+:
1734 * a = [:foo, 'bar', 2]
1735 * a[-1] # => 2
1736 * a[-2] # => "bar"
1738 * If +index+ is out of range, returns +nil+.
1740 * When two \Integer arguments +start+ and +length+ are given,
1741 * returns a new \Array of size +length+ containing successive elements beginning at offset +start+:
1742 * a = [:foo, 'bar', 2]
1743 * a[0, 2] # => [:foo, "bar"]
1744 * a[1, 2] # => ["bar", 2]
1746 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1747 * returns all elements from offset +start+ to the end:
1748 * a = [:foo, 'bar', 2]
1749 * a[0, 4] # => [:foo, "bar", 2]
1750 * a[1, 3] # => ["bar", 2]
1751 * a[2, 2] # => [2]
1753 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1754 * returns a new empty \Array.
1756 * If +length+ is negative, returns +nil+.
1758 * When a single \Range argument +range+ is given,
1759 * treats <tt>range.min</tt> as +start+ above
1760 * and <tt>range.size</tt> as +length+ above:
1761 * a = [:foo, 'bar', 2]
1762 * a[0..1] # => [:foo, "bar"]
1763 * a[1..2] # => ["bar", 2]
1765 * Special case: If <tt>range.start == a.size</tt>, returns a new empty \Array.
1767 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1768 * a = [:foo, 'bar', 2]
1769 * a[0..-1] # => [:foo, "bar", 2]
1770 * a[0..-2] # => [:foo, "bar"]
1771 * a[0..-3] # => [:foo]
1773 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1774 * a = [:foo, 'bar', 2]
1775 * a[-1..2] # => [2]
1776 * a[-2..2] # => ["bar", 2]
1777 * a[-3..2] # => [:foo, "bar", 2]
1779 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1780 * a = [:foo, 'bar', 2]
1781 * a[4..1] # => nil
1782 * a[4..0] # => nil
1783 * a[4..-1] # => nil
1785 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1786 * returns an Array of elements corresponding to the indexes produced by
1787 * the sequence.
1788 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1789 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1791 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1792 * is larger than array size, throws RangeError.
1793 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1794 * a[(1..11).step(2)]
1795 * # RangeError (((1..11).step(2)) out of range)
1796 * a[(7..).step(2)]
1797 * # RangeError (((7..).step(2)) out of range)
1799 * If given a single argument, and its type is not one of the listed, tries to
1800 * convert it to Integer, and raises if it is impossible:
1801 * a = [:foo, 'bar', 2]
1802 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1803 * a[:foo]
1805 * Array#slice is an alias for Array#[].
1808 VALUE
1809 rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
1811 rb_check_arity(argc, 1, 2);
1812 if (argc == 2) {
1813 return rb_ary_aref2(ary, argv[0], argv[1]);
1815 return rb_ary_aref1(ary, argv[0]);
1818 static VALUE
1819 rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
1821 long beg = NUM2LONG(b);
1822 long len = NUM2LONG(e);
1823 if (beg < 0) {
1824 beg += RARRAY_LEN(ary);
1826 return rb_ary_subseq(ary, beg, len);
1829 MJIT_FUNC_EXPORTED VALUE
1830 rb_ary_aref1(VALUE ary, VALUE arg)
1832 long beg, len, step;
1834 /* special case - speeding up */
1835 if (FIXNUM_P(arg)) {
1836 return rb_ary_entry(ary, FIX2LONG(arg));
1838 /* check if idx is Range or ArithmeticSequence */
1839 switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
1840 case Qfalse:
1841 break;
1842 case Qnil:
1843 return Qnil;
1844 default:
1845 return rb_ary_subseq_step(ary, beg, len, step);
1848 return rb_ary_entry(ary, NUM2LONG(arg));
1852 * call-seq:
1853 * array.at(index) -> object
1855 * Returns the element at \Integer offset +index+; does not modify +self+.
1856 * a = [:foo, 'bar', 2]
1857 * a.at(0) # => :foo
1858 * a.at(2) # => 2
1861 VALUE
1862 rb_ary_at(VALUE ary, VALUE pos)
1864 return rb_ary_entry(ary, NUM2LONG(pos));
1868 * call-seq:
1869 * array.first -> object or nil
1870 * array.first(n) -> new_array
1872 * Returns elements from +self+; does not modify +self+.
1874 * When no argument is given, returns the first element:
1875 * a = [:foo, 'bar', 2]
1876 * a.first # => :foo
1877 * a # => [:foo, "bar", 2]
1879 * If +self+ is empty, returns +nil+.
1881 * When non-negative \Integer argument +n+ is given,
1882 * returns the first +n+ elements in a new \Array:
1883 * a = [:foo, 'bar', 2]
1884 * a.first(2) # => [:foo, "bar"]
1886 * If <tt>n >= array.size</tt>, returns all elements:
1887 * a = [:foo, 'bar', 2]
1888 * a.first(50) # => [:foo, "bar", 2]
1890 * If <tt>n == 0</tt> returns an new empty \Array:
1891 * a = [:foo, 'bar', 2]
1892 * a.first(0) # []
1894 * Related: #last.
1896 static VALUE
1897 rb_ary_first(int argc, VALUE *argv, VALUE ary)
1899 if (argc == 0) {
1900 if (RARRAY_LEN(ary) == 0) return Qnil;
1901 return RARRAY_AREF(ary, 0);
1903 else {
1904 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1909 * call-seq:
1910 * array.last -> object or nil
1911 * array.last(n) -> new_array
1913 * Returns elements from +self+; +self+ is not modified.
1915 * When no argument is given, returns the last element:
1916 * a = [:foo, 'bar', 2]
1917 * a.last # => 2
1918 * a # => [:foo, "bar", 2]
1920 * If +self+ is empty, returns +nil+.
1922 * When non-negative \Innteger argument +n+ is given,
1923 * returns the last +n+ elements in a new \Array:
1924 * a = [:foo, 'bar', 2]
1925 * a.last(2) # => ["bar", 2]
1927 * If <tt>n >= array.size</tt>, returns all elements:
1928 * a = [:foo, 'bar', 2]
1929 * a.last(50) # => [:foo, "bar", 2]
1931 * If <tt>n == 0</tt>, returns an new empty \Array:
1932 * a = [:foo, 'bar', 2]
1933 * a.last(0) # []
1935 * Related: #first.
1938 VALUE
1939 rb_ary_last(int argc, const VALUE *argv, VALUE ary)
1941 if (argc == 0) {
1942 long len = RARRAY_LEN(ary);
1943 if (len == 0) return Qnil;
1944 return RARRAY_AREF(ary, len-1);
1946 else {
1947 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1952 * call-seq:
1953 * array.fetch(index) -> element
1954 * array.fetch(index, default_value) -> element
1955 * array.fetch(index) {|index| ... } -> element
1957 * Returns the element at offset +index+.
1959 * With the single \Integer argument +index+,
1960 * returns the element at offset +index+:
1961 * a = [:foo, 'bar', 2]
1962 * a.fetch(1) # => "bar"
1964 * If +index+ is negative, counts from the end of the array:
1965 * a = [:foo, 'bar', 2]
1966 * a.fetch(-1) # => 2
1967 * a.fetch(-2) # => "bar"
1969 * With arguments +index+ and +default_value+,
1970 * returns the element at offset +index+ if index is in range,
1971 * otherwise returns +default_value+:
1972 * a = [:foo, 'bar', 2]
1973 * a.fetch(1, nil) # => "bar"
1975 * With argument +index+ and a block,
1976 * returns the element at offset +index+ if index is in range
1977 * (and the block is not called); otherwise calls the block with index and returns its return value:
1979 * a = [:foo, 'bar', 2]
1980 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
1981 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
1984 static VALUE
1985 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
1987 VALUE pos, ifnone;
1988 long block_given;
1989 long idx;
1991 rb_scan_args(argc, argv, "11", &pos, &ifnone);
1992 block_given = rb_block_given_p();
1993 if (block_given && argc == 2) {
1994 rb_warn("block supersedes default value argument");
1996 idx = NUM2LONG(pos);
1998 if (idx < 0) {
1999 idx += RARRAY_LEN(ary);
2001 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
2002 if (block_given) return rb_yield(pos);
2003 if (argc == 1) {
2004 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
2005 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
2007 return ifnone;
2009 return RARRAY_AREF(ary, idx);
2013 * call-seq:
2014 * array.index(object) -> integer or nil
2015 * array.index {|element| ... } -> integer or nil
2016 * array.index -> new_enumerator
2018 * Returns the index of a specified element.
2020 * When argument +object+ is given but no block,
2021 * returns the index of the first element +element+
2022 * for which <tt>object == element</tt>:
2023 * a = [:foo, 'bar', 2, 'bar']
2024 * a.index('bar') # => 1
2026 * Returns +nil+ if no such element found.
2028 * When both argument +object+ and a block are given,
2029 * calls the block with each successive element;
2030 * returns the index of the first element for which the block returns a truthy value:
2031 * a = [:foo, 'bar', 2, 'bar']
2032 * a.index {|element| element == 'bar' } # => 1
2034 * Returns +nil+ if the block never returns a truthy value.
2036 * When neither an argument nor a block is given, returns a new Enumerator:
2037 * a = [:foo, 'bar', 2]
2038 * e = a.index
2039 * e # => #<Enumerator: [:foo, "bar", 2]:index>
2040 * e.each {|element| element == 'bar' } # => 1
2042 * Array#find_index is an alias for Array#index.
2044 * Related: #rindex.
2047 static VALUE
2048 rb_ary_index(int argc, VALUE *argv, VALUE ary)
2050 VALUE val;
2051 long i;
2053 if (argc == 0) {
2054 RETURN_ENUMERATOR(ary, 0, 0);
2055 for (i=0; i<RARRAY_LEN(ary); i++) {
2056 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
2057 return LONG2NUM(i);
2060 return Qnil;
2062 rb_check_arity(argc, 0, 1);
2063 val = argv[0];
2064 if (rb_block_given_p())
2065 rb_warn("given block not used");
2066 for (i=0; i<RARRAY_LEN(ary); i++) {
2067 VALUE e = RARRAY_AREF(ary, i);
2068 if (rb_equal(e, val)) {
2069 return LONG2NUM(i);
2072 return Qnil;
2076 * call-seq:
2077 * array.rindex(object) -> integer or nil
2078 * array.rindex {|element| ... } -> integer or nil
2079 * array.rindex -> new_enumerator
2081 * Returns the index of the last element for which <tt>object == element</tt>.
2083 * When argument +object+ is given but no block, returns the index of the last such element found:
2084 * a = [:foo, 'bar', 2, 'bar']
2085 * a.rindex('bar') # => 3
2087 * Returns +nil+ if no such object found.
2089 * When a block is given but no argument, calls the block with each successive element;
2090 * returns the index of the last element for which the block returns a truthy value:
2091 * a = [:foo, 'bar', 2, 'bar']
2092 * a.rindex {|element| element == 'bar' } # => 3
2094 * Returns +nil+ if the block never returns a truthy value.
2096 * When neither an argument nor a block is given, returns a new \Enumerator:
2098 * a = [:foo, 'bar', 2, 'bar']
2099 * e = a.rindex
2100 * e # => #<Enumerator: [:foo, "bar", 2, "bar"]:rindex>
2101 * e.each {|element| element == 'bar' } # => 3
2103 * Related: #index.
2106 static VALUE
2107 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
2109 VALUE val;
2110 long i = RARRAY_LEN(ary), len;
2112 if (argc == 0) {
2113 RETURN_ENUMERATOR(ary, 0, 0);
2114 while (i--) {
2115 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
2116 return LONG2NUM(i);
2117 if (i > (len = RARRAY_LEN(ary))) {
2118 i = len;
2121 return Qnil;
2123 rb_check_arity(argc, 0, 1);
2124 val = argv[0];
2125 if (rb_block_given_p())
2126 rb_warn("given block not used");
2127 while (i--) {
2128 VALUE e = RARRAY_AREF(ary, i);
2129 if (rb_equal(e, val)) {
2130 return LONG2NUM(i);
2132 if (i > RARRAY_LEN(ary)) {
2133 break;
2136 return Qnil;
2139 VALUE
2140 rb_ary_to_ary(VALUE obj)
2142 VALUE tmp = rb_check_array_type(obj);
2144 if (!NIL_P(tmp)) return tmp;
2145 return rb_ary_new3(1, obj);
2148 static void
2149 rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
2151 long olen;
2152 long rofs;
2154 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
2155 olen = RARRAY_LEN(ary);
2156 if (beg < 0) {
2157 beg += olen;
2158 if (beg < 0) {
2159 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2160 beg - olen, -olen);
2163 if (olen < len || olen < beg + len) {
2164 len = olen - beg;
2168 const VALUE *optr = RARRAY_CONST_PTR_TRANSIENT(ary);
2169 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
2172 if (beg >= olen) {
2173 VALUE target_ary;
2174 if (beg > ARY_MAX_SIZE - rlen) {
2175 rb_raise(rb_eIndexError, "index %ld too big", beg);
2177 target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
2178 len = beg + rlen;
2179 ary_mem_clear(ary, olen, beg - olen);
2180 if (rlen > 0) {
2181 if (rofs != -1) rptr = RARRAY_CONST_PTR_TRANSIENT(ary) + rofs;
2182 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
2184 ARY_SET_LEN(ary, len);
2186 else {
2187 long alen;
2189 if (olen - len > ARY_MAX_SIZE - rlen) {
2190 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
2192 rb_ary_modify(ary);
2193 alen = olen + rlen - len;
2194 if (alen >= ARY_CAPA(ary)) {
2195 ary_double_capa(ary, alen);
2198 if (len != rlen) {
2199 RARRAY_PTR_USE_TRANSIENT(ary, ptr,
2200 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
2201 VALUE, olen - (beg + len)));
2202 ARY_SET_LEN(ary, alen);
2204 if (rlen > 0) {
2205 if (rofs != -1) rptr = RARRAY_CONST_PTR_TRANSIENT(ary) + rofs;
2206 /* give up wb-protected ary */
2207 RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary);
2209 /* do not use RARRAY_PTR() because it can causes GC.
2210 * ary can contain T_NONE object because it is not cleared.
2212 RARRAY_PTR_USE_TRANSIENT(ary, ptr,
2213 MEMMOVE(ptr + beg, rptr, VALUE, rlen));
2218 void
2219 rb_ary_set_len(VALUE ary, long len)
2221 long capa;
2223 rb_ary_modify_check(ary);
2224 if (ARY_SHARED_P(ary)) {
2225 rb_raise(rb_eRuntimeError, "can't set length of shared ");
2227 if (len > (capa = (long)ARY_CAPA(ary))) {
2228 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
2230 ARY_SET_LEN(ary, len);
2233 VALUE
2234 rb_ary_resize(VALUE ary, long len)
2236 long olen;
2238 rb_ary_modify(ary);
2239 olen = RARRAY_LEN(ary);
2240 if (len == olen) return ary;
2241 if (len > ARY_MAX_SIZE) {
2242 rb_raise(rb_eIndexError, "index %ld too big", len);
2244 if (len > olen) {
2245 if (len >= ARY_CAPA(ary)) {
2246 ary_double_capa(ary, len);
2248 ary_mem_clear(ary, olen, len - olen);
2249 ARY_SET_LEN(ary, len);
2251 else if (ARY_EMBED_P(ary)) {
2252 ARY_SET_EMBED_LEN(ary, len);
2254 else if (len <= RARRAY_EMBED_LEN_MAX) {
2255 VALUE tmp[RARRAY_EMBED_LEN_MAX];
2256 MEMCPY(tmp, ARY_HEAP_PTR(ary), VALUE, len);
2257 ary_discard(ary);
2258 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), tmp, VALUE, len); /* WB: no new reference */
2259 ARY_SET_EMBED_LEN(ary, len);
2261 else {
2262 if (olen > len + ARY_DEFAULT_SIZE) {
2263 size_t new_capa = ary_heap_realloc(ary, len);
2264 ARY_SET_CAPA(ary, new_capa);
2266 ARY_SET_HEAP_LEN(ary, len);
2268 ary_verify(ary);
2269 return ary;
2272 static VALUE
2273 ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val)
2275 rb_ary_store(ary, key, val);
2276 return val;
2279 static VALUE
2280 ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
2282 VALUE rpl = rb_ary_to_ary(val);
2283 rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR_TRANSIENT(rpl), RARRAY_LEN(rpl));
2284 RB_GC_GUARD(rpl);
2285 return val;
2289 * call-seq:
2290 * array[index] = object -> object
2291 * array[start, length] = object -> object
2292 * array[range] = object -> object
2294 * Assigns elements in +self+; returns the given +object+.
2296 * When \Integer argument +index+ is given, assigns +object+ to an element in +self+.
2298 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2299 * a = [:foo, 'bar', 2]
2300 * a[0] = 'foo' # => "foo"
2301 * a # => ["foo", "bar", 2]
2303 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2304 * a = [:foo, 'bar', 2]
2305 * a[7] = 'foo' # => "foo"
2306 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2308 * If +index+ is negative, counts backwards from the end of the array:
2309 * a = [:foo, 'bar', 2]
2310 * a[-1] = 'two' # => "two"
2311 * a # => [:foo, "bar", "two"]
2313 * When \Integer arguments +start+ and +length+ are given and +object+ is not an \Array,
2314 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2315 * and assigns +object+ at offset +start+:
2316 * a = [:foo, 'bar', 2]
2317 * a[0, 2] = 'foo' # => "foo"
2318 * a # => ["foo", 2]
2320 * If +start+ is negative, counts backwards from the end of the array:
2321 * a = [:foo, 'bar', 2]
2322 * a[-2, 2] = 'foo' # => "foo"
2323 * a # => [:foo, "foo"]
2325 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2326 * extends the array with +nil+, assigns +object+ at offset +start+,
2327 * and ignores +length+:
2328 * a = [:foo, 'bar', 2]
2329 * a[6, 50] = 'foo' # => "foo"
2330 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2332 * If +length+ is zero, shifts elements at and following offset +start+
2333 * and assigns +object+ at offset +start+:
2334 * a = [:foo, 'bar', 2]
2335 * a[1, 0] = 'foo' # => "foo"
2336 * a # => [:foo, "foo", "bar", 2]
2338 * If +length+ is too large for the existing array, does not extend the array:
2339 * a = [:foo, 'bar', 2]
2340 * a[1, 5] = 'foo' # => "foo"
2341 * a # => [:foo, "foo"]
2343 * When \Range argument +range+ is given and +object+ is an \Array,
2344 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2345 * and assigns +object+ at offset +start+:
2346 * a = [:foo, 'bar', 2]
2347 * a[0..1] = 'foo' # => "foo"
2348 * a # => ["foo", 2]
2350 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2351 * a = [:foo, 'bar', 2]
2352 * a[-2..2] = 'foo' # => "foo"
2353 * a # => [:foo, "foo"]
2355 * If the array length is less than <tt>range.begin</tt>,
2356 * assigns +object+ at offset <tt>range.begin</tt>, and ignores +length+:
2357 * a = [:foo, 'bar', 2]
2358 * a[6..50] = 'foo' # => "foo"
2359 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2361 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2362 * and assigns +object+ at offset +start+:
2363 * a = [:foo, 'bar', 2]
2364 * a[1..0] = 'foo' # => "foo"
2365 * a # => [:foo, "foo", "bar", 2]
2367 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2368 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2369 * a = [:foo, 'bar', 2]
2370 * a[1..-1] = 'foo' # => "foo"
2371 * a # => [:foo, "foo"]
2372 * a = [:foo, 'bar', 2]
2373 * a[1..-2] = 'foo' # => "foo"
2374 * a # => [:foo, "foo", 2]
2375 * a = [:foo, 'bar', 2]
2376 * a[1..-3] = 'foo' # => "foo"
2377 * a # => [:foo, "foo", "bar", 2]
2378 * a = [:foo, 'bar', 2]
2380 * If <tt>range.end</tt> is too large for the existing array,
2381 * replaces array elements, but does not extend the array with +nil+ values:
2382 * a = [:foo, 'bar', 2]
2383 * a[1..5] = 'foo' # => "foo"
2384 * a # => [:foo, "foo"]
2387 static VALUE
2388 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
2390 long offset, beg, len;
2392 rb_check_arity(argc, 2, 3);
2393 rb_ary_modify_check(ary);
2394 if (argc == 3) {
2395 beg = NUM2LONG(argv[0]);
2396 len = NUM2LONG(argv[1]);
2397 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
2399 if (FIXNUM_P(argv[0])) {
2400 offset = FIX2LONG(argv[0]);
2401 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2403 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
2404 /* check if idx is Range */
2405 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
2408 offset = NUM2LONG(argv[0]);
2409 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2413 * call-seq:
2414 * array.insert(index, *objects) -> self
2416 * Inserts given +objects+ before or after the element at \Integer index +offset+;
2417 * returns +self+.
2419 * When +index+ is non-negative, inserts all given +objects+
2420 * before the element at offset +index+:
2421 * a = [:foo, 'bar', 2]
2422 * a.insert(1, :bat, :bam) # => [:foo, :bat, :bam, "bar", 2]
2424 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2425 * a = [:foo, 'bar', 2]
2426 * a.insert(5, :bat, :bam)
2427 * a # => [:foo, "bar", 2, nil, nil, :bat, :bam]
2429 * Does nothing if no objects given:
2430 * a = [:foo, 'bar', 2]
2431 * a.insert(1)
2432 * a.insert(50)
2433 * a.insert(-50)
2434 * a # => [:foo, "bar", 2]
2436 * When +index+ is negative, inserts all given +objects+
2437 * _after_ the element at offset <tt>index+self.size</tt>:
2438 * a = [:foo, 'bar', 2]
2439 * a.insert(-2, :bat, :bam)
2440 * a # => [:foo, "bar", :bat, :bam, 2]
2443 static VALUE
2444 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
2446 long pos;
2448 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
2449 rb_ary_modify_check(ary);
2450 pos = NUM2LONG(argv[0]);
2451 if (argc == 1) return ary;
2452 if (pos == -1) {
2453 pos = RARRAY_LEN(ary);
2455 else if (pos < 0) {
2456 long minpos = -RARRAY_LEN(ary) - 1;
2457 if (pos < minpos) {
2458 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2459 pos, minpos);
2461 pos++;
2463 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
2464 return ary;
2467 static VALUE
2468 rb_ary_length(VALUE ary);
2470 static VALUE
2471 ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
2473 return rb_ary_length(ary);
2477 * call-seq:
2478 * array.each {|element| ... } -> self
2479 * array.each -> Enumerator
2481 * Iterates over array elements.
2483 * When a block given, passes each successive array element to the block;
2484 * returns +self+:
2485 * a = [:foo, 'bar', 2]
2486 * a.each {|element| puts "#{element.class} #{element}" }
2488 * Output:
2489 * Symbol foo
2490 * String bar
2491 * Integer 2
2493 * Allows the array to be modified during iteration:
2494 * a = [:foo, 'bar', 2]
2495 * a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2497 * Output:
2498 * foo
2499 * bar
2501 * When no block given, returns a new \Enumerator:
2502 * a = [:foo, 'bar', 2]
2503 * e = a.each
2504 * e # => #<Enumerator: [:foo, "bar", 2]:each>
2505 * a1 = e.each {|element| puts "#{element.class} #{element}" }
2507 * Output:
2508 * Symbol foo
2509 * String bar
2510 * Integer 2
2512 * Related: #each_index, #reverse_each.
2515 VALUE
2516 rb_ary_each(VALUE ary)
2518 long i;
2519 ary_verify(ary);
2520 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2521 for (i=0; i<RARRAY_LEN(ary); i++) {
2522 rb_yield(RARRAY_AREF(ary, i));
2524 return ary;
2528 * call-seq:
2529 * array.each_index {|index| ... } -> self
2530 * array.each_index -> Enumerator
2532 * Iterates over array indexes.
2534 * When a block given, passes each successive array index to the block;
2535 * returns +self+:
2536 * a = [:foo, 'bar', 2]
2537 * a.each_index {|index| puts "#{index} #{a[index]}" }
2539 * Output:
2540 * 0 foo
2541 * 1 bar
2542 * 2 2
2544 * Allows the array to be modified during iteration:
2545 * a = [:foo, 'bar', 2]
2546 * a.each_index {|index| puts index; a.clear if index > 0 }
2548 * Output:
2552 * When no block given, returns a new \Enumerator:
2553 * a = [:foo, 'bar', 2]
2554 * e = a.each_index
2555 * e # => #<Enumerator: [:foo, "bar", 2]:each_index>
2556 * a1 = e.each {|index| puts "#{index} #{a[index]}"}
2558 * Output:
2559 * 0 foo
2560 * 1 bar
2561 * 2 2
2563 * Related: #each, #reverse_each.
2566 static VALUE
2567 rb_ary_each_index(VALUE ary)
2569 long i;
2570 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2572 for (i=0; i<RARRAY_LEN(ary); i++) {
2573 rb_yield(LONG2NUM(i));
2575 return ary;
2579 * call-seq:
2580 * array.reverse_each {|element| ... } -> self
2581 * array.reverse_each -> Enumerator
2583 * Iterates backwards over array elements.
2585 * When a block given, passes, in reverse order, each element to the block;
2586 * returns +self+:
2587 * a = [:foo, 'bar', 2]
2588 * a.reverse_each {|element| puts "#{element.class} #{element}" }
2590 * Output:
2591 * Integer 2
2592 * String bar
2593 * Symbol foo
2595 * Allows the array to be modified during iteration:
2596 * a = [:foo, 'bar', 2]
2597 * a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2599 * Output:
2601 * bar
2603 * When no block given, returns a new \Enumerator:
2604 * a = [:foo, 'bar', 2]
2605 * e = a.reverse_each
2606 * e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
2607 * a1 = e.each {|element| puts "#{element.class} #{element}" }
2608 * Output:
2609 * Integer 2
2610 * String bar
2611 * Symbol foo
2613 * Related: #each, #each_index.
2616 static VALUE
2617 rb_ary_reverse_each(VALUE ary)
2619 long len;
2621 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2622 len = RARRAY_LEN(ary);
2623 while (len--) {
2624 long nlen;
2625 rb_yield(RARRAY_AREF(ary, len));
2626 nlen = RARRAY_LEN(ary);
2627 if (nlen < len) {
2628 len = nlen;
2631 return ary;
2635 * call-seq:
2636 * array.length -> an_integer
2638 * Returns the count of elements in +self+.
2641 static VALUE
2642 rb_ary_length(VALUE ary)
2644 long len = RARRAY_LEN(ary);
2645 return LONG2NUM(len);
2649 * call-seq:
2650 * array.empty? -> true or false
2652 * Returns +true+ if the count of elements in +self+ is zero,
2653 * +false+ otherwise.
2656 static VALUE
2657 rb_ary_empty_p(VALUE ary)
2659 return RBOOL(RARRAY_LEN(ary) == 0);
2662 VALUE
2663 rb_ary_dup(VALUE ary)
2665 long len = RARRAY_LEN(ary);
2666 VALUE dup = rb_ary_new2(len);
2667 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR_TRANSIENT(ary));
2668 ARY_SET_LEN(dup, len);
2670 ary_verify(ary);
2671 ary_verify(dup);
2672 return dup;
2675 VALUE
2676 rb_ary_resurrect(VALUE ary)
2678 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2681 extern VALUE rb_output_fs;
2683 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
2685 static VALUE
2686 recursive_join(VALUE obj, VALUE argp, int recur)
2688 VALUE *arg = (VALUE *)argp;
2689 VALUE ary = arg[0];
2690 VALUE sep = arg[1];
2691 VALUE result = arg[2];
2692 int *first = (int *)arg[3];
2694 if (recur) {
2695 rb_raise(rb_eArgError, "recursive array join");
2697 else {
2698 ary_join_1(obj, ary, sep, 0, result, first);
2700 return Qnil;
2703 static long
2704 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
2706 long i;
2707 VALUE val;
2709 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
2710 for (i=0; i<max; i++) {
2711 val = RARRAY_AREF(ary, i);
2712 if (!RB_TYPE_P(val, T_STRING)) break;
2713 if (i > 0 && !NIL_P(sep))
2714 rb_str_buf_append(result, sep);
2715 rb_str_buf_append(result, val);
2717 return i;
2720 static void
2721 ary_join_1_str(VALUE dst, VALUE src, int *first)
2723 rb_str_buf_append(dst, src);
2724 if (*first) {
2725 rb_enc_copy(dst, src);
2726 *first = FALSE;
2730 static void
2731 ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
2733 if (val == ary) {
2734 rb_raise(rb_eArgError, "recursive array join");
2736 else {
2737 VALUE args[4];
2739 *first = FALSE;
2740 args[0] = val;
2741 args[1] = sep;
2742 args[2] = result;
2743 args[3] = (VALUE)first;
2744 rb_exec_recursive(recursive_join, obj, (VALUE)args);
2748 static void
2749 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
2751 VALUE val, tmp;
2753 for (; i<RARRAY_LEN(ary); i++) {
2754 if (i > 0 && !NIL_P(sep))
2755 rb_str_buf_append(result, sep);
2757 val = RARRAY_AREF(ary, i);
2758 if (RB_TYPE_P(val, T_STRING)) {
2759 ary_join_1_str(result, val, first);
2761 else if (RB_TYPE_P(val, T_ARRAY)) {
2762 ary_join_1_ary(val, ary, sep, result, val, first);
2764 else if (!NIL_P(tmp = rb_check_string_type(val))) {
2765 ary_join_1_str(result, tmp, first);
2767 else if (!NIL_P(tmp = rb_check_array_type(val))) {
2768 ary_join_1_ary(val, ary, sep, result, tmp, first);
2770 else {
2771 ary_join_1_str(result, rb_obj_as_string(val), first);
2776 VALUE
2777 rb_ary_join(VALUE ary, VALUE sep)
2779 long len = 1, i;
2780 VALUE val, tmp, result;
2782 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
2784 if (!NIL_P(sep)) {
2785 StringValue(sep);
2786 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
2788 for (i=0; i<RARRAY_LEN(ary); i++) {
2789 val = RARRAY_AREF(ary, i);
2790 tmp = rb_check_string_type(val);
2792 if (NIL_P(tmp) || tmp != val) {
2793 int first;
2794 long n = RARRAY_LEN(ary);
2795 if (i > n) i = n;
2796 result = rb_str_buf_new(len + (n-i)*10);
2797 rb_enc_associate(result, rb_usascii_encoding());
2798 i = ary_join_0(ary, sep, i, result);
2799 first = i == 0;
2800 ary_join_1(ary, ary, sep, i, result, &first);
2801 return result;
2804 len += RSTRING_LEN(tmp);
2807 result = rb_str_new(0, len);
2808 rb_str_set_len(result, 0);
2810 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
2812 return result;
2816 * call-seq:
2817 * array.join ->new_string
2818 * array.join(separator = $,) -> new_string
2820 * Returns the new \String formed by joining the array elements after conversion.
2821 * For each element +element+
2822 * - Uses <tt>element.to_s</tt> if +element+ is not a <tt>kind_of?(Array)</tt>.
2823 * - Uses recursive <tt>element.join(separator)</tt> if +element+ is a <tt>kind_of?(Array)</tt>.
2825 * With no argument, joins using the output field separator, <tt>$,</tt>:
2826 * a = [:foo, 'bar', 2]
2827 * $, # => nil
2828 * a.join # => "foobar2"
2830 * With \string argument +separator+, joins using that separator:
2831 * a = [:foo, 'bar', 2]
2832 * a.join("\n") # => "foo\nbar\n2"
2834 * Joins recursively for nested Arrays:
2835 * a = [:foo, [:bar, [:baz, :bat]]]
2836 * a.join # => "foobarbazbat"
2838 static VALUE
2839 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
2841 VALUE sep;
2843 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
2844 sep = rb_output_fs;
2845 if (!NIL_P(sep)) {
2846 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
2850 return rb_ary_join(ary, sep);
2853 static VALUE
2854 inspect_ary(VALUE ary, VALUE dummy, int recur)
2856 long i;
2857 VALUE s, str;
2859 if (recur) return rb_usascii_str_new_cstr("[...]");
2860 str = rb_str_buf_new2("[");
2861 for (i=0; i<RARRAY_LEN(ary); i++) {
2862 s = rb_inspect(RARRAY_AREF(ary, i));
2863 if (i > 0) rb_str_buf_cat2(str, ", ");
2864 else rb_enc_copy(str, s);
2865 rb_str_buf_append(str, s);
2867 rb_str_buf_cat2(str, "]");
2868 return str;
2872 * call-seq:
2873 * array.inspect -> new_string
2875 * Returns the new \String formed by calling method <tt>#inspect</tt>
2876 * on each array element:
2877 * a = [:foo, 'bar', 2]
2878 * a.inspect # => "[:foo, \"bar\", 2]"
2880 * Array#to_s is an alias for Array#inspect.
2883 static VALUE
2884 rb_ary_inspect(VALUE ary)
2886 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
2887 return rb_exec_recursive(inspect_ary, ary, 0);
2890 VALUE
2891 rb_ary_to_s(VALUE ary)
2893 return rb_ary_inspect(ary);
2897 * call-seq:
2898 * to_a -> self or new_array
2900 * When +self+ is an instance of \Array, returns +self+:
2901 * a = [:foo, 'bar', 2]
2902 * a.to_a # => [:foo, "bar", 2]
2904 * Otherwise, returns a new \Array containing the elements of +self+:
2905 * class MyArray < Array; end
2906 * a = MyArray.new(['foo', 'bar', 'two'])
2907 * a.instance_of?(Array) # => false
2908 * a.kind_of?(Array) # => true
2909 * a1 = a.to_a
2910 * a1 # => ["foo", "bar", "two"]
2911 * a1.class # => Array # Not MyArray
2914 static VALUE
2915 rb_ary_to_a(VALUE ary)
2917 if (rb_obj_class(ary) != rb_cArray) {
2918 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
2919 rb_ary_replace(dup, ary);
2920 return dup;
2922 return ary;
2926 * call-seq:
2927 * array.to_h -> new_hash
2928 * array.to_h {|item| ... } -> new_hash
2930 * Returns a new \Hash formed from +self+.
2932 * When a block is given, calls the block with each array element;
2933 * the block must return a 2-element \Array whose two elements
2934 * form a key-value pair in the returned \Hash:
2935 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
2936 * h = a.to_h {|item| [item, item] }
2937 * h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
2939 * When no block is given, +self+ must be an \Array of 2-element sub-arrays,
2940 * each sub-array is formed into a key-value pair in the new \Hash:
2941 * [].to_h # => {}
2942 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
2943 * h = a.to_h
2944 * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
2947 static VALUE
2948 rb_ary_to_h(VALUE ary)
2950 long i;
2951 VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
2952 int block_given = rb_block_given_p();
2954 for (i=0; i<RARRAY_LEN(ary); i++) {
2955 const VALUE e = rb_ary_elt(ary, i);
2956 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
2957 const VALUE key_value_pair = rb_check_array_type(elt);
2958 if (NIL_P(key_value_pair)) {
2959 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
2960 rb_obj_class(elt), i);
2962 if (RARRAY_LEN(key_value_pair) != 2) {
2963 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
2964 i, RARRAY_LEN(key_value_pair));
2966 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
2968 return hash;
2972 * call-seq:
2973 * array.to_ary -> self
2975 * Returns +self+.
2978 static VALUE
2979 rb_ary_to_ary_m(VALUE ary)
2981 return ary;
2984 static void
2985 ary_reverse(VALUE *p1, VALUE *p2)
2987 while (p1 < p2) {
2988 VALUE tmp = *p1;
2989 *p1++ = *p2;
2990 *p2-- = tmp;
2994 VALUE
2995 rb_ary_reverse(VALUE ary)
2997 VALUE *p2;
2998 long len = RARRAY_LEN(ary);
3000 rb_ary_modify(ary);
3001 if (len > 1) {
3002 RARRAY_PTR_USE_TRANSIENT(ary, p1, {
3003 p2 = p1 + len - 1; /* points last item */
3004 ary_reverse(p1, p2);
3005 }); /* WB: no new reference */
3007 return ary;
3011 * call-seq:
3012 * array.reverse! -> self
3014 * Reverses +self+ in place:
3015 * a = ['foo', 'bar', 'two']
3016 * a.reverse! # => ["two", "bar", "foo"]
3019 static VALUE
3020 rb_ary_reverse_bang(VALUE ary)
3022 return rb_ary_reverse(ary);
3026 * call-seq:
3027 * array.reverse -> new_array
3029 * Returns a new \Array with the elements of +self+ in reverse order.
3030 * a = ['foo', 'bar', 'two']
3031 * a1 = a.reverse
3032 * a1 # => ["two", "bar", "foo"]
3035 static VALUE
3036 rb_ary_reverse_m(VALUE ary)
3038 long len = RARRAY_LEN(ary);
3039 VALUE dup = rb_ary_new2(len);
3041 if (len > 0) {
3042 const VALUE *p1 = RARRAY_CONST_PTR_TRANSIENT(ary);
3043 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(dup) + len - 1;
3044 do *p2-- = *p1++; while (--len > 0);
3046 ARY_SET_LEN(dup, RARRAY_LEN(ary));
3047 return dup;
3050 static inline long
3051 rotate_count(long cnt, long len)
3053 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3056 static void
3057 ary_rotate_ptr(VALUE *ptr, long len, long cnt)
3059 if (cnt == 1) {
3060 VALUE tmp = *ptr;
3061 memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
3062 *(ptr + len - 1) = tmp;
3064 else if (cnt == len - 1) {
3065 VALUE tmp = *(ptr + len - 1);
3066 memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
3067 *ptr = tmp;
3069 else {
3070 --len;
3071 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3072 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3073 if (len > 0) ary_reverse(ptr, ptr + len);
3077 VALUE
3078 rb_ary_rotate(VALUE ary, long cnt)
3080 rb_ary_modify(ary);
3082 if (cnt != 0) {
3083 long len = RARRAY_LEN(ary);
3084 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3085 RARRAY_PTR_USE_TRANSIENT(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
3086 return ary;
3089 return Qnil;
3093 * call-seq:
3094 * array.rotate! -> self
3095 * array.rotate!(count) -> self
3097 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3099 * When no argument given, rotates the first element to the last position:
3100 * a = [:foo, 'bar', 2, 'bar']
3101 * a.rotate! # => ["bar", 2, "bar", :foo]
3103 * When given a non-negative \Integer +count+,
3104 * rotates +count+ elements from the beginning to the end:
3105 * a = [:foo, 'bar', 2]
3106 * a.rotate!(2)
3107 * a # => [2, :foo, "bar"]
3109 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3110 * a = [:foo, 'bar', 2]
3111 * a.rotate!(20)
3112 * a # => [2, :foo, "bar"]
3114 * If +count+ is zero, returns +self+ unmodified:
3115 * a = [:foo, 'bar', 2]
3116 * a.rotate!(0)
3117 * a # => [:foo, "bar", 2]
3119 * When given a negative Integer +count+, rotates in the opposite direction,
3120 * from end to beginning:
3121 * a = [:foo, 'bar', 2]
3122 * a.rotate!(-2)
3123 * a # => ["bar", 2, :foo]
3125 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3126 * a = [:foo, 'bar', 2]
3127 * a.rotate!(-5)
3128 * a # => ["bar", 2, :foo]
3131 static VALUE
3132 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
3134 long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3135 rb_ary_rotate(ary, n);
3136 return ary;
3140 * call-seq:
3141 * array.rotate -> new_array
3142 * array.rotate(count) -> new_array
3144 * Returns a new \Array formed from +self+ with elements
3145 * rotated from one end to the other.
3147 * When no argument given, returns a new \Array that is like +self+,
3148 * except that the first element has been rotated to the last position:
3149 * a = [:foo, 'bar', 2, 'bar']
3150 * a1 = a.rotate
3151 * a1 # => ["bar", 2, "bar", :foo]
3153 * When given a non-negative \Integer +count+,
3154 * returns a new \Array with +count+ elements rotated from the beginning to the end:
3155 * a = [:foo, 'bar', 2]
3156 * a1 = a.rotate(2)
3157 * a1 # => [2, :foo, "bar"]
3159 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3160 * a = [:foo, 'bar', 2]
3161 * a1 = a.rotate(20)
3162 * a1 # => [2, :foo, "bar"]
3164 * If +count+ is zero, returns a copy of +self+, unmodified:
3165 * a = [:foo, 'bar', 2]
3166 * a1 = a.rotate(0)
3167 * a1 # => [:foo, "bar", 2]
3169 * When given a negative \Integer +count+, rotates in the opposite direction,
3170 * from end to beginning:
3171 * a = [:foo, 'bar', 2]
3172 * a1 = a.rotate(-2)
3173 * a1 # => ["bar", 2, :foo]
3175 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3176 * a = [:foo, 'bar', 2]
3177 * a1 = a.rotate(-5)
3178 * a1 # => ["bar", 2, :foo]
3181 static VALUE
3182 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
3184 VALUE rotated;
3185 const VALUE *ptr;
3186 long len;
3187 long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3189 len = RARRAY_LEN(ary);
3190 rotated = rb_ary_new2(len);
3191 if (len > 0) {
3192 cnt = rotate_count(cnt, len);
3193 ptr = RARRAY_CONST_PTR_TRANSIENT(ary);
3194 len -= cnt;
3195 ary_memcpy(rotated, 0, len, ptr + cnt);
3196 ary_memcpy(rotated, len, cnt, ptr);
3198 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
3199 return rotated;
3202 struct ary_sort_data {
3203 VALUE ary;
3204 VALUE receiver;
3205 struct cmp_opt_data cmp_opt;
3208 static VALUE
3209 sort_reentered(VALUE ary)
3211 if (RBASIC(ary)->klass) {
3212 rb_raise(rb_eRuntimeError, "sort reentered");
3214 return Qnil;
3217 static void
3218 sort_returned(struct ary_sort_data *data)
3220 if (rb_obj_frozen_p(data->receiver)) {
3221 rb_raise(rb_eFrozenError, "array frozen during sort");
3223 sort_reentered(data->ary);
3226 static int
3227 sort_1(const void *ap, const void *bp, void *dummy)
3229 struct ary_sort_data *data = dummy;
3230 VALUE retval = sort_reentered(data->ary);
3231 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3232 VALUE args[2];
3233 int n;
3235 args[0] = a;
3236 args[1] = b;
3237 retval = rb_yield_values2(2, args);
3238 n = rb_cmpint(retval, a, b);
3239 sort_returned(data);
3240 return n;
3243 static int
3244 sort_2(const void *ap, const void *bp, void *dummy)
3246 struct ary_sort_data *data = dummy;
3247 VALUE retval = sort_reentered(data->ary);
3248 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3249 int n;
3251 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, Integer)) {
3252 if ((long)a > (long)b) return 1;
3253 if ((long)a < (long)b) return -1;
3254 return 0;
3256 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, String)) {
3257 return rb_str_cmp(a, b);
3259 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(data->cmp_opt, Float)) {
3260 return rb_float_cmp(a, b);
3263 retval = rb_funcallv(a, id_cmp, 1, &b);
3264 n = rb_cmpint(retval, a, b);
3265 sort_returned(data);
3267 return n;
3271 * call-seq:
3272 * array.sort! -> self
3273 * array.sort! {|a, b| ... } -> self
3275 * Returns +self+ with its elements sorted in place.
3277 * With no block, compares elements using operator <tt><=></tt>
3278 * (see Comparable):
3279 * a = 'abcde'.split('').shuffle
3280 * a # => ["e", "b", "d", "a", "c"]
3281 * a.sort!
3282 * a # => ["a", "b", "c", "d", "e"]
3284 * With a block, calls the block with each element pair;
3285 * for each element pair +a+ and +b+, the block should return an integer:
3286 * - Negative when +b+ is to follow +a+.
3287 * - Zero when +a+ and +b+ are equivalent.
3288 * - Positive when +a+ is to follow +b+.
3290 * Example:
3291 * a = 'abcde'.split('').shuffle
3292 * a # => ["e", "b", "d", "a", "c"]
3293 * a.sort! {|a, b| a <=> b }
3294 * a # => ["a", "b", "c", "d", "e"]
3295 * a.sort! {|a, b| b <=> a }
3296 * a # => ["e", "d", "c", "b", "a"]
3298 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3299 * and may be unstable:
3300 * a = 'abcde'.split('').shuffle
3301 * a # => ["e", "b", "d", "a", "c"]
3302 * a.sort! {|a, b| 0 }
3303 * a # => ["d", "e", "c", "a", "b"]
3306 VALUE
3307 rb_ary_sort_bang(VALUE ary)
3309 rb_ary_modify(ary);
3310 assert(!ARY_SHARED_P(ary));
3311 if (RARRAY_LEN(ary) > 1) {
3312 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
3313 struct ary_sort_data data;
3314 long len = RARRAY_LEN(ary);
3315 RBASIC_CLEAR_CLASS(tmp);
3316 data.ary = tmp;
3317 data.receiver = ary;
3318 data.cmp_opt.opt_methods = 0;
3319 data.cmp_opt.opt_inited = 0;
3320 RARRAY_PTR_USE(tmp, ptr, {
3321 ruby_qsort(ptr, len, sizeof(VALUE),
3322 rb_block_given_p()?sort_1:sort_2, &data);
3323 }); /* WB: no new reference */
3324 rb_ary_modify(ary);
3325 if (ARY_EMBED_P(tmp)) {
3326 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
3327 rb_ary_unshare(ary);
3328 FL_SET_EMBED(ary);
3330 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3331 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3333 else {
3334 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3335 FL_UNSET_SHARED(ary);
3336 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
3338 else {
3339 assert(!ARY_SHARED_P(tmp));
3340 if (ARY_EMBED_P(ary)) {
3341 FL_UNSET_EMBED(ary);
3343 else if (ARY_SHARED_P(ary)) {
3344 /* ary might be destructively operated in the given block */
3345 rb_ary_unshare(ary);
3347 else {
3348 ary_heap_free(ary);
3350 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3351 ARY_SET_HEAP_LEN(ary, len);
3352 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3354 /* tmp was lost ownership for the ptr */
3355 FL_UNSET(tmp, FL_FREEZE);
3356 FL_SET_EMBED(tmp);
3357 ARY_SET_EMBED_LEN(tmp, 0);
3358 FL_SET(tmp, FL_FREEZE);
3360 /* tmp will be GC'ed. */
3361 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
3363 ary_verify(ary);
3364 return ary;
3368 * call-seq:
3369 * array.sort -> new_array
3370 * array.sort {|a, b| ... } -> new_array
3372 * Returns a new \Array whose elements are those from +self+, sorted.
3374 * With no block, compares elements using operator <tt><=></tt>
3375 * (see Comparable):
3376 * a = 'abcde'.split('').shuffle
3377 * a # => ["e", "b", "d", "a", "c"]
3378 * a1 = a.sort
3379 * a1 # => ["a", "b", "c", "d", "e"]
3381 * With a block, calls the block with each element pair;
3382 * for each element pair +a+ and +b+, the block should return an integer:
3383 * - Negative when +b+ is to follow +a+.
3384 * - Zero when +a+ and +b+ are equivalent.
3385 * - Positive when +a+ is to follow +b+.
3387 * Example:
3388 * a = 'abcde'.split('').shuffle
3389 * a # => ["e", "b", "d", "a", "c"]
3390 * a1 = a.sort {|a, b| a <=> b }
3391 * a1 # => ["a", "b", "c", "d", "e"]
3392 * a2 = a.sort {|a, b| b <=> a }
3393 * a2 # => ["e", "d", "c", "b", "a"]
3395 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3396 * and may be unstable:
3397 * a = 'abcde'.split('').shuffle
3398 * a # => ["e", "b", "d", "a", "c"]
3399 * a1 = a.sort {|a, b| 0 }
3400 * a1 # => ["c", "e", "b", "d", "a"]
3402 * Related: Enumerable#sort_by.
3405 VALUE
3406 rb_ary_sort(VALUE ary)
3408 ary = rb_ary_dup(ary);
3409 rb_ary_sort_bang(ary);
3410 return ary;
3413 static VALUE rb_ary_bsearch_index(VALUE ary);
3416 * call-seq:
3417 * array.bsearch {|element| ... } -> object
3418 * array.bsearch -> new_enumerator
3420 * Returns an element from +self+ selected by a binary search.
3422 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3425 static VALUE
3426 rb_ary_bsearch(VALUE ary)
3428 VALUE index_result = rb_ary_bsearch_index(ary);
3430 if (FIXNUM_P(index_result)) {
3431 return rb_ary_entry(ary, FIX2LONG(index_result));
3433 return index_result;
3437 * call-seq:
3438 * array.bsearch_index {|element| ... } -> integer or nil
3439 * array.bsearch_index -> new_enumerator
3441 * Searches +self+ as described at method #bsearch,
3442 * but returns the _index_ of the found element instead of the element itself.
3445 static VALUE
3446 rb_ary_bsearch_index(VALUE ary)
3448 long low = 0, high = RARRAY_LEN(ary), mid;
3449 int smaller = 0, satisfied = 0;
3450 VALUE v, val;
3452 RETURN_ENUMERATOR(ary, 0, 0);
3453 while (low < high) {
3454 mid = low + ((high - low) / 2);
3455 val = rb_ary_entry(ary, mid);
3456 v = rb_yield(val);
3457 if (FIXNUM_P(v)) {
3458 if (v == INT2FIX(0)) return INT2FIX(mid);
3459 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
3461 else if (v == Qtrue) {
3462 satisfied = 1;
3463 smaller = 1;
3465 else if (!RTEST(v)) {
3466 smaller = 0;
3468 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
3469 const VALUE zero = INT2FIX(0);
3470 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
3471 case 0: return INT2FIX(mid);
3472 case 1: smaller = 1; break;
3473 case -1: smaller = 0;
3476 else {
3477 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
3478 " (must be numeric, true, false or nil)",
3479 rb_obj_class(v));
3481 if (smaller) {
3482 high = mid;
3484 else {
3485 low = mid + 1;
3488 if (!satisfied) return Qnil;
3489 return INT2FIX(low);
3493 static VALUE
3494 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3496 return rb_yield(i);
3500 * call-seq:
3501 * array.sort_by! {|element| ... } -> self
3502 * array.sort_by! -> new_enumerator
3504 * Sorts the elements of +self+ in place,
3505 * using an ordering determined by the block; returns self.
3507 * Calls the block with each successive element;
3508 * sorts elements based on the values returned from the block.
3510 * For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
3512 * This example sorts strings based on their sizes:
3513 * a = ['aaaa', 'bbb', 'cc', 'd']
3514 * a.sort_by! {|element| element.size }
3515 * a # => ["d", "cc", "bbb", "aaaa"]
3517 * Returns a new \Enumerator if no block given:
3519 * a = ['aaaa', 'bbb', 'cc', 'd']
3520 * a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
3523 static VALUE
3524 rb_ary_sort_by_bang(VALUE ary)
3526 VALUE sorted;
3528 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3529 rb_ary_modify(ary);
3530 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3531 rb_ary_replace(ary, sorted);
3532 return ary;
3537 * call-seq:
3538 * array.map {|element| ... } -> new_array
3539 * array.map -> new_enumerator
3541 * Calls the block, if given, with each element of +self+;
3542 * returns a new \Array whose elements are the return values from the block:
3543 * a = [:foo, 'bar', 2]
3544 * a1 = a.map {|element| element.class }
3545 * a1 # => [Symbol, String, Integer]
3547 * Returns a new \Enumerator if no block given:
3548 * a = [:foo, 'bar', 2]
3549 * a1 = a.map
3550 * a1 # => #<Enumerator: [:foo, "bar", 2]:map>
3552 * Array#collect is an alias for Array#map.
3555 static VALUE
3556 rb_ary_collect(VALUE ary)
3558 long i;
3559 VALUE collect;
3561 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3562 collect = rb_ary_new2(RARRAY_LEN(ary));
3563 for (i = 0; i < RARRAY_LEN(ary); i++) {
3564 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3566 return collect;
3571 * call-seq:
3572 * array.map! {|element| ... } -> self
3573 * array.map! -> new_enumerator
3575 * Calls the block, if given, with each element;
3576 * replaces the element with the block's return value:
3577 * a = [:foo, 'bar', 2]
3578 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3580 * Returns a new \Enumerator if no block given:
3581 * a = [:foo, 'bar', 2]
3582 * a1 = a.map!
3583 * a1 # => #<Enumerator: [:foo, "bar", 2]:map!>
3585 * Array#collect! is an alias for Array#map!.
3588 static VALUE
3589 rb_ary_collect_bang(VALUE ary)
3591 long i;
3593 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3594 rb_ary_modify(ary);
3595 for (i = 0; i < RARRAY_LEN(ary); i++) {
3596 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
3598 return ary;
3601 VALUE
3602 rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
3604 VALUE result = rb_ary_new2(argc);
3605 long beg, len, i, j;
3607 for (i=0; i<argc; i++) {
3608 if (FIXNUM_P(argv[i])) {
3609 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3610 continue;
3612 /* check if idx is Range */
3613 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3614 long end = olen < beg+len ? olen : beg+len;
3615 for (j = beg; j < end; j++) {
3616 rb_ary_push(result, (*func)(obj, j));
3618 if (beg + len > j)
3619 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
3620 continue;
3622 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
3624 return result;
3627 static VALUE
3628 append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
3630 long beg, len;
3631 if (FIXNUM_P(idx)) {
3632 beg = FIX2LONG(idx);
3634 /* check if idx is Range */
3635 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
3636 if (len > 0) {
3637 const VALUE *const src = RARRAY_CONST_PTR_TRANSIENT(ary);
3638 const long end = beg + len;
3639 const long prevlen = RARRAY_LEN(result);
3640 if (beg < olen) {
3641 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3643 if (end > olen) {
3644 rb_ary_store(result, prevlen + len - 1, Qnil);
3647 return result;
3649 else {
3650 beg = NUM2LONG(idx);
3652 return rb_ary_push(result, rb_ary_entry(ary, beg));
3656 * call-seq:
3657 * array.values_at(*indexes) -> new_array
3659 * Returns a new \Array whose elements are the elements
3660 * of +self+ at the given \Integer or \Range +indexes+.
3662 * For each positive +index+, returns the element at offset +index+:
3663 * a = [:foo, 'bar', 2]
3664 * a.values_at(0, 2) # => [:foo, 2]
3665 * a.values_at(0..1) # => [:foo, "bar"]
3667 * The given +indexes+ may be in any order, and may repeat:
3668 * a = [:foo, 'bar', 2]
3669 * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
3670 * a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
3672 * Assigns +nil+ for an +index+ that is too large:
3673 * a = [:foo, 'bar', 2]
3674 * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
3676 * Returns a new empty \Array if no arguments given.
3678 * For each negative +index+, counts backward from the end of the array:
3679 * a = [:foo, 'bar', 2]
3680 * a.values_at(-1, -3) # => [2, :foo]
3682 * Assigns +nil+ for an +index+ that is too small:
3683 * a = [:foo, 'bar', 2]
3684 * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
3686 * The given +indexes+ may have a mixture of signs:
3687 * a = [:foo, 'bar', 2]
3688 * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
3691 static VALUE
3692 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
3694 long i, olen = RARRAY_LEN(ary);
3695 VALUE result = rb_ary_new_capa(argc);
3696 for (i = 0; i < argc; ++i) {
3697 append_values_at_single(result, ary, olen, argv[i]);
3699 RB_GC_GUARD(ary);
3700 return result;
3705 * call-seq:
3706 * array.select {|element| ... } -> new_array
3707 * array.select -> new_enumerator
3709 * Calls the block, if given, with each element of +self+;
3710 * returns a new \Array containing those elements of +self+
3711 * for which the block returns a truthy value:
3712 * a = [:foo, 'bar', 2, :bam]
3713 * a1 = a.select {|element| element.to_s.start_with?('b') }
3714 * a1 # => ["bar", :bam]
3716 * Returns a new \Enumerator if no block given:
3717 * a = [:foo, 'bar', 2, :bam]
3718 * a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
3720 * Array#filter is an alias for Array#select.
3723 static VALUE
3724 rb_ary_select(VALUE ary)
3726 VALUE result;
3727 long i;
3729 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3730 result = rb_ary_new2(RARRAY_LEN(ary));
3731 for (i = 0; i < RARRAY_LEN(ary); i++) {
3732 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
3733 rb_ary_push(result, rb_ary_elt(ary, i));
3736 return result;
3739 struct select_bang_arg {
3740 VALUE ary;
3741 long len[2];
3744 static VALUE
3745 select_bang_i(VALUE a)
3747 volatile struct select_bang_arg *arg = (void *)a;
3748 VALUE ary = arg->ary;
3749 long i1, i2;
3751 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
3752 VALUE v = RARRAY_AREF(ary, i1);
3753 if (!RTEST(rb_yield(v))) continue;
3754 if (i1 != i2) {
3755 rb_ary_store(ary, i2, v);
3757 arg->len[1] = ++i2;
3759 return (i1 == i2) ? Qnil : ary;
3762 static VALUE
3763 select_bang_ensure(VALUE a)
3765 volatile struct select_bang_arg *arg = (void *)a;
3766 VALUE ary = arg->ary;
3767 long len = RARRAY_LEN(ary);
3768 long i1 = arg->len[0], i2 = arg->len[1];
3770 if (i2 < len && i2 < i1) {
3771 long tail = 0;
3772 rb_ary_modify(ary);
3773 if (i1 < len) {
3774 tail = len - i1;
3775 RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
3776 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
3779 ARY_SET_LEN(ary, i2 + tail);
3781 return ary;
3785 * call-seq:
3786 * array.select! {|element| ... } -> self or nil
3787 * array.select! -> new_enumerator
3789 * Calls the block, if given with each element of +self+;
3790 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3792 * Returns +self+ if any elements were removed:
3793 * a = [:foo, 'bar', 2, :bam]
3794 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3796 * Returns +nil+ if no elements were removed.
3798 * Returns a new \Enumerator if no block given:
3799 * a = [:foo, 'bar', 2, :bam]
3800 * a.select! # => #<Enumerator: [:foo, "bar", 2, :bam]:select!>
3802 * Array#filter! is an alias for Array#select!.
3805 static VALUE
3806 rb_ary_select_bang(VALUE ary)
3808 struct select_bang_arg args;
3810 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3811 rb_ary_modify(ary);
3813 args.ary = ary;
3814 args.len[0] = args.len[1] = 0;
3815 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
3819 * call-seq:
3820 * array.keep_if {|element| ... } -> self
3821 * array.keep_if -> new_enumeration
3823 * Retains those elements for which the block returns a truthy value;
3824 * deletes all other elements; returns +self+:
3825 * a = [:foo, 'bar', 2, :bam]
3826 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3828 * Returns a new \Enumerator if no block given:
3829 * a = [:foo, 'bar', 2, :bam]
3830 * a.keep_if # => #<Enumerator: [:foo, "bar", 2, :bam]:keep_if>
3833 static VALUE
3834 rb_ary_keep_if(VALUE ary)
3836 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3837 rb_ary_select_bang(ary);
3838 return ary;
3841 static void
3842 ary_resize_smaller(VALUE ary, long len)
3844 rb_ary_modify(ary);
3845 if (RARRAY_LEN(ary) > len) {
3846 ARY_SET_LEN(ary, len);
3847 if (len * 2 < ARY_CAPA(ary) &&
3848 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
3849 ary_resize_capa(ary, len * 2);
3855 * call-seq:
3856 * array.delete(obj) -> deleted_object
3857 * array.delete(obj) {|nosuch| ... } -> deleted_object or block_return
3859 * Removes zero or more elements from +self+; returns +self+.
3861 * When no block is given,
3862 * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>;
3863 * returns the last deleted element:
3864 * s1 = 'bar'; s2 = 'bar'
3865 * a = [:foo, s1, 2, s2]
3866 * a.delete('bar') # => "bar"
3867 * a # => [:foo, 2]
3869 * Returns +nil+ if no elements removed.
3871 * When a block is given,
3872 * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>.
3874 * If any such elements are found, ignores the block
3875 * and returns the last deleted element:
3876 * s1 = 'bar'; s2 = 'bar'
3877 * a = [:foo, s1, 2, s2]
3878 * deleted_obj = a.delete('bar') {|obj| fail 'Cannot happen' }
3879 * a # => [:foo, 2]
3881 * If no such elements are found, returns the block's return value:
3882 * a = [:foo, 'bar', 2]
3883 * a.delete(:nosuch) {|obj| "#{obj} not found" } # => "nosuch not found"
3886 VALUE
3887 rb_ary_delete(VALUE ary, VALUE item)
3889 VALUE v = item;
3890 long i1, i2;
3892 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
3893 VALUE e = RARRAY_AREF(ary, i1);
3895 if (rb_equal(e, item)) {
3896 v = e;
3897 continue;
3899 if (i1 != i2) {
3900 rb_ary_store(ary, i2, e);
3902 i2++;
3904 if (RARRAY_LEN(ary) == i2) {
3905 if (rb_block_given_p()) {
3906 return rb_yield(item);
3908 return Qnil;
3911 ary_resize_smaller(ary, i2);
3913 ary_verify(ary);
3914 return v;
3917 void
3918 rb_ary_delete_same(VALUE ary, VALUE item)
3920 long i1, i2;
3922 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
3923 VALUE e = RARRAY_AREF(ary, i1);
3925 if (e == item) {
3926 continue;
3928 if (i1 != i2) {
3929 rb_ary_store(ary, i2, e);
3931 i2++;
3933 if (RARRAY_LEN(ary) == i2) {
3934 return;
3937 ary_resize_smaller(ary, i2);
3940 VALUE
3941 rb_ary_delete_at(VALUE ary, long pos)
3943 long len = RARRAY_LEN(ary);
3944 VALUE del;
3946 if (pos >= len) return Qnil;
3947 if (pos < 0) {
3948 pos += len;
3949 if (pos < 0) return Qnil;
3952 rb_ary_modify(ary);
3953 del = RARRAY_AREF(ary, pos);
3954 RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
3955 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
3957 ARY_INCREASE_LEN(ary, -1);
3958 ary_verify(ary);
3959 return del;
3963 * call-seq:
3964 * array.delete_at(index) -> deleted_object or nil
3966 * Deletes an element from +self+, per the given \Integer +index+.
3968 * When +index+ is non-negative, deletes the element at offset +index+:
3969 * a = [:foo, 'bar', 2]
3970 * a.delete_at(1) # => "bar"
3971 * a # => [:foo, 2]
3973 * If index is too large, returns +nil+.
3975 * When +index+ is negative, counts backward from the end of the array:
3976 * a = [:foo, 'bar', 2]
3977 * a.delete_at(-2) # => "bar"
3978 * a # => [:foo, 2]
3980 * If +index+ is too small (far from zero), returns nil.
3983 static VALUE
3984 rb_ary_delete_at_m(VALUE ary, VALUE pos)
3986 return rb_ary_delete_at(ary, NUM2LONG(pos));
3989 static VALUE
3990 ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
3992 const long orig_len = RARRAY_LEN(ary);
3994 if (len < 0) {
3995 return Qnil;
3997 else if (pos < -orig_len) {
3998 return Qnil;
4000 else if (pos < 0) {
4001 pos += orig_len;
4003 else if (orig_len < pos) {
4004 return Qnil;
4006 if (orig_len < pos + len) {
4007 len = orig_len - pos;
4009 if (len == 0) {
4010 return rb_ary_new2(0);
4012 else {
4013 VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR_TRANSIENT(ary)+pos);
4014 rb_ary_splice(ary, pos, len, 0, 0);
4015 return arg2;
4020 * call-seq:
4021 * array.slice!(n) -> object or nil
4022 * array.slice!(start, length) -> new_array or nil
4023 * array.slice!(range) -> new_array or nil
4025 * Removes and returns elements from +self+.
4027 * When the only argument is an \Integer +n+,
4028 * removes and returns the _nth_ element in +self+:
4029 * a = [:foo, 'bar', 2]
4030 * a.slice!(1) # => "bar"
4031 * a # => [:foo, 2]
4033 * If +n+ is negative, counts backwards from the end of +self+:
4034 * a = [:foo, 'bar', 2]
4035 * a.slice!(-1) # => 2
4036 * a # => [:foo, "bar"]
4038 * If +n+ is out of range, returns +nil+.
4040 * When the only arguments are Integers +start+ and +length+,
4041 * removes +length+ elements from +self+ beginning at offset +start+;
4042 * returns the deleted objects in a new Array:
4043 * a = [:foo, 'bar', 2]
4044 * a.slice!(0, 2) # => [:foo, "bar"]
4045 * a # => [2]
4047 * If <tt>start + length</tt> exceeds the array size,
4048 * removes and returns all elements from offset +start+ to the end:
4049 * a = [:foo, 'bar', 2]
4050 * a.slice!(1, 50) # => ["bar", 2]
4051 * a # => [:foo]
4053 * If <tt>start == a.size</tt> and +length+ is non-negative,
4054 * returns a new empty \Array.
4056 * If +length+ is negative, returns +nil+.
4058 * When the only argument is a \Range object +range+,
4059 * treats <tt>range.min</tt> as +start+ above and <tt>range.size</tt> as +length+ above:
4060 * a = [:foo, 'bar', 2]
4061 * a.slice!(1..2) # => ["bar", 2]
4062 * a # => [:foo]
4064 * If <tt>range.start == a.size</tt>, returns a new empty \Array.
4066 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
4068 * If <tt>range.end</tt> is negative, counts backwards from the end of the array:
4069 * a = [:foo, 'bar', 2]
4070 * a.slice!(0..-2) # => [:foo, "bar"]
4071 * a # => [2]
4073 * If <tt>range.start</tt> is negative,
4074 * calculates the start index backwards from the end of the array:
4075 * a = [:foo, 'bar', 2]
4076 * a.slice!(-2..2) # => ["bar", 2]
4077 * a # => [:foo]
4080 static VALUE
4081 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
4083 VALUE arg1;
4084 long pos, len;
4086 rb_ary_modify_check(ary);
4087 rb_check_arity(argc, 1, 2);
4088 arg1 = argv[0];
4090 if (argc == 2) {
4091 pos = NUM2LONG(argv[0]);
4092 len = NUM2LONG(argv[1]);
4093 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4096 if (!FIXNUM_P(arg1)) {
4097 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
4098 case Qtrue:
4099 /* valid range */
4100 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4101 case Qnil:
4102 /* invalid range */
4103 return Qnil;
4104 default:
4105 /* not a range */
4106 break;
4110 return rb_ary_delete_at(ary, NUM2LONG(arg1));
4113 static VALUE
4114 ary_reject(VALUE orig, VALUE result)
4116 long i;
4118 for (i = 0; i < RARRAY_LEN(orig); i++) {
4119 VALUE v = RARRAY_AREF(orig, i);
4121 if (!RTEST(rb_yield(v))) {
4122 rb_ary_push(result, v);
4125 return result;
4128 static VALUE
4129 reject_bang_i(VALUE a)
4131 volatile struct select_bang_arg *arg = (void *)a;
4132 VALUE ary = arg->ary;
4133 long i1, i2;
4135 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4136 VALUE v = RARRAY_AREF(ary, i1);
4137 if (RTEST(rb_yield(v))) continue;
4138 if (i1 != i2) {
4139 rb_ary_store(ary, i2, v);
4141 arg->len[1] = ++i2;
4143 return (i1 == i2) ? Qnil : ary;
4146 static VALUE
4147 ary_reject_bang(VALUE ary)
4149 struct select_bang_arg args;
4150 rb_ary_modify_check(ary);
4151 args.ary = ary;
4152 args.len[0] = args.len[1] = 0;
4153 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4157 * call-seq:
4158 * array.reject! {|element| ... } -> self or nil
4159 * array.reject! -> new_enumerator
4161 * Removes each element for which the block returns a truthy value.
4163 * Returns +self+ if any elements removed:
4164 * a = [:foo, 'bar', 2, 'bat']
4165 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4167 * Returns +nil+ if no elements removed.
4169 * Returns a new \Enumerator if no block given:
4170 * a = [:foo, 'bar', 2]
4171 * a.reject! # => #<Enumerator: [:foo, "bar", 2]:reject!>
4174 static VALUE
4175 rb_ary_reject_bang(VALUE ary)
4177 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4178 rb_ary_modify(ary);
4179 return ary_reject_bang(ary);
4183 * call-seq:
4184 * array.reject {|element| ... } -> new_array
4185 * array.reject -> new_enumerator
4187 * Returns a new \Array whose elements are all those from +self+
4188 * for which the block returns +false+ or +nil+:
4189 * a = [:foo, 'bar', 2, 'bat']
4190 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4191 * a1 # => [:foo, 2]
4193 * Returns a new \Enumerator if no block given:
4194 * a = [:foo, 'bar', 2]
4195 * a.reject # => #<Enumerator: [:foo, "bar", 2]:reject>
4198 static VALUE
4199 rb_ary_reject(VALUE ary)
4201 VALUE rejected_ary;
4203 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4204 rejected_ary = rb_ary_new();
4205 ary_reject(ary, rejected_ary);
4206 return rejected_ary;
4210 * call-seq:
4211 * array.delete_if {|element| ... } -> self
4212 * array.delete_if -> Enumerator
4214 * Removes each element in +self+ for which the block returns a truthy value;
4215 * returns +self+:
4216 * a = [:foo, 'bar', 2, 'bat']
4217 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4219 * Returns a new \Enumerator if no block given:
4220 * a = [:foo, 'bar', 2]
4221 * a.delete_if # => #<Enumerator: [:foo, "bar", 2]:delete_if>
4224 static VALUE
4225 rb_ary_delete_if(VALUE ary)
4227 ary_verify(ary);
4228 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4229 ary_reject_bang(ary);
4230 return ary;
4233 static VALUE
4234 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
4236 VALUE *args = (VALUE *)cbarg;
4237 if (argc > 1) val = rb_ary_new4(argc, argv);
4238 rb_ary_push(args[0], val);
4239 if (--args[1] == 0) rb_iter_break();
4240 return Qnil;
4243 static VALUE
4244 take_items(VALUE obj, long n)
4246 VALUE result = rb_check_array_type(obj);
4247 VALUE args[2];
4249 if (n == 0) return result;
4250 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
4251 result = rb_ary_new2(n);
4252 args[0] = result; args[1] = (VALUE)n;
4253 if (rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args) == Qundef)
4254 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
4255 rb_obj_class(obj));
4256 return result;
4261 * call-seq:
4262 * array.zip(*other_arrays) -> new_array
4263 * array.zip(*other_arrays) {|other_array| ... } -> nil
4265 * When no block given, returns a new \Array +new_array+ of size <tt>self.size</tt>
4266 * whose elements are Arrays.
4268 * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
4269 * and contains:
4270 * - The _nth_ element of +self+.
4271 * - The _nth_ element of each of the +other_arrays+.
4273 * If all +other_arrays+ and +self+ are the same size:
4274 * a = [:a0, :a1, :a2, :a3]
4275 * b = [:b0, :b1, :b2, :b3]
4276 * c = [:c0, :c1, :c2, :c3]
4277 * d = a.zip(b, c)
4278 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4280 * If any array in +other_arrays+ is smaller than +self+,
4281 * fills to <tt>self.size</tt> with +nil+:
4282 * a = [:a0, :a1, :a2, :a3]
4283 * b = [:b0, :b1, :b2]
4284 * c = [:c0, :c1]
4285 * d = a.zip(b, c)
4286 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
4288 * If any array in +other_arrays+ is larger than +self+,
4289 * its trailing elements are ignored:
4290 * a = [:a0, :a1, :a2, :a3]
4291 * b = [:b0, :b1, :b2, :b3, :b4]
4292 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4293 * d = a.zip(b, c)
4294 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4296 * When a block is given, calls the block with each of the sub-arrays (formed as above); returns nil
4297 * a = [:a0, :a1, :a2, :a3]
4298 * b = [:b0, :b1, :b2, :b3]
4299 * c = [:c0, :c1, :c2, :c3]
4300 * a.zip(b, c) {|sub_array| p sub_array} # => nil
4302 * Output:
4303 * [:a0, :b0, :c0]
4304 * [:a1, :b1, :c1]
4305 * [:a2, :b2, :c2]
4306 * [:a3, :b3, :c3]
4309 static VALUE
4310 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
4312 int i, j;
4313 long len = RARRAY_LEN(ary);
4314 VALUE result = Qnil;
4316 for (i=0; i<argc; i++) {
4317 argv[i] = take_items(argv[i], len);
4320 if (rb_block_given_p()) {
4321 int arity = rb_block_arity();
4323 if (arity > 1) {
4324 VALUE work, *tmp;
4326 tmp = ALLOCV_N(VALUE, work, argc+1);
4328 for (i=0; i<RARRAY_LEN(ary); i++) {
4329 tmp[0] = RARRAY_AREF(ary, i);
4330 for (j=0; j<argc; j++) {
4331 tmp[j+1] = rb_ary_elt(argv[j], i);
4333 rb_yield_values2(argc+1, tmp);
4336 if (work) ALLOCV_END(work);
4338 else {
4339 for (i=0; i<RARRAY_LEN(ary); i++) {
4340 VALUE tmp = rb_ary_new2(argc+1);
4342 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4343 for (j=0; j<argc; j++) {
4344 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4346 rb_yield(tmp);
4350 else {
4351 result = rb_ary_new_capa(len);
4353 for (i=0; i<len; i++) {
4354 VALUE tmp = rb_ary_new_capa(argc+1);
4356 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4357 for (j=0; j<argc; j++) {
4358 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4360 rb_ary_push(result, tmp);
4364 return result;
4368 * call-seq:
4369 * array.transpose -> new_array
4371 * Transposes the rows and columns in an \Array of Arrays;
4372 * the nested Arrays must all be the same size:
4373 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4374 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4377 static VALUE
4378 rb_ary_transpose(VALUE ary)
4380 long elen = -1, alen, i, j;
4381 VALUE tmp, result = 0;
4383 alen = RARRAY_LEN(ary);
4384 if (alen == 0) return rb_ary_dup(ary);
4385 for (i=0; i<alen; i++) {
4386 tmp = to_ary(rb_ary_elt(ary, i));
4387 if (elen < 0) { /* first element */
4388 elen = RARRAY_LEN(tmp);
4389 result = rb_ary_new2(elen);
4390 for (j=0; j<elen; j++) {
4391 rb_ary_store(result, j, rb_ary_new2(alen));
4394 else if (elen != RARRAY_LEN(tmp)) {
4395 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
4396 RARRAY_LEN(tmp), elen);
4398 for (j=0; j<elen; j++) {
4399 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4402 return result;
4406 * call-seq:
4407 * array.replace(other_array) -> self
4409 * Replaces the content of +self+ with the content of +other_array+; returns +self+:
4410 * a = [:foo, 'bar', 2]
4411 * a.replace(['foo', :bar, 3]) # => ["foo", :bar, 3]
4414 VALUE
4415 rb_ary_replace(VALUE copy, VALUE orig)
4417 rb_ary_modify_check(copy);
4418 orig = to_ary(orig);
4419 if (copy == orig) return copy;
4421 if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
4422 VALUE shared_root = 0;
4424 if (ARY_OWNS_HEAP_P(copy)) {
4425 ary_heap_free(copy);
4427 else if (ARY_SHARED_P(copy)) {
4428 shared_root = ARY_SHARED_ROOT(copy);
4429 FL_UNSET_SHARED(copy);
4431 FL_SET_EMBED(copy);
4432 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR_TRANSIENT(orig));
4433 if (shared_root) {
4434 rb_ary_decrement_share(shared_root);
4436 ARY_SET_LEN(copy, RARRAY_LEN(orig));
4438 else {
4439 VALUE shared_root = ary_make_shared(orig);
4440 if (ARY_OWNS_HEAP_P(copy)) {
4441 ary_heap_free(copy);
4443 else {
4444 rb_ary_unshare_safe(copy);
4446 FL_UNSET_EMBED(copy);
4447 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
4448 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
4449 rb_ary_set_shared(copy, shared_root);
4451 ary_verify(copy);
4452 return copy;
4456 * call-seq:
4457 * array.clear -> self
4459 * Removes all elements from +self+:
4460 * a = [:foo, 'bar', 2]
4461 * a.clear # => []
4464 VALUE
4465 rb_ary_clear(VALUE ary)
4467 rb_ary_modify_check(ary);
4468 if (ARY_SHARED_P(ary)) {
4469 if (!ARY_EMBED_P(ary)) {
4470 rb_ary_unshare(ary);
4471 FL_SET_EMBED(ary);
4472 ARY_SET_EMBED_LEN(ary, 0);
4475 else {
4476 ARY_SET_LEN(ary, 0);
4477 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
4478 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
4481 ary_verify(ary);
4482 return ary;
4486 * call-seq:
4487 * array.fill(obj) -> self
4488 * array.fill(obj, start) -> self
4489 * array.fill(obj, start, length) -> self
4490 * array.fill(obj, range) -> self
4491 * array.fill {|index| ... } -> self
4492 * array.fill(start) {|index| ... } -> self
4493 * array.fill(start, length) {|index| ... } -> self
4494 * array.fill(range) {|index| ... } -> self
4496 * Replaces specified elements in +self+ with specified objects; returns +self+.
4498 * With argument +obj+ and no block given, replaces all elements with that one object:
4499 * a = ['a', 'b', 'c', 'd']
4500 * a # => ["a", "b", "c", "d"]
4501 * a.fill(:X) # => [:X, :X, :X, :X]
4503 * With arguments +obj+ and \Integer +start+, and no block given,
4504 * replaces elements based on the given start.
4506 * If +start+ is in range (<tt>0 <= start < array.size</tt>),
4507 * replaces all elements from offset +start+ through the end:
4508 * a = ['a', 'b', 'c', 'd']
4509 * a.fill(:X, 2) # => ["a", "b", :X, :X]
4511 * If +start+ is too large (<tt>start >= array.size</tt>), does nothing:
4512 * a = ['a', 'b', 'c', 'd']
4513 * a.fill(:X, 4) # => ["a", "b", "c", "d"]
4514 * a = ['a', 'b', 'c', 'd']
4515 * a.fill(:X, 5) # => ["a", "b", "c", "d"]
4517 * If +start+ is negative, counts from the end (starting index is <tt>start + array.size</tt>):
4518 * a = ['a', 'b', 'c', 'd']
4519 * a.fill(:X, -2) # => ["a", "b", :X, :X]
4521 * If +start+ is too small (less than and far from zero), replaces all elements:
4522 * a = ['a', 'b', 'c', 'd']
4523 * a.fill(:X, -6) # => [:X, :X, :X, :X]
4524 * a = ['a', 'b', 'c', 'd']
4525 * a.fill(:X, -50) # => [:X, :X, :X, :X]
4527 * With arguments +obj+, \Integer +start+, and \Integer +length+, and no block given,
4528 * replaces elements based on the given +start+ and +length+.
4530 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4531 * a = ['a', 'b', 'c', 'd']
4532 * a.fill(:X, 1, 1) # => ["a", :X, "c", "d"]
4534 * If +start+ is negative, counts from the end:
4535 * a = ['a', 'b', 'c', 'd']
4536 * a.fill(:X, -2, 1) # => ["a", "b", :X, "d"]
4538 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4539 * a = ['a', 'b', 'c', 'd']
4540 * a.fill(:X, 5, 0) # => ["a", "b", "c", "d", nil]
4541 * a = ['a', 'b', 'c', 'd']
4542 * a.fill(:X, 5, 2) # => ["a", "b", "c", "d", nil, :X, :X]
4544 * If +length+ is zero or negative, replaces no elements:
4545 * a = ['a', 'b', 'c', 'd']
4546 * a.fill(:X, 1, 0) # => ["a", "b", "c", "d"]
4547 * a.fill(:X, 1, -1) # => ["a", "b", "c", "d"]
4549 * With arguments +obj+ and \Range +range+, and no block given,
4550 * replaces elements based on the given range.
4552 * If the range is positive and ascending (<tt>0 < range.begin <= range.end</tt>),
4553 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4554 * a = ['a', 'b', 'c', 'd']
4555 * a.fill(:X, (1..1)) # => ["a", :X, "c", "d"]
4557 * If <tt>range.first</tt> is negative, replaces no elements:
4558 * a = ['a', 'b', 'c', 'd']
4559 * a.fill(:X, (-1..1)) # => ["a", "b", "c", "d"]
4561 * If <tt>range.last</tt> is negative, counts from the end:
4562 * a = ['a', 'b', 'c', 'd']
4563 * a.fill(:X, (0..-2)) # => [:X, :X, :X, "d"]
4564 * a = ['a', 'b', 'c', 'd']
4565 * a.fill(:X, (1..-2)) # => ["a", :X, :X, "d"]
4567 * If <tt>range.last</tt> and <tt>range.last</tt> are both negative,
4568 * both count from the end of the array:
4569 * a = ['a', 'b', 'c', 'd']
4570 * a.fill(:X, (-1..-1)) # => ["a", "b", "c", :X]
4571 * a = ['a', 'b', 'c', 'd']
4572 * a.fill(:X, (-2..-2)) # => ["a", "b", :X, "d"]
4574 * With no arguments and a block given, calls the block with each index;
4575 * replaces the corresponding element with the block's return value:
4576 * a = ['a', 'b', 'c', 'd']
4577 * a.fill { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4579 * With argument +start+ and a block given, calls the block with each index
4580 * from offset +start+ to the end; replaces the corresponding element
4581 * with the block's return value:
4583 * If start is in range (<tt>0 <= start < array.size</tt>),
4584 * replaces from offset +start+ to the end:
4585 * a = ['a', 'b', 'c', 'd']
4586 * a.fill(1) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "new_3"]
4588 * If +start+ is too large(<tt>start >= array.size</tt>), does nothing:
4589 * a = ['a', 'b', 'c', 'd']
4590 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4591 * a = ['a', 'b', 'c', 'd']
4592 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4594 * If +start+ is negative, counts from the end:
4595 * a = ['a', 'b', 'c', 'd']
4596 * a.fill(-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "new_3"]
4598 * If start is too small (<tt>start <= -array.size</tt>, replaces all elements:
4599 * a = ['a', 'b', 'c', 'd']
4600 * a.fill(-6) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4601 * a = ['a', 'b', 'c', 'd']
4602 * a.fill(-50) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4604 * With arguments +start+ and +length+, and a block given,
4605 * calls the block for each index specified by start length;
4606 * replaces the corresponding element with the block's return value.
4608 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4609 * a = ['a', 'b', 'c', 'd']
4610 * a.fill(1, 1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4612 * If start is negative, counts from the end:
4613 * a = ['a', 'b', 'c', 'd']
4614 * a.fill(-2, 1) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4616 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4617 * a = ['a', 'b', 'c', 'd']
4618 * a.fill(5, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil]
4619 * a = ['a', 'b', 'c', 'd']
4620 * a.fill(5, 2) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil, "new_5", "new_6"]
4622 * If +length+ is zero or less, replaces no elements:
4623 * a = ['a', 'b', 'c', 'd']
4624 * a.fill(1, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4625 * a.fill(1, -1) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4627 * With arguments +obj+ and +range+, and a block given,
4628 * calls the block with each index in the given range;
4629 * replaces the corresponding element with the block's return value.
4631 * If the range is positive and ascending (<tt>range 0 < range.begin <= range.end</tt>,
4632 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4633 * a = ['a', 'b', 'c', 'd']
4634 * a.fill(1..1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4636 * If +range.first+ is negative, does nothing:
4637 * a = ['a', 'b', 'c', 'd']
4638 * a.fill(-1..1) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4640 * If <tt>range.last</tt> is negative, counts from the end:
4641 * a = ['a', 'b', 'c', 'd']
4642 * a.fill(0..-2) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "d"]
4643 * a = ['a', 'b', 'c', 'd']
4644 * a.fill(1..-2) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "d"]
4646 * If <tt>range.first</tt> and <tt>range.last</tt> are both negative,
4647 * both count from the end:
4648 * a = ['a', 'b', 'c', 'd']
4649 * a.fill(-1..-1) { |index| "new_#{index}" } # => ["a", "b", "c", "new_3"]
4650 * a = ['a', 'b', 'c', 'd']
4651 * a.fill(-2..-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4654 static VALUE
4655 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
4657 VALUE item = Qundef, arg1, arg2;
4658 long beg = 0, end = 0, len = 0;
4660 if (rb_block_given_p()) {
4661 rb_scan_args(argc, argv, "02", &arg1, &arg2);
4662 argc += 1; /* hackish */
4664 else {
4665 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
4667 switch (argc) {
4668 case 1:
4669 beg = 0;
4670 len = RARRAY_LEN(ary);
4671 break;
4672 case 2:
4673 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
4674 break;
4676 /* fall through */
4677 case 3:
4678 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
4679 if (beg < 0) {
4680 beg = RARRAY_LEN(ary) + beg;
4681 if (beg < 0) beg = 0;
4683 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
4684 break;
4686 rb_ary_modify(ary);
4687 if (len < 0) {
4688 return ary;
4690 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
4691 rb_raise(rb_eArgError, "argument too big");
4693 end = beg + len;
4694 if (RARRAY_LEN(ary) < end) {
4695 if (end >= ARY_CAPA(ary)) {
4696 ary_resize_capa(ary, end);
4698 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
4699 ARY_SET_LEN(ary, end);
4702 if (item == Qundef) {
4703 VALUE v;
4704 long i;
4706 for (i=beg; i<end; i++) {
4707 v = rb_yield(LONG2NUM(i));
4708 if (i>=RARRAY_LEN(ary)) break;
4709 ARY_SET(ary, i, v);
4712 else {
4713 ary_memfill(ary, beg, len, item);
4715 return ary;
4719 * call-seq:
4720 * array + other_array -> new_array
4722 * Returns a new \Array containing all elements of +array+
4723 * followed by all elements of +other_array+:
4724 * a = [0, 1] + [2, 3]
4725 * a # => [0, 1, 2, 3]
4727 * Related: #concat.
4730 VALUE
4731 rb_ary_plus(VALUE x, VALUE y)
4733 VALUE z;
4734 long len, xlen, ylen;
4736 y = to_ary(y);
4737 xlen = RARRAY_LEN(x);
4738 ylen = RARRAY_LEN(y);
4739 len = xlen + ylen;
4740 z = rb_ary_new2(len);
4742 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR_TRANSIENT(x));
4743 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR_TRANSIENT(y));
4744 ARY_SET_LEN(z, len);
4745 return z;
4748 static VALUE
4749 ary_append(VALUE x, VALUE y)
4751 long n = RARRAY_LEN(y);
4752 if (n > 0) {
4753 rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR_TRANSIENT(y), n);
4755 RB_GC_GUARD(y);
4756 return x;
4760 * call-seq:
4761 * array.concat(*other_arrays) -> self
4763 * Adds to +array+ all elements from each \Array in +other_arrays+; returns +self+:
4764 * a = [0, 1]
4765 * a.concat([2, 3], [4, 5]) # => [0, 1, 2, 3, 4, 5]
4768 static VALUE
4769 rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
4771 rb_ary_modify_check(ary);
4773 if (argc == 1) {
4774 rb_ary_concat(ary, argv[0]);
4776 else if (argc > 1) {
4777 int i;
4778 VALUE args = rb_ary_tmp_new(argc);
4779 for (i = 0; i < argc; i++) {
4780 rb_ary_concat(args, argv[i]);
4782 ary_append(ary, args);
4785 ary_verify(ary);
4786 return ary;
4789 VALUE
4790 rb_ary_concat(VALUE x, VALUE y)
4792 return ary_append(x, to_ary(y));
4796 * call-seq:
4797 * array * n -> new_array
4798 * array * string_separator -> new_string
4800 * When non-negative argument \Integer +n+ is given,
4801 * returns a new \Array built by concatenating the +n+ copies of +self+:
4802 * a = ['x', 'y']
4803 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
4805 * When \String argument +string_separator+ is given,
4806 * equivalent to <tt>array.join(string_separator)</tt>:
4807 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
4810 static VALUE
4811 rb_ary_times(VALUE ary, VALUE times)
4813 VALUE ary2, tmp;
4814 const VALUE *ptr;
4815 long t, len;
4817 tmp = rb_check_string_type(times);
4818 if (!NIL_P(tmp)) {
4819 return rb_ary_join(ary, tmp);
4822 len = NUM2LONG(times);
4823 if (len == 0) {
4824 ary2 = ary_new(rb_cArray, 0);
4825 goto out;
4827 if (len < 0) {
4828 rb_raise(rb_eArgError, "negative argument");
4830 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
4831 rb_raise(rb_eArgError, "argument too big");
4833 len *= RARRAY_LEN(ary);
4835 ary2 = ary_new(rb_cArray, len);
4836 ARY_SET_LEN(ary2, len);
4838 ptr = RARRAY_CONST_PTR_TRANSIENT(ary);
4839 t = RARRAY_LEN(ary);
4840 if (0 < t) {
4841 ary_memcpy(ary2, 0, t, ptr);
4842 while (t <= len/2) {
4843 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR_TRANSIENT(ary2));
4844 t *= 2;
4846 if (t < len) {
4847 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR_TRANSIENT(ary2));
4850 out:
4851 return ary2;
4855 * call-seq:
4856 * array.assoc(obj) -> found_array or nil
4858 * Returns the first element in +self+ that is an \Array
4859 * whose first element <tt>==</tt> +obj+:
4860 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
4861 * a.assoc(4) # => [4, 5, 6]
4863 * Returns +nil+ if no such element is found.
4865 * Related: #rassoc.
4868 VALUE
4869 rb_ary_assoc(VALUE ary, VALUE key)
4871 long i;
4872 VALUE v;
4874 for (i = 0; i < RARRAY_LEN(ary); ++i) {
4875 v = rb_check_array_type(RARRAY_AREF(ary, i));
4876 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
4877 rb_equal(RARRAY_AREF(v, 0), key))
4878 return v;
4880 return Qnil;
4884 * call-seq:
4885 * array.rassoc(obj) -> found_array or nil
4887 * Returns the first element in +self+ that is an \Array
4888 * whose second element <tt>==</tt> +obj+:
4889 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
4890 * a.rassoc(4) # => [2, 4]
4892 * Returns +nil+ if no such element is found.
4894 * Related: #assoc.
4897 VALUE
4898 rb_ary_rassoc(VALUE ary, VALUE value)
4900 long i;
4901 VALUE v;
4903 for (i = 0; i < RARRAY_LEN(ary); ++i) {
4904 v = RARRAY_AREF(ary, i);
4905 if (RB_TYPE_P(v, T_ARRAY) &&
4906 RARRAY_LEN(v) > 1 &&
4907 rb_equal(RARRAY_AREF(v, 1), value))
4908 return v;
4910 return Qnil;
4913 static VALUE
4914 recursive_equal(VALUE ary1, VALUE ary2, int recur)
4916 long i, len1;
4917 const VALUE *p1, *p2;
4919 if (recur) return Qtrue; /* Subtle! */
4921 /* rb_equal() can evacuate ptrs */
4922 p1 = RARRAY_CONST_PTR(ary1);
4923 p2 = RARRAY_CONST_PTR(ary2);
4924 len1 = RARRAY_LEN(ary1);
4926 for (i = 0; i < len1; i++) {
4927 if (*p1 != *p2) {
4928 if (rb_equal(*p1, *p2)) {
4929 len1 = RARRAY_LEN(ary1);
4930 if (len1 != RARRAY_LEN(ary2))
4931 return Qfalse;
4932 if (len1 < i)
4933 return Qtrue;
4934 p1 = RARRAY_CONST_PTR(ary1) + i;
4935 p2 = RARRAY_CONST_PTR(ary2) + i;
4937 else {
4938 return Qfalse;
4941 p1++;
4942 p2++;
4944 return Qtrue;
4948 * call-seq:
4949 * array == other_array -> true or false
4951 * Returns +true+ if both <tt>array.size == other_array.size</tt>
4952 * and for each index +i+ in +array+, <tt>array[i] == other_array[i]</tt>:
4953 * a0 = [:foo, 'bar', 2]
4954 * a1 = [:foo, 'bar', 2.0]
4955 * a1 == a0 # => true
4956 * [] == [] # => true
4958 * Otherwise, returns +false+.
4960 * This method is different from method Array#eql?,
4961 * which compares elements using <tt>Object#eql?</tt>.
4964 static VALUE
4965 rb_ary_equal(VALUE ary1, VALUE ary2)
4967 if (ary1 == ary2) return Qtrue;
4968 if (!RB_TYPE_P(ary2, T_ARRAY)) {
4969 if (!rb_respond_to(ary2, idTo_ary)) {
4970 return Qfalse;
4972 return rb_equal(ary2, ary1);
4974 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
4975 if (RARRAY_CONST_PTR_TRANSIENT(ary1) == RARRAY_CONST_PTR_TRANSIENT(ary2)) return Qtrue;
4976 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
4979 static VALUE
4980 recursive_eql(VALUE ary1, VALUE ary2, int recur)
4982 long i;
4984 if (recur) return Qtrue; /* Subtle! */
4985 for (i=0; i<RARRAY_LEN(ary1); i++) {
4986 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
4987 return Qfalse;
4989 return Qtrue;
4993 * call-seq:
4994 * array.eql? other_array -> true or false
4996 * Returns +true+ if +self+ and +other_array+ are the same size,
4997 * and if, for each index +i+ in +self+, <tt>self[i].eql? other_array[i]</tt>:
4998 * a0 = [:foo, 'bar', 2]
4999 * a1 = [:foo, 'bar', 2]
5000 * a1.eql?(a0) # => true
5002 * Otherwise, returns +false+.
5004 * This method is different from method {Array#==}[#method-i-3D-3D],
5005 * which compares using method <tt>Object#==</tt>.
5008 static VALUE
5009 rb_ary_eql(VALUE ary1, VALUE ary2)
5011 if (ary1 == ary2) return Qtrue;
5012 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
5013 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5014 if (RARRAY_CONST_PTR_TRANSIENT(ary1) == RARRAY_CONST_PTR_TRANSIENT(ary2)) return Qtrue;
5015 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
5019 * call-seq:
5020 * array.hash -> integer
5022 * Returns the integer hash value for +self+.
5024 * Two arrays with the same content will have the same hash code (and will compare using eql?):
5025 * [0, 1, 2].hash == [0, 1, 2].hash # => true
5026 * [0, 1, 2].hash == [0, 1, 3].hash # => false
5029 static VALUE
5030 rb_ary_hash(VALUE ary)
5032 long i;
5033 st_index_t h;
5034 VALUE n;
5036 h = rb_hash_start(RARRAY_LEN(ary));
5037 h = rb_hash_uint(h, (st_index_t)rb_ary_hash);
5038 for (i=0; i<RARRAY_LEN(ary); i++) {
5039 n = rb_hash(RARRAY_AREF(ary, i));
5040 h = rb_hash_uint(h, NUM2LONG(n));
5042 h = rb_hash_end(h);
5043 return ST2FIX(h);
5047 * call-seq:
5048 * array.include?(obj) -> true or false
5050 * Returns +true+ if for some index +i+ in +self+, <tt>obj == self[i]</tt>;
5051 * otherwise +false+:
5052 * [0, 1, 2].include?(2) # => true
5053 * [0, 1, 2].include?(3) # => false
5056 VALUE
5057 rb_ary_includes(VALUE ary, VALUE item)
5059 long i;
5060 VALUE e;
5062 for (i=0; i<RARRAY_LEN(ary); i++) {
5063 e = RARRAY_AREF(ary, i);
5064 if (rb_equal(e, item)) {
5065 return Qtrue;
5068 return Qfalse;
5071 static VALUE
5072 rb_ary_includes_by_eql(VALUE ary, VALUE item)
5074 long i;
5075 VALUE e;
5077 for (i=0; i<RARRAY_LEN(ary); i++) {
5078 e = RARRAY_AREF(ary, i);
5079 if (rb_eql(item, e)) {
5080 return Qtrue;
5083 return Qfalse;
5086 static VALUE
5087 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5089 long i, len;
5091 if (recur) return Qundef; /* Subtle! */
5092 len = RARRAY_LEN(ary1);
5093 if (len > RARRAY_LEN(ary2)) {
5094 len = RARRAY_LEN(ary2);
5096 for (i=0; i<len; i++) {
5097 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5098 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5099 if (v != INT2FIX(0)) {
5100 return v;
5103 return Qundef;
5107 * call-seq:
5108 * array <=> other_array -> -1, 0, or 1
5110 * Returns -1, 0, or 1 as +self+ is less than, equal to, or greater than +other_array+.
5111 * For each index +i+ in +self+, evaluates <tt>result = self[i] <=> other_array[i]</tt>.
5113 * Returns -1 if any result is -1:
5114 * [0, 1, 2] <=> [0, 1, 3] # => -1
5116 * Returns 1 if any result is 1:
5117 * [0, 1, 2] <=> [0, 1, 1] # => 1
5119 * When all results are zero:
5120 * - Returns -1 if +array+ is smaller than +other_array+:
5121 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5122 * - Returns 1 if +array+ is larger than +other_array+:
5123 * [0, 1, 2] <=> [0, 1] # => 1
5124 * - Returns 0 if +array+ and +other_array+ are the same size:
5125 * [0, 1, 2] <=> [0, 1, 2] # => 0
5128 VALUE
5129 rb_ary_cmp(VALUE ary1, VALUE ary2)
5131 long len;
5132 VALUE v;
5134 ary2 = rb_check_array_type(ary2);
5135 if (NIL_P(ary2)) return Qnil;
5136 if (ary1 == ary2) return INT2FIX(0);
5137 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5138 if (v != Qundef) return v;
5139 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5140 if (len == 0) return INT2FIX(0);
5141 if (len > 0) return INT2FIX(1);
5142 return INT2FIX(-1);
5145 static VALUE
5146 ary_add_hash(VALUE hash, VALUE ary)
5148 long i;
5150 for (i=0; i<RARRAY_LEN(ary); i++) {
5151 VALUE elt = RARRAY_AREF(ary, i);
5152 rb_hash_add_new_element(hash, elt, elt);
5154 return hash;
5157 static inline VALUE
5158 ary_tmp_hash_new(VALUE ary)
5160 long size = RARRAY_LEN(ary);
5161 VALUE hash = rb_hash_new_with_size(size);
5163 RBASIC_CLEAR_CLASS(hash);
5164 return hash;
5167 static VALUE
5168 ary_make_hash(VALUE ary)
5170 VALUE hash = ary_tmp_hash_new(ary);
5171 return ary_add_hash(hash, ary);
5174 static VALUE
5175 ary_add_hash_by(VALUE hash, VALUE ary)
5177 long i;
5179 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5180 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
5181 rb_hash_add_new_element(hash, k, v);
5183 return hash;
5186 static VALUE
5187 ary_make_hash_by(VALUE ary)
5189 VALUE hash = ary_tmp_hash_new(ary);
5190 return ary_add_hash_by(hash, ary);
5193 static inline void
5194 ary_recycle_hash(VALUE hash)
5196 assert(RBASIC_CLASS(hash) == 0);
5197 if (RHASH_ST_TABLE_P(hash)) {
5198 st_table *tbl = RHASH_ST_TABLE(hash);
5199 st_free_table(tbl);
5200 RHASH_ST_CLEAR(hash);
5205 * call-seq:
5206 * array - other_array -> new_array
5208 * Returns a new \Array containing only those elements from +array+
5209 * that are not found in \Array +other_array+;
5210 * items are compared using <tt>eql?</tt>;
5211 * the order from +array+ is preserved:
5212 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5213 * [0, 1, 2, 3] - [3, 0] # => [1, 2]
5214 * [0, 1, 2] - [4] # => [0, 1, 2]
5216 * Related: Array#difference.
5219 static VALUE
5220 rb_ary_diff(VALUE ary1, VALUE ary2)
5222 VALUE ary3;
5223 VALUE hash;
5224 long i;
5226 ary2 = to_ary(ary2);
5227 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5228 ary3 = rb_ary_new();
5230 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5231 for (i=0; i<RARRAY_LEN(ary1); i++) {
5232 VALUE elt = rb_ary_elt(ary1, i);
5233 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5234 rb_ary_push(ary3, elt);
5236 return ary3;
5239 hash = ary_make_hash(ary2);
5240 for (i=0; i<RARRAY_LEN(ary1); i++) {
5241 if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
5242 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5244 ary_recycle_hash(hash);
5245 return ary3;
5249 * call-seq:
5250 * array.difference(*other_arrays) -> new_array
5252 * Returns a new \Array containing only those elements from +self+
5253 * that are not found in any of the Arrays +other_arrays+;
5254 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5255 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5256 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5257 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5259 * Returns a copy of +self+ if no arguments given.
5261 * Related: Array#-.
5264 static VALUE
5265 rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5267 VALUE ary_diff;
5268 long i, length;
5269 volatile VALUE t0;
5270 bool *is_hash = ALLOCV_N(bool, t0, argc);
5271 ary_diff = rb_ary_new();
5272 length = RARRAY_LEN(ary);
5274 for (i = 0; i < argc; i++) {
5275 argv[i] = to_ary(argv[i]);
5276 is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5277 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
5280 for (i = 0; i < RARRAY_LEN(ary); i++) {
5281 int j;
5282 VALUE elt = rb_ary_elt(ary, i);
5283 for (j = 0; j < argc; j++) {
5284 if (is_hash[j]) {
5285 if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL))
5286 break;
5288 else {
5289 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5292 if (j == argc) rb_ary_push(ary_diff, elt);
5295 ALLOCV_END(t0);
5297 return ary_diff;
5302 * call-seq:
5303 * array & other_array -> new_array
5305 * Returns a new \Array containing each element found in both +array+ and \Array +other_array+;
5306 * duplicates are omitted; items are compared using <tt>eql?</tt>:
5307 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5308 * [0, 1, 0, 1] & [0, 1] # => [0, 1]
5310 * Preserves order from +array+:
5311 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5313 * Related: Array#intersection.
5317 static VALUE
5318 rb_ary_and(VALUE ary1, VALUE ary2)
5320 VALUE hash, ary3, v;
5321 st_data_t vv;
5322 long i;
5324 ary2 = to_ary(ary2);
5325 ary3 = rb_ary_new();
5326 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5328 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5329 for (i=0; i<RARRAY_LEN(ary1); i++) {
5330 v = RARRAY_AREF(ary1, i);
5331 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5332 if (rb_ary_includes_by_eql(ary3, v)) continue;
5333 rb_ary_push(ary3, v);
5335 return ary3;
5338 hash = ary_make_hash(ary2);
5340 for (i=0; i<RARRAY_LEN(ary1); i++) {
5341 v = RARRAY_AREF(ary1, i);
5342 vv = (st_data_t)v;
5343 if (rb_hash_stlike_delete(hash, &vv, 0)) {
5344 rb_ary_push(ary3, v);
5347 ary_recycle_hash(hash);
5349 return ary3;
5353 * call-seq:
5354 * array.intersection(*other_arrays) -> new_array
5356 * Returns a new \Array containing each element found both in +self+
5357 * and in all of the given Arrays +other_arrays+;
5358 * duplicates are omitted; items are compared using <tt>eql?</tt>:
5359 * [0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5360 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5362 * Preserves order from +self+:
5363 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5365 * Returns a copy of +self+ if no arguments given.
5367 * Related: Array#&.
5370 static VALUE
5371 rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5373 VALUE result = rb_ary_dup(ary);
5374 int i;
5376 for (i = 0; i < argc; i++) {
5377 result = rb_ary_and(result, argv[i]);
5380 return result;
5383 static int
5384 ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
5386 if (existing) return ST_STOP;
5387 *key = *value = (VALUE)arg;
5388 return ST_CONTINUE;
5391 static void
5392 rb_ary_union(VALUE ary_union, VALUE ary)
5394 long i;
5395 for (i = 0; i < RARRAY_LEN(ary); i++) {
5396 VALUE elt = rb_ary_elt(ary, i);
5397 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
5398 rb_ary_push(ary_union, elt);
5402 static void
5403 rb_ary_union_hash(VALUE hash, VALUE ary2)
5405 long i;
5406 for (i = 0; i < RARRAY_LEN(ary2); i++) {
5407 VALUE elt = RARRAY_AREF(ary2, i);
5408 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
5409 RB_OBJ_WRITTEN(hash, Qundef, elt);
5415 * call-seq:
5416 * array | other_array -> new_array
5418 * Returns the union of +array+ and \Array +other_array+;
5419 * duplicates are removed; order is preserved;
5420 * items are compared using <tt>eql?</tt>:
5421 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5422 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5423 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5425 * Related: Array#union.
5428 static VALUE
5429 rb_ary_or(VALUE ary1, VALUE ary2)
5431 VALUE hash, ary3;
5433 ary2 = to_ary(ary2);
5434 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5435 ary3 = rb_ary_new();
5436 rb_ary_union(ary3, ary1);
5437 rb_ary_union(ary3, ary2);
5438 return ary3;
5441 hash = ary_make_hash(ary1);
5442 rb_ary_union_hash(hash, ary2);
5444 ary3 = rb_hash_values(hash);
5445 ary_recycle_hash(hash);
5446 return ary3;
5450 * call-seq:
5451 * array.union(*other_arrays) -> new_array
5453 * Returns a new \Array that is the union of +self+ and all given Arrays +other_arrays+;
5454 * duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
5455 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5456 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5457 * [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3]
5459 * Returns a copy of +self+ if no arguments given.
5461 * Related: Array#|.
5464 static VALUE
5465 rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
5467 int i;
5468 long sum;
5469 VALUE hash, ary_union;
5471 sum = RARRAY_LEN(ary);
5472 for (i = 0; i < argc; i++) {
5473 argv[i] = to_ary(argv[i]);
5474 sum += RARRAY_LEN(argv[i]);
5477 if (sum <= SMALL_ARRAY_LEN) {
5478 ary_union = rb_ary_new();
5480 rb_ary_union(ary_union, ary);
5481 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
5483 return ary_union;
5486 hash = ary_make_hash(ary);
5487 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
5489 ary_union = rb_hash_values(hash);
5490 ary_recycle_hash(hash);
5491 return ary_union;
5495 * call-seq:
5496 * ary.intersect?(other_ary) -> true or false
5498 * Returns +true+ if the array and +other_ary+ have at least one element in
5499 * common, otherwise returns +false+.
5501 * a = [ 1, 2, 3 ]
5502 * b = [ 3, 4, 5 ]
5503 * c = [ 5, 6, 7 ]
5504 * a.intersect?(b) #=> true
5505 * a.intersect?(c) #=> false
5508 static VALUE
5509 rb_ary_intersect_p(VALUE ary1, VALUE ary2)
5511 VALUE hash, v, result, shorter, longer;
5512 st_data_t vv;
5513 long i;
5515 ary2 = to_ary(ary2);
5516 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
5518 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5519 for (i=0; i<RARRAY_LEN(ary1); i++) {
5520 v = RARRAY_AREF(ary1, i);
5521 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
5523 return Qfalse;
5526 shorter = ary1;
5527 longer = ary2;
5528 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
5529 longer = ary1;
5530 shorter = ary2;
5533 hash = ary_make_hash(shorter);
5534 result = Qfalse;
5536 for (i=0; i<RARRAY_LEN(longer); i++) {
5537 v = RARRAY_AREF(longer, i);
5538 vv = (st_data_t)v;
5539 if (rb_hash_stlike_lookup(hash, vv, 0)) {
5540 result = Qtrue;
5541 break;
5544 ary_recycle_hash(hash);
5546 return result;
5549 static VALUE
5550 ary_max_generic(VALUE ary, long i, VALUE vmax)
5552 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
5554 VALUE v;
5555 for (; i < RARRAY_LEN(ary); ++i) {
5556 v = RARRAY_AREF(ary, i);
5558 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
5559 vmax = v;
5563 return vmax;
5566 static VALUE
5567 ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
5569 const long n = RARRAY_LEN(ary);
5570 RUBY_ASSERT(i > 0 && i < n);
5571 RUBY_ASSERT(FIXNUM_P(vmax));
5573 VALUE v;
5574 for (; i < n; ++i) {
5575 v = RARRAY_AREF(ary, i);
5577 if (FIXNUM_P(v)) {
5578 if ((long)vmax < (long)v) {
5579 vmax = v;
5582 else {
5583 return ary_max_generic(ary, i, vmax);
5587 return vmax;
5590 static VALUE
5591 ary_max_opt_float(VALUE ary, long i, VALUE vmax)
5593 const long n = RARRAY_LEN(ary);
5594 RUBY_ASSERT(i > 0 && i < n);
5595 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax));
5597 VALUE v;
5598 for (; i < n; ++i) {
5599 v = RARRAY_AREF(ary, i);
5601 if (RB_FLOAT_TYPE_P(v)) {
5602 if (rb_float_cmp(vmax, v) < 0) {
5603 vmax = v;
5606 else {
5607 return ary_max_generic(ary, i, vmax);
5611 return vmax;
5614 static VALUE
5615 ary_max_opt_string(VALUE ary, long i, VALUE vmax)
5617 const long n = RARRAY_LEN(ary);
5618 RUBY_ASSERT(i > 0 && i < n);
5619 RUBY_ASSERT(STRING_P(vmax));
5621 VALUE v;
5622 for (; i < n; ++i) {
5623 v = RARRAY_AREF(ary, i);
5625 if (STRING_P(v)) {
5626 if (rb_str_cmp(vmax, v) < 0) {
5627 vmax = v;
5630 else {
5631 return ary_max_generic(ary, i, vmax);
5635 return vmax;
5639 * call-seq:
5640 * array.max -> element
5641 * array.max {|a, b| ... } -> element
5642 * array.max(n) -> new_array
5643 * array.max(n) {|a, b| ... } -> new_array
5645 * Returns one of the following:
5646 * - The maximum-valued element from +self+.
5647 * - A new \Array of maximum-valued elements selected from +self+.
5649 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
5650 * with an \Integer.
5652 * With no argument and no block, returns the element in +self+
5653 * having the maximum value per method <tt><=></tt>:
5654 * [0, 1, 2].max # => 2
5656 * With an argument \Integer +n+ and no block, returns a new \Array with at most +n+ elements,
5657 * in descending order per method <tt><=></tt>:
5658 * [0, 1, 2, 3].max(3) # => [3, 2, 1]
5659 * [0, 1, 2, 3].max(6) # => [3, 2, 1, 0]
5661 * When a block is given, the block must return an \Integer.
5663 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
5664 * returns the element having the maximum value per the block:
5665 * ['0', '00', '000'].max {|a, b| a.size <=> b.size } # => "000"
5667 * With an argument +n+ and a block, returns a new \Array with at most +n+ elements,
5668 * in descending order per the block:
5669 * ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"]
5671 static VALUE
5672 rb_ary_max(int argc, VALUE *argv, VALUE ary)
5674 struct cmp_opt_data cmp_opt = { 0, 0 };
5675 VALUE result = Qundef, v;
5676 VALUE num;
5677 long i;
5679 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
5680 return rb_nmin_run(ary, num, 0, 1, 1);
5682 const long n = RARRAY_LEN(ary);
5683 if (rb_block_given_p()) {
5684 for (i = 0; i < RARRAY_LEN(ary); i++) {
5685 v = RARRAY_AREF(ary, i);
5686 if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
5687 result = v;
5691 else if (n > 0) {
5692 result = RARRAY_AREF(ary, 0);
5693 if (n > 1) {
5694 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) {
5695 return ary_max_opt_fixnum(ary, 1, result);
5697 else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) {
5698 return ary_max_opt_string(ary, 1, result);
5700 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) {
5701 return ary_max_opt_float(ary, 1, result);
5703 else {
5704 return ary_max_generic(ary, 1, result);
5708 if (result == Qundef) return Qnil;
5709 return result;
5712 static VALUE
5713 ary_min_generic(VALUE ary, long i, VALUE vmin)
5715 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
5717 VALUE v;
5718 for (; i < RARRAY_LEN(ary); ++i) {
5719 v = RARRAY_AREF(ary, i);
5721 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
5722 vmin = v;
5726 return vmin;
5729 static VALUE
5730 ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
5732 const long n = RARRAY_LEN(ary);
5733 RUBY_ASSERT(i > 0 && i < n);
5734 RUBY_ASSERT(FIXNUM_P(vmin));
5736 VALUE a;
5737 for (; i < n; ++i) {
5738 a = RARRAY_AREF(ary, i);
5740 if (FIXNUM_P(a)) {
5741 if ((long)vmin > (long)a) {
5742 vmin = a;
5745 else {
5746 return ary_min_generic(ary, i, vmin);
5750 return vmin;
5753 static VALUE
5754 ary_min_opt_float(VALUE ary, long i, VALUE vmin)
5756 const long n = RARRAY_LEN(ary);
5757 RUBY_ASSERT(i > 0 && i < n);
5758 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin));
5760 VALUE a;
5761 for (; i < n; ++i) {
5762 a = RARRAY_AREF(ary, i);
5764 if (RB_FLOAT_TYPE_P(a)) {
5765 if (rb_float_cmp(vmin, a) > 0) {
5766 vmin = a;
5769 else {
5770 return ary_min_generic(ary, i, vmin);
5774 return vmin;
5777 static VALUE
5778 ary_min_opt_string(VALUE ary, long i, VALUE vmin)
5780 const long n = RARRAY_LEN(ary);
5781 RUBY_ASSERT(i > 0 && i < n);
5782 RUBY_ASSERT(STRING_P(vmin));
5784 VALUE a;
5785 for (; i < n; ++i) {
5786 a = RARRAY_AREF(ary, i);
5788 if (STRING_P(a)) {
5789 if (rb_str_cmp(vmin, a) > 0) {
5790 vmin = a;
5793 else {
5794 return ary_min_generic(ary, i, vmin);
5798 return vmin;
5802 * call-seq:
5803 * array.min -> element
5804 * array.min { |a, b| ... } -> element
5805 * array.min(n) -> new_array
5806 * array.min(n) { |a, b| ... } -> new_array
5808 * Returns one of the following:
5809 * - The minimum-valued element from +self+.
5810 * - A new \Array of minimum-valued elements selected from +self+.
5812 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
5813 * with an \Integer.
5815 * With no argument and no block, returns the element in +self+
5816 * having the minimum value per method <tt><=></tt>:
5817 * [0, 1, 2].min # => 0
5819 * With \Integer argument +n+ and no block, returns a new \Array with at most +n+ elements,
5820 * in ascending order per method <tt><=></tt>:
5821 * [0, 1, 2, 3].min(3) # => [0, 1, 2]
5822 * [0, 1, 2, 3].min(6) # => [0, 1, 2, 3]
5824 * When a block is given, the block must return an Integer.
5826 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
5827 * returns the element having the minimum value per the block:
5828 * ['0', '00', '000'].min { |a, b| a.size <=> b.size } # => "0"
5830 * With an argument +n+ and a block, returns a new \Array with at most +n+ elements,
5831 * in ascending order per the block:
5832 * ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"]
5834 static VALUE
5835 rb_ary_min(int argc, VALUE *argv, VALUE ary)
5837 struct cmp_opt_data cmp_opt = { 0, 0 };
5838 VALUE result = Qundef, v;
5839 VALUE num;
5840 long i;
5842 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
5843 return rb_nmin_run(ary, num, 0, 0, 1);
5845 const long n = RARRAY_LEN(ary);
5846 if (rb_block_given_p()) {
5847 for (i = 0; i < RARRAY_LEN(ary); i++) {
5848 v = RARRAY_AREF(ary, i);
5849 if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
5850 result = v;
5854 else if (n > 0) {
5855 result = RARRAY_AREF(ary, 0);
5856 if (n > 1) {
5857 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) {
5858 return ary_min_opt_fixnum(ary, 1, result);
5860 else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) {
5861 return ary_min_opt_string(ary, 1, result);
5863 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) {
5864 return ary_min_opt_float(ary, 1, result);
5866 else {
5867 return ary_min_generic(ary, 1, result);
5871 if (result == Qundef) return Qnil;
5872 return result;
5876 * call-seq:
5877 * array.minmax -> [min_val, max_val]
5878 * array.minmax {|a, b| ... } -> [min_val, max_val]
5880 * Returns a new 2-element \Array containing the minimum and maximum values
5881 * from +self+, either per method <tt><=></tt> or per a given block:.
5883 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
5884 * with an \Integer;
5885 * returns a new 2-element \Array containing the minimum and maximum values
5886 * from +self+, per method <tt><=></tt>:
5887 * [0, 1, 2].minmax # => [0, 2]
5889 * When a block is given, the block must return an \Integer;
5890 * the block is called <tt>self.size-1</tt> times to compare elements;
5891 * returns a new 2-element \Array containing the minimum and maximum values
5892 * from +self+, per the block:
5893 * ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"]
5895 static VALUE
5896 rb_ary_minmax(VALUE ary)
5898 if (rb_block_given_p()) {
5899 return rb_call_super(0, NULL);
5901 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
5904 static int
5905 push_value(st_data_t key, st_data_t val, st_data_t ary)
5907 rb_ary_push((VALUE)ary, (VALUE)val);
5908 return ST_CONTINUE;
5912 * call-seq:
5913 * array.uniq! -> self or nil
5914 * array.uniq! {|element| ... } -> self or nil
5916 * Removes duplicate elements from +self+, the first occurrence always being retained;
5917 * returns +self+ if any elements removed, +nil+ otherwise.
5919 * With no block given, identifies and removes elements using method <tt>eql?</tt>
5920 * to compare.
5922 * Returns +self+ if any elements removed:
5923 * a = [0, 0, 1, 1, 2, 2]
5924 * a.uniq! # => [0, 1, 2]
5926 * Returns +nil+ if no elements removed.
5928 * With a block given, calls the block for each element;
5929 * identifies (using method <tt>eql?</tt>) and removes
5930 * elements for which the block returns duplicate values.
5932 * Returns +self+ if any elements removed:
5933 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
5934 * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
5936 * Returns +nil+ if no elements removed.
5938 static VALUE
5939 rb_ary_uniq_bang(VALUE ary)
5941 VALUE hash;
5942 long hash_size;
5944 rb_ary_modify_check(ary);
5945 if (RARRAY_LEN(ary) <= 1)
5946 return Qnil;
5947 if (rb_block_given_p())
5948 hash = ary_make_hash_by(ary);
5949 else
5950 hash = ary_make_hash(ary);
5952 hash_size = RHASH_SIZE(hash);
5953 if (RARRAY_LEN(ary) == hash_size) {
5954 return Qnil;
5956 rb_ary_modify_check(ary);
5957 ARY_SET_LEN(ary, 0);
5958 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
5959 rb_ary_unshare(ary);
5960 FL_SET_EMBED(ary);
5962 ary_resize_capa(ary, hash_size);
5963 rb_hash_foreach(hash, push_value, ary);
5964 ary_recycle_hash(hash);
5966 return ary;
5970 * call-seq:
5971 * array.uniq -> new_array
5972 * array.uniq {|element| ... } -> new_array
5974 * Returns a new \Array containing those elements from +self+ that are not duplicates,
5975 * the first occurrence always being retained.
5977 * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
5978 * to compare.
5979 * a = [0, 0, 1, 1, 2, 2]
5980 * a.uniq # => [0, 1, 2]
5982 * With a block given, calls the block for each element;
5983 * identifies (using method <tt>eql?</tt>) and omits duplicate values,
5984 * that is, those elements for which the block returns the same value:
5985 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
5986 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
5989 static VALUE
5990 rb_ary_uniq(VALUE ary)
5992 VALUE hash, uniq;
5994 if (RARRAY_LEN(ary) <= 1) {
5995 hash = 0;
5996 uniq = rb_ary_dup(ary);
5998 else if (rb_block_given_p()) {
5999 hash = ary_make_hash_by(ary);
6000 uniq = rb_hash_values(hash);
6002 else {
6003 hash = ary_make_hash(ary);
6004 uniq = rb_hash_values(hash);
6006 if (hash) {
6007 ary_recycle_hash(hash);
6010 return uniq;
6014 * call-seq:
6015 * array.compact! -> self or nil
6017 * Removes all +nil+ elements from +self+.
6019 * Returns +self+ if any elements removed, otherwise +nil+.
6022 static VALUE
6023 rb_ary_compact_bang(VALUE ary)
6025 VALUE *p, *t, *end;
6026 long n;
6028 rb_ary_modify(ary);
6029 p = t = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(ary); /* WB: no new reference */
6030 end = p + RARRAY_LEN(ary);
6032 while (t < end) {
6033 if (NIL_P(*t)) t++;
6034 else *p++ = *t++;
6036 n = p - RARRAY_CONST_PTR_TRANSIENT(ary);
6037 if (RARRAY_LEN(ary) == n) {
6038 return Qnil;
6040 ary_resize_smaller(ary, n);
6042 return ary;
6046 * call-seq:
6047 * array.compact -> new_array
6049 * Returns a new \Array containing all non-+nil+ elements from +self+:
6050 * a = [nil, 0, nil, 1, nil, 2, nil]
6051 * a.compact # => [0, 1, 2]
6054 static VALUE
6055 rb_ary_compact(VALUE ary)
6057 ary = rb_ary_dup(ary);
6058 rb_ary_compact_bang(ary);
6059 return ary;
6063 * call-seq:
6064 * array.count -> an_integer
6065 * array.count(obj) -> an_integer
6066 * array.count {|element| ... } -> an_integer
6068 * Returns a count of specified elements.
6070 * With no argument and no block, returns the count of all elements:
6071 * [0, 1, 2].count # => 3
6072 * [].count # => 0
6074 * With argument +obj+, returns the count of elements <tt>==</tt> to +obj+:
6075 * [0, 1, 2, 0.0].count(0) # => 2
6076 * [0, 1, 2].count(3) # => 0
6078 * With no argument and a block given, calls the block with each element;
6079 * returns the count of elements for which the block returns a truthy value:
6080 * [0, 1, 2, 3].count {|element| element > 1} # => 2
6082 * With argument +obj+ and a block given, issues a warning, ignores the block,
6083 * and returns the count of elements <tt>==</tt> to +obj+:
6086 static VALUE
6087 rb_ary_count(int argc, VALUE *argv, VALUE ary)
6089 long i, n = 0;
6091 if (rb_check_arity(argc, 0, 1) == 0) {
6092 VALUE v;
6094 if (!rb_block_given_p())
6095 return LONG2NUM(RARRAY_LEN(ary));
6097 for (i = 0; i < RARRAY_LEN(ary); i++) {
6098 v = RARRAY_AREF(ary, i);
6099 if (RTEST(rb_yield(v))) n++;
6102 else {
6103 VALUE obj = argv[0];
6105 if (rb_block_given_p()) {
6106 rb_warn("given block not used");
6108 for (i = 0; i < RARRAY_LEN(ary); i++) {
6109 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6113 return LONG2NUM(n);
6116 static VALUE
6117 flatten(VALUE ary, int level)
6119 long i;
6120 VALUE stack, result, tmp = 0, elt, vmemo;
6121 st_table *memo = 0;
6122 st_data_t id;
6124 for (i = 0; i < RARRAY_LEN(ary); i++) {
6125 elt = RARRAY_AREF(ary, i);
6126 tmp = rb_check_array_type(elt);
6127 if (!NIL_P(tmp)) {
6128 break;
6131 if (i == RARRAY_LEN(ary)) {
6132 return ary;
6135 result = ary_new(0, RARRAY_LEN(ary));
6136 ary_memcpy(result, 0, i, RARRAY_CONST_PTR_TRANSIENT(ary));
6137 ARY_SET_LEN(result, i);
6139 stack = ary_new(0, ARY_DEFAULT_SIZE);
6140 rb_ary_push(stack, ary);
6141 rb_ary_push(stack, LONG2NUM(i + 1));
6143 if (level < 0) {
6144 vmemo = rb_hash_new();
6145 RBASIC_CLEAR_CLASS(vmemo);
6146 memo = st_init_numtable();
6147 rb_hash_st_table_set(vmemo, memo);
6148 st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
6149 st_insert(memo, (st_data_t)tmp, (st_data_t)Qtrue);
6152 ary = tmp;
6153 i = 0;
6155 while (1) {
6156 while (i < RARRAY_LEN(ary)) {
6157 elt = RARRAY_AREF(ary, i++);
6158 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6159 rb_ary_push(result, elt);
6160 continue;
6162 tmp = rb_check_array_type(elt);
6163 if (RBASIC(result)->klass) {
6164 if (memo) {
6165 RB_GC_GUARD(vmemo);
6166 st_clear(memo);
6168 rb_raise(rb_eRuntimeError, "flatten reentered");
6170 if (NIL_P(tmp)) {
6171 rb_ary_push(result, elt);
6173 else {
6174 if (memo) {
6175 id = (st_data_t)tmp;
6176 if (st_is_member(memo, id)) {
6177 st_clear(memo);
6178 rb_raise(rb_eArgError, "tried to flatten recursive array");
6180 st_insert(memo, id, (st_data_t)Qtrue);
6182 rb_ary_push(stack, ary);
6183 rb_ary_push(stack, LONG2NUM(i));
6184 ary = tmp;
6185 i = 0;
6188 if (RARRAY_LEN(stack) == 0) {
6189 break;
6191 if (memo) {
6192 id = (st_data_t)ary;
6193 st_delete(memo, &id, 0);
6195 tmp = rb_ary_pop(stack);
6196 i = NUM2LONG(tmp);
6197 ary = rb_ary_pop(stack);
6200 if (memo) {
6201 st_clear(memo);
6204 RBASIC_SET_CLASS(result, rb_cArray);
6205 return result;
6209 * call-seq:
6210 * array.flatten! -> self or nil
6211 * array.flatten!(level) -> self or nil
6213 * Replaces each nested \Array in +self+ with the elements from that \Array;
6214 * returns +self+ if any changes, +nil+ otherwise.
6216 * With non-negative \Integer argument +level+, flattens recursively through +level+ levels:
6217 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6218 * a.flatten!(1) # => [0, 1, [2, 3], 4, 5]
6219 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6220 * a.flatten!(2) # => [0, 1, 2, 3, 4, 5]
6221 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6222 * a.flatten!(3) # => [0, 1, 2, 3, 4, 5]
6223 * [0, 1, 2].flatten!(1) # => nil
6225 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6226 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6227 * a.flatten! # => [0, 1, 2, 3, 4, 5]
6228 * [0, 1, 2].flatten! # => nil
6229 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6230 * a.flatten!(-1) # => [0, 1, 2, 3, 4, 5]
6231 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6232 * a.flatten!(-2) # => [0, 1, 2, 3, 4, 5]
6233 * [0, 1, 2].flatten!(-1) # => nil
6236 static VALUE
6237 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6239 int mod = 0, level = -1;
6240 VALUE result, lv;
6242 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6243 rb_ary_modify_check(ary);
6244 if (!NIL_P(lv)) level = NUM2INT(lv);
6245 if (level == 0) return Qnil;
6247 result = flatten(ary, level);
6248 if (result == ary) {
6249 return Qnil;
6251 if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
6252 rb_ary_replace(ary, result);
6253 if (mod) ARY_SET_EMBED_LEN(result, 0);
6255 return ary;
6259 * call-seq:
6260 * array.flatten -> new_array
6261 * array.flatten(level) -> new_array
6263 * Returns a new \Array that is a recursive flattening of +self+:
6264 * - Each non-Array element is unchanged.
6265 * - Each \Array is replaced by its individual elements.
6267 * With non-negative \Integer argument +level+, flattens recursively through +level+ levels:
6268 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6269 * a.flatten(0) # => [0, [1, [2, 3], 4], 5]
6270 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6271 * a.flatten(1) # => [0, 1, [2, 3], 4, 5]
6272 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6273 * a.flatten(2) # => [0, 1, 2, 3, 4, 5]
6274 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6275 * a.flatten(3) # => [0, 1, 2, 3, 4, 5]
6277 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6278 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6279 * a.flatten # => [0, 1, 2, 3, 4, 5]
6280 * [0, 1, 2].flatten # => [0, 1, 2]
6281 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6282 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5]
6283 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6284 * a.flatten(-2) # => [0, 1, 2, 3, 4, 5]
6285 * [0, 1, 2].flatten(-1) # => [0, 1, 2]
6288 static VALUE
6289 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6291 int level = -1;
6292 VALUE result;
6294 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6295 level = NUM2INT(argv[0]);
6296 if (level == 0) return ary_make_shared_copy(ary);
6299 result = flatten(ary, level);
6300 if (result == ary) {
6301 result = ary_make_shared_copy(ary);
6304 return result;
6307 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6309 static VALUE
6310 rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6312 long i, len;
6314 rb_ary_modify(ary);
6315 i = len = RARRAY_LEN(ary);
6316 RARRAY_PTR_USE(ary, ptr, {
6317 while (i) {
6318 long j = RAND_UPTO(i);
6319 VALUE tmp;
6320 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR_TRANSIENT(ary)) {
6321 rb_raise(rb_eRuntimeError, "modified during shuffle");
6323 tmp = ptr[--i];
6324 ptr[i] = ptr[j];
6325 ptr[j] = tmp;
6327 }); /* WB: no new reference */
6328 return ary;
6331 static VALUE
6332 rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6334 ary = rb_ary_dup(ary);
6335 rb_ary_shuffle_bang(ec, ary, randgen);
6336 return ary;
6339 static VALUE
6340 ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
6342 VALUE result;
6343 long n, len, i, j, k, idx[10];
6344 long rnds[numberof(idx)];
6345 long memo_threshold;
6347 len = RARRAY_LEN(ary);
6348 if (!to_array) {
6349 if (len < 2)
6350 i = 0;
6351 else
6352 i = RAND_UPTO(len);
6354 return rb_ary_elt(ary, i);
6356 n = NUM2LONG(nv);
6357 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
6358 if (n > len) n = len;
6359 if (n <= numberof(idx)) {
6360 for (i = 0; i < n; ++i) {
6361 rnds[i] = RAND_UPTO(len - i);
6364 k = len;
6365 len = RARRAY_LEN(ary);
6366 if (len < k && n <= numberof(idx)) {
6367 for (i = 0; i < n; ++i) {
6368 if (rnds[i] >= len) return rb_ary_new_capa(0);
6371 if (n > len) n = len;
6372 switch (n) {
6373 case 0:
6374 return rb_ary_new_capa(0);
6375 case 1:
6376 i = rnds[0];
6377 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
6378 case 2:
6379 i = rnds[0];
6380 j = rnds[1];
6381 if (j >= i) j++;
6382 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
6383 case 3:
6384 i = rnds[0];
6385 j = rnds[1];
6386 k = rnds[2];
6388 long l = j, g = i;
6389 if (j >= i) l = i, g = ++j;
6390 if (k >= l && (++k >= g)) ++k;
6392 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
6394 memo_threshold =
6395 len < 2560 ? len / 128 :
6396 len < 5120 ? len / 64 :
6397 len < 10240 ? len / 32 :
6398 len / 16;
6399 if (n <= numberof(idx)) {
6400 long sorted[numberof(idx)];
6401 sorted[0] = idx[0] = rnds[0];
6402 for (i=1; i<n; i++) {
6403 k = rnds[i];
6404 for (j = 0; j < i; ++j) {
6405 if (k < sorted[j]) break;
6406 ++k;
6408 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
6409 sorted[j] = idx[i] = k;
6411 result = rb_ary_new_capa(n);
6412 RARRAY_PTR_USE_TRANSIENT(result, ptr_result, {
6413 for (i=0; i<n; i++) {
6414 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
6418 else if (n <= memo_threshold / 2) {
6419 long max_idx = 0;
6420 #undef RUBY_UNTYPED_DATA_WARNING
6421 #define RUBY_UNTYPED_DATA_WARNING 0
6422 VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0);
6423 st_table *memo = st_init_numtable_with_size(n);
6424 DATA_PTR(vmemo) = memo;
6425 result = rb_ary_new_capa(n);
6426 RARRAY_PTR_USE(result, ptr_result, {
6427 for (i=0; i<n; i++) {
6428 long r = RAND_UPTO(len-i) + i;
6429 ptr_result[i] = r;
6430 if (r > max_idx) max_idx = r;
6432 len = RARRAY_LEN(ary);
6433 if (len <= max_idx) n = 0;
6434 else if (n > len) n = len;
6435 RARRAY_PTR_USE_TRANSIENT(ary, ptr_ary, {
6436 for (i=0; i<n; i++) {
6437 long j2 = j = ptr_result[i];
6438 long i2 = i;
6439 st_data_t value;
6440 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
6441 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
6442 st_insert(memo, (st_data_t)j, (st_data_t)i2);
6443 ptr_result[i] = ptr_ary[j2];
6447 DATA_PTR(vmemo) = 0;
6448 st_free_table(memo);
6450 else {
6451 result = rb_ary_dup(ary);
6452 RBASIC_CLEAR_CLASS(result);
6453 RB_GC_GUARD(ary);
6454 RARRAY_PTR_USE(result, ptr_result, {
6455 for (i=0; i<n; i++) {
6456 j = RAND_UPTO(len-i) + i;
6457 nv = ptr_result[j];
6458 ptr_result[j] = ptr_result[i];
6459 ptr_result[i] = nv;
6462 RBASIC_SET_CLASS_RAW(result, rb_cArray);
6464 ARY_SET_LEN(result, n);
6466 return result;
6469 static VALUE
6470 ary_sample0(rb_execution_context_t *ec, VALUE ary)
6472 return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
6475 static VALUE
6476 rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
6478 long mul;
6479 VALUE n = Qnil;
6480 if (args && (RARRAY_LEN(args) > 0)) {
6481 n = RARRAY_AREF(args, 0);
6483 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
6484 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
6485 mul = NUM2LONG(n);
6486 if (mul <= 0) return INT2FIX(0);
6487 n = LONG2FIX(mul);
6488 return rb_fix_mul_fix(rb_ary_length(self), n);
6492 * call-seq:
6493 * array.cycle {|element| ... } -> nil
6494 * array.cycle(count) {|element| ... } -> nil
6495 * array.cycle -> new_enumerator
6496 * array.cycle(count) -> new_enumerator
6498 * When called with positive \Integer argument +count+ and a block,
6499 * calls the block with each element, then does so again,
6500 * until it has done so +count+ times; returns +nil+:
6501 * output = []
6502 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6503 * output # => [0, 1, 0, 1]
6505 * If +count+ is zero or negative, does not call the block:
6506 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6507 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6509 * When a block is given, and argument is omitted or +nil+, cycles forever:
6510 * # Prints 0 and 1 forever.
6511 * [0, 1].cycle {|element| puts element }
6512 * [0, 1].cycle(nil) {|element| puts element }
6514 * When no block is given, returns a new \Enumerator:
6516 * [0, 1].cycle(2) # => #<Enumerator: [0, 1]:cycle(2)>
6517 * [0, 1].cycle # => # => #<Enumerator: [0, 1]:cycle>
6518 * [0, 1].cycle.first(5) # => [0, 1, 0, 1, 0]
6520 static VALUE
6521 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
6523 long n, i;
6525 rb_check_arity(argc, 0, 1);
6527 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
6528 if (argc == 0 || NIL_P(argv[0])) {
6529 n = -1;
6531 else {
6532 n = NUM2LONG(argv[0]);
6533 if (n <= 0) return Qnil;
6536 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
6537 for (i=0; i<RARRAY_LEN(ary); i++) {
6538 rb_yield(RARRAY_AREF(ary, i));
6541 return Qnil;
6544 #define tmpary(n) rb_ary_tmp_new(n)
6545 #define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
6548 * Build a ruby array of the corresponding values and yield it to the
6549 * associated block.
6550 * Return the class of +values+ for reentry check.
6552 static int
6553 yield_indexed_values(const VALUE values, const long r, const long *const p)
6555 const VALUE result = rb_ary_new2(r);
6556 long i;
6558 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
6559 ARY_SET_LEN(result, r);
6560 rb_yield(result);
6561 return !RBASIC(values)->klass;
6565 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6567 * When we have a complete permutation of array indices, copy the values
6568 * at those indices into a new array and yield that array.
6570 * n: the size of the set
6571 * r: the number of elements in each permutation
6572 * p: the array (of size r) that we're filling in
6573 * used: an array of booleans: whether a given index is already used
6574 * values: the Ruby array that holds the actual values to permute
6576 static void
6577 permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
6579 long i = 0, index = 0;
6581 for (;;) {
6582 const char *const unused = memchr(&used[i], 0, n-i);
6583 if (!unused) {
6584 if (!index) break;
6585 i = p[--index]; /* pop index */
6586 used[i++] = 0; /* index unused */
6588 else {
6589 i = unused - used;
6590 p[index] = i;
6591 used[i] = 1; /* mark index used */
6592 ++index;
6593 if (index < r-1) { /* if not done yet */
6594 p[index] = i = 0;
6595 continue;
6597 for (i = 0; i < n; ++i) {
6598 if (used[i]) continue;
6599 p[index] = i;
6600 if (!yield_indexed_values(values, r, p)) {
6601 rb_raise(rb_eRuntimeError, "permute reentered");
6604 i = p[--index]; /* pop index */
6605 used[i] = 0; /* index unused */
6606 p[index] = ++i;
6612 * Returns the product of from, from-1, ..., from - how_many + 1.
6613 * https://en.wikipedia.org/wiki/Pochhammer_symbol
6615 static VALUE
6616 descending_factorial(long from, long how_many)
6618 VALUE cnt;
6619 if (how_many > 0) {
6620 cnt = LONG2FIX(from);
6621 while (--how_many > 0) {
6622 long v = --from;
6623 cnt = rb_int_mul(cnt, LONG2FIX(v));
6626 else {
6627 cnt = LONG2FIX(how_many == 0);
6629 return cnt;
6632 static VALUE
6633 binomial_coefficient(long comb, long size)
6635 VALUE r;
6636 long i;
6637 if (comb > size-comb) {
6638 comb = size-comb;
6640 if (comb < 0) {
6641 return LONG2FIX(0);
6643 else if (comb == 0) {
6644 return LONG2FIX(1);
6646 r = LONG2FIX(size);
6647 for (i = 1; i < comb; ++i) {
6648 r = rb_int_mul(r, LONG2FIX(size - i));
6649 r = rb_int_idiv(r, LONG2FIX(i + 1));
6651 return r;
6654 static VALUE
6655 rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
6657 long n = RARRAY_LEN(ary);
6658 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
6660 return descending_factorial(n, k);
6664 * call-seq:
6665 * array.permutation {|element| ... } -> self
6666 * array.permutation(n) {|element| ... } -> self
6667 * array.permutation -> new_enumerator
6668 * array.permutation(n) -> new_enumerator
6670 * When invoked with a block, yield all permutations of elements of +self+; returns +self+.
6671 * The order of permutations is indeterminate.
6673 * When a block and an in-range positive \Integer argument +n+ (<tt>0 < n <= self.size</tt>)
6674 * are given, calls the block with all +n+-tuple permutations of +self+.
6676 * Example:
6677 * a = [0, 1, 2]
6678 * a.permutation(2) {|permutation| p permutation }
6679 * Output:
6680 * [0, 1]
6681 * [0, 2]
6682 * [1, 0]
6683 * [1, 2]
6684 * [2, 0]
6685 * [2, 1]
6686 * Another example:
6687 * a = [0, 1, 2]
6688 * a.permutation(3) {|permutation| p permutation }
6689 * Output:
6690 * [0, 1, 2]
6691 * [0, 2, 1]
6692 * [1, 0, 2]
6693 * [1, 2, 0]
6694 * [2, 0, 1]
6695 * [2, 1, 0]
6697 * When +n+ is zero, calls the block once with a new empty \Array:
6698 * a = [0, 1, 2]
6699 * a.permutation(0) {|permutation| p permutation }
6700 * Output:
6701 * []
6703 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
6704 * does not call the block:
6705 * a = [0, 1, 2]
6706 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
6707 * a.permutation(4) {|permutation| fail 'Cannot happen' }
6709 * When a block given but no argument,
6710 * behaves the same as <tt>a.permutation(a.size)</tt>:
6711 * a = [0, 1, 2]
6712 * a.permutation {|permutation| p permutation }
6713 * Output:
6714 * [0, 1, 2]
6715 * [0, 2, 1]
6716 * [1, 0, 2]
6717 * [1, 2, 0]
6718 * [2, 0, 1]
6719 * [2, 1, 0]
6721 * Returns a new \Enumerator if no block given:
6722 * a = [0, 1, 2]
6723 * a.permutation # => #<Enumerator: [0, 1, 2]:permutation>
6724 * a.permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
6727 static VALUE
6728 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
6730 long r, n, i;
6732 n = RARRAY_LEN(ary); /* Array length */
6733 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
6734 r = n;
6735 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
6736 r = NUM2LONG(argv[0]); /* Permutation size from argument */
6738 if (r < 0 || n < r) {
6739 /* no permutations: yield nothing */
6741 else if (r == 0) { /* exactly one permutation: the zero-length array */
6742 rb_yield(rb_ary_new2(0));
6744 else if (r == 1) { /* this is a special, easy case */
6745 for (i = 0; i < RARRAY_LEN(ary); i++) {
6746 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
6749 else { /* this is the general case */
6750 volatile VALUE t0;
6751 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
6752 char *used = (char*)(p + r);
6753 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
6754 RBASIC_CLEAR_CLASS(ary0);
6756 MEMZERO(used, char, n); /* initialize array */
6758 permute0(n, r, p, used, ary0); /* compute and yield permutations */
6759 ALLOCV_END(t0);
6760 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
6762 return ary;
6765 static void
6766 combinate0(const long len, const long n, long *const stack, const VALUE values)
6768 long lev = 0;
6770 MEMZERO(stack+1, long, n);
6771 stack[0] = -1;
6772 for (;;) {
6773 for (lev++; lev < n; lev++) {
6774 stack[lev+1] = stack[lev]+1;
6776 if (!yield_indexed_values(values, n, stack+1)) {
6777 rb_raise(rb_eRuntimeError, "combination reentered");
6779 do {
6780 if (lev == 0) return;
6781 stack[lev--]++;
6782 } while (stack[lev+1]+n == len+lev+1);
6786 static VALUE
6787 rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
6789 long n = RARRAY_LEN(ary);
6790 long k = NUM2LONG(RARRAY_AREF(args, 0));
6792 return binomial_coefficient(k, n);
6796 * call-seq:
6797 * array.combination(n) {|element| ... } -> self
6798 * array.combination(n) -> new_enumerator
6800 * Calls the block, if given, with combinations of elements of +self+;
6801 * returns +self+. The order of combinations is indeterminate.
6803 * When a block and an in-range positive \Integer argument +n+ (<tt>0 < n <= self.size</tt>)
6804 * are given, calls the block with all +n+-tuple combinations of +self+.
6806 * Example:
6807 * a = [0, 1, 2]
6808 * a.combination(2) {|combination| p combination }
6809 * Output:
6810 * [0, 1]
6811 * [0, 2]
6812 * [1, 2]
6814 * Another example:
6815 * a = [0, 1, 2]
6816 * a.combination(3) {|combination| p combination }
6817 * Output:
6818 * [0, 1, 2]
6820 * When +n+ is zero, calls the block once with a new empty \Array:
6821 * a = [0, 1, 2]
6822 * a1 = a.combination(0) {|combination| p combination }
6823 * Output:
6824 * []
6826 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
6827 * does not call the block:
6828 * a = [0, 1, 2]
6829 * a.combination(-1) {|combination| fail 'Cannot happen' }
6830 * a.combination(4) {|combination| fail 'Cannot happen' }
6832 * Returns a new \Enumerator if no block given:
6833 * a = [0, 1, 2]
6834 * a.combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
6837 static VALUE
6838 rb_ary_combination(VALUE ary, VALUE num)
6840 long i, n, len;
6842 n = NUM2LONG(num);
6843 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
6844 len = RARRAY_LEN(ary);
6845 if (n < 0 || len < n) {
6846 /* yield nothing */
6848 else if (n == 0) {
6849 rb_yield(rb_ary_new2(0));
6851 else if (n == 1) {
6852 for (i = 0; i < RARRAY_LEN(ary); i++) {
6853 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
6856 else {
6857 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
6858 volatile VALUE t0;
6859 long *stack = ALLOCV_N(long, t0, n+1);
6861 RBASIC_CLEAR_CLASS(ary0);
6862 combinate0(len, n, stack, ary0);
6863 ALLOCV_END(t0);
6864 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
6866 return ary;
6870 * Compute repeated permutations of +r+ elements of the set
6871 * <code>[0..n-1]</code>.
6873 * When we have a complete repeated permutation of array indices, copy the
6874 * values at those indices into a new array and yield that array.
6876 * n: the size of the set
6877 * r: the number of elements in each permutation
6878 * p: the array (of size r) that we're filling in
6879 * values: the Ruby array that holds the actual values to permute
6881 static void
6882 rpermute0(const long n, const long r, long *const p, const VALUE values)
6884 long i = 0, index = 0;
6886 p[index] = i;
6887 for (;;) {
6888 if (++index < r-1) {
6889 p[index] = i = 0;
6890 continue;
6892 for (i = 0; i < n; ++i) {
6893 p[index] = i;
6894 if (!yield_indexed_values(values, r, p)) {
6895 rb_raise(rb_eRuntimeError, "repeated permute reentered");
6898 do {
6899 if (index <= 0) return;
6900 } while ((i = ++p[--index]) >= n);
6904 static VALUE
6905 rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
6907 long n = RARRAY_LEN(ary);
6908 long k = NUM2LONG(RARRAY_AREF(args, 0));
6910 if (k < 0) {
6911 return LONG2FIX(0);
6913 if (n <= 0) {
6914 return LONG2FIX(!k);
6916 return rb_int_positive_pow(n, (unsigned long)k);
6920 * call-seq:
6921 * array.repeated_permutation(n) {|permutation| ... } -> self
6922 * array.repeated_permutation(n) -> new_enumerator
6924 * Calls the block with each repeated permutation of length +n+ of the elements of +self+;
6925 * each permutation is an \Array;
6926 * returns +self+. The order of the permutations is indeterminate.
6928 * When a block and a positive \Integer argument +n+ are given, calls the block with each
6929 * +n+-tuple repeated permutation of the elements of +self+.
6930 * The number of permutations is <tt>self.size**n</tt>.
6932 * +n+ = 1:
6933 * a = [0, 1, 2]
6934 * a.repeated_permutation(1) {|permutation| p permutation }
6935 * Output:
6936 * [0]
6937 * [1]
6938 * [2]
6940 * +n+ = 2:
6941 * a.repeated_permutation(2) {|permutation| p permutation }
6942 * Output:
6943 * [0, 0]
6944 * [0, 1]
6945 * [0, 2]
6946 * [1, 0]
6947 * [1, 1]
6948 * [1, 2]
6949 * [2, 0]
6950 * [2, 1]
6951 * [2, 2]
6953 * If +n+ is zero, calls the block once with an empty \Array.
6955 * If +n+ is negative, does not call the block:
6956 * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
6958 * Returns a new \Enumerator if no block given:
6959 * a = [0, 1, 2]
6960 * a.repeated_permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
6962 * Using Enumerators, it's convenient to show the permutations and counts
6963 * for some values of +n+:
6964 * e = a.repeated_permutation(0)
6965 * e.size # => 1
6966 * e.to_a # => [[]]
6967 * e = a.repeated_permutation(1)
6968 * e.size # => 3
6969 * e.to_a # => [[0], [1], [2]]
6970 * e = a.repeated_permutation(2)
6971 * e.size # => 9
6972 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
6974 static VALUE
6975 rb_ary_repeated_permutation(VALUE ary, VALUE num)
6977 long r, n, i;
6979 n = RARRAY_LEN(ary); /* Array length */
6980 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
6981 r = NUM2LONG(num); /* Permutation size from argument */
6983 if (r < 0) {
6984 /* no permutations: yield nothing */
6986 else if (r == 0) { /* exactly one permutation: the zero-length array */
6987 rb_yield(rb_ary_new2(0));
6989 else if (r == 1) { /* this is a special, easy case */
6990 for (i = 0; i < RARRAY_LEN(ary); i++) {
6991 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
6994 else { /* this is the general case */
6995 volatile VALUE t0;
6996 long *p = ALLOCV_N(long, t0, r);
6997 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
6998 RBASIC_CLEAR_CLASS(ary0);
7000 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7001 ALLOCV_END(t0);
7002 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7004 return ary;
7007 static void
7008 rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
7010 long i = 0, index = 0;
7012 p[index] = i;
7013 for (;;) {
7014 if (++index < r-1) {
7015 p[index] = i;
7016 continue;
7018 for (; i < n; ++i) {
7019 p[index] = i;
7020 if (!yield_indexed_values(values, r, p)) {
7021 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7024 do {
7025 if (index <= 0) return;
7026 } while ((i = ++p[--index]) >= n);
7030 static VALUE
7031 rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7033 long n = RARRAY_LEN(ary);
7034 long k = NUM2LONG(RARRAY_AREF(args, 0));
7035 if (k == 0) {
7036 return LONG2FIX(1);
7038 return binomial_coefficient(k, n + k - 1);
7042 * call-seq:
7043 * array.repeated_combination(n) {|combination| ... } -> self
7044 * array.repeated_combination(n) -> new_enumerator
7046 * Calls the block with each repeated combination of length +n+ of the elements of +self+;
7047 * each combination is an \Array;
7048 * returns +self+. The order of the combinations is indeterminate.
7050 * When a block and a positive \Integer argument +n+ are given, calls the block with each
7051 * +n+-tuple repeated combination of the elements of +self+.
7052 * The number of combinations is <tt>(n+1)(n+2)/2</tt>.
7054 * +n+ = 1:
7055 * a = [0, 1, 2]
7056 * a.repeated_combination(1) {|combination| p combination }
7057 * Output:
7058 * [0]
7059 * [1]
7060 * [2]
7062 * +n+ = 2:
7063 * a.repeated_combination(2) {|combination| p combination }
7064 * Output:
7065 * [0, 0]
7066 * [0, 1]
7067 * [0, 2]
7068 * [1, 1]
7069 * [1, 2]
7070 * [2, 2]
7072 * If +n+ is zero, calls the block once with an empty \Array.
7074 * If +n+ is negative, does not call the block:
7075 * a.repeated_combination(-1) {|combination| fail 'Cannot happen' }
7077 * Returns a new \Enumerator if no block given:
7078 * a = [0, 1, 2]
7079 * a.repeated_combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
7081 * Using Enumerators, it's convenient to show the combinations and counts
7082 * for some values of +n+:
7083 * e = a.repeated_combination(0)
7084 * e.size # => 1
7085 * e.to_a # => [[]]
7086 * e = a.repeated_combination(1)
7087 * e.size # => 3
7088 * e.to_a # => [[0], [1], [2]]
7089 * e = a.repeated_combination(2)
7090 * e.size # => 6
7091 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7094 static VALUE
7095 rb_ary_repeated_combination(VALUE ary, VALUE num)
7097 long n, i, len;
7099 n = NUM2LONG(num); /* Combination size from argument */
7100 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7101 len = RARRAY_LEN(ary);
7102 if (n < 0) {
7103 /* yield nothing */
7105 else if (n == 0) {
7106 rb_yield(rb_ary_new2(0));
7108 else if (n == 1) {
7109 for (i = 0; i < RARRAY_LEN(ary); i++) {
7110 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7113 else if (len == 0) {
7114 /* yield nothing */
7116 else {
7117 volatile VALUE t0;
7118 long *p = ALLOCV_N(long, t0, n);
7119 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7120 RBASIC_CLEAR_CLASS(ary0);
7122 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7123 ALLOCV_END(t0);
7124 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7126 return ary;
7130 * call-seq:
7131 * array.product(*other_arrays) -> new_array
7132 * array.product(*other_arrays) {|combination| ... } -> self
7134 * Computes and returns or yields all combinations of elements from all the Arrays,
7135 * including both +self+ and +other_arrays+.
7136 * - The number of combinations is the product of the sizes of all the arrays,
7137 * including both +self+ and +other_arrays+.
7138 * - The order of the returned combinations is indeterminate.
7140 * When no block is given, returns the combinations as an \Array of Arrays:
7141 * a = [0, 1, 2]
7142 * a1 = [3, 4]
7143 * a2 = [5, 6]
7144 * p = a.product(a1)
7145 * p.size # => 6 # a.size * a1.size
7146 * p # => [[0, 3], [0, 4], [1, 3], [1, 4], [2, 3], [2, 4]]
7147 * p = a.product(a1, a2)
7148 * p.size # => 12 # a.size * a1.size * a2.size
7149 * p # => [[0, 3, 5], [0, 3, 6], [0, 4, 5], [0, 4, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
7151 * If any argument is an empty \Array, returns an empty \Array.
7153 * If no argument is given, returns an \Array of 1-element Arrays,
7154 * each containing an element of +self+:
7155 * a.product # => [[0], [1], [2]]
7157 * When a block is given, yields each combination as an \Array; returns +self+:
7158 * a.product(a1) {|combination| p combination }
7159 * Output:
7160 * [0, 3]
7161 * [0, 4]
7162 * [1, 3]
7163 * [1, 4]
7164 * [2, 3]
7165 * [2, 4]
7167 * If any argument is an empty \Array, does not call the block:
7168 * a.product(a1, a2, []) {|combination| fail 'Cannot happen' }
7170 * If no argument is given, yields each element of +self+ as a 1-element \Array:
7171 * a.product {|combination| p combination }
7172 * Output:
7173 * [0]
7174 * [1]
7175 * [2]
7178 static VALUE
7179 rb_ary_product(int argc, VALUE *argv, VALUE ary)
7181 int n = argc+1; /* How many arrays we're operating on */
7182 volatile VALUE t0 = tmpary(n);
7183 volatile VALUE t1 = Qundef;
7184 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7185 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
7186 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7187 long i,j;
7188 long resultlen = 1;
7190 RBASIC_CLEAR_CLASS(t0);
7192 /* initialize the arrays of arrays */
7193 ARY_SET_LEN(t0, n);
7194 arrays[0] = ary;
7195 for (i = 1; i < n; i++) arrays[i] = Qnil;
7196 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7198 /* initialize the counters for the arrays */
7199 for (i = 0; i < n; i++) counters[i] = 0;
7201 /* Otherwise, allocate and fill in an array of results */
7202 if (rb_block_given_p()) {
7203 /* Make defensive copies of arrays; exit if any is empty */
7204 for (i = 0; i < n; i++) {
7205 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7206 arrays[i] = ary_make_shared_copy(arrays[i]);
7209 else {
7210 /* Compute the length of the result array; return [] if any is empty */
7211 for (i = 0; i < n; i++) {
7212 long k = RARRAY_LEN(arrays[i]);
7213 if (k == 0) {
7214 result = rb_ary_new2(0);
7215 goto done;
7217 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7218 rb_raise(rb_eRangeError, "too big to product");
7219 resultlen *= k;
7221 result = rb_ary_new2(resultlen);
7223 for (;;) {
7224 int m;
7225 /* fill in one subarray */
7226 VALUE subarray = rb_ary_new2(n);
7227 for (j = 0; j < n; j++) {
7228 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7231 /* put it on the result array */
7232 if (NIL_P(result)) {
7233 FL_SET(t0, FL_USER5);
7234 rb_yield(subarray);
7235 if (! FL_TEST(t0, FL_USER5)) {
7236 rb_raise(rb_eRuntimeError, "product reentered");
7238 else {
7239 FL_UNSET(t0, FL_USER5);
7242 else {
7243 rb_ary_push(result, subarray);
7247 * Increment the last counter. If it overflows, reset to 0
7248 * and increment the one before it.
7250 m = n-1;
7251 counters[m]++;
7252 while (counters[m] == RARRAY_LEN(arrays[m])) {
7253 counters[m] = 0;
7254 /* If the first counter overflows, we are done */
7255 if (--m < 0) goto done;
7256 counters[m]++;
7259 done:
7260 tmpary_discard(t0);
7261 ALLOCV_END(t1);
7263 return NIL_P(result) ? ary : result;
7267 * call-seq:
7268 * array.take(n) -> new_array
7270 * Returns a new \Array containing the first +n+ element of +self+,
7271 * where +n+ is a non-negative \Integer;
7272 * does not modify +self+.
7274 * Examples:
7275 * a = [0, 1, 2, 3, 4, 5]
7276 * a.take(1) # => [0]
7277 * a.take(2) # => [0, 1]
7278 * a.take(50) # => [0, 1, 2, 3, 4, 5]
7279 * a # => [0, 1, 2, 3, 4, 5]
7282 static VALUE
7283 rb_ary_take(VALUE obj, VALUE n)
7285 long len = NUM2LONG(n);
7286 if (len < 0) {
7287 rb_raise(rb_eArgError, "attempt to take negative size");
7289 return rb_ary_subseq(obj, 0, len);
7293 * call-seq:
7294 * array.take_while {|element| ... } -> new_array
7295 * array.take_while -> new_enumerator
7297 * Returns a new \Array containing zero or more leading elements of +self+;
7298 * does not modify +self+.
7300 * With a block given, calls the block with each successive element of +self+;
7301 * stops if the block returns +false+ or +nil+;
7302 * returns a new Array containing those elements for which the block returned a truthy value:
7303 * a = [0, 1, 2, 3, 4, 5]
7304 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7305 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7306 * a # => [0, 1, 2, 3, 4, 5]
7308 * With no block given, returns a new \Enumerator:
7309 * [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
7312 static VALUE
7313 rb_ary_take_while(VALUE ary)
7315 long i;
7317 RETURN_ENUMERATOR(ary, 0, 0);
7318 for (i = 0; i < RARRAY_LEN(ary); i++) {
7319 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7321 return rb_ary_take(ary, LONG2FIX(i));
7325 * call-seq:
7326 * array.drop(n) -> new_array
7328 * Returns a new \Array containing all but the first +n+ element of +self+,
7329 * where +n+ is a non-negative \Integer;
7330 * does not modify +self+.
7332 * Examples:
7333 * a = [0, 1, 2, 3, 4, 5]
7334 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7335 * a.drop(1) # => [1, 2, 3, 4, 5]
7336 * a.drop(2) # => [2, 3, 4, 5]
7339 static VALUE
7340 rb_ary_drop(VALUE ary, VALUE n)
7342 VALUE result;
7343 long pos = NUM2LONG(n);
7344 if (pos < 0) {
7345 rb_raise(rb_eArgError, "attempt to drop negative size");
7348 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
7349 if (NIL_P(result)) result = rb_ary_new();
7350 return result;
7354 * call-seq:
7355 * array.drop_while {|element| ... } -> new_array
7356 * array.drop_while -> new_enumerator
7358 * Returns a new \Array containing zero or more trailing elements of +self+;
7359 * does not modify +self+.
7361 * With a block given, calls the block with each successive element of +self+;
7362 * stops if the block returns +false+ or +nil+;
7363 * returns a new Array _omitting_ those elements for which the block returned a truthy value:
7364 * a = [0, 1, 2, 3, 4, 5]
7365 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7367 * With no block given, returns a new \Enumerator:
7368 * [0, 1].drop_while # => # => #<Enumerator: [0, 1]:drop_while>
7371 static VALUE
7372 rb_ary_drop_while(VALUE ary)
7374 long i;
7376 RETURN_ENUMERATOR(ary, 0, 0);
7377 for (i = 0; i < RARRAY_LEN(ary); i++) {
7378 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7380 return rb_ary_drop(ary, LONG2FIX(i));
7384 * call-seq:
7385 * array.any? -> true or false
7386 * array.any? {|element| ... } -> true or false
7387 * array.any?(obj) -> true or false
7389 * Returns +true+ if any element of +self+ meets a given criterion.
7391 * With no block given and no argument, returns +true+ if +self+ has any truthy element,
7392 * +false+ otherwise:
7393 * [nil, 0, false].any? # => true
7394 * [nil, false].any? # => false
7395 * [].any? # => false
7397 * With a block given and no argument, calls the block with each element in +self+;
7398 * returns +true+ if the block returns any truthy value, +false+ otherwise:
7399 * [0, 1, 2].any? {|element| element > 1 } # => true
7400 * [0, 1, 2].any? {|element| element > 2 } # => false
7402 * If argument +obj+ is given, returns +true+ if +obj+.<tt>===</tt> any element,
7403 * +false+ otherwise:
7404 * ['food', 'drink'].any?(/foo/) # => true
7405 * ['food', 'drink'].any?(/bar/) # => false
7406 * [].any?(/foo/) # => false
7407 * [0, 1, 2].any?(1) # => true
7408 * [0, 1, 2].any?(3) # => false
7410 * Related: Enumerable#any?
7413 static VALUE
7414 rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
7416 long i, len = RARRAY_LEN(ary);
7418 rb_check_arity(argc, 0, 1);
7419 if (!len) return Qfalse;
7420 if (argc) {
7421 if (rb_block_given_p()) {
7422 rb_warn("given block not used");
7424 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7425 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
7428 else if (!rb_block_given_p()) {
7429 for (i = 0; i < len; ++i) {
7430 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
7433 else {
7434 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7435 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
7438 return Qfalse;
7442 * call-seq:
7443 * array.all? -> true or false
7444 * array.all? {|element| ... } -> true or false
7445 * array.all?(obj) -> true or false
7447 * Returns +true+ if all elements of +self+ meet a given criterion.
7449 * With no block given and no argument, returns +true+ if +self+ contains only truthy elements,
7450 * +false+ otherwise:
7451 * [0, 1, :foo].all? # => true
7452 * [0, nil, 2].all? # => false
7453 * [].all? # => true
7455 * With a block given and no argument, calls the block with each element in +self+;
7456 * returns +true+ if the block returns only truthy values, +false+ otherwise:
7457 * [0, 1, 2].all? { |element| element < 3 } # => true
7458 * [0, 1, 2].all? { |element| element < 2 } # => false
7460 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> every element, +false+ otherwise:
7461 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7462 * ['food', 'drink'].all?(/bar/) # => false
7463 * [].all?(/foo/) # => true
7464 * [0, 0, 0].all?(0) # => true
7465 * [0, 1, 2].all?(1) # => false
7467 * Related: Enumerable#all?
7470 static VALUE
7471 rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
7473 long i, len = RARRAY_LEN(ary);
7475 rb_check_arity(argc, 0, 1);
7476 if (!len) return Qtrue;
7477 if (argc) {
7478 if (rb_block_given_p()) {
7479 rb_warn("given block not used");
7481 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7482 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7485 else if (!rb_block_given_p()) {
7486 for (i = 0; i < len; ++i) {
7487 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7490 else {
7491 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7492 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7495 return Qtrue;
7499 * call-seq:
7500 * array.none? -> true or false
7501 * array.none? {|element| ... } -> true or false
7502 * array.none?(obj) -> true or false
7504 * Returns +true+ if no element of +self+ meet a given criterion.
7506 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7507 * +false+ otherwise:
7508 * [nil, false].none? # => true
7509 * [nil, 0, false].none? # => false
7510 * [].none? # => true
7512 * With a block given and no argument, calls the block with each element in +self+;
7513 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7514 * [0, 1, 2].none? {|element| element > 3 } # => true
7515 * [0, 1, 2].none? {|element| element > 1 } # => false
7517 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> no element, +false+ otherwise:
7518 * ['food', 'drink'].none?(/bar/) # => true
7519 * ['food', 'drink'].none?(/foo/) # => false
7520 * [].none?(/foo/) # => true
7521 * [0, 1, 2].none?(3) # => true
7522 * [0, 1, 2].none?(1) # => false
7524 * Related: Enumerable#none?
7527 static VALUE
7528 rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
7530 long i, len = RARRAY_LEN(ary);
7532 rb_check_arity(argc, 0, 1);
7533 if (!len) return Qtrue;
7534 if (argc) {
7535 if (rb_block_given_p()) {
7536 rb_warn("given block not used");
7538 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7539 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7542 else if (!rb_block_given_p()) {
7543 for (i = 0; i < len; ++i) {
7544 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7547 else {
7548 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7549 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7552 return Qtrue;
7556 * call-seq:
7557 * array.one? -> true or false
7558 * array.one? {|element| ... } -> true or false
7559 * array.one?(obj) -> true or false
7561 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7563 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7564 * +false+ otherwise:
7565 * [nil, 0].one? # => true
7566 * [0, 0].one? # => false
7567 * [nil, nil].one? # => false
7568 * [].one? # => false
7570 * With a block given and no argument, calls the block with each element in +self+;
7571 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7572 * [0, 1, 2].one? {|element| element > 0 } # => false
7573 * [0, 1, 2].one? {|element| element > 1 } # => true
7574 * [0, 1, 2].one? {|element| element > 2 } # => false
7576 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> exactly one element,
7577 * +false+ otherwise:
7578 * [0, 1, 2].one?(0) # => true
7579 * [0, 0, 1].one?(0) # => false
7580 * [1, 1, 2].one?(0) # => false
7581 * ['food', 'drink'].one?(/bar/) # => false
7582 * ['food', 'drink'].one?(/foo/) # => true
7583 * [].one?(/foo/) # => false
7585 * Related: Enumerable#one?
7588 static VALUE
7589 rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
7591 long i, len = RARRAY_LEN(ary);
7592 VALUE result = Qfalse;
7594 rb_check_arity(argc, 0, 1);
7595 if (!len) return Qfalse;
7596 if (argc) {
7597 if (rb_block_given_p()) {
7598 rb_warn("given block not used");
7600 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7601 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
7602 if (result) return Qfalse;
7603 result = Qtrue;
7607 else if (!rb_block_given_p()) {
7608 for (i = 0; i < len; ++i) {
7609 if (RTEST(RARRAY_AREF(ary, i))) {
7610 if (result) return Qfalse;
7611 result = Qtrue;
7615 else {
7616 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7617 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
7618 if (result) return Qfalse;
7619 result = Qtrue;
7623 return result;
7627 * call-seq:
7628 * array.dig(index, *identifiers) -> object
7630 * Finds and returns the object in nested objects
7631 * that is specified by +index+ and +identifiers+.
7632 * The nested objects may be instances of various classes.
7633 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
7635 * Examples:
7636 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
7637 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
7638 * a.dig(1, 2) # => [:bat, :bam]
7639 * a.dig(1, 2, 0) # => :bat
7640 * a.dig(1, 2, 3) # => nil
7643 static VALUE
7644 rb_ary_dig(int argc, VALUE *argv, VALUE self)
7646 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
7647 self = rb_ary_at(self, *argv);
7648 if (!--argc) return self;
7649 ++argv;
7650 return rb_obj_dig(argc, argv, self, Qnil);
7653 static inline VALUE
7654 finish_exact_sum(long n, VALUE r, VALUE v, int z)
7656 if (n != 0)
7657 v = rb_fix_plus(LONG2FIX(n), v);
7658 if (r != Qundef) {
7659 v = rb_rational_plus(r, v);
7661 else if (!n && z) {
7662 v = rb_fix_plus(LONG2FIX(0), v);
7664 return v;
7668 * call-seq:
7669 * array.sum(init = 0) -> object
7670 * array.sum(init = 0) {|element| ... } -> object
7672 * When no block is given, returns the object equivalent to:
7673 * sum = init
7674 * array.each {|element| sum += element }
7675 * sum
7676 * For example, <tt>[e1, e2, e3].sum</tt> returns <tt>init + e1 + e2 + e3</tt>.
7678 * Examples:
7679 * a = [0, 1, 2, 3]
7680 * a.sum # => 6
7681 * a.sum(100) # => 106
7683 * The elements need not be numeric, but must be <tt>+</tt>-compatible
7684 * with each other and with +init+:
7685 * a = ['abc', 'def', 'ghi']
7686 * a.sum('jkl') # => "jklabcdefghi"
7688 * When a block is given, it is called with each element
7689 * and the block's return value (instead of the element itself) is used as the addend:
7690 * a = ['zero', 1, :two]
7691 * s = a.sum('Coerced and concatenated: ') {|element| element.to_s }
7692 * s # => "Coerced and concatenated: zero1two"
7694 * Notes:
7695 * - Array#join and Array#flatten may be faster than Array#sum
7696 * for an \Array of Strings or an \Array of Arrays.
7697 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
7700 static VALUE
7701 rb_ary_sum(int argc, VALUE *argv, VALUE ary)
7703 VALUE e, v, r;
7704 long i, n;
7705 int block_given;
7707 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
7709 block_given = rb_block_given_p();
7711 if (RARRAY_LEN(ary) == 0)
7712 return v;
7714 n = 0;
7715 r = Qundef;
7716 for (i = 0; i < RARRAY_LEN(ary); i++) {
7717 e = RARRAY_AREF(ary, i);
7718 if (block_given)
7719 e = rb_yield(e);
7720 if (FIXNUM_P(e)) {
7721 n += FIX2LONG(e); /* should not overflow long type */
7722 if (!FIXABLE(n)) {
7723 v = rb_big_plus(LONG2NUM(n), v);
7724 n = 0;
7727 else if (RB_BIGNUM_TYPE_P(e))
7728 v = rb_big_plus(e, v);
7729 else if (RB_TYPE_P(e, T_RATIONAL)) {
7730 if (r == Qundef)
7731 r = e;
7732 else
7733 r = rb_rational_plus(r, e);
7735 else
7736 goto not_exact;
7738 v = finish_exact_sum(n, r, v, argc!=0);
7739 return v;
7741 not_exact:
7742 v = finish_exact_sum(n, r, v, i!=0);
7744 if (RB_FLOAT_TYPE_P(e)) {
7746 * Kahan-Babuska balancing compensated summation algorithm
7747 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
7749 double f, c;
7750 double x, t;
7752 f = NUM2DBL(v);
7753 c = 0.0;
7754 goto has_float_value;
7755 for (; i < RARRAY_LEN(ary); i++) {
7756 e = RARRAY_AREF(ary, i);
7757 if (block_given)
7758 e = rb_yield(e);
7759 if (RB_FLOAT_TYPE_P(e))
7760 has_float_value:
7761 x = RFLOAT_VALUE(e);
7762 else if (FIXNUM_P(e))
7763 x = FIX2LONG(e);
7764 else if (RB_BIGNUM_TYPE_P(e))
7765 x = rb_big2dbl(e);
7766 else if (RB_TYPE_P(e, T_RATIONAL))
7767 x = rb_num2dbl(e);
7768 else
7769 goto not_float;
7771 if (isnan(f)) continue;
7772 if (isnan(x)) {
7773 f = x;
7774 continue;
7776 if (isinf(x)) {
7777 if (isinf(f) && signbit(x) != signbit(f))
7778 f = NAN;
7779 else
7780 f = x;
7781 continue;
7783 if (isinf(f)) continue;
7785 t = f + x;
7786 if (fabs(f) >= fabs(x))
7787 c += ((f - t) + x);
7788 else
7789 c += ((x - t) + f);
7790 f = t;
7792 f += c;
7793 return DBL2NUM(f);
7795 not_float:
7796 v = DBL2NUM(f);
7799 goto has_some_value;
7800 for (; i < RARRAY_LEN(ary); i++) {
7801 e = RARRAY_AREF(ary, i);
7802 if (block_given)
7803 e = rb_yield(e);
7804 has_some_value:
7805 v = rb_funcall(v, idPLUS, 1, e);
7807 return v;
7810 static VALUE
7811 rb_ary_deconstruct(VALUE ary)
7813 return ary;
7817 * An \Array is an ordered, integer-indexed collection of objects,
7818 * called _elements_. Any object may be an \Array element.
7820 * == \Array Indexes
7822 * \Array indexing starts at 0, as in C or Java.
7824 * A positive index is an offset from the first element:
7825 * - Index 0 indicates the first element.
7826 * - Index 1 indicates the second element.
7827 * - ...
7829 * A negative index is an offset, backwards, from the end of the array:
7830 * - Index -1 indicates the last element.
7831 * - Index -2 indicates the next-to-last element.
7832 * - ...
7834 * A non-negative index is <i>in range</i> if it is smaller than
7835 * the size of the array. For a 3-element array:
7836 * - Indexes 0 through 2 are in range.
7837 * - Index 3 is out of range.
7839 * A negative index is <i>in range</i> if its absolute value is
7840 * not larger than the size of the array. For a 3-element array:
7841 * - Indexes -1 through -3 are in range.
7842 * - Index -4 is out of range.
7844 * == Creating Arrays
7846 * You can create an \Array object explicitly with:
7848 * - An {array literal}[doc/syntax/literals_rdoc.html#label-Array+Literals].
7850 * You can convert certain objects to Arrays with:
7852 * - \Method {Array}[Kernel.html#method-i-Array].
7854 * An \Array can contain different types of objects. For
7855 * example, the array below contains an Integer, a String and a Float:
7857 * ary = [1, "two", 3.0] #=> [1, "two", 3.0]
7859 * An array can also be created by calling Array.new with zero, one
7860 * (the initial size of the Array) or two arguments (the initial size and a
7861 * default object).
7863 * ary = Array.new #=> []
7864 * Array.new(3) #=> [nil, nil, nil]
7865 * Array.new(3, true) #=> [true, true, true]
7867 * Note that the second argument populates the array with references to the
7868 * same object. Therefore, it is only recommended in cases when you need to
7869 * instantiate arrays with natively immutable objects such as Symbols,
7870 * numbers, true or false.
7872 * To create an array with separate objects a block can be passed instead.
7873 * This method is safe to use with mutable objects such as hashes, strings or
7874 * other arrays:
7876 * Array.new(4) {Hash.new} #=> [{}, {}, {}, {}]
7877 * Array.new(4) {|i| i.to_s } #=> ["0", "1", "2", "3"]
7879 * This is also a quick way to build up multi-dimensional arrays:
7881 * empty_table = Array.new(3) {Array.new(3)}
7882 * #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
7884 * An array can also be created by using the Array() method, provided by
7885 * Kernel, which tries to call #to_ary, then #to_a on its argument.
7887 * Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]
7889 * == Example Usage
7891 * In addition to the methods it mixes in through the Enumerable module, the
7892 * Array class has proprietary methods for accessing, searching and otherwise
7893 * manipulating arrays.
7895 * Some of the more common ones are illustrated below.
7897 * == Accessing Elements
7899 * Elements in an array can be retrieved using the Array#[] method. It can
7900 * take a single integer argument (a numeric index), a pair of arguments
7901 * (start and length) or a range. Negative indices start counting from the end,
7902 * with -1 being the last element.
7904 * arr = [1, 2, 3, 4, 5, 6]
7905 * arr[2] #=> 3
7906 * arr[100] #=> nil
7907 * arr[-3] #=> 4
7908 * arr[2, 3] #=> [3, 4, 5]
7909 * arr[1..4] #=> [2, 3, 4, 5]
7910 * arr[1..-3] #=> [2, 3, 4]
7912 * Another way to access a particular array element is by using the #at method
7914 * arr.at(0) #=> 1
7916 * The #slice method works in an identical manner to Array#[].
7918 * To raise an error for indices outside of the array bounds or else to
7919 * provide a default value when that happens, you can use #fetch.
7921 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
7922 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
7923 * arr.fetch(100, "oops") #=> "oops"
7925 * The special methods #first and #last will return the first and last
7926 * elements of an array, respectively.
7928 * arr.first #=> 1
7929 * arr.last #=> 6
7931 * To return the first +n+ elements of an array, use #take
7933 * arr.take(3) #=> [1, 2, 3]
7935 * #drop does the opposite of #take, by returning the elements after +n+
7936 * elements have been dropped:
7938 * arr.drop(3) #=> [4, 5, 6]
7940 * == Obtaining Information about an Array
7942 * Arrays keep track of their own length at all times. To query an array
7943 * about the number of elements it contains, use #length, #count or #size.
7945 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
7946 * browsers.length #=> 5
7947 * browsers.count #=> 5
7949 * To check whether an array contains any elements at all
7951 * browsers.empty? #=> false
7953 * To check whether a particular item is included in the array
7955 * browsers.include?('Konqueror') #=> false
7957 * == Adding Items to Arrays
7959 * Items can be added to the end of an array by using either #push or #<<
7961 * arr = [1, 2, 3, 4]
7962 * arr.push(5) #=> [1, 2, 3, 4, 5]
7963 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
7965 * #unshift will add a new item to the beginning of an array.
7967 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
7969 * With #insert you can add a new element to an array at any position.
7971 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
7973 * Using the #insert method, you can also insert multiple values at once:
7975 * arr.insert(3, 'orange', 'pear', 'grapefruit')
7976 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
7978 * == Removing Items from an Array
7980 * The method #pop removes the last element in an array and returns it:
7982 * arr = [1, 2, 3, 4, 5, 6]
7983 * arr.pop #=> 6
7984 * arr #=> [1, 2, 3, 4, 5]
7986 * To retrieve and at the same time remove the first item, use #shift:
7988 * arr.shift #=> 1
7989 * arr #=> [2, 3, 4, 5]
7991 * To delete an element at a particular index:
7993 * arr.delete_at(2) #=> 4
7994 * arr #=> [2, 3, 5]
7996 * To delete a particular element anywhere in an array, use #delete:
7998 * arr = [1, 2, 2, 3]
7999 * arr.delete(2) #=> 2
8000 * arr #=> [1,3]
8002 * A useful method if you need to remove +nil+ values from an array is
8003 * #compact:
8005 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8006 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8007 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8008 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8009 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8011 * Another common need is to remove duplicate elements from an array.
8013 * It has the non-destructive #uniq, and destructive method #uniq!
8015 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8016 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8018 * == Iterating over Arrays
8020 * Like all classes that include the Enumerable module, Array has an each
8021 * method, which defines what elements should be iterated over and how. In
8022 * case of Array's #each, all elements in the Array instance are yielded to
8023 * the supplied block in sequence.
8025 * Note that this operation leaves the array unchanged.
8027 * arr = [1, 2, 3, 4, 5]
8028 * arr.each {|a| print a -= 10, " "}
8029 * # prints: -9 -8 -7 -6 -5
8030 * #=> [1, 2, 3, 4, 5]
8032 * Another sometimes useful iterator is #reverse_each which will iterate over
8033 * the elements in the array in reverse order.
8035 * words = %w[first second third fourth fifth sixth]
8036 * str = ""
8037 * words.reverse_each {|word| str += "#{word} "}
8038 * p str #=> "sixth fifth fourth third second first "
8040 * The #map method can be used to create a new array based on the original
8041 * array, but with the values modified by the supplied block:
8043 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8044 * arr #=> [1, 2, 3, 4, 5]
8045 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8046 * arr #=> [1, 4, 9, 16, 25]
8048 * == Selecting Items from an Array
8050 * Elements can be selected from an array according to criteria defined in a
8051 * block. The selection can happen in a destructive or a non-destructive
8052 * manner. While the destructive operations will modify the array they were
8053 * called on, the non-destructive methods usually return a new array with the
8054 * selected elements, but leave the original array unchanged.
8056 * === Non-destructive Selection
8058 * arr = [1, 2, 3, 4, 5, 6]
8059 * arr.select {|a| a > 3} #=> [4, 5, 6]
8060 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8061 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8062 * arr #=> [1, 2, 3, 4, 5, 6]
8064 * === Destructive Selection
8066 * #select! and #reject! are the corresponding destructive methods to #select
8067 * and #reject
8069 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8070 * opposite result when supplied with the same block:
8072 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8073 * arr #=> [4, 5, 6]
8075 * arr = [1, 2, 3, 4, 5, 6]
8076 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8077 * arr #=> [1, 2, 3]
8079 * == What's Here
8081 * First, what's elsewhere. \Class \Array:
8083 * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
8084 * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here],
8085 * which provides dozens of additional methods.
8087 * Here, class \Array provides methods that are useful for:
8089 * - {Creating an Array}[#class-Array-label-Methods+for+Creating+an+Array]
8090 * - {Querying}[#class-Array-label-Methods+for+Querying]
8091 * - {Comparing}[#class-Array-label-Methods+for+Comparing]
8092 * - {Fetching}[#class-Array-label-Methods+for+Fetching]
8093 * - {Assigning}[#class-Array-label-Methods+for+Assigning]
8094 * - {Deleting}[#class-Array-label-Methods+for+Deleting]
8095 * - {Combining}[#class-Array-label-Methods+for+Combining]
8096 * - {Iterating}[#class-Array-label-Methods+for+Iterating]
8097 * - {Converting}[#class-Array-label-Methods+for+Converting]
8098 * - {And more....}[#class-Array-label-Other+Methods]
8100 * === Methods for Creating an Array
8102 * ::[]:: Returns a new array populated with given objects.
8103 * ::new:: Returns a new array.
8104 * ::try_convert:: Returns a new array created from a given object.
8106 * === Methods for Querying
8108 * #length, #size:: Returns the count of elements.
8109 * #include?:: Returns whether any element <tt>==</tt> a given object.
8110 * #empty?:: Returns whether there are no elements.
8111 * #all?:: Returns whether all elements meet a given criterion.
8112 * #any?:: Returns whether any element meets a given criterion.
8113 * #none?:: Returns whether no element <tt>==</tt> a given object.
8114 * #one?:: Returns whether exactly one element <tt>==</tt> a given object.
8115 * #count:: Returns the count of elements that meet a given criterion.
8116 * #find_index, #index:: Returns the index of the first element that meets a given criterion.
8117 * #rindex:: Returns the index of the last element that meets a given criterion.
8118 * #hash:: Returns the integer hash code.
8120 * === Methods for Comparing
8121 * {#<=>}[#method-i-3C-3D-3E]:: Returns -1, 0, or 1
8122 * as +self+ is less than, equal to, or greater than a given object.
8123 * {#==}[#method-i-3D-3D]:: Returns whether each element in +self+ is <tt>==</tt> to the
8124 * corresponding element in a given object.
8125 * #eql?:: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
8126 * element in a given object.
8128 * === Methods for Fetching
8130 * These methods do not modify +self+.
8132 * #[]:: Returns one or more elements.
8133 * #fetch:: Returns the element at a given offset.
8134 * #first:: Returns one or more leading elements.
8135 * #last:: Returns one or more trailing elements.
8136 * #max:: Returns one or more maximum-valued elements,
8137 * as determined by <tt><=></tt> or a given block.
8138 * #max:: Returns one or more minimum-valued elements,
8139 * as determined by <tt><=></tt> or a given block.
8140 * #minmax:: Returns the minimum-valued and maximum-valued elements,
8141 * as determined by <tt><=></tt> or a given block.
8142 * #assoc:: Returns the first element that is an array
8143 * whose first element <tt>==</tt> a given object.
8144 * #rassoc:: Returns the first element that is an array
8145 * whose second element <tt>==</tt> a given object.
8146 * #at:: Returns the element at a given offset.
8147 * #values_at:: Returns the elements at given offsets.
8148 * #dig:: Returns the object in nested objects
8149 * that is specified by a given index and additional arguments.
8150 * #drop:: Returns trailing elements as determined by a given index.
8151 * #take:: Returns leading elements as determined by a given index.
8152 * #drop_while:: Returns trailing elements as determined by a given block.
8153 * #take_while:: Returns leading elements as determined by a given block.
8154 * #slice:: Returns consecutive elements as determined by a given argument.
8155 * #sort:: Returns all elements in an order determined by <tt><=></tt> or a given block.
8156 * #reverse:: Returns all elements in reverse order.
8157 * #compact:: Returns an array containing all non-+nil+ elements.
8158 * #select, #filter:: Returns an array containing elements selected by a given block.
8159 * #uniq:: Returns an array containing non-duplicate elements.
8160 * #rotate:: Returns all elements with some rotated from one end to the other.
8161 * #bsearch:: Returns an element selected via a binary search
8162 * as determined by a given block.
8163 * #bsearch_index:: Returns the index of an element selected via a binary search
8164 * as determined by a given block.
8165 * #sample:: Returns one or more random elements.
8166 * #shuffle:: Returns elements in a random order.
8168 * === Methods for Assigning
8170 * These methods add, replace, or reorder elements in +self+.
8172 * #[]=:: Assigns specified elements with a given object.
8173 * #push, #append, #<<:: Appends trailing elements.
8174 * #unshift, #prepend:: Prepends leading elements.
8175 * #insert:: Inserts given objects at a given offset; does not replace elements.
8176 * #concat:: Appends all elements from given arrays.
8177 * #fill:: Replaces specified elements with specified objects.
8178 * #replace:: Replaces the content of +self+ with the content of a given array.
8179 * #reverse!:: Replaces +self+ with its elements reversed.
8180 * #rotate!:: Replaces +self+ with its elements rotated.
8181 * #shuffle!:: Replaces +self+ with its elements in random order.
8182 * #sort!:: Replaces +self+ with its elements sorted,
8183 * as determined by <tt><=></tt> or a given block.
8184 * #sort_by!:: Replaces +self+ with its elements sorted, as determined by a given block.
8186 * === Methods for Deleting
8188 * Each of these methods removes elements from +self+:
8190 * #pop:: Removes and returns the last element.
8191 * #shift:: Removes and returns the first element.
8192 * #compact!:: Removes all non-+nil+ elements.
8193 * #delete:: Removes elements equal to a given object.
8194 * #delete_at:: Removes the element at a given offset.
8195 * #delete_if:: Removes elements specified by a given block.
8196 * #keep_if:: Removes elements not specified by a given block.
8197 * #reject!:: Removes elements specified by a given block.
8198 * #select!, #filter!:: Removes elements not specified by a given block.
8199 * #slice!:: Removes and returns a sequence of elements.
8200 * #uniq!:: Removes duplicates.
8202 * === Methods for Combining
8204 * {#&}[#method-i-26]:: Returns an array containing elements found both in +self+ and a given array.
8205 * #intersection:: Returns an array containing elements found both in +self+
8206 * and in each given array.
8207 * #+:: Returns an array containing all elements of +self+ followed by all elements of a given array.
8208 * #-:: Returns an array containiing all elements of +self+ that are not found in a given array.
8209 * {#|}[#method-i-7C]:: Returns an array containing all elements of +self+ and all elements of a given array,
8210 * duplicates removed.
8211 * #union:: Returns an array containing all elements of +self+ and all elements of given arrays,
8212 * duplicates removed.
8213 * #difference:: Returns an array containing all elements of +self+ that are not found
8214 * in any of the given arrays..
8215 * #product:: Returns or yields all combinations of elements from +self+ and given arrays.
8217 * === Methods for Iterating
8219 * #each:: Passes each element to a given block.
8220 * #reverse_each:: Passes each element, in reverse order, to a given block.
8221 * #each_index:: Passes each element index to a given block.
8222 * #cycle:: Calls a given block with each element, then does so again,
8223 * for a specified number of times, or forever.
8224 * #combination:: Calls a given block with combinations of elements of +self+;
8225 * a combination does not use the same element more than once.
8226 * #permutation:: Calls a given block with permutations of elements of +self+;
8227 * a permutation does not use the same element more than once.
8228 * #repeated_combination:: Calls a given block with combinations of elements of +self+;
8229 * a combination may use the same element more than once.
8230 * #repeated_permutation:: Calls a given block with permutations of elements of +self+;
8231 * a permutation may use the same element more than once.
8233 * === Methods for Converting
8235 * #map, #collect:: Returns an array containing the block return-value for each element.
8236 * #map!, #collect!:: Replaces each element with a block return-value.
8237 * #flatten:: Returns an array that is a recursive flattening of +self+.
8238 * #flatten!:: Replaces each nested array in +self+ with the elements from that array.
8239 * #inspect, #to_s:: Returns a new String containing the elements.
8240 * #join:: Returns a newsString containing the elements joined by the field separator.
8241 * #to_a:: Returns +self+ or a new array containing all elements.
8242 * #to_ary:: Returns +self+.
8243 * #to_h:: Returns a new hash formed from the elements.
8244 * #transpose:: Transposes +self+, which must be an array of arrays.
8245 * #zip:: Returns a new array of arrays containing +self+ and given arrays;
8246 * follow the link for details.
8248 * === Other Methods
8250 * #*:: Returns one of the following:
8251 * - With integer argument +n+, a new array that is the concatenation
8252 * of +n+ copies of +self+.
8253 * - With string argument +field_separator+, a new string that is equivalent to
8254 * <tt>join(field_separator)</tt>.
8255 * #abbrev:: Returns a hash of unambiguous abbreviations for elements.
8256 * #pack:: Packs the elements into a binary sequence.
8257 * #sum:: Returns a sum of elements according to either <tt>+</tt> or a given block.
8260 void
8261 Init_Array(void)
8263 rb_cArray = rb_define_class("Array", rb_cObject);
8264 rb_include_module(rb_cArray, rb_mEnumerable);
8266 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
8267 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
8268 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
8269 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
8270 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
8272 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
8273 rb_define_alias(rb_cArray, "to_s", "inspect");
8274 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
8275 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
8276 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
8278 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
8279 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
8280 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
8282 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
8283 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
8284 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
8285 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
8286 rb_define_method(rb_cArray, "first", rb_ary_first, -1);
8287 rb_define_method(rb_cArray, "last", rb_ary_last, -1);
8288 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
8289 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
8290 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
8291 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
8292 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
8293 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
8294 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
8295 rb_define_alias(rb_cArray, "append", "push");
8296 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
8297 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
8298 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
8299 rb_define_alias(rb_cArray, "prepend", "unshift");
8300 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
8301 rb_define_method(rb_cArray, "each", rb_ary_each, 0);
8302 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
8303 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
8304 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
8305 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
8306 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
8307 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
8308 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
8309 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
8310 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
8311 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
8312 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
8313 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
8314 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
8315 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
8316 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
8317 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
8318 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
8319 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
8320 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
8321 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
8322 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
8323 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
8324 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
8325 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
8326 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
8327 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
8328 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
8329 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
8330 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
8331 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
8332 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
8333 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
8334 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
8335 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
8336 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
8337 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
8338 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
8339 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
8341 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
8342 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
8344 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
8345 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
8347 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
8348 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
8350 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
8351 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
8352 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
8354 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
8355 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
8356 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
8358 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
8359 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
8360 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
8361 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
8362 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
8363 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
8364 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
8365 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
8366 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
8367 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
8368 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
8369 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
8370 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
8372 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
8373 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
8374 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
8375 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
8376 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
8377 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
8378 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
8379 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
8380 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
8381 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
8382 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
8383 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
8385 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
8388 #include "array.rbinc"