Fix an ASAN error in Array#difference
[ruby.git] / array.c
blobb0a874bc836233f7ceedac81e46d67cd38347469
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/thread.h"
31 #include "ruby/util.h"
32 #include "vm_core.h"
33 #include "builtin.h"
35 #if !ARRAY_DEBUG
36 # undef NDEBUG
37 # define NDEBUG
38 #endif
39 #include "ruby_assert.h"
41 VALUE rb_cArray;
42 VALUE rb_cArray_empty_frozen;
44 /* Flags of RArray
46 * 0: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
47 * The array is shared. The buffer this array points to is owned by
48 * another array (the shared root).
49 * 1: RARRAY_EMBED_FLAG
50 * The array is embedded (its contents follow the header, rather than
51 * being on a separately allocated buffer).
52 * 3-9: RARRAY_EMBED_LEN
53 * The length of the array when RARRAY_EMBED_FLAG is set.
54 * 12: RARRAY_SHARED_ROOT_FLAG
55 * The array is a shared root that does reference counting. The buffer
56 * this array points to is owned by this array but may be pointed to
57 * by other arrays.
58 * Note: Frozen arrays may be a shared root without this flag being
59 * set. Frozen arrays do not have reference counting because
60 * they cannot be modified. Not updating the reference count
61 * improves copy-on-write performance. Their reference count is
62 * assumed to be infinity.
63 * 14: RARRAY_PTR_IN_USE_FLAG
64 * The buffer of the array is in use. This is only used during
65 * debugging.
68 /* for OPTIMIZED_CMP: */
69 #define id_cmp idCmp
71 #define ARY_DEFAULT_SIZE 16
72 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
73 #define SMALL_ARRAY_LEN 16
75 RBIMPL_ATTR_MAYBE_UNUSED()
76 static int
77 should_be_T_ARRAY(VALUE ary)
79 return RB_TYPE_P(ary, T_ARRAY);
82 #define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
83 #define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
84 #define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \
85 RARRAY(a)->as.heap.aux.capa)
87 #define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
88 #define ARY_EMBED_LEN(a) \
89 (RUBY_ASSERT(ARY_EMBED_P(a)), \
90 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
91 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
92 #define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
94 #define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \
95 !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
97 #define FL_SET_EMBED(a) do { \
98 RUBY_ASSERT(!ARY_SHARED_P(a)); \
99 FL_SET((a), RARRAY_EMBED_FLAG); \
100 ary_verify(a); \
101 } while (0)
103 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
104 #define FL_SET_SHARED(ary) do { \
105 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
106 FL_SET((ary), RARRAY_SHARED_FLAG); \
107 } while (0)
108 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
110 #define ARY_SET_PTR(ary, p) do { \
111 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
112 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
113 RARRAY(ary)->as.heap.ptr = (p); \
114 } while (0)
115 #define ARY_SET_EMBED_LEN(ary, n) do { \
116 long tmp_n = (n); \
117 RUBY_ASSERT(ARY_EMBED_P(ary)); \
118 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
119 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
120 } while (0)
121 #define ARY_SET_HEAP_LEN(ary, n) do { \
122 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
123 RARRAY(ary)->as.heap.len = (n); \
124 } while (0)
125 #define ARY_SET_LEN(ary, n) do { \
126 if (ARY_EMBED_P(ary)) { \
127 ARY_SET_EMBED_LEN((ary), (n)); \
129 else { \
130 ARY_SET_HEAP_LEN((ary), (n)); \
132 RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \
133 } while (0)
134 #define ARY_INCREASE_PTR(ary, n) do { \
135 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
136 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
137 RARRAY(ary)->as.heap.ptr += (n); \
138 } while (0)
139 #define ARY_INCREASE_LEN(ary, n) do { \
140 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
141 if (ARY_EMBED_P(ary)) { \
142 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
144 else { \
145 RARRAY(ary)->as.heap.len += (n); \
147 } while (0)
149 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
150 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
151 #define ARY_SET_CAPA(ary, n) do { \
152 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
153 RUBY_ASSERT(!ARY_SHARED_P(ary)); \
154 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
155 RARRAY(ary)->as.heap.aux.capa = (n); \
156 } while (0)
158 #define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
159 #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
160 RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \
161 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
162 RUBY_ASSERT((value) >= 0); \
163 RARRAY(ary)->as.heap.aux.capa = (value); \
164 } while (0)
165 #define FL_SET_SHARED_ROOT(ary) do { \
166 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
167 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
168 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
169 } while (0)
171 static inline void
172 ARY_SET(VALUE a, long i, VALUE v)
174 RUBY_ASSERT(!ARY_SHARED_P(a));
175 RUBY_ASSERT(!OBJ_FROZEN(a));
177 RARRAY_ASET(a, i, v);
179 #undef RARRAY_ASET
181 static long
182 ary_embed_capa(VALUE ary)
184 size_t size = rb_gc_obj_slot_size(ary) - offsetof(struct RArray, as.ary);
185 RUBY_ASSERT(size % sizeof(VALUE) == 0);
186 return size / sizeof(VALUE);
189 static size_t
190 ary_embed_size(long capa)
192 return offsetof(struct RArray, as.ary) + (sizeof(VALUE) * capa);
195 static bool
196 ary_embeddable_p(long capa)
198 return rb_gc_size_allocatable_p(ary_embed_size(capa));
201 bool
202 rb_ary_embeddable_p(VALUE ary)
204 /* An array cannot be turned embeddable when the array is:
205 * - Shared root: other objects may point to the buffer of this array
206 * so we cannot make it embedded.
207 * - Frozen: this array may also be a shared root without the shared root
208 * flag.
209 * - Shared: we don't want to re-embed an array that points to a shared
210 * root (to save memory).
212 return !(ARY_SHARED_ROOT_P(ary) || OBJ_FROZEN(ary) || ARY_SHARED_P(ary));
215 size_t
216 rb_ary_size_as_embedded(VALUE ary)
218 size_t real_size;
220 if (ARY_EMBED_P(ary)) {
221 real_size = ary_embed_size(ARY_EMBED_LEN(ary));
223 else if (rb_ary_embeddable_p(ary)) {
224 real_size = ary_embed_size(ARY_HEAP_CAPA(ary));
226 else {
227 real_size = sizeof(struct RArray);
229 return real_size;
233 #if ARRAY_DEBUG
234 #define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
236 static VALUE
237 ary_verify_(VALUE ary, const char *file, int line)
239 RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
241 if (ARY_SHARED_P(ary)) {
242 VALUE root = ARY_SHARED_ROOT(ary);
243 const VALUE *ptr = ARY_HEAP_PTR(ary);
244 const VALUE *root_ptr = RARRAY_CONST_PTR(root);
245 long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
246 RUBY_ASSERT(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root));
247 RUBY_ASSERT(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
248 ary_verify(root);
250 else if (ARY_EMBED_P(ary)) {
251 RUBY_ASSERT(!ARY_SHARED_P(ary));
252 RUBY_ASSERT(RARRAY_LEN(ary) <= ary_embed_capa(ary));
254 else {
255 const VALUE *ptr = RARRAY_CONST_PTR(ary);
256 long i, len = RARRAY_LEN(ary);
257 volatile VALUE v;
258 if (len > 1) len = 1; /* check only HEAD */
259 for (i=0; i<len; i++) {
260 v = ptr[i]; /* access check */
262 v = v;
265 return ary;
267 #else
268 #define ary_verify(ary) ((void)0)
269 #endif
271 VALUE *
272 rb_ary_ptr_use_start(VALUE ary)
274 #if ARRAY_DEBUG
275 FL_SET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
276 #endif
277 return (VALUE *)RARRAY_CONST_PTR(ary);
280 void
281 rb_ary_ptr_use_end(VALUE ary)
283 #if ARRAY_DEBUG
284 FL_UNSET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
285 #endif
288 void
289 rb_mem_clear(VALUE *mem, long size)
291 while (size--) {
292 *mem++ = Qnil;
296 static void
297 ary_mem_clear(VALUE ary, long beg, long size)
299 RARRAY_PTR_USE(ary, ptr, {
300 rb_mem_clear(ptr + beg, size);
304 static inline void
305 memfill(register VALUE *mem, register long size, register VALUE val)
307 while (size--) {
308 *mem++ = val;
312 static void
313 ary_memfill(VALUE ary, long beg, long size, VALUE val)
315 RARRAY_PTR_USE(ary, ptr, {
316 memfill(ptr + beg, size, val);
317 RB_OBJ_WRITTEN(ary, Qundef, val);
321 static void
322 ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary)
324 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary));
326 if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
327 rb_gc_writebarrier_remember(buff_owner_ary);
328 RARRAY_PTR_USE(ary, ptr, {
329 MEMCPY(ptr+beg, argv, VALUE, argc);
332 else {
333 int i;
334 RARRAY_PTR_USE(ary, ptr, {
335 for (i=0; i<argc; i++) {
336 RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
342 static void
343 ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
345 ary_memcpy0(ary, beg, argc, argv, ary);
348 static VALUE *
349 ary_heap_alloc_buffer(size_t capa)
351 return ALLOC_N(VALUE, capa);
354 static void
355 ary_heap_free_ptr(VALUE ary, const VALUE *ptr, long size)
357 ruby_sized_xfree((void *)ptr, size);
360 static void
361 ary_heap_free(VALUE ary)
363 ary_heap_free_ptr(ary, ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
366 static size_t
367 ary_heap_realloc(VALUE ary, size_t new_capa)
369 RUBY_ASSERT(!OBJ_FROZEN(ary));
370 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, ARY_HEAP_CAPA(ary));
371 ary_verify(ary);
373 return new_capa;
376 void
377 rb_ary_make_embedded(VALUE ary)
379 RUBY_ASSERT(rb_ary_embeddable_p(ary));
380 if (!ARY_EMBED_P(ary)) {
381 const VALUE *buf = ARY_HEAP_PTR(ary);
382 long len = ARY_HEAP_LEN(ary);
384 FL_SET_EMBED(ary);
385 ARY_SET_EMBED_LEN(ary, len);
387 MEMCPY((void *)ARY_EMBED_PTR(ary), (void *)buf, VALUE, len);
389 ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
393 static void
394 ary_resize_capa(VALUE ary, long capacity)
396 RUBY_ASSERT(RARRAY_LEN(ary) <= capacity);
397 RUBY_ASSERT(!OBJ_FROZEN(ary));
398 RUBY_ASSERT(!ARY_SHARED_P(ary));
400 if (capacity > ary_embed_capa(ary)) {
401 size_t new_capa = capacity;
402 if (ARY_EMBED_P(ary)) {
403 long len = ARY_EMBED_LEN(ary);
404 VALUE *ptr = ary_heap_alloc_buffer(capacity);
406 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
407 FL_UNSET_EMBED(ary);
408 ARY_SET_PTR(ary, ptr);
409 ARY_SET_HEAP_LEN(ary, len);
411 else {
412 new_capa = ary_heap_realloc(ary, capacity);
414 ARY_SET_CAPA(ary, new_capa);
416 else {
417 if (!ARY_EMBED_P(ary)) {
418 long len = ARY_HEAP_LEN(ary);
419 long old_capa = ARY_HEAP_CAPA(ary);
420 const VALUE *ptr = ARY_HEAP_PTR(ary);
422 if (len > capacity) len = capacity;
423 MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
424 ary_heap_free_ptr(ary, ptr, old_capa);
426 FL_SET_EMBED(ary);
427 ARY_SET_LEN(ary, len);
431 ary_verify(ary);
434 static inline void
435 ary_shrink_capa(VALUE ary)
437 long capacity = ARY_HEAP_LEN(ary);
438 long old_capa = ARY_HEAP_CAPA(ary);
439 RUBY_ASSERT(!ARY_SHARED_P(ary));
440 RUBY_ASSERT(old_capa >= capacity);
441 if (old_capa > capacity) {
442 size_t new_capa = ary_heap_realloc(ary, capacity);
443 ARY_SET_CAPA(ary, new_capa);
446 ary_verify(ary);
449 static void
450 ary_double_capa(VALUE ary, long min)
452 long new_capa = ARY_CAPA(ary) / 2;
454 if (new_capa < ARY_DEFAULT_SIZE) {
455 new_capa = ARY_DEFAULT_SIZE;
457 if (new_capa >= ARY_MAX_SIZE - min) {
458 new_capa = (ARY_MAX_SIZE - min) / 2;
460 new_capa += min;
461 ary_resize_capa(ary, new_capa);
463 ary_verify(ary);
466 static void
467 rb_ary_decrement_share(VALUE shared_root)
469 if (!OBJ_FROZEN(shared_root)) {
470 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
471 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num - 1);
475 static void
476 rb_ary_unshare(VALUE ary)
478 VALUE shared_root = ARY_SHARED_ROOT(ary);
479 rb_ary_decrement_share(shared_root);
480 FL_UNSET_SHARED(ary);
483 static void
484 rb_ary_reset(VALUE ary)
486 if (ARY_OWNS_HEAP_P(ary)) {
487 ary_heap_free(ary);
489 else if (ARY_SHARED_P(ary)) {
490 rb_ary_unshare(ary);
493 FL_SET_EMBED(ary);
494 ARY_SET_EMBED_LEN(ary, 0);
497 static VALUE
498 rb_ary_increment_share(VALUE shared_root)
500 if (!OBJ_FROZEN(shared_root)) {
501 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
502 RUBY_ASSERT(num >= 0);
503 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
505 return shared_root;
508 static void
509 rb_ary_set_shared(VALUE ary, VALUE shared_root)
511 RUBY_ASSERT(!ARY_EMBED_P(ary));
512 RUBY_ASSERT(!OBJ_FROZEN(ary));
513 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root) || OBJ_FROZEN(shared_root));
515 rb_ary_increment_share(shared_root);
516 FL_SET_SHARED(ary);
517 RB_OBJ_WRITE(ary, &RARRAY(ary)->as.heap.aux.shared_root, shared_root);
519 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
522 static inline void
523 rb_ary_modify_check(VALUE ary)
525 RUBY_ASSERT(ruby_thread_has_gvl_p());
527 rb_check_frozen(ary);
528 ary_verify(ary);
531 void
532 rb_ary_cancel_sharing(VALUE ary)
534 if (ARY_SHARED_P(ary)) {
535 long shared_len, len = RARRAY_LEN(ary);
536 VALUE shared_root = ARY_SHARED_ROOT(ary);
538 ary_verify(shared_root);
540 if (len <= ary_embed_capa(ary)) {
541 const VALUE *ptr = ARY_HEAP_PTR(ary);
542 FL_UNSET_SHARED(ary);
543 FL_SET_EMBED(ary);
544 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
545 rb_ary_decrement_share(shared_root);
546 ARY_SET_EMBED_LEN(ary, len);
548 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) {
549 long shift = RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared_root);
550 FL_UNSET_SHARED(ary);
551 ARY_SET_PTR(ary, RARRAY_CONST_PTR(shared_root));
552 ARY_SET_CAPA(ary, shared_len);
553 RARRAY_PTR_USE(ary, ptr, {
554 MEMMOVE(ptr, ptr+shift, VALUE, len);
556 FL_SET_EMBED(shared_root);
557 rb_ary_decrement_share(shared_root);
559 else {
560 VALUE *ptr = ary_heap_alloc_buffer(len);
561 MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len);
562 rb_ary_unshare(ary);
563 ARY_SET_CAPA(ary, len);
564 ARY_SET_PTR(ary, ptr);
567 rb_gc_writebarrier_remember(ary);
569 ary_verify(ary);
572 void
573 rb_ary_modify(VALUE ary)
575 rb_ary_modify_check(ary);
576 rb_ary_cancel_sharing(ary);
579 static VALUE
580 ary_ensure_room_for_push(VALUE ary, long add_len)
582 long old_len = RARRAY_LEN(ary);
583 long new_len = old_len + add_len;
584 long capa;
586 if (old_len > ARY_MAX_SIZE - add_len) {
587 rb_raise(rb_eIndexError, "index %ld too big", new_len);
589 if (ARY_SHARED_P(ary)) {
590 if (new_len > ary_embed_capa(ary)) {
591 VALUE shared_root = ARY_SHARED_ROOT(ary);
592 if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
593 if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
594 rb_ary_modify_check(ary);
596 ary_verify(ary);
597 ary_verify(shared_root);
598 return shared_root;
600 else {
601 /* if array is shared, then it is likely it participate in push/shift pattern */
602 rb_ary_modify(ary);
603 capa = ARY_CAPA(ary);
604 if (new_len > capa - (capa >> 6)) {
605 ary_double_capa(ary, new_len);
607 ary_verify(ary);
608 return ary;
612 ary_verify(ary);
613 rb_ary_modify(ary);
615 else {
616 rb_ary_modify_check(ary);
618 capa = ARY_CAPA(ary);
619 if (new_len > capa) {
620 ary_double_capa(ary, new_len);
623 ary_verify(ary);
624 return ary;
628 * call-seq:
629 * freeze -> self
631 * Freezes +self+ (if not already frozen); returns +self+:
633 * a = []
634 * a.frozen? # => false
635 * a.freeze
636 * a.frozen? # => true
638 * No further changes may be made to +self+;
639 * raises FrozenError if a change is attempted.
641 * Related: Kernel#frozen?.
644 VALUE
645 rb_ary_freeze(VALUE ary)
647 RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
649 if (OBJ_FROZEN(ary)) return ary;
651 if (!ARY_EMBED_P(ary) && !ARY_SHARED_P(ary) && !ARY_SHARED_ROOT_P(ary)) {
652 ary_shrink_capa(ary);
655 return rb_obj_freeze(ary);
658 /* This can be used to take a snapshot of an array (with
659 e.g. rb_ary_replace) and check later whether the array has been
660 modified from the snapshot. The snapshot is cheap, though if
661 something does modify the array it will pay the cost of copying
662 it. If Array#pop or Array#shift has been called, the array will
663 be still shared with the snapshot, but the array length will
664 differ. */
665 VALUE
666 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
668 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
669 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
670 ARY_SHARED_ROOT(ary1) == ARY_SHARED_ROOT(ary2) &&
671 ARY_HEAP_LEN(ary1) == ARY_HEAP_LEN(ary2)) {
672 return Qtrue;
674 return Qfalse;
677 static VALUE
678 ary_alloc_embed(VALUE klass, long capa)
680 size_t size = ary_embed_size(capa);
681 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
682 NEWOBJ_OF(ary, struct RArray, klass,
683 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
684 size, 0);
685 /* Created array is:
686 * FL_SET_EMBED((VALUE)ary);
687 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
689 return (VALUE)ary;
692 static VALUE
693 ary_alloc_heap(VALUE klass)
695 NEWOBJ_OF(ary, struct RArray, klass,
696 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
697 sizeof(struct RArray), 0);
698 return (VALUE)ary;
701 static VALUE
702 empty_ary_alloc(VALUE klass)
704 RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
705 return ary_alloc_embed(klass, 0);
708 static VALUE
709 ary_new(VALUE klass, long capa)
711 RUBY_ASSERT(ruby_thread_has_gvl_p());
713 VALUE ary;
715 if (capa < 0) {
716 rb_raise(rb_eArgError, "negative array size (or size too big)");
718 if (capa > ARY_MAX_SIZE) {
719 rb_raise(rb_eArgError, "array size too big");
722 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
724 if (ary_embeddable_p(capa)) {
725 ary = ary_alloc_embed(klass, capa);
727 else {
728 ary = ary_alloc_heap(klass);
729 ARY_SET_CAPA(ary, capa);
730 RUBY_ASSERT(!ARY_EMBED_P(ary));
732 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
733 ARY_SET_HEAP_LEN(ary, 0);
736 return ary;
739 VALUE
740 rb_ary_new_capa(long capa)
742 return ary_new(rb_cArray, capa);
745 VALUE
746 rb_ary_new(void)
748 return rb_ary_new_capa(0);
751 VALUE
752 (rb_ary_new_from_args)(long n, ...)
754 va_list ar;
755 VALUE ary;
756 long i;
758 ary = rb_ary_new2(n);
760 va_start(ar, n);
761 for (i=0; i<n; i++) {
762 ARY_SET(ary, i, va_arg(ar, VALUE));
764 va_end(ar);
766 ARY_SET_LEN(ary, n);
767 return ary;
770 VALUE
771 rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
773 VALUE ary;
775 ary = ary_new(klass, n);
776 if (n > 0 && elts) {
777 ary_memcpy(ary, 0, n, elts);
778 ARY_SET_LEN(ary, n);
781 return ary;
784 VALUE
785 rb_ary_new_from_values(long n, const VALUE *elts)
787 return rb_ary_tmp_new_from_values(rb_cArray, n, elts);
790 static VALUE
791 ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
793 size_t size = ary_embed_size(capa);
794 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
795 NEWOBJ_OF(ary, struct RArray, klass,
796 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
797 size, ec);
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_alloc_heap(rb_execution_context_t *ec, VALUE klass)
808 NEWOBJ_OF(ary, struct RArray, klass,
809 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
810 sizeof(struct RArray), ec);
811 return (VALUE)ary;
814 static VALUE
815 ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
817 VALUE ary;
819 if (capa < 0) {
820 rb_raise(rb_eArgError, "negative array size (or size too big)");
822 if (capa > ARY_MAX_SIZE) {
823 rb_raise(rb_eArgError, "array size too big");
826 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
828 if (ary_embeddable_p(capa)) {
829 ary = ec_ary_alloc_embed(ec, klass, capa);
831 else {
832 ary = ec_ary_alloc_heap(ec, klass);
833 ARY_SET_CAPA(ary, capa);
834 RUBY_ASSERT(!ARY_EMBED_P(ary));
836 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
837 ARY_SET_HEAP_LEN(ary, 0);
840 return ary;
843 VALUE
844 rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
846 VALUE ary;
848 ary = ec_ary_new(ec, rb_cArray, n);
849 if (n > 0 && elts) {
850 ary_memcpy(ary, 0, n, elts);
851 ARY_SET_LEN(ary, n);
854 return ary;
857 VALUE
858 rb_ary_hidden_new(long capa)
860 VALUE ary = ary_new(0, capa);
861 return ary;
864 VALUE
865 rb_ary_hidden_new_fill(long capa)
867 VALUE ary = rb_ary_hidden_new(capa);
868 ary_memfill(ary, 0, capa, Qnil);
869 ARY_SET_LEN(ary, capa);
870 return ary;
873 void
874 rb_ary_free(VALUE ary)
876 if (ARY_OWNS_HEAP_P(ary)) {
877 if (USE_DEBUG_COUNTER &&
878 !ARY_SHARED_ROOT_P(ary) &&
879 ARY_HEAP_CAPA(ary) > RARRAY_LEN(ary)) {
880 RB_DEBUG_COUNTER_INC(obj_ary_extracapa);
883 RB_DEBUG_COUNTER_INC(obj_ary_ptr);
884 ary_heap_free(ary);
886 else {
887 RB_DEBUG_COUNTER_INC(obj_ary_embed);
890 if (ARY_SHARED_P(ary)) {
891 RB_DEBUG_COUNTER_INC(obj_ary_shared);
893 if (ARY_SHARED_ROOT_P(ary) && ARY_SHARED_ROOT_OCCUPIED(ary)) {
894 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
898 static VALUE fake_ary_flags;
900 static VALUE
901 init_fake_ary_flags(void)
903 struct RArray fake_ary = {0};
904 fake_ary.basic.flags = T_ARRAY;
905 VALUE ary = (VALUE)&fake_ary;
906 rb_ary_freeze(ary);
907 return fake_ary.basic.flags;
910 VALUE
911 rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len)
913 fake_ary->basic.flags = fake_ary_flags;
914 RBASIC_CLEAR_CLASS((VALUE)fake_ary);
916 // bypass frozen checks
917 fake_ary->as.heap.ptr = list;
918 fake_ary->as.heap.len = len;
919 fake_ary->as.heap.aux.capa = len;
920 return (VALUE)fake_ary;
923 size_t
924 rb_ary_memsize(VALUE ary)
926 if (ARY_OWNS_HEAP_P(ary)) {
927 return ARY_CAPA(ary) * sizeof(VALUE);
929 else {
930 return 0;
934 static VALUE
935 ary_make_shared(VALUE ary)
937 ary_verify(ary);
939 if (ARY_SHARED_P(ary)) {
940 return ARY_SHARED_ROOT(ary);
942 else if (ARY_SHARED_ROOT_P(ary)) {
943 return ary;
945 else if (OBJ_FROZEN(ary)) {
946 return ary;
948 else {
949 long capa = ARY_CAPA(ary);
950 long len = RARRAY_LEN(ary);
952 /* Shared roots cannot be embedded because the reference count
953 * (refcnt) is stored in as.heap.aux.capa. */
954 VALUE shared = ary_alloc_heap(0);
955 FL_SET_SHARED_ROOT(shared);
957 if (ARY_EMBED_P(ary)) {
958 VALUE *ptr = ary_heap_alloc_buffer(capa);
959 ARY_SET_PTR(shared, ptr);
960 ary_memcpy(shared, 0, len, RARRAY_CONST_PTR(ary));
962 FL_UNSET_EMBED(ary);
963 ARY_SET_HEAP_LEN(ary, len);
964 ARY_SET_PTR(ary, ptr);
966 else {
967 ARY_SET_PTR(shared, RARRAY_CONST_PTR(ary));
970 ARY_SET_LEN(shared, capa);
971 ary_mem_clear(shared, len, capa - len);
972 rb_ary_set_shared(ary, shared);
974 ary_verify(shared);
975 ary_verify(ary);
977 return shared;
981 static VALUE
982 ary_make_substitution(VALUE ary)
984 long len = RARRAY_LEN(ary);
986 if (ary_embeddable_p(len)) {
987 VALUE subst = rb_ary_new_capa(len);
988 RUBY_ASSERT(ARY_EMBED_P(subst));
990 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
991 ARY_SET_EMBED_LEN(subst, len);
992 return subst;
994 else {
995 return rb_ary_increment_share(ary_make_shared(ary));
999 VALUE
1000 rb_assoc_new(VALUE car, VALUE cdr)
1002 return rb_ary_new3(2, car, cdr);
1005 VALUE
1006 rb_to_array_type(VALUE ary)
1008 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1010 #define to_ary rb_to_array_type
1012 VALUE
1013 rb_check_array_type(VALUE ary)
1015 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1018 VALUE
1019 rb_check_to_array(VALUE ary)
1021 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1024 VALUE
1025 rb_to_array(VALUE ary)
1027 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1031 * call-seq:
1032 * Array.try_convert(object) -> object, new_array, or nil
1034 * Attempts to return an array, based on the given +object+.
1036 * If +object+ is an array, returns +object+.
1038 * Otherwise if +object+ responds to <tt>:to_ary</tt>.
1039 * calls <tt>object.to_ary</tt>:
1040 * if the return value is an array or +nil+, returns that value;
1041 * if not, raises TypeError.
1043 * Otherwise returns +nil+.
1045 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1048 static VALUE
1049 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
1051 return rb_check_array_type(ary);
1054 /* :nodoc: */
1055 static VALUE
1056 rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
1058 VALUE ary;
1060 if (klass == rb_cArray) {
1061 long size = 0;
1062 if (argc > 0 && FIXNUM_P(argv[0])) {
1063 size = FIX2LONG(argv[0]);
1064 if (size < 0) size = 0;
1067 ary = ary_new(klass, size);
1069 rb_obj_call_init_kw(ary, argc, argv, RB_PASS_CALLED_KEYWORDS);
1071 else {
1072 ary = rb_class_new_instance_pass_kw(argc, argv, klass);
1075 return ary;
1079 * call-seq:
1080 * Array.new -> new_empty_array
1081 * Array.new(array) -> new_array
1082 * Array.new(size, default_value = nil) -> new_array
1083 * Array.new(size = 0) {|index| ... } -> new_array
1085 * Returns a new array.
1087 * With no block and no argument given, returns a new empty array:
1089 * Array.new # => []
1091 * With no block and array argument given, returns a new array with the same elements:
1093 * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
1095 * With no block and integer argument given, returns a new array containing
1096 * that many instances of the given +default_value+:
1098 * Array.new(0) # => []
1099 * Array.new(3) # => [nil, nil, nil]
1100 * Array.new(2, 3) # => [3, 3]
1102 * With a block given, returns an array of the given +size+;
1103 * calls the block with each +index+ in the range <tt>(0...size)</tt>;
1104 * the element at that +index+ in the returned array is the blocks return value:
1106 * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
1108 * A common pitfall for new Rubyists is providing an expression as +default_value+:
1110 * array = Array.new(2, {})
1111 * array # => [{}, {}]
1112 * array[0][:a] = 1
1113 * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
1115 * If you want the elements of the array to be distinct, you should pass a block:
1117 * array = Array.new(2) { {} }
1118 * array # => [{}, {}]
1119 * array[0][:a] = 1
1120 * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
1122 * Raises TypeError if the first argument is not either an array
1123 * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
1124 * Raises ArgumentError if the first argument is a negative integer.
1126 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1129 static VALUE
1130 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
1132 long len;
1133 VALUE size, val;
1135 rb_ary_modify(ary);
1136 if (argc == 0) {
1137 rb_ary_reset(ary);
1138 RUBY_ASSERT(ARY_EMBED_P(ary));
1139 RUBY_ASSERT(ARY_EMBED_LEN(ary) == 0);
1140 if (rb_block_given_p()) {
1141 rb_warning("given block not used");
1143 return ary;
1145 rb_scan_args(argc, argv, "02", &size, &val);
1146 if (argc == 1 && !FIXNUM_P(size)) {
1147 val = rb_check_array_type(size);
1148 if (!NIL_P(val)) {
1149 rb_ary_replace(ary, val);
1150 return ary;
1154 len = NUM2LONG(size);
1155 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1156 if (len < 0) {
1157 rb_raise(rb_eArgError, "negative array size");
1159 if (len > ARY_MAX_SIZE) {
1160 rb_raise(rb_eArgError, "array size too big");
1162 /* recheck after argument conversion */
1163 rb_ary_modify(ary);
1164 ary_resize_capa(ary, len);
1165 if (rb_block_given_p()) {
1166 long i;
1168 if (argc == 2) {
1169 rb_warn("block supersedes default value argument");
1171 for (i=0; i<len; i++) {
1172 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
1173 ARY_SET_LEN(ary, i + 1);
1176 else {
1177 ary_memfill(ary, 0, len, val);
1178 ARY_SET_LEN(ary, len);
1180 return ary;
1184 * Returns a new array, populated with the given objects:
1186 * Array[1, 'a', /^A/] # => [1, "a", /^A/]
1187 * Array[] # => []
1188 * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
1190 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1193 static VALUE
1194 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
1196 VALUE ary = ary_new(klass, argc);
1197 if (argc > 0 && argv) {
1198 ary_memcpy(ary, 0, argc, argv);
1199 ARY_SET_LEN(ary, argc);
1202 return ary;
1205 void
1206 rb_ary_store(VALUE ary, long idx, VALUE val)
1208 long len = RARRAY_LEN(ary);
1210 if (idx < 0) {
1211 idx += len;
1212 if (idx < 0) {
1213 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1214 idx - len, -len);
1217 else if (idx >= ARY_MAX_SIZE) {
1218 rb_raise(rb_eIndexError, "index %ld too big", idx);
1221 rb_ary_modify(ary);
1222 if (idx >= ARY_CAPA(ary)) {
1223 ary_double_capa(ary, idx);
1225 if (idx > len) {
1226 ary_mem_clear(ary, len, idx - len + 1);
1229 if (idx >= len) {
1230 ARY_SET_LEN(ary, idx + 1);
1232 ARY_SET(ary, idx, val);
1235 static VALUE
1236 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
1238 RUBY_ASSERT(offset >= 0);
1239 RUBY_ASSERT(len >= 0);
1240 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1242 VALUE result = ary_alloc_heap(klass);
1243 size_t embed_capa = ary_embed_capa(result);
1244 if ((size_t)len <= embed_capa) {
1245 FL_SET_EMBED(result);
1246 ary_memcpy(result, 0, len, RARRAY_CONST_PTR(ary) + offset);
1247 ARY_SET_EMBED_LEN(result, len);
1249 else {
1250 VALUE shared = ary_make_shared(ary);
1252 /* The ary_make_shared call may allocate, which can trigger a GC
1253 * compaction. This can cause the array to be embedded because it has
1254 * a length of 0. */
1255 FL_UNSET_EMBED(result);
1257 ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
1258 ARY_SET_LEN(result, RARRAY_LEN(ary));
1259 rb_ary_set_shared(result, shared);
1261 ARY_INCREASE_PTR(result, offset);
1262 ARY_SET_LEN(result, len);
1264 ary_verify(shared);
1267 ary_verify(result);
1268 return result;
1271 static VALUE
1272 ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
1274 RUBY_ASSERT(offset >= 0);
1275 RUBY_ASSERT(len >= 0);
1276 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1277 RUBY_ASSERT(step != 0);
1279 const long orig_len = len;
1281 if (step > 0 && step >= len) {
1282 VALUE result = ary_new(klass, 1);
1283 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1284 const VALUE *values = RARRAY_CONST_PTR(ary);
1286 RB_OBJ_WRITE(result, ptr, values[offset]);
1287 ARY_SET_EMBED_LEN(result, 1);
1288 return result;
1290 else if (step < 0 && step < -len) {
1291 step = -len;
1294 long ustep = (step < 0) ? -step : step;
1295 len = roomof(len, ustep);
1297 long i;
1298 long j = offset + ((step > 0) ? 0 : (orig_len - 1));
1300 VALUE result = ary_new(klass, len);
1301 if (ARY_EMBED_P(result)) {
1302 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1303 const VALUE *values = RARRAY_CONST_PTR(ary);
1305 for (i = 0; i < len; ++i) {
1306 RB_OBJ_WRITE(result, ptr+i, values[j]);
1307 j += step;
1309 ARY_SET_EMBED_LEN(result, len);
1311 else {
1312 const VALUE *values = RARRAY_CONST_PTR(ary);
1314 RARRAY_PTR_USE(result, ptr, {
1315 for (i = 0; i < len; ++i) {
1316 RB_OBJ_WRITE(result, ptr+i, values[j]);
1317 j += step;
1320 ARY_SET_LEN(result, len);
1323 return result;
1326 static VALUE
1327 ary_make_shared_copy(VALUE ary)
1329 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
1332 enum ary_take_pos_flags
1334 ARY_TAKE_FIRST = 0,
1335 ARY_TAKE_LAST = 1
1338 static VALUE
1339 ary_take_first_or_last_n(VALUE ary, long n, enum ary_take_pos_flags last)
1341 long len = RARRAY_LEN(ary);
1342 long offset = 0;
1344 if (n > len) {
1345 n = len;
1347 else if (n < 0) {
1348 rb_raise(rb_eArgError, "negative array size");
1350 if (last) {
1351 offset = len - n;
1353 return ary_make_partial(ary, rb_cArray, offset, n);
1356 static VALUE
1357 ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1359 argc = rb_check_arity(argc, 0, 1);
1360 /* the case optional argument is omitted should be handled in
1361 * callers of this function. if another arity case is added,
1362 * this arity check needs to rewrite. */
1363 RUBY_ASSERT_ALWAYS(argc == 1);
1364 return ary_take_first_or_last_n(ary, NUM2LONG(argv[0]), last);
1368 * call-seq:
1369 * self << object -> self
1371 * Appends +object+ as the last element in +self+; returns +self+:
1373 * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
1375 * Appends +object+ as a single element, even if it is another array:
1377 * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
1379 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1382 VALUE
1383 rb_ary_push(VALUE ary, VALUE item)
1385 long idx = RARRAY_LEN((ary_verify(ary), ary));
1386 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
1387 RARRAY_PTR_USE(ary, ptr, {
1388 RB_OBJ_WRITE(target_ary, &ptr[idx], item);
1390 ARY_SET_LEN(ary, idx + 1);
1391 ary_verify(ary);
1392 return ary;
1395 VALUE
1396 rb_ary_cat(VALUE ary, const VALUE *argv, long len)
1398 long oldlen = RARRAY_LEN(ary);
1399 VALUE target_ary = ary_ensure_room_for_push(ary, len);
1400 ary_memcpy0(ary, oldlen, len, argv, target_ary);
1401 ARY_SET_LEN(ary, oldlen + len);
1402 return ary;
1406 * call-seq:
1407 * push(*objects) -> self
1408 * append(*objects) -> self
1410 * Appends each argument in +objects+ to +self+; returns +self+:
1412 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1413 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1415 * Appends each argument as a single element, even if it is another array:
1417 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1418 a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1420 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1423 static VALUE
1424 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
1426 return rb_ary_cat(ary, argv, argc);
1429 VALUE
1430 rb_ary_pop(VALUE ary)
1432 long n;
1433 rb_ary_modify_check(ary);
1434 n = RARRAY_LEN(ary);
1435 if (n == 0) return Qnil;
1436 if (ARY_OWNS_HEAP_P(ary) &&
1437 n * 3 < ARY_CAPA(ary) &&
1438 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
1440 ary_resize_capa(ary, n * 2);
1442 --n;
1443 ARY_SET_LEN(ary, n);
1444 ary_verify(ary);
1445 return RARRAY_AREF(ary, n);
1449 * call-seq:
1450 * pop -> object or nil
1451 * pop(count) -> new_array
1453 * Removes and returns trailing elements of +self+.
1455 * With no argument given, removes and returns the last element, if available;
1456 * otherwise returns +nil+:
1458 * a = [:foo, 'bar', 2]
1459 * a.pop # => 2
1460 * a # => [:foo, "bar"]
1461 * [].pop # => nil
1463 * With non-negative integer argument +count+ given,
1464 * returns a new array containing the trailing +count+ elements of +self+, as available:
1466 * a = [:foo, 'bar', 2]
1467 * a.pop(2) # => ["bar", 2]
1468 * a # => [:foo]
1470 * a = [:foo, 'bar', 2]
1471 * a.pop(50) # => [:foo, "bar", 2]
1472 * a # => []
1474 * Related: Array#push;
1475 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1478 static VALUE
1479 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
1481 VALUE result;
1483 if (argc == 0) {
1484 return rb_ary_pop(ary);
1487 rb_ary_modify_check(ary);
1488 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1489 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
1490 ary_verify(ary);
1491 return result;
1494 VALUE
1495 rb_ary_shift(VALUE ary)
1497 VALUE top;
1498 long len = RARRAY_LEN(ary);
1500 if (len == 0) {
1501 rb_ary_modify_check(ary);
1502 return Qnil;
1505 top = RARRAY_AREF(ary, 0);
1507 rb_ary_behead(ary, 1);
1509 return top;
1513 * call-seq:
1514 * shift -> object or nil
1515 * shift(count) -> new_array or nil
1517 * Removes and returns leading elements from +self+.
1519 * With no argument, removes and returns one element, if available,
1520 * or +nil+ otherwise:
1522 * a = [0, 1, 2, 3]
1523 * a.shift # => 0
1524 * a # => [1, 2, 3]
1525 * [].shift # => nil
1527 * With non-negative numeric argument +count+ given,
1528 * removes and returns the first +count+ elements:
1530 * a = [0, 1, 2, 3]
1531 * a.shift(2) # => [0, 1]
1532 * a # => [2, 3]
1533 * a.shift(1.1) # => [2]
1534 * a # => [3]
1535 * a.shift(0) # => []
1536 * a # => [3]
1538 * If +count+ is large,
1539 * removes and returns all elements:
1541 * a = [0, 1, 2, 3]
1542 * a.shift(50) # => [0, 1, 2, 3]
1543 * a # => []
1545 * If +self+ is empty, returns a new empty array.
1547 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1550 static VALUE
1551 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
1553 VALUE result;
1554 long n;
1556 if (argc == 0) {
1557 return rb_ary_shift(ary);
1560 rb_ary_modify_check(ary);
1561 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1562 n = RARRAY_LEN(result);
1563 rb_ary_behead(ary,n);
1565 return result;
1568 VALUE
1569 rb_ary_behead(VALUE ary, long n)
1571 if (n <= 0) {
1572 return ary;
1575 rb_ary_modify_check(ary);
1577 if (!ARY_SHARED_P(ary)) {
1578 if (ARY_EMBED_P(ary) || RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
1579 RARRAY_PTR_USE(ary, ptr, {
1580 MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary) - n);
1581 }); /* WB: no new reference */
1582 ARY_INCREASE_LEN(ary, -n);
1583 ary_verify(ary);
1584 return ary;
1587 ary_mem_clear(ary, 0, n);
1588 ary_make_shared(ary);
1590 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1591 ary_mem_clear(ary, 0, n);
1594 ARY_INCREASE_PTR(ary, n);
1595 ARY_INCREASE_LEN(ary, -n);
1596 ary_verify(ary);
1598 return ary;
1601 static VALUE
1602 make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, long capa, long len)
1604 if (head - sharedp < argc) {
1605 long room = capa - len - argc;
1607 room -= room >> 4;
1608 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
1609 head = sharedp + argc + room;
1611 ARY_SET_PTR(ary, head - argc);
1612 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
1614 ary_verify(ary);
1615 return ARY_SHARED_ROOT(ary);
1618 static VALUE
1619 ary_modify_for_unshift(VALUE ary, int argc)
1621 long len = RARRAY_LEN(ary);
1622 long new_len = len + argc;
1623 long capa;
1624 const VALUE *head, *sharedp;
1626 rb_ary_modify(ary);
1627 capa = ARY_CAPA(ary);
1628 if (capa - (capa >> 6) <= new_len) {
1629 ary_double_capa(ary, new_len);
1632 /* use shared array for big "queues" */
1633 if (new_len > ARY_DEFAULT_SIZE * 4 && !ARY_EMBED_P(ary)) {
1634 ary_verify(ary);
1636 /* make a room for unshifted items */
1637 capa = ARY_CAPA(ary);
1638 ary_make_shared(ary);
1640 head = sharedp = RARRAY_CONST_PTR(ary);
1641 return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
1643 else {
1644 /* sliding items */
1645 RARRAY_PTR_USE(ary, ptr, {
1646 MEMMOVE(ptr + argc, ptr, VALUE, len);
1649 ary_verify(ary);
1650 return ary;
1654 static VALUE
1655 ary_ensure_room_for_unshift(VALUE ary, int argc)
1657 long len = RARRAY_LEN(ary);
1658 long new_len = len + argc;
1660 if (len > ARY_MAX_SIZE - argc) {
1661 rb_raise(rb_eIndexError, "index %ld too big", new_len);
1663 else if (! ARY_SHARED_P(ary)) {
1664 return ary_modify_for_unshift(ary, argc);
1666 else {
1667 VALUE shared_root = ARY_SHARED_ROOT(ary);
1668 long capa = RARRAY_LEN(shared_root);
1670 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
1671 return ary_modify_for_unshift(ary, argc);
1673 else if (new_len > capa) {
1674 return ary_modify_for_unshift(ary, argc);
1676 else {
1677 const VALUE * head = RARRAY_CONST_PTR(ary);
1678 void *sharedp = (void *)RARRAY_CONST_PTR(shared_root);
1680 rb_ary_modify_check(ary);
1681 return make_room_for_unshift(ary, head, sharedp, argc, capa, len);
1687 * call-seq:
1688 * unshift(*objects) -> self
1689 * prepend(*objects) -> self
1691 * Prepends the given +objects+ to +self+:
1693 * a = [:foo, 'bar', 2]
1694 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1696 * Related: Array#shift;
1697 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1700 VALUE
1701 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1703 long len = RARRAY_LEN(ary);
1704 VALUE target_ary;
1706 if (argc == 0) {
1707 rb_ary_modify_check(ary);
1708 return ary;
1711 target_ary = ary_ensure_room_for_unshift(ary, argc);
1712 ary_memcpy0(ary, 0, argc, argv, target_ary);
1713 ARY_SET_LEN(ary, len + argc);
1714 return ary;
1717 VALUE
1718 rb_ary_unshift(VALUE ary, VALUE item)
1720 return rb_ary_unshift_m(1, &item, ary);
1723 /* faster version - use this if you don't need to treat negative offset */
1724 static inline VALUE
1725 rb_ary_elt(VALUE ary, long offset)
1727 long len = RARRAY_LEN(ary);
1728 if (len == 0) return Qnil;
1729 if (offset < 0 || len <= offset) {
1730 return Qnil;
1732 return RARRAY_AREF(ary, offset);
1735 VALUE
1736 rb_ary_entry(VALUE ary, long offset)
1738 return rb_ary_entry_internal(ary, offset);
1741 VALUE
1742 rb_ary_subseq_step(VALUE ary, long beg, long len, long step)
1744 VALUE klass;
1745 long alen = RARRAY_LEN(ary);
1747 if (beg > alen) return Qnil;
1748 if (beg < 0 || len < 0) return Qnil;
1750 if (alen < len || alen < beg + len) {
1751 len = alen - beg;
1753 klass = rb_cArray;
1754 if (len == 0) return ary_new(klass, 0);
1755 if (step == 0)
1756 rb_raise(rb_eArgError, "slice step cannot be zero");
1757 if (step == 1)
1758 return ary_make_partial(ary, klass, beg, len);
1759 else
1760 return ary_make_partial_step(ary, klass, beg, len, step);
1763 VALUE
1764 rb_ary_subseq(VALUE ary, long beg, long len)
1766 return rb_ary_subseq_step(ary, beg, len, 1);
1769 static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
1772 * call-seq:
1773 * self[index] -> object or nil
1774 * self[start, length] -> object or nil
1775 * self[range] -> object or nil
1776 * self[aseq] -> object or nil
1777 * slice(index) -> object or nil
1778 * slice(start, length) -> object or nil
1779 * slice(range) -> object or nil
1780 * slice(aseq) -> object or nil
1782 * Returns elements from +self+; does not modify +self+.
1784 * In brief:
1786 * a = [:foo, 'bar', 2]
1788 * # Single argument index: returns one element.
1789 * a[0] # => :foo # Zero-based index.
1790 * a[-1] # => 2 # Negative index counts backwards from end.
1792 * # Arguments start and length: returns an array.
1793 * a[1, 2] # => ["bar", 2]
1794 * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end.
1796 * # Single argument range: returns an array.
1797 * a[0..1] # => [:foo, "bar"]
1798 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1799 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1801 * When a single integer argument +index+ is given, returns the element at offset +index+:
1803 * a = [:foo, 'bar', 2]
1804 * a[0] # => :foo
1805 * a[2] # => 2
1806 * a # => [:foo, "bar", 2]
1808 * If +index+ is negative, counts backwards from the end of +self+:
1810 * a = [:foo, 'bar', 2]
1811 * a[-1] # => 2
1812 * a[-2] # => "bar"
1814 * If +index+ is out of range, returns +nil+.
1816 * When two Integer arguments +start+ and +length+ are given,
1817 * returns a new array of size +length+ containing successive elements beginning at offset +start+:
1819 * a = [:foo, 'bar', 2]
1820 * a[0, 2] # => [:foo, "bar"]
1821 * a[1, 2] # => ["bar", 2]
1823 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1824 * returns all elements from offset +start+ to the end:
1826 * a = [:foo, 'bar', 2]
1827 * a[0, 4] # => [:foo, "bar", 2]
1828 * a[1, 3] # => ["bar", 2]
1829 * a[2, 2] # => [2]
1831 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1832 * returns a new empty array.
1834 * If +length+ is negative, returns +nil+.
1836 * When a single Range argument +range+ is given,
1837 * treats <tt>range.min</tt> as +start+ above
1838 * and <tt>range.size</tt> as +length+ above:
1840 * a = [:foo, 'bar', 2]
1841 * a[0..1] # => [:foo, "bar"]
1842 * a[1..2] # => ["bar", 2]
1844 * Special case: If <tt>range.start == a.size</tt>, returns a new empty array.
1846 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1848 * a = [:foo, 'bar', 2]
1849 * a[0..-1] # => [:foo, "bar", 2]
1850 * a[0..-2] # => [:foo, "bar"]
1851 * a[0..-3] # => [:foo]
1853 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1855 * a = [:foo, 'bar', 2]
1856 * a[-1..2] # => [2]
1857 * a[-2..2] # => ["bar", 2]
1858 * a[-3..2] # => [:foo, "bar", 2]
1860 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1862 * a = [:foo, 'bar', 2]
1863 * a[4..1] # => nil
1864 * a[4..0] # => nil
1865 * a[4..-1] # => nil
1867 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1868 * returns an array of elements corresponding to the indexes produced by
1869 * the sequence.
1871 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1872 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1874 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1875 * is larger than array size, throws RangeError.
1877 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1878 * a[(1..11).step(2)]
1879 * # RangeError (((1..11).step(2)) out of range)
1880 * a[(7..).step(2)]
1881 * # RangeError (((7..).step(2)) out of range)
1883 * If given a single argument, and its type is not one of the listed, tries to
1884 * convert it to Integer, and raises if it is impossible:
1886 * a = [:foo, 'bar', 2]
1887 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1888 * a[:foo]
1890 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1893 VALUE
1894 rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
1896 rb_check_arity(argc, 1, 2);
1897 if (argc == 2) {
1898 return rb_ary_aref2(ary, argv[0], argv[1]);
1900 return rb_ary_aref1(ary, argv[0]);
1903 static VALUE
1904 rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
1906 long beg = NUM2LONG(b);
1907 long len = NUM2LONG(e);
1908 if (beg < 0) {
1909 beg += RARRAY_LEN(ary);
1911 return rb_ary_subseq(ary, beg, len);
1914 VALUE
1915 rb_ary_aref1(VALUE ary, VALUE arg)
1917 long beg, len, step;
1919 /* special case - speeding up */
1920 if (FIXNUM_P(arg)) {
1921 return rb_ary_entry(ary, FIX2LONG(arg));
1923 /* check if idx is Range or ArithmeticSequence */
1924 switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
1925 case Qfalse:
1926 break;
1927 case Qnil:
1928 return Qnil;
1929 default:
1930 return rb_ary_subseq_step(ary, beg, len, step);
1933 return rb_ary_entry(ary, NUM2LONG(arg));
1937 * call-seq:
1938 * at(index) -> object or nil
1940 * Returns the element of +self+ specified by the given +index+
1941 * or +nil+ if there is no such element;
1942 * +index+ must be an
1943 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1945 * For non-negative +index+, returns the element of +self+ at offset +index+:
1947 * a = [:foo, 'bar', 2]
1948 * a.at(0) # => :foo
1949 * a.at(2) # => 2
1950 * a.at(2.0) # => 2
1952 * For negative +index+, counts backwards from the end of +self+:
1954 * a.at(-2) # => "bar"
1956 * Related: Array#[];
1957 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1960 VALUE
1961 rb_ary_at(VALUE ary, VALUE pos)
1963 return rb_ary_entry(ary, NUM2LONG(pos));
1966 #if 0
1967 static VALUE
1968 rb_ary_first(int argc, VALUE *argv, VALUE ary)
1970 if (argc == 0) {
1971 if (RARRAY_LEN(ary) == 0) return Qnil;
1972 return RARRAY_AREF(ary, 0);
1974 else {
1975 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1978 #endif
1980 static VALUE
1981 ary_first(VALUE self)
1983 return (RARRAY_LEN(self) == 0) ? Qnil : RARRAY_AREF(self, 0);
1986 static VALUE
1987 ary_last(VALUE self)
1989 long len = RARRAY_LEN(self);
1990 return (len == 0) ? Qnil : RARRAY_AREF(self, len-1);
1993 VALUE
1994 rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
1996 if (argc == 0) {
1997 return ary_last(ary);
1999 else {
2000 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
2005 * call-seq:
2006 * fetch(index) -> element
2007 * fetch(index, default_value) -> element or default_value
2008 * fetch(index) {|index| ... } -> element or block_return_value
2010 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2011 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2013 * With the single argument +index+ and no block,
2014 * returns the element at offset +index+:
2016 * a = [:foo, 'bar', 2]
2017 * a.fetch(1) # => "bar"
2018 * a.fetch(1.1) # => "bar"
2020 * If +index+ is negative, counts from the end of the array:
2022 * a = [:foo, 'bar', 2]
2023 * a.fetch(-1) # => 2
2024 * a.fetch(-2) # => "bar"
2026 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2027 * returns +default_value+ if +index+ is out-of-range:
2029 * a = [:foo, 'bar', 2]
2030 * a.fetch(1, nil) # => "bar"
2031 * a.fetch(3, :foo) # => :foo
2033 * With argument +index+ and a block,
2034 * returns the element at offset +index+ if index is in range
2035 * (and the block is not called); otherwise calls the block with index and returns its return value:
2037 * a = [:foo, 'bar', 2]
2038 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2039 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2041 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2044 static VALUE
2045 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
2047 VALUE pos, ifnone;
2048 long block_given;
2049 long idx;
2051 rb_scan_args(argc, argv, "11", &pos, &ifnone);
2052 block_given = rb_block_given_p();
2053 if (block_given && argc == 2) {
2054 rb_warn("block supersedes default value argument");
2056 idx = NUM2LONG(pos);
2058 if (idx < 0) {
2059 idx += RARRAY_LEN(ary);
2061 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
2062 if (block_given) return rb_yield(pos);
2063 if (argc == 1) {
2064 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
2065 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
2067 return ifnone;
2069 return RARRAY_AREF(ary, idx);
2073 * call-seq:
2074 * find_index(object) -> integer or nil
2075 * find_index {|element| ... } -> integer or nil
2076 * find_index -> new_enumerator
2077 * index(object) -> integer or nil
2078 * index {|element| ... } -> integer or nil
2079 * index -> new_enumerator
2081 * Returns the zero-based integer index of a specified element, or +nil+.
2083 * With only argument +object+ given,
2084 * returns the index of the first element +element+
2085 * for which <tt>object == element</tt>:
2087 * a = [:foo, 'bar', 2, 'bar']
2088 * a.index('bar') # => 1
2090 * Returns +nil+ if no such element found.
2092 * With only a block given,
2093 * calls the block with each successive element;
2094 * returns the index of the first element for which the block returns a truthy value:
2096 * a = [:foo, 'bar', 2, 'bar']
2097 * a.index {|element| element == 'bar' } # => 1
2099 * Returns +nil+ if the block never returns a truthy value.
2101 * With neither an argument nor a block given, returns a new Enumerator.
2103 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2106 static VALUE
2107 rb_ary_index(int argc, VALUE *argv, VALUE ary)
2109 VALUE val;
2110 long i;
2112 if (argc == 0) {
2113 RETURN_ENUMERATOR(ary, 0, 0);
2114 for (i=0; i<RARRAY_LEN(ary); i++) {
2115 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
2116 return LONG2NUM(i);
2119 return Qnil;
2121 rb_check_arity(argc, 0, 1);
2122 val = argv[0];
2123 if (rb_block_given_p())
2124 rb_warn("given block not used");
2125 for (i=0; i<RARRAY_LEN(ary); i++) {
2126 VALUE e = RARRAY_AREF(ary, i);
2127 if (rb_equal(e, val)) {
2128 return LONG2NUM(i);
2131 return Qnil;
2135 * call-seq:
2136 * rindex(object) -> integer or nil
2137 * rindex {|element| ... } -> integer or nil
2138 * rindex -> new_enumerator
2140 * Returns the index of the last element for which <tt>object == element</tt>.
2142 * With argument +object+ given, returns the index of the last such element found:
2144 * a = [:foo, 'bar', 2, 'bar']
2145 * a.rindex('bar') # => 3
2147 * Returns +nil+ if no such object found.
2149 * With a block given, calls the block with each successive element;
2150 * returns the index of the last element for which the block returns a truthy value:
2152 * a = [:foo, 'bar', 2, 'bar']
2153 * a.rindex {|element| element == 'bar' } # => 3
2155 * Returns +nil+ if the block never returns a truthy value.
2157 * When neither an argument nor a block is given, returns a new Enumerator.
2159 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2162 static VALUE
2163 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
2165 VALUE val;
2166 long i = RARRAY_LEN(ary), len;
2168 if (argc == 0) {
2169 RETURN_ENUMERATOR(ary, 0, 0);
2170 while (i--) {
2171 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
2172 return LONG2NUM(i);
2173 if (i > (len = RARRAY_LEN(ary))) {
2174 i = len;
2177 return Qnil;
2179 rb_check_arity(argc, 0, 1);
2180 val = argv[0];
2181 if (rb_block_given_p())
2182 rb_warn("given block not used");
2183 while (i--) {
2184 VALUE e = RARRAY_AREF(ary, i);
2185 if (rb_equal(e, val)) {
2186 return LONG2NUM(i);
2188 if (i > RARRAY_LEN(ary)) {
2189 break;
2192 return Qnil;
2195 VALUE
2196 rb_ary_to_ary(VALUE obj)
2198 VALUE tmp = rb_check_array_type(obj);
2200 if (!NIL_P(tmp)) return tmp;
2201 return rb_ary_new3(1, obj);
2204 static void
2205 rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
2207 long olen;
2208 long rofs;
2210 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
2211 olen = RARRAY_LEN(ary);
2212 if (beg < 0) {
2213 beg += olen;
2214 if (beg < 0) {
2215 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2216 beg - olen, -olen);
2219 if (olen < len || olen < beg + len) {
2220 len = olen - beg;
2224 const VALUE *optr = RARRAY_CONST_PTR(ary);
2225 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
2228 if (beg >= olen) {
2229 VALUE target_ary;
2230 if (beg > ARY_MAX_SIZE - rlen) {
2231 rb_raise(rb_eIndexError, "index %ld too big", beg);
2233 target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
2234 len = beg + rlen;
2235 ary_mem_clear(ary, olen, beg - olen);
2236 if (rlen > 0) {
2237 if (rofs != -1) rptr = RARRAY_CONST_PTR(ary) + rofs;
2238 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
2240 ARY_SET_LEN(ary, len);
2242 else {
2243 long alen;
2245 if (olen - len > ARY_MAX_SIZE - rlen) {
2246 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
2248 rb_ary_modify(ary);
2249 alen = olen + rlen - len;
2250 if (alen >= ARY_CAPA(ary)) {
2251 ary_double_capa(ary, alen);
2254 if (len != rlen) {
2255 RARRAY_PTR_USE(ary, ptr,
2256 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
2257 VALUE, olen - (beg + len)));
2258 ARY_SET_LEN(ary, alen);
2260 if (rlen > 0) {
2261 if (rofs == -1) {
2262 rb_gc_writebarrier_remember(ary);
2264 else {
2265 /* In this case, we're copying from a region in this array, so
2266 * we don't need to fire the write barrier. */
2267 rptr = RARRAY_CONST_PTR(ary) + rofs;
2270 /* do not use RARRAY_PTR() because it can causes GC.
2271 * ary can contain T_NONE object because it is not cleared.
2273 RARRAY_PTR_USE(ary, ptr,
2274 MEMMOVE(ptr + beg, rptr, VALUE, rlen));
2279 void
2280 rb_ary_set_len(VALUE ary, long len)
2282 long capa;
2284 rb_ary_modify_check(ary);
2285 if (ARY_SHARED_P(ary)) {
2286 rb_raise(rb_eRuntimeError, "can't set length of shared ");
2288 if (len > (capa = (long)ARY_CAPA(ary))) {
2289 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
2291 ARY_SET_LEN(ary, len);
2294 VALUE
2295 rb_ary_resize(VALUE ary, long len)
2297 long olen;
2299 rb_ary_modify(ary);
2300 olen = RARRAY_LEN(ary);
2301 if (len == olen) return ary;
2302 if (len > ARY_MAX_SIZE) {
2303 rb_raise(rb_eIndexError, "index %ld too big", len);
2305 if (len > olen) {
2306 if (len > ARY_CAPA(ary)) {
2307 ary_double_capa(ary, len);
2309 ary_mem_clear(ary, olen, len - olen);
2310 ARY_SET_LEN(ary, len);
2312 else if (ARY_EMBED_P(ary)) {
2313 ARY_SET_EMBED_LEN(ary, len);
2315 else if (len <= ary_embed_capa(ary)) {
2316 const VALUE *ptr = ARY_HEAP_PTR(ary);
2317 long ptr_capa = ARY_HEAP_SIZE(ary);
2318 bool is_malloc_ptr = !ARY_SHARED_P(ary);
2320 FL_SET_EMBED(ary);
2322 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); /* WB: no new reference */
2323 ARY_SET_EMBED_LEN(ary, len);
2325 if (is_malloc_ptr) ruby_sized_xfree((void *)ptr, ptr_capa);
2327 else {
2328 if (olen > len + ARY_DEFAULT_SIZE) {
2329 size_t new_capa = ary_heap_realloc(ary, len);
2330 ARY_SET_CAPA(ary, new_capa);
2332 ARY_SET_HEAP_LEN(ary, len);
2334 ary_verify(ary);
2335 return ary;
2338 static VALUE
2339 ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val)
2341 rb_ary_store(ary, key, val);
2342 return val;
2345 static VALUE
2346 ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
2348 VALUE rpl = rb_ary_to_ary(val);
2349 rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR(rpl), RARRAY_LEN(rpl));
2350 RB_GC_GUARD(rpl);
2351 return val;
2355 * call-seq:
2356 * self[index] = object -> object
2357 * self[start, length] = object -> object
2358 * self[range] = object -> object
2360 * Assigns elements in +self+, based on the given +object+; returns +object+.
2362 * In brief:
2364 * a_orig = [:foo, 'bar', 2]
2366 * # With argument index.
2367 * a = a_orig.dup
2368 * a[0] = 'foo' # => "foo"
2369 * a # => ["foo", "bar", 2]
2370 * a = a_orig.dup
2371 * a[7] = 'foo' # => "foo"
2372 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2374 * # With arguments start and length.
2375 * a = a_orig.dup
2376 * a[0, 2] = 'foo' # => "foo"
2377 * a # => ["foo", 2]
2378 * a = a_orig.dup
2379 * a[6, 50] = 'foo' # => "foo"
2380 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2382 * # With argument range.
2383 * a = a_orig.dup
2384 * a[0..1] = 'foo' # => "foo"
2385 * a # => ["foo", 2]
2386 * a = a_orig.dup
2387 * a[6..50] = 'foo' # => "foo"
2388 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2390 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2392 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2394 * a = [:foo, 'bar', 2]
2395 * a[0] = 'foo' # => "foo"
2396 * a # => ["foo", "bar", 2]
2398 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2400 * a = [:foo, 'bar', 2]
2401 * a[7] = 'foo' # => "foo"
2402 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2404 * If +index+ is negative, counts backwards from the end of the array:
2406 * a = [:foo, 'bar', 2]
2407 * a[-1] = 'two' # => "two"
2408 * a # => [:foo, "bar", "two"]
2410 * When Integer arguments +start+ and +length+ are given and +object+ is not an array,
2411 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2412 * and assigns +object+ at offset +start+:
2414 * a = [:foo, 'bar', 2]
2415 * a[0, 2] = 'foo' # => "foo"
2416 * a # => ["foo", 2]
2418 * If +start+ is negative, counts backwards from the end of the array:
2420 * a = [:foo, 'bar', 2]
2421 * a[-2, 2] = 'foo' # => "foo"
2422 * a # => [:foo, "foo"]
2424 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2425 * extends the array with +nil+, assigns +object+ at offset +start+,
2426 * and ignores +length+:
2428 * a = [:foo, 'bar', 2]
2429 * a[6, 50] = 'foo' # => "foo"
2430 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2432 * If +length+ is zero, shifts elements at and following offset +start+
2433 * and assigns +object+ at offset +start+:
2435 * a = [:foo, 'bar', 2]
2436 * a[1, 0] = 'foo' # => "foo"
2437 * a # => [:foo, "foo", "bar", 2]
2439 * If +length+ is too large for the existing array, does not extend the array:
2441 * a = [:foo, 'bar', 2]
2442 * a[1, 5] = 'foo' # => "foo"
2443 * a # => [:foo, "foo"]
2445 * When Range argument +range+ is given and +object+ is not an array,
2446 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2447 * and assigns +object+ at offset +start+:
2449 * a = [:foo, 'bar', 2]
2450 * a[0..1] = 'foo' # => "foo"
2451 * a # => ["foo", 2]
2453 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2455 * a = [:foo, 'bar', 2]
2456 * a[-2..2] = 'foo' # => "foo"
2457 * a # => [:foo, "foo"]
2459 * If the array length is less than <tt>range.begin</tt>,
2460 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2461 * and ignores +length+:
2463 * a = [:foo, 'bar', 2]
2464 * a[6..50] = 'foo' # => "foo"
2465 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2467 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2468 * and assigns +object+ at offset +start+:
2470 * a = [:foo, 'bar', 2]
2471 * a[1..0] = 'foo' # => "foo"
2472 * a # => [:foo, "foo", "bar", 2]
2474 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2475 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2477 * a = [:foo, 'bar', 2]
2478 * a[1..-1] = 'foo' # => "foo"
2479 * a # => [:foo, "foo"]
2480 * a = [:foo, 'bar', 2]
2481 * a[1..-2] = 'foo' # => "foo"
2482 * a # => [:foo, "foo", 2]
2483 * a = [:foo, 'bar', 2]
2484 * a[1..-3] = 'foo' # => "foo"
2485 * a # => [:foo, "foo", "bar", 2]
2486 * a = [:foo, 'bar', 2]
2488 * If <tt>range.end</tt> is too large for the existing array,
2489 * replaces array elements, but does not extend the array with +nil+ values:
2491 * a = [:foo, 'bar', 2]
2492 * a[1..5] = 'foo' # => "foo"
2493 * a # => [:foo, "foo"]
2495 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2498 static VALUE
2499 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
2501 long offset, beg, len;
2503 rb_check_arity(argc, 2, 3);
2504 rb_ary_modify_check(ary);
2505 if (argc == 3) {
2506 beg = NUM2LONG(argv[0]);
2507 len = NUM2LONG(argv[1]);
2508 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
2510 if (FIXNUM_P(argv[0])) {
2511 offset = FIX2LONG(argv[0]);
2512 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2514 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
2515 /* check if idx is Range */
2516 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
2519 offset = NUM2LONG(argv[0]);
2520 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2524 * call-seq:
2525 * insert(index, *objects) -> self
2527 * Inserts the given +objects+ as elements of +self+;
2528 * returns +self+.
2530 * When +index+ is non-negative, inserts +objects+
2531 * _before_ the element at offset +index+:
2533 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2534 * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]
2536 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2538 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2539 * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]
2541 * When +index+ is negative, inserts +objects+
2542 * _after_ the element at offset <tt>index + self.size</tt>:
2544 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2545 * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]
2547 * With no +objects+ given, does nothing:
2549 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2550 * a.insert(1) # => ["a", "b", "c"]
2551 * a.insert(50) # => ["a", "b", "c"]
2552 * a.insert(-50) # => ["a", "b", "c"]
2554 * Raises IndexError if +objects+ are given and +index+ is negative and out of range.
2556 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2559 static VALUE
2560 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
2562 long pos;
2564 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
2565 rb_ary_modify_check(ary);
2566 pos = NUM2LONG(argv[0]);
2567 if (argc == 1) return ary;
2568 if (pos == -1) {
2569 pos = RARRAY_LEN(ary);
2571 else if (pos < 0) {
2572 long minpos = -RARRAY_LEN(ary) - 1;
2573 if (pos < minpos) {
2574 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2575 pos, minpos);
2577 pos++;
2579 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
2580 return ary;
2583 static VALUE
2584 rb_ary_length(VALUE ary);
2586 static VALUE
2587 ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
2589 return rb_ary_length(ary);
2592 // Primitive to avoid a race condition in Array#each.
2593 // Return `true` and write `value` and `index` if the element exists.
2594 static VALUE
2595 ary_fetch_next(VALUE self, VALUE *index, VALUE *value)
2597 long i = NUM2LONG(*index);
2598 if (i >= RARRAY_LEN(self)) {
2599 return Qfalse;
2601 *value = RARRAY_AREF(self, i);
2602 *index = LONG2NUM(i + 1);
2603 return Qtrue;
2607 * call-seq:
2608 * each {|element| ... } -> self
2609 * each -> new_enumerator
2611 * With a block given, iterates over the elements of +self+,
2612 * passing each element to the block;
2613 * returns +self+:
2615 * a = [:foo, 'bar', 2]
2616 * a.each {|element| puts "#{element.class} #{element}" }
2618 * Output:
2620 * Symbol foo
2621 * String bar
2622 * Integer 2
2624 * Allows the array to be modified during iteration:
2626 * a = [:foo, 'bar', 2]
2627 * a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2629 * Output:
2631 * foo
2632 * bar
2634 * With no block given, returns a new Enumerator.
2636 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2639 VALUE
2640 rb_ary_each(VALUE ary)
2642 long i;
2643 ary_verify(ary);
2644 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2645 for (i=0; i<RARRAY_LEN(ary); i++) {
2646 rb_yield(RARRAY_AREF(ary, i));
2648 return ary;
2652 * call-seq:
2653 * each_index {|index| ... } -> self
2654 * each_index -> new_enumerator
2656 * With a block given, iterates over the elements of +self+,
2657 * passing each <i>array index</i> to the block;
2658 * returns +self+:
2660 * a = [:foo, 'bar', 2]
2661 * a.each_index {|index| puts "#{index} #{a[index]}" }
2663 * Output:
2665 * 0 foo
2666 * 1 bar
2667 * 2 2
2669 * Allows the array to be modified during iteration:
2671 * a = [:foo, 'bar', 2]
2672 * a.each_index {|index| puts index; a.clear if index > 0 }
2673 * a # => []
2675 * Output:
2680 * With no block given, returns a new Enumerator.
2682 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2685 static VALUE
2686 rb_ary_each_index(VALUE ary)
2688 long i;
2689 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2691 for (i=0; i<RARRAY_LEN(ary); i++) {
2692 rb_yield(LONG2NUM(i));
2694 return ary;
2698 * call-seq:
2699 * reverse_each {|element| ... } -> self
2700 * reverse_each -> Enumerator
2702 * When a block given, iterates backwards over the elements of +self+,
2703 * passing, in reverse order, each element to the block;
2704 * returns +self+:
2706 * a = []
2707 * [0, 1, 2].reverse_each {|element| a.push(element) }
2708 * a # => [2, 1, 0]
2710 * Allows the array to be modified during iteration:
2712 * a = ['a', 'b', 'c']
2713 * a.reverse_each {|element| a.clear if element.start_with?('b') }
2714 * a # => []
2716 * When no block given, returns a new Enumerator.
2718 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2721 static VALUE
2722 rb_ary_reverse_each(VALUE ary)
2724 long len;
2726 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2727 len = RARRAY_LEN(ary);
2728 while (len--) {
2729 long nlen;
2730 rb_yield(RARRAY_AREF(ary, len));
2731 nlen = RARRAY_LEN(ary);
2732 if (nlen < len) {
2733 len = nlen;
2736 return ary;
2740 * call-seq:
2741 * length -> integer
2742 * size -> integer
2744 * Returns the count of elements in +self+:
2746 * [0, 1, 2].length # => 3
2747 * [].length # => 0
2749 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2752 static VALUE
2753 rb_ary_length(VALUE ary)
2755 long len = RARRAY_LEN(ary);
2756 return LONG2NUM(len);
2760 * call-seq:
2761 * empty? -> true or false
2763 * Returns +true+ if the count of elements in +self+ is zero,
2764 * +false+ otherwise.
2766 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2769 static VALUE
2770 rb_ary_empty_p(VALUE ary)
2772 return RBOOL(RARRAY_LEN(ary) == 0);
2775 VALUE
2776 rb_ary_dup(VALUE ary)
2778 long len = RARRAY_LEN(ary);
2779 VALUE dup = rb_ary_new2(len);
2780 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
2781 ARY_SET_LEN(dup, len);
2783 ary_verify(ary);
2784 ary_verify(dup);
2785 return dup;
2788 VALUE
2789 rb_ary_resurrect(VALUE ary)
2791 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2794 extern VALUE rb_output_fs;
2796 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
2798 static VALUE
2799 recursive_join(VALUE obj, VALUE argp, int recur)
2801 VALUE *arg = (VALUE *)argp;
2802 VALUE ary = arg[0];
2803 VALUE sep = arg[1];
2804 VALUE result = arg[2];
2805 int *first = (int *)arg[3];
2807 if (recur) {
2808 rb_raise(rb_eArgError, "recursive array join");
2810 else {
2811 ary_join_1(obj, ary, sep, 0, result, first);
2813 return Qnil;
2816 static long
2817 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
2819 long i;
2820 VALUE val;
2822 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
2823 for (i=0; i<max; i++) {
2824 val = RARRAY_AREF(ary, i);
2825 if (!RB_TYPE_P(val, T_STRING)) break;
2826 if (i > 0 && !NIL_P(sep))
2827 rb_str_buf_append(result, sep);
2828 rb_str_buf_append(result, val);
2830 return i;
2833 static void
2834 ary_join_1_str(VALUE dst, VALUE src, int *first)
2836 rb_str_buf_append(dst, src);
2837 if (*first) {
2838 rb_enc_copy(dst, src);
2839 *first = FALSE;
2843 static void
2844 ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
2846 if (val == ary) {
2847 rb_raise(rb_eArgError, "recursive array join");
2849 else {
2850 VALUE args[4];
2852 *first = FALSE;
2853 args[0] = val;
2854 args[1] = sep;
2855 args[2] = result;
2856 args[3] = (VALUE)first;
2857 rb_exec_recursive(recursive_join, obj, (VALUE)args);
2861 static void
2862 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
2864 VALUE val, tmp;
2866 for (; i<RARRAY_LEN(ary); i++) {
2867 if (i > 0 && !NIL_P(sep))
2868 rb_str_buf_append(result, sep);
2870 val = RARRAY_AREF(ary, i);
2871 if (RB_TYPE_P(val, T_STRING)) {
2872 ary_join_1_str(result, val, first);
2874 else if (RB_TYPE_P(val, T_ARRAY)) {
2875 ary_join_1_ary(val, ary, sep, result, val, first);
2877 else if (!NIL_P(tmp = rb_check_string_type(val))) {
2878 ary_join_1_str(result, tmp, first);
2880 else if (!NIL_P(tmp = rb_check_array_type(val))) {
2881 ary_join_1_ary(val, ary, sep, result, tmp, first);
2883 else {
2884 ary_join_1_str(result, rb_obj_as_string(val), first);
2889 VALUE
2890 rb_ary_join(VALUE ary, VALUE sep)
2892 long len = 1, i;
2893 VALUE val, tmp, result;
2895 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
2897 if (!NIL_P(sep)) {
2898 StringValue(sep);
2899 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
2901 for (i=0; i<RARRAY_LEN(ary); i++) {
2902 val = RARRAY_AREF(ary, i);
2903 tmp = rb_check_string_type(val);
2905 if (NIL_P(tmp) || tmp != val) {
2906 int first;
2907 long n = RARRAY_LEN(ary);
2908 if (i > n) i = n;
2909 result = rb_str_buf_new(len + (n-i)*10);
2910 rb_enc_associate(result, rb_usascii_encoding());
2911 i = ary_join_0(ary, sep, i, result);
2912 first = i == 0;
2913 ary_join_1(ary, ary, sep, i, result, &first);
2914 return result;
2917 len += RSTRING_LEN(tmp);
2920 result = rb_str_new(0, len);
2921 rb_str_set_len(result, 0);
2923 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
2925 return result;
2929 * call-seq:
2930 * join(separator = $,) -> new_string
2932 * Returns the new string formed by joining the converted elements of +self+;
2933 * for each element +element+:
2935 * - Converts recursively using <tt>element.join(separator)</tt>
2936 * if +element+ is a <tt>kind_of?(Array)</tt>.
2937 * - Otherwise, converts using <tt>element.to_s</tt>.
2939 * With no argument given, joins using the output field separator, <tt>$,</tt>:
2941 * a = [:foo, 'bar', 2]
2942 * $, # => nil
2943 * a.join # => "foobar2"
2945 * With string argument +separator+ given, joins using that separator:
2947 * a = [:foo, 'bar', 2]
2948 * a.join("\n") # => "foo\nbar\n2"
2950 * Joins recursively for nested arrays:
2952 * a = [:foo, [:bar, [:baz, :bat]]]
2953 * a.join # => "foobarbazbat"
2955 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
2957 static VALUE
2958 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
2960 VALUE sep;
2962 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
2963 sep = rb_output_fs;
2964 if (!NIL_P(sep)) {
2965 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
2969 return rb_ary_join(ary, sep);
2972 static VALUE
2973 inspect_ary(VALUE ary, VALUE dummy, int recur)
2975 long i;
2976 VALUE s, str;
2978 if (recur) return rb_usascii_str_new_cstr("[...]");
2979 str = rb_str_buf_new2("[");
2980 for (i=0; i<RARRAY_LEN(ary); i++) {
2981 s = rb_inspect(RARRAY_AREF(ary, i));
2982 if (i > 0) rb_str_buf_cat2(str, ", ");
2983 else rb_enc_copy(str, s);
2984 rb_str_buf_append(str, s);
2986 rb_str_buf_cat2(str, "]");
2987 return str;
2991 * call-seq:
2992 * inspect -> new_string
2993 * to_s -> new_string
2995 * Returns the new string formed by calling method <tt>#inspect</tt>
2996 * on each array element:
2998 * a = [:foo, 'bar', 2]
2999 * a.inspect # => "[:foo, \"bar\", 2]"
3001 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3004 static VALUE
3005 rb_ary_inspect(VALUE ary)
3007 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
3008 return rb_exec_recursive(inspect_ary, ary, 0);
3011 VALUE
3012 rb_ary_to_s(VALUE ary)
3014 return rb_ary_inspect(ary);
3018 * call-seq:
3019 * to_a -> self or new_array
3021 * When +self+ is an instance of \Array, returns +self+.
3023 * Otherwise, returns a new array containing the elements of +self+:
3025 * class MyArray < Array; end
3026 * my_a = MyArray.new(['foo', 'bar', 'two'])
3027 * a = my_a.to_a
3028 * a # => ["foo", "bar", "two"]
3029 * a.class # => Array # Not MyArray.
3031 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3034 static VALUE
3035 rb_ary_to_a(VALUE ary)
3037 if (rb_obj_class(ary) != rb_cArray) {
3038 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
3039 rb_ary_replace(dup, ary);
3040 return dup;
3042 return ary;
3046 * call-seq:
3047 * to_h -> new_hash
3048 * to_h {|element| ... } -> new_hash
3050 * Returns a new hash formed from +self+.
3052 * With no block given, each element of +self+ must be a 2-element sub-array;
3053 * forms each sub-array into a key-value pair in the new hash:
3055 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3056 * a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
3057 * [].to_h # => {}
3059 * With a block given, the block must return a 2-element array;
3060 * calls the block with each element of +self+;
3061 * forms each returned array into a key-value pair in the returned hash:
3063 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3064 * a.to_h {|element| [element, element.class] }
3065 * # => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}
3067 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3070 static VALUE
3071 rb_ary_to_h(VALUE ary)
3073 long i;
3074 VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
3075 int block_given = rb_block_given_p();
3077 for (i=0; i<RARRAY_LEN(ary); i++) {
3078 const VALUE e = rb_ary_elt(ary, i);
3079 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
3080 const VALUE key_value_pair = rb_check_array_type(elt);
3081 if (NIL_P(key_value_pair)) {
3082 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
3083 rb_obj_class(elt), i);
3085 if (RARRAY_LEN(key_value_pair) != 2) {
3086 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
3087 i, RARRAY_LEN(key_value_pair));
3089 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
3091 return hash;
3095 * call-seq:
3096 * to_ary -> self
3098 * Returns +self+.
3101 static VALUE
3102 rb_ary_to_ary_m(VALUE ary)
3104 return ary;
3107 static void
3108 ary_reverse(VALUE *p1, VALUE *p2)
3110 while (p1 < p2) {
3111 VALUE tmp = *p1;
3112 *p1++ = *p2;
3113 *p2-- = tmp;
3117 VALUE
3118 rb_ary_reverse(VALUE ary)
3120 VALUE *p2;
3121 long len = RARRAY_LEN(ary);
3123 rb_ary_modify(ary);
3124 if (len > 1) {
3125 RARRAY_PTR_USE(ary, p1, {
3126 p2 = p1 + len - 1; /* points last item */
3127 ary_reverse(p1, p2);
3128 }); /* WB: no new reference */
3130 return ary;
3134 * call-seq:
3135 * reverse! -> self
3137 * Reverses the order of the elements of +self+;
3138 * returns +self+:
3140 * a = [0, 1, 2]
3141 * a.reverse! # => [2, 1, 0]
3142 * a # => [2, 1, 0]
3144 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3147 static VALUE
3148 rb_ary_reverse_bang(VALUE ary)
3150 return rb_ary_reverse(ary);
3154 * call-seq:
3155 * reverse -> new_array
3157 * Returns a new array containing the elements of +self+ in reverse order:
3159 * [0, 1, 2].reverse # => [2, 1, 0]
3161 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3164 static VALUE
3165 rb_ary_reverse_m(VALUE ary)
3167 long len = RARRAY_LEN(ary);
3168 VALUE dup = rb_ary_new2(len);
3170 if (len > 0) {
3171 const VALUE *p1 = RARRAY_CONST_PTR(ary);
3172 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
3173 do *p2-- = *p1++; while (--len > 0);
3175 ARY_SET_LEN(dup, RARRAY_LEN(ary));
3176 return dup;
3179 static inline long
3180 rotate_count(long cnt, long len)
3182 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3185 static void
3186 ary_rotate_ptr(VALUE *ptr, long len, long cnt)
3188 if (cnt == 1) {
3189 VALUE tmp = *ptr;
3190 memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
3191 *(ptr + len - 1) = tmp;
3193 else if (cnt == len - 1) {
3194 VALUE tmp = *(ptr + len - 1);
3195 memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
3196 *ptr = tmp;
3198 else {
3199 --len;
3200 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3201 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3202 if (len > 0) ary_reverse(ptr, ptr + len);
3206 VALUE
3207 rb_ary_rotate(VALUE ary, long cnt)
3209 rb_ary_modify(ary);
3211 if (cnt != 0) {
3212 long len = RARRAY_LEN(ary);
3213 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3214 RARRAY_PTR_USE(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
3215 return ary;
3218 return Qnil;
3222 * call-seq:
3223 * rotate!(count = 1) -> self
3225 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3227 * With non-negative numeric +count+,
3228 * rotates +count+ elements from the beginning to the end:
3230 * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1]
3231 [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]
3233 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3235 * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]
3237 * If +count+ is zero, rotates no elements:
3239 * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]
3241 * With a negative numeric +count+, rotates in the opposite direction,
3242 * from end to beginning:
3244 * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]
3246 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3248 * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]
3250 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3253 static VALUE
3254 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
3256 long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3257 rb_ary_rotate(ary, n);
3258 return ary;
3262 * call-seq:
3263 * rotate(count = 1) -> new_array
3265 * Returns a new array formed from +self+ with elements
3266 * rotated from one end to the other.
3268 * With non-negative numeric +count+,
3269 * rotates elements from the beginning to the end:
3271 * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1]
3272 * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]
3274 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3276 * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]
3278 * With a +count+ of zero, rotates no elements:
3280 * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]
3282 * With negative numeric +count+, rotates in the opposite direction,
3283 * from the end to the beginning:
3285 * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]
3287 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3289 * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]
3291 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3294 static VALUE
3295 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
3297 VALUE rotated;
3298 const VALUE *ptr;
3299 long len;
3300 long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3302 len = RARRAY_LEN(ary);
3303 rotated = rb_ary_new2(len);
3304 if (len > 0) {
3305 cnt = rotate_count(cnt, len);
3306 ptr = RARRAY_CONST_PTR(ary);
3307 len -= cnt;
3308 ary_memcpy(rotated, 0, len, ptr + cnt);
3309 ary_memcpy(rotated, len, cnt, ptr);
3311 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
3312 return rotated;
3315 struct ary_sort_data {
3316 VALUE ary;
3317 VALUE receiver;
3320 static VALUE
3321 sort_reentered(VALUE ary)
3323 if (RBASIC(ary)->klass) {
3324 rb_raise(rb_eRuntimeError, "sort reentered");
3326 return Qnil;
3329 static void
3330 sort_returned(struct ary_sort_data *data)
3332 if (rb_obj_frozen_p(data->receiver)) {
3333 rb_raise(rb_eFrozenError, "array frozen during sort");
3335 sort_reentered(data->ary);
3338 static int
3339 sort_1(const void *ap, const void *bp, void *dummy)
3341 struct ary_sort_data *data = dummy;
3342 VALUE retval = sort_reentered(data->ary);
3343 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3344 VALUE args[2];
3345 int n;
3347 args[0] = a;
3348 args[1] = b;
3349 retval = rb_yield_values2(2, args);
3350 n = rb_cmpint(retval, a, b);
3351 sort_returned(data);
3352 return n;
3355 static int
3356 sort_2(const void *ap, const void *bp, void *dummy)
3358 struct ary_sort_data *data = dummy;
3359 VALUE retval = sort_reentered(data->ary);
3360 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3361 int n;
3363 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
3364 if ((long)a > (long)b) return 1;
3365 if ((long)a < (long)b) return -1;
3366 return 0;
3368 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
3369 return rb_str_cmp(a, b);
3371 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
3372 return rb_float_cmp(a, b);
3375 retval = rb_funcallv(a, id_cmp, 1, &b);
3376 n = rb_cmpint(retval, a, b);
3377 sort_returned(data);
3379 return n;
3383 * call-seq:
3384 * sort! -> self
3385 * sort! {|a, b| ... } -> self
3387 * Like Array#sort, but returns +self+ with its elements sorted in place.
3389 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3392 VALUE
3393 rb_ary_sort_bang(VALUE ary)
3395 rb_ary_modify(ary);
3396 RUBY_ASSERT(!ARY_SHARED_P(ary));
3397 if (RARRAY_LEN(ary) > 1) {
3398 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
3399 struct ary_sort_data data;
3400 long len = RARRAY_LEN(ary);
3401 RBASIC_CLEAR_CLASS(tmp);
3402 data.ary = tmp;
3403 data.receiver = ary;
3404 RARRAY_PTR_USE(tmp, ptr, {
3405 ruby_qsort(ptr, len, sizeof(VALUE),
3406 rb_block_given_p()?sort_1:sort_2, &data);
3407 }); /* WB: no new reference */
3408 rb_ary_modify(ary);
3409 if (ARY_EMBED_P(tmp)) {
3410 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
3411 rb_ary_unshare(ary);
3412 FL_SET_EMBED(ary);
3414 if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
3415 ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
3417 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3418 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3420 else {
3421 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3422 FL_UNSET_SHARED(ary);
3423 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
3425 else {
3426 RUBY_ASSERT(!ARY_SHARED_P(tmp));
3427 if (ARY_EMBED_P(ary)) {
3428 FL_UNSET_EMBED(ary);
3430 else if (ARY_SHARED_P(ary)) {
3431 /* ary might be destructively operated in the given block */
3432 rb_ary_unshare(ary);
3434 else {
3435 ary_heap_free(ary);
3437 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3438 ARY_SET_HEAP_LEN(ary, len);
3439 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3441 /* tmp was lost ownership for the ptr */
3442 FL_UNSET(tmp, FL_FREEZE);
3443 FL_SET_EMBED(tmp);
3444 ARY_SET_EMBED_LEN(tmp, 0);
3445 FL_SET(tmp, FL_FREEZE);
3447 /* tmp will be GC'ed. */
3448 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
3450 ary_verify(ary);
3451 return ary;
3455 * call-seq:
3456 * sort -> new_array
3457 * sort {|a, b| ... } -> new_array
3459 * Returns a new array containing the elements of +self+, sorted.
3461 * With no block given, compares elements using operator <tt>#<=></tt>
3462 * (see Object#<=>):
3464 * [0, 2, 3, 1].sort # => [0, 1, 2, 3]
3466 * With a block given, calls the block with each combination of pairs of elements from +self+;
3467 * for each pair +a+ and +b+, the block should return a numeric:
3469 * - Negative when +b+ is to follow +a+.
3470 * - Zero when +a+ and +b+ are equivalent.
3471 * - Positive when +a+ is to follow +b+.
3473 * Example:
3475 * a = [3, 2, 0, 1]
3476 * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
3477 * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]
3479 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3480 * and may be unstable.
3482 * See an example in Numeric#nonzero? for the idiom to sort more
3483 * complex structure.
3485 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3488 VALUE
3489 rb_ary_sort(VALUE ary)
3491 ary = rb_ary_dup(ary);
3492 rb_ary_sort_bang(ary);
3493 return ary;
3496 static VALUE rb_ary_bsearch_index(VALUE ary);
3499 * call-seq:
3500 * bsearch {|element| ... } -> found_element or nil
3501 * bsearch -> new_enumerator
3503 * Returns the element from +self+ found by a binary search,
3504 * or +nil+ if the search found no suitable element.
3506 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3508 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3511 static VALUE
3512 rb_ary_bsearch(VALUE ary)
3514 VALUE index_result = rb_ary_bsearch_index(ary);
3516 if (FIXNUM_P(index_result)) {
3517 return rb_ary_entry(ary, FIX2LONG(index_result));
3519 return index_result;
3523 * call-seq:
3524 * bsearch_index {|element| ... } -> integer or nil
3525 * bsearch_index -> new_enumerator
3527 * Returns the integer index of the element from +self+ found by a binary search,
3528 * or +nil+ if the search found no suitable element.
3530 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3532 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3535 static VALUE
3536 rb_ary_bsearch_index(VALUE ary)
3538 long low = 0, high = RARRAY_LEN(ary), mid;
3539 int smaller = 0, satisfied = 0;
3540 VALUE v, val;
3542 RETURN_ENUMERATOR(ary, 0, 0);
3543 while (low < high) {
3544 mid = low + ((high - low) / 2);
3545 val = rb_ary_entry(ary, mid);
3546 v = rb_yield(val);
3547 if (FIXNUM_P(v)) {
3548 if (v == INT2FIX(0)) return INT2FIX(mid);
3549 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
3551 else if (v == Qtrue) {
3552 satisfied = 1;
3553 smaller = 1;
3555 else if (!RTEST(v)) {
3556 smaller = 0;
3558 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
3559 const VALUE zero = INT2FIX(0);
3560 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
3561 case 0: return INT2FIX(mid);
3562 case 1: smaller = 0; break;
3563 case -1: smaller = 1;
3566 else {
3567 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
3568 " (must be numeric, true, false or nil)",
3569 rb_obj_class(v));
3571 if (smaller) {
3572 high = mid;
3574 else {
3575 low = mid + 1;
3578 if (!satisfied) return Qnil;
3579 return INT2FIX(low);
3583 static VALUE
3584 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3586 return rb_yield(i);
3590 * call-seq:
3591 * sort_by! {|element| ... } -> self
3592 * sort_by! -> new_enumerator
3594 * With a block given, sorts the elements of +self+ in place;
3595 * returns self.
3597 * Calls the block with each successive element;
3598 * sorts elements based on the values returned from the block:
3600 * a = ['aaaa', 'bbb', 'cc', 'd']
3601 * a.sort_by! {|element| element.size }
3602 * a # => ["d", "cc", "bbb", "aaaa"]
3604 * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable.
3606 * With no block given, returns a new Enumerator.
3608 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3611 static VALUE
3612 rb_ary_sort_by_bang(VALUE ary)
3614 VALUE sorted;
3616 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3617 rb_ary_modify(ary);
3618 if (RARRAY_LEN(ary) > 1) {
3619 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3620 rb_ary_replace(ary, sorted);
3622 return ary;
3627 * call-seq:
3628 * collect {|element| ... } -> new_array
3629 * collect -> new_enumerator
3630 * map {|element| ... } -> new_array
3631 * map -> new_enumerator
3633 * With a block given, calls the block with each element of +self+;
3634 * returns a new array whose elements are the return values from the block:
3636 * a = [:foo, 'bar', 2]
3637 * a1 = a.map {|element| element.class }
3638 * a1 # => [Symbol, String, Integer]
3640 * With no block given, returns a new Enumerator.
3642 * Related: #collect!;
3643 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3646 static VALUE
3647 rb_ary_collect(VALUE ary)
3649 long i;
3650 VALUE collect;
3652 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3653 collect = rb_ary_new2(RARRAY_LEN(ary));
3654 for (i = 0; i < RARRAY_LEN(ary); i++) {
3655 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3657 return collect;
3662 * call-seq:
3663 * collect! {|element| ... } -> new_array
3664 * collect! -> new_enumerator
3665 * map! {|element| ... } -> new_array
3666 * map! -> new_enumerator
3668 * With a block given, calls the block with each element of +self+
3669 * and replaces the element with the block's return value;
3670 * returns +self+:
3672 * a = [:foo, 'bar', 2]
3673 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3675 * With no block given, returns a new Enumerator.
3677 * Related: #collect;
3678 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3681 static VALUE
3682 rb_ary_collect_bang(VALUE ary)
3684 long i;
3686 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3687 rb_ary_modify(ary);
3688 for (i = 0; i < RARRAY_LEN(ary); i++) {
3689 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
3691 return ary;
3694 VALUE
3695 rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
3697 VALUE result = rb_ary_new2(argc);
3698 long beg, len, i, j;
3700 for (i=0; i<argc; i++) {
3701 if (FIXNUM_P(argv[i])) {
3702 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3703 continue;
3705 /* check if idx is Range */
3706 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3707 long end = olen < beg+len ? olen : beg+len;
3708 for (j = beg; j < end; j++) {
3709 rb_ary_push(result, (*func)(obj, j));
3711 if (beg + len > j)
3712 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
3713 continue;
3715 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
3717 return result;
3720 static VALUE
3721 append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
3723 long beg, len;
3724 if (FIXNUM_P(idx)) {
3725 beg = FIX2LONG(idx);
3727 /* check if idx is Range */
3728 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
3729 if (len > 0) {
3730 const VALUE *const src = RARRAY_CONST_PTR(ary);
3731 const long end = beg + len;
3732 const long prevlen = RARRAY_LEN(result);
3733 if (beg < olen) {
3734 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3736 if (end > olen) {
3737 rb_ary_store(result, prevlen + len - 1, Qnil);
3740 return result;
3742 else {
3743 beg = NUM2LONG(idx);
3745 return rb_ary_push(result, rb_ary_entry(ary, beg));
3749 * call-seq:
3750 * values_at(*specifiers) -> new_array
3752 * Returns elements from +self+ in a new array; does not modify +self+.
3754 * The objects included in the returned array are the elements of +self+
3755 * selected by the given +specifiers+,
3756 * each of which must be a numeric index or a Range.
3758 * In brief:
3760 * a = ['a', 'b', 'c', 'd']
3762 * # Index specifiers.
3763 * a.values_at(2, 0, 2, 0) # => ["c", "a", "c", "a"] # May repeat.
3764 * a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative.
3765 * a.values_at(-50, 50) # => [nil, nil] # Outside of self.
3767 * # Range specifiers.
3768 * a.values_at(1..3) # => ["b", "c", "d"] # From range.begin to range.end.
3769 * a.values_at(1...3) # => ["b", "c"] # End excluded.
3770 * a.values_at(3..1) # => [] # No such elements.
3772 * a.values_at(-3..3) # => ["b", "c", "d"] # Negative range.begin counts backwards.
3773 * a.values_at(-50..3) # Raises RangeError.
3775 * a.values_at(1..-2) # => ["b", "c"] # Negative range.end counts backwards.
3776 * a.values_at(1..-50) # => [] # No such elements.
3778 * # Mixture of specifiers.
3779 * a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"]
3781 * With no +specifiers+ given, returns a new empty array:
3783 * a = ['a', 'b', 'c', 'd']
3784 * a.values_at # => []
3786 * For each numeric specifier +index+, includes an element:
3788 * - For each non-negative numeric specifier +index+ that is in-range (less than <tt>self.size</tt>),
3789 * includes the element at offset +index+:
3791 * a.values_at(0, 2) # => ["a", "c"]
3792 * a.values_at(0.1, 2.9) # => ["a", "c"]
3794 * - For each negative numeric +index+ that is in-range (greater than or equal to <tt>- self.size</tt>),
3795 * counts backwards from the end of +self+:
3797 * a.values_at(-1, -4) # => ["d", "a"]
3799 * The given indexes may be in any order, and may repeat:
3801 * a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"]
3803 * For each +index+ that is out-of-range, includes +nil+:
3805 * a.values_at(4, -5) # => [nil, nil]
3807 * For each Range specifier +range+, includes elements
3808 * according to <tt>range.begin</tt> and <tt>range.end</tt>:
3810 * - If both <tt>range.begin</tt> and <tt>range.end</tt>
3811 * are non-negative and in-range (less than <tt>self.size</tt>),
3812 * includes elements from index <tt>range.begin</tt>
3813 * through <tt>range.end - 1</tt> (if <tt>range.exclude_end?</tt>),
3814 * or through <tt>range.end</tt> (otherwise):
3816 * a.values_at(1..2) # => ["b", "c"]
3817 * a.values_at(1...2) # => ["b"]
3819 * - If <tt>range.begin</tt> is negative and in-range (greater than or equal to <tt>- self.size</tt>),
3820 * counts backwards from the end of +self+:
3822 * a.values_at(-2..3) # => ["c", "d"]
3824 * - If <tt>range.begin</tt> is negative and out-of-range, raises an exception:
3826 * a.values_at(-5..3) # Raises RangeError.
3828 * - If <tt>range.end</tt> is positive and out-of-range,
3829 * extends the returned array with +nil+ elements:
3831 * a.values_at(1..5) # => ["b", "c", "d", nil, nil]
3833 * - If <tt>range.end</tt> is negative and in-range,
3834 * counts backwards from the end of +self+:
3836 * a.values_at(1..-2) # => ["b", "c"]
3838 * - If <tt>range.end</tt> is negative and out-of-range,
3839 * returns an empty array:
3841 * a.values_at(1..-5) # => []
3843 * The given ranges may be in any order and may repeat:
3845 * a.values_at(2..3, 0..1, 2..3) # => ["c", "d", "a", "b", "c", "d"]
3847 * The given specifiers may be any mixture of indexes and ranges:
3849 * a.values_at(3, 1..2, 0, 2..3) # => ["d", "b", "c", "a", "c", "d"]
3851 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3854 static VALUE
3855 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
3857 long i, olen = RARRAY_LEN(ary);
3858 VALUE result = rb_ary_new_capa(argc);
3859 for (i = 0; i < argc; ++i) {
3860 append_values_at_single(result, ary, olen, argv[i]);
3862 RB_GC_GUARD(ary);
3863 return result;
3868 * call-seq:
3869 * select {|element| ... } -> new_array
3870 * select -> new_enumerator
3871 * filter {|element| ... } -> new_array
3872 * filter -> new_enumerator
3874 * With a block given, calls the block with each element of +self+;
3875 * returns a new array containing those elements of +self+
3876 * for which the block returns a truthy value:
3878 * a = [:foo, 'bar', 2, :bam]
3879 * a.select {|element| element.to_s.start_with?('b') }
3880 * # => ["bar", :bam]
3882 * With no block given, returns a new Enumerator.
3884 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3887 static VALUE
3888 rb_ary_select(VALUE ary)
3890 VALUE result;
3891 long i;
3893 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3894 result = rb_ary_new2(RARRAY_LEN(ary));
3895 for (i = 0; i < RARRAY_LEN(ary); i++) {
3896 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
3897 rb_ary_push(result, rb_ary_elt(ary, i));
3900 return result;
3903 struct select_bang_arg {
3904 VALUE ary;
3905 long len[2];
3908 static VALUE
3909 select_bang_i(VALUE a)
3911 volatile struct select_bang_arg *arg = (void *)a;
3912 VALUE ary = arg->ary;
3913 long i1, i2;
3915 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
3916 VALUE v = RARRAY_AREF(ary, i1);
3917 if (!RTEST(rb_yield(v))) continue;
3918 if (i1 != i2) {
3919 rb_ary_store(ary, i2, v);
3921 arg->len[1] = ++i2;
3923 return (i1 == i2) ? Qnil : ary;
3926 static VALUE
3927 select_bang_ensure(VALUE a)
3929 volatile struct select_bang_arg *arg = (void *)a;
3930 VALUE ary = arg->ary;
3931 long len = RARRAY_LEN(ary);
3932 long i1 = arg->len[0], i2 = arg->len[1];
3934 if (i2 < len && i2 < i1) {
3935 long tail = 0;
3936 rb_ary_modify(ary);
3937 if (i1 < len) {
3938 tail = len - i1;
3939 RARRAY_PTR_USE(ary, ptr, {
3940 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
3943 ARY_SET_LEN(ary, i2 + tail);
3945 return ary;
3949 * call-seq:
3950 * select! {|element| ... } -> self or nil
3951 * select! -> new_enumerator
3952 * filter! {|element| ... } -> self or nil
3953 * filter! -> new_enumerator
3955 * With a block given, calls the block with each element of +self+;
3956 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3958 * Returns +self+ if any elements were removed:
3960 * a = [:foo, 'bar', 2, :bam]
3961 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3963 * Returns +nil+ if no elements were removed.
3965 * With no block given, returns a new Enumerator.
3967 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3970 static VALUE
3971 rb_ary_select_bang(VALUE ary)
3973 struct select_bang_arg args;
3975 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3976 rb_ary_modify(ary);
3978 args.ary = ary;
3979 args.len[0] = args.len[1] = 0;
3980 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
3984 * call-seq:
3985 * keep_if {|element| ... } -> self
3986 * keep_if -> new_enumerator
3988 * With a block given, calls the block with each element of +self+;
3989 * removes the element from +self+ if the block does not return a truthy value:
3991 * a = [:foo, 'bar', 2, :bam]
3992 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3994 * With no block given, returns a new Enumerator.
3996 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3999 static VALUE
4000 rb_ary_keep_if(VALUE ary)
4002 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4003 rb_ary_select_bang(ary);
4004 return ary;
4007 static void
4008 ary_resize_smaller(VALUE ary, long len)
4010 rb_ary_modify(ary);
4011 if (RARRAY_LEN(ary) > len) {
4012 ARY_SET_LEN(ary, len);
4013 if (len * 2 < ARY_CAPA(ary) &&
4014 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
4015 ary_resize_capa(ary, len * 2);
4021 * call-seq:
4022 * delete(object) -> last_removed_object
4023 * delete(object) {|element| ... } -> last_removed_object or block_return
4025 * Removes zero or more elements from +self+.
4027 * With no block given,
4028 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4029 * returns the last removed element:
4031 * a = [0, 1, 2, 2.0]
4032 * a.delete(2) # => 2.0
4033 * a # => [0, 1]
4035 * Returns +nil+ if no elements removed:
4037 * a.delete(2) # => nil
4039 * With a block given,
4040 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4042 * If any such elements are found, ignores the block
4043 * and returns the last removed element:
4045 * a = [0, 1, 2, 2.0]
4046 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4047 * a # => [0, 1]
4049 * If no such element is found, returns the block's return value:
4051 * a.delete(2) {|element| "Element #{element} not found." }
4052 * # => "Element 2 not found."
4054 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4057 VALUE
4058 rb_ary_delete(VALUE ary, VALUE item)
4060 VALUE v = item;
4061 long i1, i2;
4063 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4064 VALUE e = RARRAY_AREF(ary, i1);
4066 if (rb_equal(e, item)) {
4067 v = e;
4068 continue;
4070 if (i1 != i2) {
4071 rb_ary_store(ary, i2, e);
4073 i2++;
4075 if (RARRAY_LEN(ary) == i2) {
4076 if (rb_block_given_p()) {
4077 return rb_yield(item);
4079 return Qnil;
4082 ary_resize_smaller(ary, i2);
4084 ary_verify(ary);
4085 return v;
4088 void
4089 rb_ary_delete_same(VALUE ary, VALUE item)
4091 long i1, i2;
4093 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4094 VALUE e = RARRAY_AREF(ary, i1);
4096 if (e == item) {
4097 continue;
4099 if (i1 != i2) {
4100 rb_ary_store(ary, i2, e);
4102 i2++;
4104 if (RARRAY_LEN(ary) == i2) {
4105 return;
4108 ary_resize_smaller(ary, i2);
4111 VALUE
4112 rb_ary_delete_at(VALUE ary, long pos)
4114 long len = RARRAY_LEN(ary);
4115 VALUE del;
4117 if (pos >= len) return Qnil;
4118 if (pos < 0) {
4119 pos += len;
4120 if (pos < 0) return Qnil;
4123 rb_ary_modify(ary);
4124 del = RARRAY_AREF(ary, pos);
4125 RARRAY_PTR_USE(ary, ptr, {
4126 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
4128 ARY_INCREASE_LEN(ary, -1);
4129 ary_verify(ary);
4130 return del;
4134 * call-seq:
4135 * delete_at(index) -> removed_object or nil
4137 * Removes the element of +self+ at the given +index+, which must be an
4138 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4140 * When +index+ is non-negative, deletes the element at offset +index+:
4142 * a = [:foo, 'bar', 2]
4143 * a.delete_at(1) # => "bar"
4144 * a # => [:foo, 2]
4146 * When +index+ is negative, counts backward from the end of the array:
4148 * a = [:foo, 'bar', 2]
4149 * a.delete_at(-2) # => "bar"
4150 * a # => [:foo, 2]
4152 * When +index+ is out of range, returns +nil+.
4154 * a = [:foo, 'bar', 2]
4155 * a.delete_at(3) # => nil
4156 * a.delete_at(-4) # => nil
4158 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4161 static VALUE
4162 rb_ary_delete_at_m(VALUE ary, VALUE pos)
4164 return rb_ary_delete_at(ary, NUM2LONG(pos));
4167 static VALUE
4168 ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
4170 const long orig_len = RARRAY_LEN(ary);
4172 if (len < 0) {
4173 return Qnil;
4175 else if (pos < -orig_len) {
4176 return Qnil;
4178 else if (pos < 0) {
4179 pos += orig_len;
4181 else if (orig_len < pos) {
4182 return Qnil;
4184 if (orig_len < pos + len) {
4185 len = orig_len - pos;
4187 if (len == 0) {
4188 return rb_ary_new2(0);
4190 else {
4191 VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
4192 rb_ary_splice(ary, pos, len, 0, 0);
4193 return arg2;
4198 * call-seq:
4199 * slice!(index) -> object or nil
4200 * slice!(start, length) -> new_array or nil
4201 * slice!(range) -> new_array or nil
4203 * Removes and returns elements from +self+.
4205 * With numeric argument +index+ given,
4206 * removes and returns the element at offset +index+:
4208 * a = ['a', 'b', 'c', 'd']
4209 * a.slice!(2) # => "c"
4210 * a # => ["a", "b", "d"]
4211 * a.slice!(2.1) # => "d"
4212 * a # => ["a", "b"]
4214 * If +index+ is negative, counts backwards from the end of +self+:
4216 * a = ['a', 'b', 'c', 'd']
4217 * a.slice!(-2) # => "c"
4218 * a # => ["a", "b", "d"]
4220 * If +index+ is out of range, returns +nil+.
4222 * With numeric arguments +start+ and +length+ given,
4223 * removes +length+ elements from +self+ beginning at zero-based offset +start+;
4224 * returns the removed objects in a new array:
4226 * a = ['a', 'b', 'c', 'd']
4227 * a.slice!(1, 2) # => ["b", "c"]
4228 * a # => ["a", "d"]
4229 * a.slice!(0.1, 1.1) # => ["a"]
4230 * a # => ["d"]
4232 * If +start+ is negative, counts backwards from the end of +self+:
4234 * a = ['a', 'b', 'c', 'd']
4235 * a.slice!(-2, 1) # => ["c"]
4236 * a # => ["a", "b", "d"]
4238 * If +start+ is out-of-range, returns +nil+:
4240 * a = ['a', 'b', 'c', 'd']
4241 * a.slice!(5, 1) # => nil
4242 * a.slice!(-5, 1) # => nil
4244 * If <tt>start + length</tt> exceeds the array size,
4245 * removes and returns all elements from offset +start+ to the end:
4247 * a = ['a', 'b', 'c', 'd']
4248 * a.slice!(2, 50) # => ["c", "d"]
4249 * a # => ["a", "b"]
4251 * If <tt>start == a.size</tt> and +length+ is non-negative,
4252 * returns a new empty array.
4254 * If +length+ is negative, returns +nil+.
4256 * With Range argument +range+ given,
4257 * treats <tt>range.min</tt> as +start+ (as above)
4258 * and <tt>range.size</tt> as +length+ (as above):
4260 * a = ['a', 'b', 'c', 'd']
4261 * a.slice!(1..2) # => ["b", "c"]
4262 * a # => ["a", "d"]
4264 * If <tt>range.start == a.size</tt>, returns a new empty array:
4266 * a = ['a', 'b', 'c', 'd']
4267 * a.slice!(4..5) # => []
4269 * If <tt>range.start</tt> is larger than the array size, returns +nil+:
4271 * a = ['a', 'b', 'c', 'd']
4272 a.slice!(5..6) # => nil
4274 * If <tt>range.start</tt> is negative,
4275 * calculates the start index by counting backwards from the end of +self+:
4277 * a = ['a', 'b', 'c', 'd']
4278 * a.slice!(-2..2) # => ["c"]
4280 * If <tt>range.end</tt> is negative,
4281 * calculates the end index by counting backwards from the end of +self+:
4283 * a = ['a', 'b', 'c', 'd']
4284 * a.slice!(0..-2) # => ["a", "b", "c"]
4286 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4289 static VALUE
4290 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
4292 VALUE arg1;
4293 long pos, len;
4295 rb_ary_modify_check(ary);
4296 rb_check_arity(argc, 1, 2);
4297 arg1 = argv[0];
4299 if (argc == 2) {
4300 pos = NUM2LONG(argv[0]);
4301 len = NUM2LONG(argv[1]);
4302 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4305 if (!FIXNUM_P(arg1)) {
4306 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
4307 case Qtrue:
4308 /* valid range */
4309 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4310 case Qnil:
4311 /* invalid range */
4312 return Qnil;
4313 default:
4314 /* not a range */
4315 break;
4319 return rb_ary_delete_at(ary, NUM2LONG(arg1));
4322 static VALUE
4323 ary_reject(VALUE orig, VALUE result)
4325 long i;
4327 for (i = 0; i < RARRAY_LEN(orig); i++) {
4328 VALUE v = RARRAY_AREF(orig, i);
4330 if (!RTEST(rb_yield(v))) {
4331 rb_ary_push(result, v);
4334 return result;
4337 static VALUE
4338 reject_bang_i(VALUE a)
4340 volatile struct select_bang_arg *arg = (void *)a;
4341 VALUE ary = arg->ary;
4342 long i1, i2;
4344 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4345 VALUE v = RARRAY_AREF(ary, i1);
4346 if (RTEST(rb_yield(v))) continue;
4347 if (i1 != i2) {
4348 rb_ary_store(ary, i2, v);
4350 arg->len[1] = ++i2;
4352 return (i1 == i2) ? Qnil : ary;
4355 static VALUE
4356 ary_reject_bang(VALUE ary)
4358 struct select_bang_arg args;
4359 rb_ary_modify_check(ary);
4360 args.ary = ary;
4361 args.len[0] = args.len[1] = 0;
4362 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4366 * call-seq:
4367 * reject! {|element| ... } -> self or nil
4368 * reject! -> new_enumerator
4370 * With a block given, calls the block with each element of +self+;
4371 * removes each element for which the block returns a truthy value.
4373 * Returns +self+ if any elements removed:
4375 * a = [:foo, 'bar', 2, 'bat']
4376 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4378 * Returns +nil+ if no elements removed.
4380 * With no block given, returns a new Enumerator.
4382 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4385 static VALUE
4386 rb_ary_reject_bang(VALUE ary)
4388 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4389 rb_ary_modify(ary);
4390 return ary_reject_bang(ary);
4394 * call-seq:
4395 * reject {|element| ... } -> new_array
4396 * reject -> new_enumerator
4398 * With a block given, returns a new array whose elements are all those from +self+
4399 * for which the block returns +false+ or +nil+:
4401 * a = [:foo, 'bar', 2, 'bat']
4402 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4403 * a1 # => [:foo, 2]
4405 * With no block given, returns a new Enumerator.
4407 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4410 static VALUE
4411 rb_ary_reject(VALUE ary)
4413 VALUE rejected_ary;
4415 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4416 rejected_ary = rb_ary_new();
4417 ary_reject(ary, rejected_ary);
4418 return rejected_ary;
4422 * call-seq:
4423 * delete_if {|element| ... } -> self
4424 * delete_if -> new_numerator
4426 * With a block given, calls the block with each element of +self+;
4427 * removes the element if the block returns a truthy value;
4428 * returns +self+:
4430 * a = [:foo, 'bar', 2, 'bat']
4431 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4433 * With no block given, returns a new Enumerator.
4435 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4438 static VALUE
4439 rb_ary_delete_if(VALUE ary)
4441 ary_verify(ary);
4442 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4443 ary_reject_bang(ary);
4444 return ary;
4447 static VALUE
4448 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
4450 VALUE *args = (VALUE *)cbarg;
4451 if (argc > 1) val = rb_ary_new4(argc, argv);
4452 rb_ary_push(args[0], val);
4453 if (--args[1] == 0) rb_iter_break();
4454 return Qnil;
4457 static VALUE
4458 take_items(VALUE obj, long n)
4460 VALUE result = rb_check_array_type(obj);
4461 VALUE args[2];
4463 if (n == 0) return result;
4464 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
4465 result = rb_ary_new2(n);
4466 args[0] = result; args[1] = (VALUE)n;
4467 if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
4468 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
4469 rb_obj_class(obj));
4470 return result;
4475 * call-seq:
4476 * zip(*other_arrays) -> new_array
4477 * zip(*other_arrays) {|sub_array| ... } -> nil
4479 * With no block given, combines +self+ with the collection of +other_arrays+;
4480 * returns a new array of sub-arrays:
4482 * [0, 1].zip(['zero', 'one'], [:zero, :one])
4483 * # => [[0, "zero", :zero], [1, "one", :one]]
4485 * Returned:
4487 * - The outer array is of size <tt>self.size</tt>.
4488 * - Each sub-array is of size <tt>other_arrays.size + 1</tt>.
4489 * - The _nth_ sub-array contains (in order):
4491 * - The _nth_ element of +self+.
4492 * - The _nth_ element of each of the other arrays, as available.
4494 * Example:
4496 * a = [0, 1]
4497 * zipped = a.zip(['zero', 'one'], [:zero, :one])
4498 * # => [[0, "zero", :zero], [1, "one", :one]]
4499 * zipped.size # => 2 # Same size as a.
4500 * zipped.first.size # => 3 # Size of other arrays plus 1.
4502 * When the other arrays are all the same size as +self+,
4503 * the returned sub-arrays are a rearrangement containing exactly elements of all the arrays
4504 * (including +self+), with no omissions or additions:
4506 * a = [:a0, :a1, :a2, :a3]
4507 * b = [:b0, :b1, :b2, :b3]
4508 * c = [:c0, :c1, :c2, :c3]
4509 * d = a.zip(b, c)
4510 * pp d
4511 * # =>
4512 * [[:a0, :b0, :c0],
4513 * [:a1, :b1, :c1],
4514 * [:a2, :b2, :c2],
4515 * [:a3, :b3, :c3]]
4517 * When one of the other arrays is smaller than +self+,
4518 * pads the corresponding sub-array with +nil+ elements:
4520 * a = [:a0, :a1, :a2, :a3]
4521 * b = [:b0, :b1, :b2]
4522 * c = [:c0, :c1]
4523 * d = a.zip(b, c)
4524 * pp d
4525 * # =>
4526 * [[:a0, :b0, :c0],
4527 * [:a1, :b1, :c1],
4528 * [:a2, :b2, nil],
4529 * [:a3, nil, nil]]
4531 * When one of the other arrays is larger than +self+,
4532 * _ignores_ its trailing elements:
4534 * a = [:a0, :a1, :a2, :a3]
4535 * b = [:b0, :b1, :b2, :b3, :b4]
4536 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4537 * d = a.zip(b, c)
4538 * pp d
4539 * # =>
4540 * [[:a0, :b0, :c0],
4541 * [:a1, :b1, :c1],
4542 * [:a2, :b2, :c2],
4543 * [:a3, :b3, :c3]]
4545 * With a block given, calls the block with each of the other arrays;
4546 * returns +nil+:
4548 * d = []
4549 * a = [:a0, :a1, :a2, :a3]
4550 * b = [:b0, :b1, :b2, :b3]
4551 * c = [:c0, :c1, :c2, :c3]
4552 * a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil
4553 * pp d
4554 * # =>
4555 * [[:c0, :b0, :a0],
4556 * [:c1, :b1, :a1],
4557 * [:c2, :b2, :a2],
4558 * [:c3, :b3, :a3]]
4560 * For an *object* in *other_arrays* that is not actually an array,
4561 * forms the the "other array" as <tt>object.to_ary</tt>, if defined,
4562 * or as <tt>object.each.to_a</tt> otherwise.
4564 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4567 static VALUE
4568 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
4570 int i, j;
4571 long len = RARRAY_LEN(ary);
4572 VALUE result = Qnil;
4574 for (i=0; i<argc; i++) {
4575 argv[i] = take_items(argv[i], len);
4578 if (rb_block_given_p()) {
4579 int arity = rb_block_arity();
4581 if (arity > 1) {
4582 VALUE work, *tmp;
4584 tmp = ALLOCV_N(VALUE, work, argc+1);
4586 for (i=0; i<RARRAY_LEN(ary); i++) {
4587 tmp[0] = RARRAY_AREF(ary, i);
4588 for (j=0; j<argc; j++) {
4589 tmp[j+1] = rb_ary_elt(argv[j], i);
4591 rb_yield_values2(argc+1, tmp);
4594 if (work) ALLOCV_END(work);
4596 else {
4597 for (i=0; i<RARRAY_LEN(ary); i++) {
4598 VALUE tmp = rb_ary_new2(argc+1);
4600 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4601 for (j=0; j<argc; j++) {
4602 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4604 rb_yield(tmp);
4608 else {
4609 result = rb_ary_new_capa(len);
4611 for (i=0; i<len; i++) {
4612 VALUE tmp = rb_ary_new_capa(argc+1);
4614 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4615 for (j=0; j<argc; j++) {
4616 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4618 rb_ary_push(result, tmp);
4622 return result;
4626 * call-seq:
4627 * transpose -> new_array
4629 * Returns a new array that is +self+
4630 * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]:
4632 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4633 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4635 * The elements of +self+ must all be the same size.
4637 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4640 static VALUE
4641 rb_ary_transpose(VALUE ary)
4643 long elen = -1, alen, i, j;
4644 VALUE tmp, result = 0;
4646 alen = RARRAY_LEN(ary);
4647 if (alen == 0) return rb_ary_dup(ary);
4648 for (i=0; i<alen; i++) {
4649 tmp = to_ary(rb_ary_elt(ary, i));
4650 if (elen < 0) { /* first element */
4651 elen = RARRAY_LEN(tmp);
4652 result = rb_ary_new2(elen);
4653 for (j=0; j<elen; j++) {
4654 rb_ary_store(result, j, rb_ary_new2(alen));
4657 else if (elen != RARRAY_LEN(tmp)) {
4658 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
4659 RARRAY_LEN(tmp), elen);
4661 for (j=0; j<elen; j++) {
4662 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4665 return result;
4669 * call-seq:
4670 * initialize_copy(other_array) -> self
4671 * replace(other_array) -> self
4673 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4674 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4675 * returns +self+:
4677 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4678 * a.replace(['d', 'e']) # => ["d", "e"]
4680 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4683 VALUE
4684 rb_ary_replace(VALUE copy, VALUE orig)
4686 rb_ary_modify_check(copy);
4687 orig = to_ary(orig);
4688 if (copy == orig) return copy;
4690 rb_ary_reset(copy);
4692 /* orig has enough space to embed the contents of orig. */
4693 if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
4694 RUBY_ASSERT(ARY_EMBED_P(copy));
4695 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
4696 ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
4698 /* orig is embedded but copy does not have enough space to embed the
4699 * contents of orig. */
4700 else if (ARY_EMBED_P(orig)) {
4701 long len = ARY_EMBED_LEN(orig);
4702 VALUE *ptr = ary_heap_alloc_buffer(len);
4704 FL_UNSET_EMBED(copy);
4705 ARY_SET_PTR(copy, ptr);
4706 ARY_SET_LEN(copy, len);
4707 ARY_SET_CAPA(copy, len);
4709 // No allocation and exception expected that could leave `copy` in a
4710 // bad state from the edits above.
4711 ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
4713 /* Otherwise, orig is on heap and copy does not have enough space to embed
4714 * the contents of orig. */
4715 else {
4716 VALUE shared_root = ary_make_shared(orig);
4717 FL_UNSET_EMBED(copy);
4718 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
4719 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
4720 rb_ary_set_shared(copy, shared_root);
4722 ary_verify(copy);
4723 return copy;
4727 * call-seq:
4728 * clear -> self
4730 * Removes all elements from +self+; returns +self+:
4732 * a = [:foo, 'bar', 2]
4733 * a.clear # => []
4735 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4738 VALUE
4739 rb_ary_clear(VALUE ary)
4741 rb_ary_modify_check(ary);
4742 if (ARY_SHARED_P(ary)) {
4743 rb_ary_unshare(ary);
4744 FL_SET_EMBED(ary);
4745 ARY_SET_EMBED_LEN(ary, 0);
4747 else {
4748 ARY_SET_LEN(ary, 0);
4749 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
4750 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
4753 ary_verify(ary);
4754 return ary;
4758 * call-seq:
4759 * fill(object, start = nil, count = nil) -> new_array
4760 * fill(object, range) -> new_array
4761 * fill(start = nil, count = nil) {|element| ... } -> new_array
4762 * fill(range) {|element| ... } -> new_array
4764 * Replaces selected elements in +self+;
4765 * may add elements to +self+;
4766 * always returns +self+ (never a new array).
4768 * In brief:
4770 * # Non-negative start.
4771 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4772 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4774 * # Extends with specified values if necessary.
4775 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4776 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4778 * # Fills with nils if necessary.
4779 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4780 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4782 * # For negative start, counts backwards from the end.
4783 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4784 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4786 * # Range.
4787 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4788 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4790 * When arguments +start+ and +count+ are given,
4791 * they select the elements of +self+ to be replaced;
4792 * each must be an
4793 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
4794 * (or +nil+):
4796 * - +start+ specifies the zero-based offset of the first element to be replaced;
4797 * +nil+ means zero.
4798 * - +count+ is the number of consecutive elements to be replaced;
4799 * +nil+ means "all the rest."
4801 * With argument +object+ given,
4802 * that one object is used for all replacements:
4804 * o = Object.new # => #<Object:0x0000014e7bff7600>
4805 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4806 * a.fill(o, 1, 2)
4807 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
4809 * With a block given, the block is called once for each element to be replaced;
4810 * the value passed to the block is the _index_ of the element to be replaced
4811 * (not the element itself);
4812 * the block's return value replaces the element:
4814 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4815 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
4817 * For arguments +start+ and +count+:
4819 * - If +start+ is non-negative,
4820 * replaces +count+ elements beginning at offset +start+:
4822 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
4823 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4824 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
4826 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4827 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4828 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
4830 * Extends +self+ if necessary:
4832 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4833 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
4835 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4836 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
4838 * Fills with +nil+ if necessary:
4840 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
4841 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4843 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
4844 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4846 * Does nothing if +count+ is non-positive:
4848 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
4849 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
4850 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
4852 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4853 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4854 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4856 * - If +start+ is negative, counts backwards from the end of +self+:
4858 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
4859 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4861 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
4862 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4864 * Extends +self+ if necessary:
4866 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
4867 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
4869 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
4870 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
4872 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
4874 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
4875 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
4877 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4878 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4880 * Does nothing if +count+ is non-positive:
4882 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
4883 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
4885 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4886 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4888 * When argument +range+ is given,
4889 * it must be a Range object whose members are numeric;
4890 * its +begin+ and +end+ values determine the elements of +self+
4891 * to be replaced:
4893 * - If both +begin+ and +end+ are positive, they specify the first and last elements
4894 * to be replaced:
4896 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4897 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4899 * If +end+ is smaller than +begin+, replaces no elements:
4901 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
4902 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
4904 * - If either is negative (or both are negative), counts backwards from the end of +self+:
4906 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
4907 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
4908 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
4910 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4911 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4912 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4914 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
4916 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
4917 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
4919 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4920 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4922 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
4923 * replaces elements to the end of +self+:
4925 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
4926 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
4928 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
4929 * replaces elements from the beginning of +self+:
4931 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
4932 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
4934 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4937 static VALUE
4938 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
4940 VALUE item = Qundef, arg1, arg2;
4941 long beg = 0, end = 0, len = 0;
4943 if (rb_block_given_p()) {
4944 rb_scan_args(argc, argv, "02", &arg1, &arg2);
4945 argc += 1; /* hackish */
4947 else {
4948 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
4950 switch (argc) {
4951 case 1:
4952 beg = 0;
4953 len = RARRAY_LEN(ary);
4954 break;
4955 case 2:
4956 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
4957 break;
4959 /* fall through */
4960 case 3:
4961 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
4962 if (beg < 0) {
4963 beg = RARRAY_LEN(ary) + beg;
4964 if (beg < 0) beg = 0;
4966 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
4967 break;
4969 rb_ary_modify(ary);
4970 if (len < 0) {
4971 return ary;
4973 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
4974 rb_raise(rb_eArgError, "argument too big");
4976 end = beg + len;
4977 if (RARRAY_LEN(ary) < end) {
4978 if (end >= ARY_CAPA(ary)) {
4979 ary_resize_capa(ary, end);
4981 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
4982 ARY_SET_LEN(ary, end);
4985 if (UNDEF_P(item)) {
4986 VALUE v;
4987 long i;
4989 for (i=beg; i<end; i++) {
4990 v = rb_yield(LONG2NUM(i));
4991 if (i>=RARRAY_LEN(ary)) break;
4992 ARY_SET(ary, i, v);
4995 else {
4996 ary_memfill(ary, beg, len, item);
4998 return ary;
5002 * call-seq:
5003 * self + other_array -> new_array
5005 * Returns a new array containing all elements of +self+
5006 * followed by all elements of +other_array+:
5008 * a = [0, 1] + [2, 3]
5009 * a # => [0, 1, 2, 3]
5011 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5014 VALUE
5015 rb_ary_plus(VALUE x, VALUE y)
5017 VALUE z;
5018 long len, xlen, ylen;
5020 y = to_ary(y);
5021 xlen = RARRAY_LEN(x);
5022 ylen = RARRAY_LEN(y);
5023 len = xlen + ylen;
5024 z = rb_ary_new2(len);
5026 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
5027 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
5028 ARY_SET_LEN(z, len);
5029 return z;
5032 static VALUE
5033 ary_append(VALUE x, VALUE y)
5035 long n = RARRAY_LEN(y);
5036 if (n > 0) {
5037 rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR(y), n);
5039 RB_GC_GUARD(y);
5040 return x;
5044 * call-seq:
5045 * concat(*other_arrays) -> self
5047 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
5049 * a = [0, 1]
5050 * a.concat(['two', 'three'], [:four, :five], a)
5051 * # => [0, 1, "two", "three", :four, :five, 0, 1]
5053 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5056 static VALUE
5057 rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
5059 rb_ary_modify_check(ary);
5061 if (argc == 1) {
5062 rb_ary_concat(ary, argv[0]);
5064 else if (argc > 1) {
5065 int i;
5066 VALUE args = rb_ary_hidden_new(argc);
5067 for (i = 0; i < argc; i++) {
5068 rb_ary_concat(args, argv[i]);
5070 ary_append(ary, args);
5073 ary_verify(ary);
5074 return ary;
5077 VALUE
5078 rb_ary_concat(VALUE x, VALUE y)
5080 return ary_append(x, to_ary(y));
5084 * call-seq:
5085 * self * n -> new_array
5086 * self * string_separator -> new_string
5088 * When non-negative integer argument +n+ is given,
5089 * returns a new array built by concatenating +n+ copies of +self+:
5091 * a = ['x', 'y']
5092 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5094 * When string argument +string_separator+ is given,
5095 * equivalent to <tt>self.join(string_separator)</tt>:
5097 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}"
5101 static VALUE
5102 rb_ary_times(VALUE ary, VALUE times)
5104 VALUE ary2, tmp;
5105 const VALUE *ptr;
5106 long t, len;
5108 tmp = rb_check_string_type(times);
5109 if (!NIL_P(tmp)) {
5110 return rb_ary_join(ary, tmp);
5113 len = NUM2LONG(times);
5114 if (len == 0) {
5115 ary2 = ary_new(rb_cArray, 0);
5116 goto out;
5118 if (len < 0) {
5119 rb_raise(rb_eArgError, "negative argument");
5121 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
5122 rb_raise(rb_eArgError, "argument too big");
5124 len *= RARRAY_LEN(ary);
5126 ary2 = ary_new(rb_cArray, len);
5127 ARY_SET_LEN(ary2, len);
5129 ptr = RARRAY_CONST_PTR(ary);
5130 t = RARRAY_LEN(ary);
5131 if (0 < t) {
5132 ary_memcpy(ary2, 0, t, ptr);
5133 while (t <= len/2) {
5134 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
5135 t *= 2;
5137 if (t < len) {
5138 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
5141 out:
5142 return ary2;
5146 * call-seq:
5147 * assoc(object) -> found_array or nil
5149 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5150 * and <tt>ele[0] == object</tt>:
5152 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5153 * a.assoc(4) # => [4, 5, 6]
5155 * Returns +nil+ if no such element is found.
5157 * Related: Array#rassoc;
5158 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5161 VALUE
5162 rb_ary_assoc(VALUE ary, VALUE key)
5164 long i;
5165 VALUE v;
5167 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5168 v = rb_check_array_type(RARRAY_AREF(ary, i));
5169 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
5170 rb_equal(RARRAY_AREF(v, 0), key))
5171 return v;
5173 return Qnil;
5177 * call-seq:
5178 * rassoc(object) -> found_array or nil
5180 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5181 * and <tt>ele[1] == object</tt>:
5183 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5184 * a.rassoc(4) # => [2, 4]
5185 * a.rassoc(5) # => [4, 5, 6]
5187 * Returns +nil+ if no such element is found.
5189 * Related: Array#assoc;
5190 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5193 VALUE
5194 rb_ary_rassoc(VALUE ary, VALUE value)
5196 long i;
5197 VALUE v;
5199 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5200 v = rb_check_array_type(RARRAY_AREF(ary, i));
5201 if (RB_TYPE_P(v, T_ARRAY) &&
5202 RARRAY_LEN(v) > 1 &&
5203 rb_equal(RARRAY_AREF(v, 1), value))
5204 return v;
5206 return Qnil;
5209 static VALUE
5210 recursive_equal(VALUE ary1, VALUE ary2, int recur)
5212 long i, len1;
5213 const VALUE *p1, *p2;
5215 if (recur) return Qtrue; /* Subtle! */
5217 /* rb_equal() can evacuate ptrs */
5218 p1 = RARRAY_CONST_PTR(ary1);
5219 p2 = RARRAY_CONST_PTR(ary2);
5220 len1 = RARRAY_LEN(ary1);
5222 for (i = 0; i < len1; i++) {
5223 if (*p1 != *p2) {
5224 if (rb_equal(*p1, *p2)) {
5225 len1 = RARRAY_LEN(ary1);
5226 if (len1 != RARRAY_LEN(ary2))
5227 return Qfalse;
5228 if (len1 < i)
5229 return Qtrue;
5230 p1 = RARRAY_CONST_PTR(ary1) + i;
5231 p2 = RARRAY_CONST_PTR(ary2) + i;
5233 else {
5234 return Qfalse;
5237 p1++;
5238 p2++;
5240 return Qtrue;
5244 * call-seq:
5245 * self == other_array -> true or false
5247 * Returns whether both:
5249 * - +self+ and +other_array+ are the same size.
5250 * - Their corresponding elements are the same;
5251 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5252 * <tt>self[i] == other_array[i]</tt>.
5254 * Examples:
5256 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5257 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5258 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5259 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5261 * This method is different from method Array#eql?,
5262 * which compares elements using <tt>Object#eql?</tt>.
5264 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5267 static VALUE
5268 rb_ary_equal(VALUE ary1, VALUE ary2)
5270 if (ary1 == ary2) return Qtrue;
5271 if (!RB_TYPE_P(ary2, T_ARRAY)) {
5272 if (!rb_respond_to(ary2, idTo_ary)) {
5273 return Qfalse;
5275 return rb_equal(ary2, ary1);
5277 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5278 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5279 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
5282 static VALUE
5283 recursive_eql(VALUE ary1, VALUE ary2, int recur)
5285 long i;
5287 if (recur) return Qtrue; /* Subtle! */
5288 for (i=0; i<RARRAY_LEN(ary1); i++) {
5289 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5290 return Qfalse;
5292 return Qtrue;
5296 * call-seq:
5297 * eql?(other_array) -> true or false
5299 * Returns +true+ if +self+ and +other_array+ are the same size,
5300 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5302 * a0 = [:foo, 'bar', 2]
5303 * a1 = [:foo, 'bar', 2]
5304 * a1.eql?(a0) # => true
5306 * Otherwise, returns +false+.
5308 * This method is different from method Array#==,
5309 * which compares using method <tt>Object#==</tt>.
5311 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5314 static VALUE
5315 rb_ary_eql(VALUE ary1, VALUE ary2)
5317 if (ary1 == ary2) return Qtrue;
5318 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
5319 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5320 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5321 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
5324 VALUE
5325 rb_ary_hash_values(long len, const VALUE *elements)
5327 long i;
5328 st_index_t h;
5329 VALUE n;
5331 h = rb_hash_start(len);
5332 h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
5333 for (i=0; i<len; i++) {
5334 n = rb_hash(elements[i]);
5335 h = rb_hash_uint(h, NUM2LONG(n));
5337 h = rb_hash_end(h);
5338 return ST2FIX(h);
5342 * call-seq:
5343 * hash -> integer
5345 * Returns the integer hash value for +self+.
5347 * Two arrays with the same content will have the same hash value
5348 * (and will compare using eql?):
5350 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5351 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5352 * ['a', 'b'].hash == ['a'].hash # => false
5356 static VALUE
5357 rb_ary_hash(VALUE ary)
5359 return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
5363 * call-seq:
5364 * include?(object) -> true or false
5366 * Returns whether for some element +element+ in +self+,
5367 * <tt>object == element</tt>:
5369 * [0, 1, 2].include?(2) # => true
5370 * [0, 1, 2].include?(2.0) # => true
5371 * [0, 1, 2].include?(2.1) # => false
5373 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5376 VALUE
5377 rb_ary_includes(VALUE ary, VALUE item)
5379 long i;
5380 VALUE e;
5382 for (i=0; i<RARRAY_LEN(ary); i++) {
5383 e = RARRAY_AREF(ary, i);
5384 if (rb_equal(e, item)) {
5385 return Qtrue;
5388 return Qfalse;
5391 static VALUE
5392 rb_ary_includes_by_eql(VALUE ary, VALUE item)
5394 long i;
5395 VALUE e;
5397 for (i=0; i<RARRAY_LEN(ary); i++) {
5398 e = RARRAY_AREF(ary, i);
5399 if (rb_eql(item, e)) {
5400 return Qtrue;
5403 return Qfalse;
5406 static VALUE
5407 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5409 long i, len;
5411 if (recur) return Qundef; /* Subtle! */
5412 len = RARRAY_LEN(ary1);
5413 if (len > RARRAY_LEN(ary2)) {
5414 len = RARRAY_LEN(ary2);
5416 for (i=0; i<len; i++) {
5417 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5418 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5419 if (v != INT2FIX(0)) {
5420 return v;
5423 return Qundef;
5427 * call-seq:
5428 * self <=> other_array -> -1, 0, or 1
5430 * Returns -1, 0, or 1 as +self+ is determined
5431 * to be less than, equal to, or greater than +other_array+.
5433 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5435 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5436 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5438 * [0, 1, 2] <=> [0, 0, 2] # => 1
5440 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5442 * [0, 1, 2] <=> [0, 2, 2] # => -1
5444 * - Continues if <tt>result[i]</tt> is 0.
5446 * When every +result+ is 0,
5447 * returns <tt>self.size <=> other_array.size</tt>
5448 * (see Integer#<=>):
5450 * [0, 1, 2] <=> [0, 1] # => 1
5451 * [0, 1, 2] <=> [0, 1, 2] # => 0
5452 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5454 * Note that when +other_array+ is larger than +self+,
5455 * its trailing elements do not affect the result:
5457 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5458 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5459 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5461 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5464 VALUE
5465 rb_ary_cmp(VALUE ary1, VALUE ary2)
5467 long len;
5468 VALUE v;
5470 ary2 = rb_check_array_type(ary2);
5471 if (NIL_P(ary2)) return Qnil;
5472 if (ary1 == ary2) return INT2FIX(0);
5473 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5474 if (!UNDEF_P(v)) return v;
5475 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5476 if (len == 0) return INT2FIX(0);
5477 if (len > 0) return INT2FIX(1);
5478 return INT2FIX(-1);
5481 static VALUE
5482 ary_add_hash(VALUE hash, VALUE ary)
5484 long i;
5486 for (i=0; i<RARRAY_LEN(ary); i++) {
5487 VALUE elt = RARRAY_AREF(ary, i);
5488 rb_hash_add_new_element(hash, elt, elt);
5490 return hash;
5493 static inline VALUE
5494 ary_tmp_hash_new(VALUE ary)
5496 long size = RARRAY_LEN(ary);
5497 VALUE hash = rb_hash_new_with_size(size);
5499 RBASIC_CLEAR_CLASS(hash);
5500 return hash;
5503 static VALUE
5504 ary_make_hash(VALUE ary)
5506 VALUE hash = ary_tmp_hash_new(ary);
5507 return ary_add_hash(hash, ary);
5510 static VALUE
5511 ary_add_hash_by(VALUE hash, VALUE ary)
5513 long i;
5515 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5516 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
5517 rb_hash_add_new_element(hash, k, v);
5519 return hash;
5522 static VALUE
5523 ary_make_hash_by(VALUE ary)
5525 VALUE hash = ary_tmp_hash_new(ary);
5526 return ary_add_hash_by(hash, ary);
5530 * call-seq:
5531 * self - other_array -> new_array
5533 * Returns a new array containing only those elements of +self+
5534 * that are not found in +other_array+;
5535 * the order from +self+ is preserved:
5537 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5538 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5539 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5541 * Element are compared using method <tt>#eql?</tt>
5542 * (as defined in each element of +self+).
5544 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5547 VALUE
5548 rb_ary_diff(VALUE ary1, VALUE ary2)
5550 VALUE ary3;
5551 VALUE hash;
5552 long i;
5554 ary2 = to_ary(ary2);
5555 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5556 ary3 = rb_ary_new();
5558 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5559 for (i=0; i<RARRAY_LEN(ary1); i++) {
5560 VALUE elt = rb_ary_elt(ary1, i);
5561 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5562 rb_ary_push(ary3, elt);
5564 return ary3;
5567 hash = ary_make_hash(ary2);
5568 for (i=0; i<RARRAY_LEN(ary1); i++) {
5569 if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
5570 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5573 return ary3;
5577 * call-seq:
5578 * difference(*other_arrays = []) -> new_array
5580 * Returns a new array containing only those elements from +self+
5581 * that are not found in any of the given +other_arrays+;
5582 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5584 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5585 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5586 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5587 * [0, 1, 2].difference # => [0, 1, 2]
5589 * Returns a copy of +self+ if no arguments are given.
5591 * Related: Array#-;
5592 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5595 static VALUE
5596 rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5598 VALUE ary_diff;
5599 long i, length;
5600 volatile VALUE t0;
5601 bool *is_hash = ALLOCV_N(bool, t0, argc);
5602 ary_diff = rb_ary_new();
5603 length = RARRAY_LEN(ary);
5605 for (i = 0; i < argc; i++) {
5606 argv[i] = to_ary(argv[i]);
5607 is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5608 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
5611 for (i = 0; i < RARRAY_LEN(ary); i++) {
5612 int j;
5613 VALUE elt = rb_ary_elt(ary, i);
5614 for (j = 0; j < argc; j++) {
5615 if (is_hash[j]) {
5616 if (rb_hash_stlike_lookup(argv[j], elt, NULL))
5617 break;
5619 else {
5620 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5623 if (j == argc) rb_ary_push(ary_diff, elt);
5626 ALLOCV_END(t0);
5628 return ary_diff;
5633 * call-seq:
5634 * self & other_array -> new_array
5636 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5637 * that is, containing those elements found in both +self+ and +other_array+:
5639 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5641 * Omits duplicates:
5643 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5645 * Preserves order from +self+:
5647 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5649 * Identifies common elements using method <tt>#eql?</tt>
5650 * (as defined in each element of +self+).
5652 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5656 static VALUE
5657 rb_ary_and(VALUE ary1, VALUE ary2)
5659 VALUE hash, ary3, v;
5660 st_data_t vv;
5661 long i;
5663 ary2 = to_ary(ary2);
5664 ary3 = rb_ary_new();
5665 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5667 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5668 for (i=0; i<RARRAY_LEN(ary1); i++) {
5669 v = RARRAY_AREF(ary1, i);
5670 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5671 if (rb_ary_includes_by_eql(ary3, v)) continue;
5672 rb_ary_push(ary3, v);
5674 return ary3;
5677 hash = ary_make_hash(ary2);
5679 for (i=0; i<RARRAY_LEN(ary1); i++) {
5680 v = RARRAY_AREF(ary1, i);
5681 vv = (st_data_t)v;
5682 if (rb_hash_stlike_delete(hash, &vv, 0)) {
5683 rb_ary_push(ary3, v);
5687 return ary3;
5691 * call-seq:
5692 * intersection(*other_arrays) -> new_array
5694 * Returns a new array containing each element in +self+ that is +#eql?+
5695 * to at least one element in each of the given +other_arrays+;
5696 * duplicates are omitted:
5698 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5700 * Each element must correctly implement method <tt>#hash</tt>.
5702 * Order from +self+ is preserved:
5704 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5706 * Returns a copy of +self+ if no arguments are given.
5708 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5711 static VALUE
5712 rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5714 VALUE result = rb_ary_dup(ary);
5715 int i;
5717 for (i = 0; i < argc; i++) {
5718 result = rb_ary_and(result, argv[i]);
5721 return result;
5724 static int
5725 ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
5727 if (existing) return ST_STOP;
5728 *key = *value = (VALUE)arg;
5729 return ST_CONTINUE;
5732 static void
5733 rb_ary_union(VALUE ary_union, VALUE ary)
5735 long i;
5736 for (i = 0; i < RARRAY_LEN(ary); i++) {
5737 VALUE elt = rb_ary_elt(ary, i);
5738 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
5739 rb_ary_push(ary_union, elt);
5743 static void
5744 rb_ary_union_hash(VALUE hash, VALUE ary2)
5746 long i;
5747 for (i = 0; i < RARRAY_LEN(ary2); i++) {
5748 VALUE elt = RARRAY_AREF(ary2, i);
5749 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
5750 RB_OBJ_WRITTEN(hash, Qundef, elt);
5756 * call-seq:
5757 * self | other_array -> new_array
5759 * Returns the union of +self+ and +other_array+;
5760 * duplicates are removed; order is preserved;
5761 * items are compared using <tt>eql?</tt>:
5763 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5764 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5765 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5767 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5770 static VALUE
5771 rb_ary_or(VALUE ary1, VALUE ary2)
5773 VALUE hash;
5775 ary2 = to_ary(ary2);
5776 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5777 VALUE ary3 = rb_ary_new();
5778 rb_ary_union(ary3, ary1);
5779 rb_ary_union(ary3, ary2);
5780 return ary3;
5783 hash = ary_make_hash(ary1);
5784 rb_ary_union_hash(hash, ary2);
5786 return rb_hash_values(hash);
5790 * call-seq:
5791 * union(*other_arrays) -> new_array
5793 * Returns a new array that is the union of the elements of +self+
5794 * and all given arrays +other_arrays+;
5795 * items are compared using <tt>eql?</tt>:
5797 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5799 * Removes duplicates (preserving the first found):
5801 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5803 * Preserves order (preserving the position of the first found):
5805 * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
5807 * With no arguments given, returns a copy of +self+.
5809 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5812 static VALUE
5813 rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
5815 int i;
5816 long sum;
5817 VALUE hash;
5819 sum = RARRAY_LEN(ary);
5820 for (i = 0; i < argc; i++) {
5821 argv[i] = to_ary(argv[i]);
5822 sum += RARRAY_LEN(argv[i]);
5825 if (sum <= SMALL_ARRAY_LEN) {
5826 VALUE ary_union = rb_ary_new();
5828 rb_ary_union(ary_union, ary);
5829 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
5831 return ary_union;
5834 hash = ary_make_hash(ary);
5835 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
5837 return rb_hash_values(hash);
5841 * call-seq:
5842 * intersect?(other_array) -> true or false
5844 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
5846 * [1, 2, 3].intersect?([3, 4, 5]) # => true
5847 * [1, 2, 3].intersect?([4, 5, 6]) # => false
5849 * Each element must correctly implement method <tt>#hash</tt>.
5851 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5854 static VALUE
5855 rb_ary_intersect_p(VALUE ary1, VALUE ary2)
5857 VALUE hash, v, result, shorter, longer;
5858 st_data_t vv;
5859 long i;
5861 ary2 = to_ary(ary2);
5862 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
5864 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5865 for (i=0; i<RARRAY_LEN(ary1); i++) {
5866 v = RARRAY_AREF(ary1, i);
5867 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
5869 return Qfalse;
5872 shorter = ary1;
5873 longer = ary2;
5874 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
5875 longer = ary1;
5876 shorter = ary2;
5879 hash = ary_make_hash(shorter);
5880 result = Qfalse;
5882 for (i=0; i<RARRAY_LEN(longer); i++) {
5883 v = RARRAY_AREF(longer, i);
5884 vv = (st_data_t)v;
5885 if (rb_hash_stlike_lookup(hash, vv, 0)) {
5886 result = Qtrue;
5887 break;
5891 return result;
5894 static VALUE
5895 ary_max_generic(VALUE ary, long i, VALUE vmax)
5897 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
5899 VALUE v;
5900 for (; i < RARRAY_LEN(ary); ++i) {
5901 v = RARRAY_AREF(ary, i);
5903 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
5904 vmax = v;
5908 return vmax;
5911 static VALUE
5912 ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
5914 const long n = RARRAY_LEN(ary);
5915 RUBY_ASSERT(i > 0 && i < n);
5916 RUBY_ASSERT(FIXNUM_P(vmax));
5918 VALUE v;
5919 for (; i < n; ++i) {
5920 v = RARRAY_AREF(ary, i);
5922 if (FIXNUM_P(v)) {
5923 if ((long)vmax < (long)v) {
5924 vmax = v;
5927 else {
5928 return ary_max_generic(ary, i, vmax);
5932 return vmax;
5935 static VALUE
5936 ary_max_opt_float(VALUE ary, long i, VALUE vmax)
5938 const long n = RARRAY_LEN(ary);
5939 RUBY_ASSERT(i > 0 && i < n);
5940 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax));
5942 VALUE v;
5943 for (; i < n; ++i) {
5944 v = RARRAY_AREF(ary, i);
5946 if (RB_FLOAT_TYPE_P(v)) {
5947 if (rb_float_cmp(vmax, v) < 0) {
5948 vmax = v;
5951 else {
5952 return ary_max_generic(ary, i, vmax);
5956 return vmax;
5959 static VALUE
5960 ary_max_opt_string(VALUE ary, long i, VALUE vmax)
5962 const long n = RARRAY_LEN(ary);
5963 RUBY_ASSERT(i > 0 && i < n);
5964 RUBY_ASSERT(STRING_P(vmax));
5966 VALUE v;
5967 for (; i < n; ++i) {
5968 v = RARRAY_AREF(ary, i);
5970 if (STRING_P(v)) {
5971 if (rb_str_cmp(vmax, v) < 0) {
5972 vmax = v;
5975 else {
5976 return ary_max_generic(ary, i, vmax);
5980 return vmax;
5984 * call-seq:
5985 * max -> element
5986 * max(count) -> new_array
5987 * max {|a, b| ... } -> element
5988 * max(count) {|a, b| ... } -> new_array
5990 * Returns one of the following:
5992 * - The maximum-valued element from +self+.
5993 * - A new array of maximum-valued elements from +self+.
5995 * Does not modify +self+.
5997 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
5998 * with a numeric.
6000 * With no argument and no block, returns the element in +self+
6001 * having the maximum value per method <tt>#<=></tt>:
6003 * [1, 0, 3, 2].max # => 3
6005 * With non-negative numeric argument +count+ and no block,
6006 * returns a new array with at most +count+ elements,
6007 * in descending order, per method <tt>#<=></tt>:
6009 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
6010 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
6011 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
6012 * [1, 0, 3, 2].max(0) # => []
6014 * With a block given, the block must return a numeric.
6016 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6017 * returns the element having the maximum value per the block:
6019 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
6020 * # => "000"
6022 * With non-negative numeric argument +count+ and a block,
6023 * returns a new array with at most +count+ elements,
6024 * in descending order, per the block:
6026 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
6027 * # => ["000", "00"]
6029 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6031 static VALUE
6032 rb_ary_max(int argc, VALUE *argv, VALUE ary)
6034 VALUE result = Qundef, v;
6035 VALUE num;
6036 long i;
6038 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6039 return rb_nmin_run(ary, num, 0, 1, 1);
6041 const long n = RARRAY_LEN(ary);
6042 if (rb_block_given_p()) {
6043 for (i = 0; i < RARRAY_LEN(ary); i++) {
6044 v = RARRAY_AREF(ary, i);
6045 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
6046 result = v;
6050 else if (n > 0) {
6051 result = RARRAY_AREF(ary, 0);
6052 if (n > 1) {
6053 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6054 return ary_max_opt_fixnum(ary, 1, result);
6056 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6057 return ary_max_opt_string(ary, 1, result);
6059 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6060 return ary_max_opt_float(ary, 1, result);
6062 else {
6063 return ary_max_generic(ary, 1, result);
6067 if (UNDEF_P(result)) return Qnil;
6068 return result;
6071 static VALUE
6072 ary_min_generic(VALUE ary, long i, VALUE vmin)
6074 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6076 VALUE v;
6077 for (; i < RARRAY_LEN(ary); ++i) {
6078 v = RARRAY_AREF(ary, i);
6080 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
6081 vmin = v;
6085 return vmin;
6088 static VALUE
6089 ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
6091 const long n = RARRAY_LEN(ary);
6092 RUBY_ASSERT(i > 0 && i < n);
6093 RUBY_ASSERT(FIXNUM_P(vmin));
6095 VALUE a;
6096 for (; i < n; ++i) {
6097 a = RARRAY_AREF(ary, i);
6099 if (FIXNUM_P(a)) {
6100 if ((long)vmin > (long)a) {
6101 vmin = a;
6104 else {
6105 return ary_min_generic(ary, i, vmin);
6109 return vmin;
6112 static VALUE
6113 ary_min_opt_float(VALUE ary, long i, VALUE vmin)
6115 const long n = RARRAY_LEN(ary);
6116 RUBY_ASSERT(i > 0 && i < n);
6117 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin));
6119 VALUE a;
6120 for (; i < n; ++i) {
6121 a = RARRAY_AREF(ary, i);
6123 if (RB_FLOAT_TYPE_P(a)) {
6124 if (rb_float_cmp(vmin, a) > 0) {
6125 vmin = a;
6128 else {
6129 return ary_min_generic(ary, i, vmin);
6133 return vmin;
6136 static VALUE
6137 ary_min_opt_string(VALUE ary, long i, VALUE vmin)
6139 const long n = RARRAY_LEN(ary);
6140 RUBY_ASSERT(i > 0 && i < n);
6141 RUBY_ASSERT(STRING_P(vmin));
6143 VALUE a;
6144 for (; i < n; ++i) {
6145 a = RARRAY_AREF(ary, i);
6147 if (STRING_P(a)) {
6148 if (rb_str_cmp(vmin, a) > 0) {
6149 vmin = a;
6152 else {
6153 return ary_min_generic(ary, i, vmin);
6157 return vmin;
6161 * call-seq:
6162 * min -> element
6163 * min(count) -> new_array
6164 * min {|a, b| ... } -> element
6165 * min(count) {|a, b| ... } -> new_array
6167 * Returns one of the following:
6169 * - The minimum-valued element from +self+.
6170 * - A new array of minimum-valued elements from +self+.
6172 * Does not modify +self+.
6174 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6175 * with a numeric.
6177 * With no argument and no block, returns the element in +self+
6178 * having the minimum value per method <tt>#<=></tt>:
6180 * [1, 0, 3, 2].min # => 0
6182 * With non-negative numeric argument +count+ and no block,
6183 * returns a new array with at most +count+ elements,
6184 * in ascending order, per method <tt>#<=></tt>:
6186 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6187 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6188 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6189 * [1, 0, 3, 2].min(0) # => []
6191 * With a block given, the block must return a numeric.
6193 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6194 * returns the element having the minimum value per the block:
6196 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6197 * # => ""
6199 * With non-negative numeric argument +count+ and a block,
6200 * returns a new array with at most +count+ elements,
6201 * in ascending order, per the block:
6203 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6204 * # => ["", "0"]
6206 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6208 static VALUE
6209 rb_ary_min(int argc, VALUE *argv, VALUE ary)
6211 VALUE result = Qundef, v;
6212 VALUE num;
6213 long i;
6215 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6216 return rb_nmin_run(ary, num, 0, 0, 1);
6218 const long n = RARRAY_LEN(ary);
6219 if (rb_block_given_p()) {
6220 for (i = 0; i < RARRAY_LEN(ary); i++) {
6221 v = RARRAY_AREF(ary, i);
6222 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
6223 result = v;
6227 else if (n > 0) {
6228 result = RARRAY_AREF(ary, 0);
6229 if (n > 1) {
6230 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6231 return ary_min_opt_fixnum(ary, 1, result);
6233 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6234 return ary_min_opt_string(ary, 1, result);
6236 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6237 return ary_min_opt_float(ary, 1, result);
6239 else {
6240 return ary_min_generic(ary, 1, result);
6244 if (UNDEF_P(result)) return Qnil;
6245 return result;
6249 * call-seq:
6250 * minmax -> array
6251 * minmax {|a, b| ... } -> array
6253 * Returns a 2-element array containing the minimum-valued and maximum-valued
6254 * elements from +self+;
6255 * does not modify +self+.
6257 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6259 * [1, 0, 3, 2].minmax # => [0, 3]
6261 * With a block given, the block must return a numeric;
6262 * the block is called <tt>self.size - 1</tt> times to compare elements;
6263 * returns the elements having the minimum and maximum values per the block:
6265 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6266 * # => ["", "000"]
6268 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6270 static VALUE
6271 rb_ary_minmax(VALUE ary)
6273 if (rb_block_given_p()) {
6274 return rb_call_super(0, NULL);
6276 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
6279 static int
6280 push_value(st_data_t key, st_data_t val, st_data_t ary)
6282 rb_ary_push((VALUE)ary, (VALUE)val);
6283 return ST_CONTINUE;
6287 * call-seq:
6288 * uniq! -> self or nil
6289 * uniq! {|element| ... } -> self or nil
6291 * Removes duplicate elements from +self+, the first occurrence always being retained;
6292 * returns +self+ if any elements removed, +nil+ otherwise.
6294 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6295 * to compare elements:
6297 * a = [0, 0, 1, 1, 2, 2]
6298 * a.uniq! # => [0, 1, 2]
6299 * a.uniq! # => nil
6301 * With a block given, calls the block for each element;
6302 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6303 * to compare <i>block return values</i>;
6304 * that is, an element is a duplicate if its block return value
6305 * is the same as that of a previous element:
6307 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6308 * a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
6309 * a.uniq! {|element| element.size } # => nil
6311 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6313 static VALUE
6314 rb_ary_uniq_bang(VALUE ary)
6316 VALUE hash;
6317 long hash_size;
6319 rb_ary_modify_check(ary);
6320 if (RARRAY_LEN(ary) <= 1)
6321 return Qnil;
6322 if (rb_block_given_p())
6323 hash = ary_make_hash_by(ary);
6324 else
6325 hash = ary_make_hash(ary);
6327 hash_size = RHASH_SIZE(hash);
6328 if (RARRAY_LEN(ary) == hash_size) {
6329 return Qnil;
6331 rb_ary_modify_check(ary);
6332 ARY_SET_LEN(ary, 0);
6333 if (ARY_SHARED_P(ary)) {
6334 rb_ary_unshare(ary);
6335 FL_SET_EMBED(ary);
6337 ary_resize_capa(ary, hash_size);
6338 rb_hash_foreach(hash, push_value, ary);
6340 return ary;
6344 * call-seq:
6345 * uniq -> new_array
6346 * uniq {|element| ... } -> new_array
6348 * Returns a new array containing those elements from +self+ that are not duplicates,
6349 * the first occurrence always being retained.
6351 * With no block given, identifies and omits duplicate elements using method <tt>eql?</tt>
6352 * to compare elements:
6354 * a = [0, 0, 1, 1, 2, 2]
6355 * a.uniq # => [0, 1, 2]
6357 * With a block given, calls the block for each element;
6358 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6359 * to compare <i>block return values</i>;
6360 * that is, an element is a duplicate if its block return value
6361 * is the same as that of a previous element:
6363 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6364 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6366 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6369 static VALUE
6370 rb_ary_uniq(VALUE ary)
6372 VALUE hash, uniq;
6374 if (RARRAY_LEN(ary) <= 1) {
6375 hash = 0;
6376 uniq = rb_ary_dup(ary);
6378 else if (rb_block_given_p()) {
6379 hash = ary_make_hash_by(ary);
6380 uniq = rb_hash_values(hash);
6382 else {
6383 hash = ary_make_hash(ary);
6384 uniq = rb_hash_values(hash);
6387 return uniq;
6391 * call-seq:
6392 * compact! -> self or nil
6394 * Removes all +nil+ elements from +self+;
6395 * Returns +self+ if any elements are removed, +nil+ otherwise:
6397 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6398 * a.compact! # => [0, false, "", [], {}]
6399 * a # => [0, false, "", [], {}]
6400 * a.compact! # => nil
6402 * Related: Array#compact;
6403 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6406 static VALUE
6407 rb_ary_compact_bang(VALUE ary)
6409 VALUE *p, *t, *end;
6410 long n;
6412 rb_ary_modify(ary);
6413 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
6414 end = p + RARRAY_LEN(ary);
6416 while (t < end) {
6417 if (NIL_P(*t)) t++;
6418 else *p++ = *t++;
6420 n = p - RARRAY_CONST_PTR(ary);
6421 if (RARRAY_LEN(ary) == n) {
6422 return Qnil;
6424 ary_resize_smaller(ary, n);
6426 return ary;
6430 * call-seq:
6431 * compact -> new_array
6433 * Returns a new array containing only the non-+nil+ elements from +self+;
6434 * element order is preserved:
6436 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6437 * a.compact # => [0, false, "", [], {}]
6439 * Related: Array#compact!;
6440 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6443 static VALUE
6444 rb_ary_compact(VALUE ary)
6446 ary = rb_ary_dup(ary);
6447 rb_ary_compact_bang(ary);
6448 return ary;
6452 * call-seq:
6453 * count -> integer
6454 * count(object) -> integer
6455 * count {|element| ... } -> integer
6457 * Returns a count of specified elements.
6459 * With no argument and no block, returns the count of all elements:
6461 * [0, :one, 'two', 3, 3.0].count # => 5
6463 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6465 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6467 * With no argument and a block given, calls the block with each element;
6468 * returns the count of elements for which the block returns a truthy value:
6470 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6472 * With argument +object+ and a block given, issues a warning, ignores the block,
6473 * and returns the count of elements <tt>==</tt> to +object+.
6475 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6478 static VALUE
6479 rb_ary_count(int argc, VALUE *argv, VALUE ary)
6481 long i, n = 0;
6483 if (rb_check_arity(argc, 0, 1) == 0) {
6484 VALUE v;
6486 if (!rb_block_given_p())
6487 return LONG2NUM(RARRAY_LEN(ary));
6489 for (i = 0; i < RARRAY_LEN(ary); i++) {
6490 v = RARRAY_AREF(ary, i);
6491 if (RTEST(rb_yield(v))) n++;
6494 else {
6495 VALUE obj = argv[0];
6497 if (rb_block_given_p()) {
6498 rb_warn("given block not used");
6500 for (i = 0; i < RARRAY_LEN(ary); i++) {
6501 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6505 return LONG2NUM(n);
6508 static VALUE
6509 flatten(VALUE ary, int level)
6511 long i;
6512 VALUE stack, result, tmp = 0, elt;
6513 VALUE memo = Qfalse;
6515 for (i = 0; i < RARRAY_LEN(ary); i++) {
6516 elt = RARRAY_AREF(ary, i);
6517 tmp = rb_check_array_type(elt);
6518 if (!NIL_P(tmp)) {
6519 break;
6522 if (i == RARRAY_LEN(ary)) {
6523 return ary;
6526 result = ary_new(0, RARRAY_LEN(ary));
6527 ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));
6528 ARY_SET_LEN(result, i);
6530 stack = ary_new(0, ARY_DEFAULT_SIZE);
6531 rb_ary_push(stack, ary);
6532 rb_ary_push(stack, LONG2NUM(i + 1));
6534 if (level < 0) {
6535 memo = rb_obj_hide(rb_ident_hash_new());
6536 rb_hash_aset(memo, ary, Qtrue);
6537 rb_hash_aset(memo, tmp, Qtrue);
6540 ary = tmp;
6541 i = 0;
6543 while (1) {
6544 while (i < RARRAY_LEN(ary)) {
6545 elt = RARRAY_AREF(ary, i++);
6546 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6547 rb_ary_push(result, elt);
6548 continue;
6550 tmp = rb_check_array_type(elt);
6551 if (RBASIC(result)->klass) {
6552 if (RTEST(memo)) {
6553 rb_hash_clear(memo);
6555 rb_raise(rb_eRuntimeError, "flatten reentered");
6557 if (NIL_P(tmp)) {
6558 rb_ary_push(result, elt);
6560 else {
6561 if (memo) {
6562 if (rb_hash_aref(memo, tmp) == Qtrue) {
6563 rb_hash_clear(memo);
6564 rb_raise(rb_eArgError, "tried to flatten recursive array");
6566 rb_hash_aset(memo, tmp, Qtrue);
6568 rb_ary_push(stack, ary);
6569 rb_ary_push(stack, LONG2NUM(i));
6570 ary = tmp;
6571 i = 0;
6574 if (RARRAY_LEN(stack) == 0) {
6575 break;
6577 if (memo) {
6578 rb_hash_delete(memo, ary);
6580 tmp = rb_ary_pop(stack);
6581 i = NUM2LONG(tmp);
6582 ary = rb_ary_pop(stack);
6585 if (memo) {
6586 rb_hash_clear(memo);
6589 RBASIC_SET_CLASS(result, rb_cArray);
6590 return result;
6594 * call-seq:
6595 * flatten!(depth = nil) -> self or nil
6597 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6598 * +depth+ must be an
6599 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6600 * or +nil+.
6601 * At each level of recursion:
6603 * - Each element that is an array is "flattened"
6604 * (that is, replaced by its individual array elements).
6605 * - Each element that is not an array is unchanged
6606 * (even if the element is an object that has instance method +flatten+).
6608 * Returns +nil+ if no elements were flattened.
6610 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6612 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6613 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6614 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6615 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6616 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6617 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6619 * With +nil+ or negative argument +depth+, flattens all levels:
6621 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6622 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6624 * Related: Array#flatten;
6625 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6628 static VALUE
6629 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6631 int mod = 0, level = -1;
6632 VALUE result, lv;
6634 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6635 rb_ary_modify_check(ary);
6636 if (!NIL_P(lv)) level = NUM2INT(lv);
6637 if (level == 0) return Qnil;
6639 result = flatten(ary, level);
6640 if (result == ary) {
6641 return Qnil;
6643 if (!(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
6644 rb_ary_replace(ary, result);
6645 if (mod) ARY_SET_EMBED_LEN(result, 0);
6647 return ary;
6651 * call-seq:
6652 * flatten(depth = nil) -> new_array
6654 * Returns a new array that is a recursive flattening of +self+
6655 * to +depth+ levels of recursion;
6656 * +depth+ must be an
6657 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6658 * or +nil+.
6659 * At each level of recursion:
6661 * - Each element that is an array is "flattened"
6662 * (that is, replaced by its individual array elements).
6663 * - Each element that is not an array is unchanged
6664 * (even if the element is an object that has instance method +flatten+).
6666 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6668 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6669 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6670 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6671 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6672 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6673 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6674 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6676 * With +nil+ or negative +depth+, flattens all levels.
6678 * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6679 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6681 * Related: Array#flatten!;
6682 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6685 static VALUE
6686 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6688 int level = -1;
6689 VALUE result;
6691 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6692 level = NUM2INT(argv[0]);
6693 if (level == 0) return ary_make_shared_copy(ary);
6696 result = flatten(ary, level);
6697 if (result == ary) {
6698 result = ary_make_shared_copy(ary);
6701 return result;
6704 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6706 static VALUE
6707 rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6709 long i, len;
6711 rb_ary_modify(ary);
6712 i = len = RARRAY_LEN(ary);
6713 RARRAY_PTR_USE(ary, ptr, {
6714 while (i > 1) {
6715 long j = RAND_UPTO(i);
6716 VALUE tmp;
6717 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
6718 rb_raise(rb_eRuntimeError, "modified during shuffle");
6720 tmp = ptr[--i];
6721 ptr[i] = ptr[j];
6722 ptr[j] = tmp;
6724 }); /* WB: no new reference */
6725 return ary;
6728 static VALUE
6729 rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6731 ary = rb_ary_dup(ary);
6732 rb_ary_shuffle_bang(ec, ary, randgen);
6733 return ary;
6736 static const rb_data_type_t ary_sample_memo_type = {
6737 .wrap_struct_name = "ary_sample_memo",
6738 .function = {
6739 .dfree = (RUBY_DATA_FUNC)st_free_table,
6741 .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
6744 static VALUE
6745 ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
6747 VALUE result;
6748 long n, len, i, j, k, idx[10];
6749 long rnds[numberof(idx)];
6750 long memo_threshold;
6752 len = RARRAY_LEN(ary);
6753 if (!to_array) {
6754 if (len < 2)
6755 i = 0;
6756 else
6757 i = RAND_UPTO(len);
6759 return rb_ary_elt(ary, i);
6761 n = NUM2LONG(nv);
6762 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
6763 if (n > len) n = len;
6764 if (n <= numberof(idx)) {
6765 for (i = 0; i < n; ++i) {
6766 rnds[i] = RAND_UPTO(len - i);
6769 k = len;
6770 len = RARRAY_LEN(ary);
6771 if (len < k && n <= numberof(idx)) {
6772 for (i = 0; i < n; ++i) {
6773 if (rnds[i] >= len) return rb_ary_new_capa(0);
6776 if (n > len) n = len;
6777 switch (n) {
6778 case 0:
6779 return rb_ary_new_capa(0);
6780 case 1:
6781 i = rnds[0];
6782 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
6783 case 2:
6784 i = rnds[0];
6785 j = rnds[1];
6786 if (j >= i) j++;
6787 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
6788 case 3:
6789 i = rnds[0];
6790 j = rnds[1];
6791 k = rnds[2];
6793 long l = j, g = i;
6794 if (j >= i) l = i, g = ++j;
6795 if (k >= l && (++k >= g)) ++k;
6797 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
6799 memo_threshold =
6800 len < 2560 ? len / 128 :
6801 len < 5120 ? len / 64 :
6802 len < 10240 ? len / 32 :
6803 len / 16;
6804 if (n <= numberof(idx)) {
6805 long sorted[numberof(idx)];
6806 sorted[0] = idx[0] = rnds[0];
6807 for (i=1; i<n; i++) {
6808 k = rnds[i];
6809 for (j = 0; j < i; ++j) {
6810 if (k < sorted[j]) break;
6811 ++k;
6813 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
6814 sorted[j] = idx[i] = k;
6816 result = rb_ary_new_capa(n);
6817 RARRAY_PTR_USE(result, ptr_result, {
6818 for (i=0; i<n; i++) {
6819 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
6823 else if (n <= memo_threshold / 2) {
6824 long max_idx = 0;
6825 VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
6826 st_table *memo = st_init_numtable_with_size(n);
6827 RTYPEDDATA_DATA(vmemo) = memo;
6828 result = rb_ary_new_capa(n);
6829 RARRAY_PTR_USE(result, ptr_result, {
6830 for (i=0; i<n; i++) {
6831 long r = RAND_UPTO(len-i) + i;
6832 ptr_result[i] = r;
6833 if (r > max_idx) max_idx = r;
6835 len = RARRAY_LEN(ary);
6836 if (len <= max_idx) n = 0;
6837 else if (n > len) n = len;
6838 RARRAY_PTR_USE(ary, ptr_ary, {
6839 for (i=0; i<n; i++) {
6840 long j2 = j = ptr_result[i];
6841 long i2 = i;
6842 st_data_t value;
6843 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
6844 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
6845 st_insert(memo, (st_data_t)j, (st_data_t)i2);
6846 ptr_result[i] = ptr_ary[j2];
6850 RTYPEDDATA_DATA(vmemo) = 0;
6851 st_free_table(memo);
6852 RB_GC_GUARD(vmemo);
6854 else {
6855 result = rb_ary_dup(ary);
6856 RBASIC_CLEAR_CLASS(result);
6857 RB_GC_GUARD(ary);
6858 RARRAY_PTR_USE(result, ptr_result, {
6859 for (i=0; i<n; i++) {
6860 j = RAND_UPTO(len-i) + i;
6861 nv = ptr_result[j];
6862 ptr_result[j] = ptr_result[i];
6863 ptr_result[i] = nv;
6866 RBASIC_SET_CLASS_RAW(result, rb_cArray);
6868 ARY_SET_LEN(result, n);
6870 return result;
6873 static VALUE
6874 ary_sized_alloc(rb_execution_context_t *ec, VALUE self)
6876 return rb_ary_new2(RARRAY_LEN(self));
6879 static VALUE
6880 ary_sample0(rb_execution_context_t *ec, VALUE ary)
6882 return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
6885 static VALUE
6886 rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
6888 long mul;
6889 VALUE n = Qnil;
6890 if (args && (RARRAY_LEN(args) > 0)) {
6891 n = RARRAY_AREF(args, 0);
6893 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
6894 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
6895 mul = NUM2LONG(n);
6896 if (mul <= 0) return INT2FIX(0);
6897 n = LONG2FIX(mul);
6898 return rb_fix_mul_fix(rb_ary_length(self), n);
6902 * call-seq:
6903 * cycle(count = nil) {|element| ... } -> nil
6904 * cycle(count = nil) -> new_enumerator
6906 * With a block given, may call the block, depending on the value of argument +count+;
6907 * +count+ must be an
6908 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6909 * or +nil+.
6911 * When +count+ is positive,
6912 * calls the block with each element, then does so repeatedly,
6913 * until it has done so +count+ times; returns +nil+:
6915 * output = []
6916 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6917 * output # => [0, 1, 0, 1]
6919 * When +count+ is zero or negative, does not call the block:
6921 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6922 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6924 * When +count+ is +nil+, cycles forever:
6926 * # Prints 0 and 1 forever.
6927 * [0, 1].cycle {|element| puts element }
6928 * [0, 1].cycle(nil) {|element| puts element }
6930 * With no block given, returns a new Enumerator.
6932 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6934 static VALUE
6935 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
6937 long n, i;
6939 rb_check_arity(argc, 0, 1);
6941 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
6942 if (argc == 0 || NIL_P(argv[0])) {
6943 n = -1;
6945 else {
6946 n = NUM2LONG(argv[0]);
6947 if (n <= 0) return Qnil;
6950 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
6951 for (i=0; i<RARRAY_LEN(ary); i++) {
6952 rb_yield(RARRAY_AREF(ary, i));
6955 return Qnil;
6959 * Build a ruby array of the corresponding values and yield it to the
6960 * associated block.
6961 * Return the class of +values+ for reentry check.
6963 static int
6964 yield_indexed_values(const VALUE values, const long r, const long *const p)
6966 const VALUE result = rb_ary_new2(r);
6967 long i;
6969 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
6970 ARY_SET_LEN(result, r);
6971 rb_yield(result);
6972 return !RBASIC(values)->klass;
6976 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6978 * When we have a complete permutation of array indices, copy the values
6979 * at those indices into a new array and yield that array.
6981 * n: the size of the set
6982 * r: the number of elements in each permutation
6983 * p: the array (of size r) that we're filling in
6984 * used: an array of booleans: whether a given index is already used
6985 * values: the Ruby array that holds the actual values to permute
6987 static void
6988 permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
6990 long i = 0, index = 0;
6992 for (;;) {
6993 const char *const unused = memchr(&used[i], 0, n-i);
6994 if (!unused) {
6995 if (!index) break;
6996 i = p[--index]; /* pop index */
6997 used[i++] = 0; /* index unused */
6999 else {
7000 i = unused - used;
7001 p[index] = i;
7002 used[i] = 1; /* mark index used */
7003 ++index;
7004 if (index < r-1) { /* if not done yet */
7005 p[index] = i = 0;
7006 continue;
7008 for (i = 0; i < n; ++i) {
7009 if (used[i]) continue;
7010 p[index] = i;
7011 if (!yield_indexed_values(values, r, p)) {
7012 rb_raise(rb_eRuntimeError, "permute reentered");
7015 i = p[--index]; /* pop index */
7016 used[i] = 0; /* index unused */
7017 p[index] = ++i;
7023 * Returns the product of from, from-1, ..., from - how_many + 1.
7024 * https://en.wikipedia.org/wiki/Pochhammer_symbol
7026 static VALUE
7027 descending_factorial(long from, long how_many)
7029 VALUE cnt;
7030 if (how_many > 0) {
7031 cnt = LONG2FIX(from);
7032 while (--how_many > 0) {
7033 long v = --from;
7034 cnt = rb_int_mul(cnt, LONG2FIX(v));
7037 else {
7038 cnt = LONG2FIX(how_many == 0);
7040 return cnt;
7043 static VALUE
7044 binomial_coefficient(long comb, long size)
7046 VALUE r;
7047 long i;
7048 if (comb > size-comb) {
7049 comb = size-comb;
7051 if (comb < 0) {
7052 return LONG2FIX(0);
7054 else if (comb == 0) {
7055 return LONG2FIX(1);
7057 r = LONG2FIX(size);
7058 for (i = 1; i < comb; ++i) {
7059 r = rb_int_mul(r, LONG2FIX(size - i));
7060 r = rb_int_idiv(r, LONG2FIX(i + 1));
7062 return r;
7065 static VALUE
7066 rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7068 long n = RARRAY_LEN(ary);
7069 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
7071 return descending_factorial(n, k);
7075 * call-seq:
7076 * permutation(count = self.size) {|permutation| ... } -> self
7077 * permutation(count = self.size) -> new_enumerator
7079 * Iterates over permutations of the elements of +self+;
7080 * the order of permutations is indeterminate.
7082 * With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
7083 * calls the block with each permutation of +self+ of size +count+;
7084 * returns +self+:
7086 * a = [0, 1, 2]
7087 * perms = []
7088 * a.permutation(1) {|perm| perms.push(perm) }
7089 * perms # => [[0], [1], [2]]
7091 * perms = []
7092 * a.permutation(2) {|perm| perms.push(perm) }
7093 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
7095 * perms = []
7096 * a.permutation(3) {|perm| perms.push(perm) }
7097 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
7099 * When +count+ is zero, calls the block once with a new empty array:
7101 * perms = []
7102 * a.permutation(0) {|perm| perms.push(perm) }
7103 * perms # => [[]]
7105 * When +count+ is out of range (negative or larger than <tt>self.size</tt>),
7106 * does not call the block:
7108 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7109 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7111 * With no block given, returns a new Enumerator.
7113 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7116 static VALUE
7117 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
7119 long r, n, i;
7121 n = RARRAY_LEN(ary); /* Array length */
7122 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
7123 r = n;
7124 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
7125 r = NUM2LONG(argv[0]); /* Permutation size from argument */
7127 if (r < 0 || n < r) {
7128 /* no permutations: yield nothing */
7130 else if (r == 0) { /* exactly one permutation: the zero-length array */
7131 rb_yield(rb_ary_new2(0));
7133 else if (r == 1) { /* this is a special, easy case */
7134 for (i = 0; i < RARRAY_LEN(ary); i++) {
7135 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7138 else { /* this is the general case */
7139 volatile VALUE t0;
7140 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
7141 char *used = (char*)(p + r);
7142 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7143 RBASIC_CLEAR_CLASS(ary0);
7145 MEMZERO(used, char, n); /* initialize array */
7147 permute0(n, r, p, used, ary0); /* compute and yield permutations */
7148 ALLOCV_END(t0);
7149 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7151 return ary;
7154 static void
7155 combinate0(const long len, const long n, long *const stack, const VALUE values)
7157 long lev = 0;
7159 MEMZERO(stack+1, long, n);
7160 stack[0] = -1;
7161 for (;;) {
7162 for (lev++; lev < n; lev++) {
7163 stack[lev+1] = stack[lev]+1;
7165 if (!yield_indexed_values(values, n, stack+1)) {
7166 rb_raise(rb_eRuntimeError, "combination reentered");
7168 do {
7169 if (lev == 0) return;
7170 stack[lev--]++;
7171 } while (stack[lev+1]+n == len+lev+1);
7175 static VALUE
7176 rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
7178 long n = RARRAY_LEN(ary);
7179 long k = NUM2LONG(RARRAY_AREF(args, 0));
7181 return binomial_coefficient(k, n);
7185 * call-seq:
7186 * combination(count) {|element| ... } -> self
7187 * combination(count) -> new_enumerator
7189 * When a block and a positive
7190 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7191 * argument +count+ (<tt>0 < count <= self.size</tt>)
7192 * are given, calls the block with each combination of +self+ of size +count+;
7193 * returns +self+:
7195 * a = %w[a b c] # => ["a", "b", "c"]
7196 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7198 * Output:
7200 * ["a", "b"]
7201 * ["a", "c"]
7202 * ["b", "c"]
7204 * The order of the yielded combinations is not guaranteed.
7206 * When +count+ is zero, calls the block once with a new empty array:
7208 * a.combination(0) {|combination| p combination }
7209 * [].combination(0) {|combination| p combination }
7211 * Output:
7213 * []
7214 * []
7216 * When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
7217 * does not call the block:
7219 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7220 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7222 * With no block given, returns a new Enumerator.
7224 * Related: Array#permutation;
7225 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7228 static VALUE
7229 rb_ary_combination(VALUE ary, VALUE num)
7231 long i, n, len;
7233 n = NUM2LONG(num);
7234 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
7235 len = RARRAY_LEN(ary);
7236 if (n < 0 || len < n) {
7237 /* yield nothing */
7239 else if (n == 0) {
7240 rb_yield(rb_ary_new2(0));
7242 else if (n == 1) {
7243 for (i = 0; i < RARRAY_LEN(ary); i++) {
7244 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7247 else {
7248 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7249 volatile VALUE t0;
7250 long *stack = ALLOCV_N(long, t0, n+1);
7252 RBASIC_CLEAR_CLASS(ary0);
7253 combinate0(len, n, stack, ary0);
7254 ALLOCV_END(t0);
7255 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7257 return ary;
7261 * Compute repeated permutations of +r+ elements of the set
7262 * <code>[0..n-1]</code>.
7264 * When we have a complete repeated permutation of array indices, copy the
7265 * values at those indices into a new array and yield that array.
7267 * n: the size of the set
7268 * r: the number of elements in each permutation
7269 * p: the array (of size r) that we're filling in
7270 * values: the Ruby array that holds the actual values to permute
7272 static void
7273 rpermute0(const long n, const long r, long *const p, const VALUE values)
7275 long i = 0, index = 0;
7277 p[index] = i;
7278 for (;;) {
7279 if (++index < r-1) {
7280 p[index] = i = 0;
7281 continue;
7283 for (i = 0; i < n; ++i) {
7284 p[index] = i;
7285 if (!yield_indexed_values(values, r, p)) {
7286 rb_raise(rb_eRuntimeError, "repeated permute reentered");
7289 do {
7290 if (index <= 0) return;
7291 } while ((i = ++p[--index]) >= n);
7295 static VALUE
7296 rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7298 long n = RARRAY_LEN(ary);
7299 long k = NUM2LONG(RARRAY_AREF(args, 0));
7301 if (k < 0) {
7302 return LONG2FIX(0);
7304 if (n <= 0) {
7305 return LONG2FIX(!k);
7307 return rb_int_positive_pow(n, (unsigned long)k);
7311 * call-seq:
7312 * repeated_permutation(size) {|permutation| ... } -> self
7313 * repeated_permutation(size) -> new_enumerator
7315 * With a block given, calls the block with each repeated permutation of length +size+
7316 * of the elements of +self+;
7317 * each permutation is an array;
7318 * returns +self+. The order of the permutations is indeterminate.
7320 * If a positive integer argument +size+ is given,
7321 * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
7322 * The number of permutations is <tt>self.size**size</tt>.
7324 * Examples:
7326 * - +size+ is 1:
7328 * p = []
7329 * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
7330 * p # => [[0], [1], [2]]
7332 * - +size+ is 2:
7334 * p = []
7335 * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
7336 * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7338 * If +size+ is zero, calls the block once with an empty array.
7340 * If +size+ is negative, does not call the block:
7342 * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7344 * With no block given, returns a new Enumerator.
7346 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7348 static VALUE
7349 rb_ary_repeated_permutation(VALUE ary, VALUE num)
7351 long r, n, i;
7353 n = RARRAY_LEN(ary); /* Array length */
7354 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
7355 r = NUM2LONG(num); /* Permutation size from argument */
7357 if (r < 0) {
7358 /* no permutations: yield nothing */
7360 else if (r == 0) { /* exactly one permutation: the zero-length array */
7361 rb_yield(rb_ary_new2(0));
7363 else if (r == 1) { /* this is a special, easy case */
7364 for (i = 0; i < RARRAY_LEN(ary); i++) {
7365 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7368 else { /* this is the general case */
7369 volatile VALUE t0;
7370 long *p = ALLOCV_N(long, t0, r);
7371 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7372 RBASIC_CLEAR_CLASS(ary0);
7374 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7375 ALLOCV_END(t0);
7376 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7378 return ary;
7381 static void
7382 rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
7384 long i = 0, index = 0;
7386 p[index] = i;
7387 for (;;) {
7388 if (++index < r-1) {
7389 p[index] = i;
7390 continue;
7392 for (; i < n; ++i) {
7393 p[index] = i;
7394 if (!yield_indexed_values(values, r, p)) {
7395 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7398 do {
7399 if (index <= 0) return;
7400 } while ((i = ++p[--index]) >= n);
7404 static VALUE
7405 rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7407 long n = RARRAY_LEN(ary);
7408 long k = NUM2LONG(RARRAY_AREF(args, 0));
7409 if (k == 0) {
7410 return LONG2FIX(1);
7412 return binomial_coefficient(k, n + k - 1);
7416 * call-seq:
7417 * repeated_combination(size) {|combination| ... } -> self
7418 * repeated_combination(size) -> new_enumerator
7420 * With a block given, calls the block with each repeated combination of length +size+
7421 * of the elements of +self+;
7422 * each combination is an array;
7423 * returns +self+. The order of the combinations is indeterminate.
7425 * If a positive integer argument +size+ is given,
7426 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7427 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7429 * Examples:
7431 * - +size+ is 1:
7433 * c = []
7434 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7435 * c # => [[0], [1], [2]]
7437 * - +size+ is 2:
7439 * c = []
7440 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7441 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7443 * If +size+ is zero, calls the block once with an empty array.
7445 * If +size+ is negative, does not call the block:
7447 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7449 * With no block given, returns a new Enumerator.
7451 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7454 static VALUE
7455 rb_ary_repeated_combination(VALUE ary, VALUE num)
7457 long n, i, len;
7459 n = NUM2LONG(num); /* Combination size from argument */
7460 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7461 len = RARRAY_LEN(ary);
7462 if (n < 0) {
7463 /* yield nothing */
7465 else if (n == 0) {
7466 rb_yield(rb_ary_new2(0));
7468 else if (n == 1) {
7469 for (i = 0; i < RARRAY_LEN(ary); i++) {
7470 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7473 else if (len == 0) {
7474 /* yield nothing */
7476 else {
7477 volatile VALUE t0;
7478 long *p = ALLOCV_N(long, t0, n);
7479 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7480 RBASIC_CLEAR_CLASS(ary0);
7482 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7483 ALLOCV_END(t0);
7484 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7486 return ary;
7490 * call-seq:
7491 * product(*other_arrays) -> new_array
7492 * product(*other_arrays) {|combination| ... } -> self
7494 * Computes all combinations of elements from all the arrays,
7495 * including both +self+ and +other_arrays+:
7497 * - The number of combinations is the product of the sizes of all the arrays,
7498 * including both +self+ and +other_arrays+.
7499 * - The order of the returned combinations is indeterminate.
7501 * With no block given, returns the combinations as an array of arrays:
7503 * p = [0, 1].product([2, 3])
7504 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7505 * p.size # => 4
7506 * p = [0, 1].product([2, 3], [4, 5])
7507 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7508 * p.size # => 8
7510 * If +self+ or any argument is empty, returns an empty array:
7512 * [].product([2, 3], [4, 5]) # => []
7513 * [0, 1].product([2, 3], []) # => []
7515 * If no argument is given, returns an array of 1-element arrays,
7516 * each containing an element of +self+:
7518 * a.product # => [[0], [1], [2]]
7520 * With a block given, calls the block with each combination; returns +self+:
7522 * p = []
7523 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7524 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7526 * If +self+ or any argument is empty, does not call the block:
7528 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7529 * # => []
7530 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7531 * # => [0, 1]
7533 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7535 * p = []
7536 * [0, 1].product {|combination| p.push(combination) }
7537 * p # => [[0], [1]]
7539 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7542 static VALUE
7543 rb_ary_product(int argc, VALUE *argv, VALUE ary)
7545 int n = argc+1; /* How many arrays we're operating on */
7546 volatile VALUE t0 = rb_ary_hidden_new(n);
7547 volatile VALUE t1 = Qundef;
7548 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7549 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
7550 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7551 long i,j;
7552 long resultlen = 1;
7554 RBASIC_CLEAR_CLASS(t0);
7556 /* initialize the arrays of arrays */
7557 ARY_SET_LEN(t0, n);
7558 arrays[0] = ary;
7559 for (i = 1; i < n; i++) arrays[i] = Qnil;
7560 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7562 /* initialize the counters for the arrays */
7563 for (i = 0; i < n; i++) counters[i] = 0;
7565 /* Otherwise, allocate and fill in an array of results */
7566 if (rb_block_given_p()) {
7567 /* Make defensive copies of arrays; exit if any is empty */
7568 for (i = 0; i < n; i++) {
7569 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7570 arrays[i] = ary_make_shared_copy(arrays[i]);
7573 else {
7574 /* Compute the length of the result array; return [] if any is empty */
7575 for (i = 0; i < n; i++) {
7576 long k = RARRAY_LEN(arrays[i]);
7577 if (k == 0) {
7578 result = rb_ary_new2(0);
7579 goto done;
7581 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7582 rb_raise(rb_eRangeError, "too big to product");
7583 resultlen *= k;
7585 result = rb_ary_new2(resultlen);
7587 for (;;) {
7588 int m;
7589 /* fill in one subarray */
7590 VALUE subarray = rb_ary_new2(n);
7591 for (j = 0; j < n; j++) {
7592 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7595 /* put it on the result array */
7596 if (NIL_P(result)) {
7597 FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
7598 rb_yield(subarray);
7599 if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
7600 rb_raise(rb_eRuntimeError, "product reentered");
7602 else {
7603 FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
7606 else {
7607 rb_ary_push(result, subarray);
7611 * Increment the last counter. If it overflows, reset to 0
7612 * and increment the one before it.
7614 m = n-1;
7615 counters[m]++;
7616 while (counters[m] == RARRAY_LEN(arrays[m])) {
7617 counters[m] = 0;
7618 /* If the first counter overflows, we are done */
7619 if (--m < 0) goto done;
7620 counters[m]++;
7624 done:
7625 ALLOCV_END(t1);
7627 return NIL_P(result) ? ary : result;
7631 * call-seq:
7632 * take(count) -> new_array
7634 * Returns a new array containing the first +count+ element of +self+
7635 * (as available);
7636 * +count+ must be a non-negative numeric;
7637 * does not modify +self+:
7639 * a = ['a', 'b', 'c', 'd']
7640 * a.take(2) # => ["a", "b"]
7641 * a.take(2.1) # => ["a", "b"]
7642 * a.take(50) # => ["a", "b", "c", "d"]
7643 * a.take(0) # => []
7645 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7648 static VALUE
7649 rb_ary_take(VALUE obj, VALUE n)
7651 long len = NUM2LONG(n);
7652 if (len < 0) {
7653 rb_raise(rb_eArgError, "attempt to take negative size");
7655 return rb_ary_subseq(obj, 0, len);
7659 * call-seq:
7660 * take_while {|element| ... } -> new_array
7661 * take_while -> new_enumerator
7663 * With a block given, calls the block with each successive element of +self+;
7664 * stops iterating if the block returns +false+ or +nil+;
7665 * returns a new array containing those elements for which the block returned a truthy value:
7667 * a = [0, 1, 2, 3, 4, 5]
7668 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7669 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7670 * a.take_while {|element| false } # => []
7672 * With no block given, returns a new Enumerator.
7674 * Does not modify +self+.
7676 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7679 static VALUE
7680 rb_ary_take_while(VALUE ary)
7682 long i;
7684 RETURN_ENUMERATOR(ary, 0, 0);
7685 for (i = 0; i < RARRAY_LEN(ary); i++) {
7686 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7688 return rb_ary_take(ary, LONG2FIX(i));
7692 * call-seq:
7693 * drop(count) -> new_array
7695 * Returns a new array containing all but the first +count+ element of +self+,
7696 * where +count+ is a non-negative integer;
7697 * does not modify +self+.
7699 * Examples:
7701 * a = [0, 1, 2, 3, 4, 5]
7702 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7703 * a.drop(1) # => [1, 2, 3, 4, 5]
7704 * a.drop(2) # => [2, 3, 4, 5]
7705 * a.drop(9) # => []
7707 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7710 static VALUE
7711 rb_ary_drop(VALUE ary, VALUE n)
7713 VALUE result;
7714 long pos = NUM2LONG(n);
7715 if (pos < 0) {
7716 rb_raise(rb_eArgError, "attempt to drop negative size");
7719 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
7720 if (NIL_P(result)) result = rb_ary_new();
7721 return result;
7725 * call-seq:
7726 * drop_while {|element| ... } -> new_array
7727 * drop_while -> new_enumerator
7729 * With a block given, calls the block with each successive element of +self+;
7730 * stops if the block returns +false+ or +nil+;
7731 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7732 * does not modify +self+:
7734 * a = [0, 1, 2, 3, 4, 5]
7735 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7737 * With no block given, returns a new Enumerator.
7739 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7742 static VALUE
7743 rb_ary_drop_while(VALUE ary)
7745 long i;
7747 RETURN_ENUMERATOR(ary, 0, 0);
7748 for (i = 0; i < RARRAY_LEN(ary); i++) {
7749 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7751 return rb_ary_drop(ary, LONG2FIX(i));
7755 * call-seq:
7756 * any? -> true or false
7757 * any?(object) -> true or false
7758 * any? {|element| ... } -> true or false
7760 * Returns whether for any element of +self+, a given criterion is satisfied.
7762 * With no block and no argument, returns whether any element of +self+ is truthy:
7764 * [nil, false, []].any? # => true # Array object is truthy.
7765 * [nil, false, {}].any? # => true # Hash object is truthy.
7766 * [nil, false, ''].any? # => true # String object is truthy.
7767 * [nil, false].any? # => false # Nil and false are not truthy.
7769 * With argument +object+ given,
7770 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7772 * [nil, false, 0].any?(0) # => true
7773 * [nil, false, 1].any?(0) # => false
7774 * [nil, false, 'food'].any?(/foo/) # => true
7775 * [nil, false, 'food'].any?(/bar/) # => false
7777 * With a block given,
7778 * calls the block with each element in +self+;
7779 * returns whether the block returns any truthy value:
7781 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7782 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7784 * With both a block and argument +object+ given,
7785 * ignores the block and uses +object+ as above.
7787 * <b>Special case</b>: returns +false+ if +self+ is empty
7788 * (regardless of any given argument or block).
7790 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7793 static VALUE
7794 rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
7796 long i, len = RARRAY_LEN(ary);
7798 rb_check_arity(argc, 0, 1);
7799 if (!len) return Qfalse;
7800 if (argc) {
7801 if (rb_block_given_p()) {
7802 rb_warn("given block not used");
7804 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7805 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
7808 else if (!rb_block_given_p()) {
7809 for (i = 0; i < len; ++i) {
7810 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
7813 else {
7814 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7815 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
7818 return Qfalse;
7822 * call-seq:
7823 * all? -> true or false
7824 * all?(object) -> true or false
7825 * all? {|element| ... } -> true or false
7827 * Returns whether for every element of +self+,
7828 * a given criterion is satisfied.
7830 * With no block and no argument,
7831 * returns whether every element of +self+ is truthy:
7833 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7834 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7835 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7837 * With argument +object+ given, returns whether <tt>object === ele</tt>
7838 * for every element +ele+ in +self+:
7840 * [0, 0, 0].all?(0) # => true
7841 * [0, 1, 2].all?(1) # => false
7842 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7843 * ['food', 'drink'].all?(/foo/) # => false
7845 * With a block given, calls the block with each element in +self+;
7846 * returns whether the block returns only truthy values:
7848 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7849 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7851 * With both a block and argument +object+ given,
7852 * ignores the block and uses +object+ as above.
7854 * <b>Special case</b>: returns +true+ if +self+ is empty
7855 * (regardless of any given argument or block).
7857 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7860 static VALUE
7861 rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
7863 long i, len = RARRAY_LEN(ary);
7865 rb_check_arity(argc, 0, 1);
7866 if (!len) return Qtrue;
7867 if (argc) {
7868 if (rb_block_given_p()) {
7869 rb_warn("given block not used");
7871 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7872 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7875 else if (!rb_block_given_p()) {
7876 for (i = 0; i < len; ++i) {
7877 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7880 else {
7881 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7882 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7885 return Qtrue;
7889 * call-seq:
7890 * none? -> true or false
7891 * none?(object) -> true or false
7892 * none? {|element| ... } -> true or false
7894 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
7896 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7897 * +false+ otherwise:
7899 * [nil, false].none? # => true
7900 * [nil, 0, false].none? # => false
7901 * [].none? # => true
7903 * With argument +object+ given, returns +false+ if for any element +element+,
7904 * <tt>object === element</tt>; +true+ otherwise:
7906 * ['food', 'drink'].none?(/bar/) # => true
7907 * ['food', 'drink'].none?(/foo/) # => false
7908 * [].none?(/foo/) # => true
7909 * [0, 1, 2].none?(3) # => true
7910 * [0, 1, 2].none?(1) # => false
7912 * With a block given, calls the block with each element in +self+;
7913 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7915 * [0, 1, 2].none? {|element| element > 3 } # => true
7916 * [0, 1, 2].none? {|element| element > 1 } # => false
7918 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7921 static VALUE
7922 rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
7924 long i, len = RARRAY_LEN(ary);
7926 rb_check_arity(argc, 0, 1);
7927 if (!len) return Qtrue;
7928 if (argc) {
7929 if (rb_block_given_p()) {
7930 rb_warn("given block not used");
7932 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7933 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7936 else if (!rb_block_given_p()) {
7937 for (i = 0; i < len; ++i) {
7938 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7941 else {
7942 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7943 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7946 return Qtrue;
7950 * call-seq:
7951 * one? -> true or false
7952 * one? {|element| ... } -> true or false
7953 * one?(object) -> true or false
7955 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7957 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7958 * +false+ otherwise:
7960 * [nil, 0].one? # => true
7961 * [0, 0].one? # => false
7962 * [nil, nil].one? # => false
7963 * [].one? # => false
7965 * With a block given, calls the block with each element in +self+;
7966 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7968 * [0, 1, 2].one? {|element| element > 0 } # => false
7969 * [0, 1, 2].one? {|element| element > 1 } # => true
7970 * [0, 1, 2].one? {|element| element > 2 } # => false
7972 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
7973 * +false+ otherwise:
7975 * [0, 1, 2].one?(0) # => true
7976 * [0, 0, 1].one?(0) # => false
7977 * [1, 1, 2].one?(0) # => false
7978 * ['food', 'drink'].one?(/bar/) # => false
7979 * ['food', 'drink'].one?(/foo/) # => true
7980 * [].one?(/foo/) # => false
7982 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7985 static VALUE
7986 rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
7988 long i, len = RARRAY_LEN(ary);
7989 VALUE result = Qfalse;
7991 rb_check_arity(argc, 0, 1);
7992 if (!len) return Qfalse;
7993 if (argc) {
7994 if (rb_block_given_p()) {
7995 rb_warn("given block not used");
7997 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7998 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
7999 if (result) return Qfalse;
8000 result = Qtrue;
8004 else if (!rb_block_given_p()) {
8005 for (i = 0; i < len; ++i) {
8006 if (RTEST(RARRAY_AREF(ary, i))) {
8007 if (result) return Qfalse;
8008 result = Qtrue;
8012 else {
8013 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8014 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
8015 if (result) return Qfalse;
8016 result = Qtrue;
8020 return result;
8024 * call-seq:
8025 * dig(index, *identifiers) -> object
8027 * Finds and returns the object in nested object
8028 * specified by +index+ and +identifiers+;
8029 * the nested objects may be instances of various classes.
8030 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
8032 * Examples:
8034 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
8035 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
8036 * a.dig(1, 2) # => [:bat, :bam]
8037 * a.dig(1, 2, 0) # => :bat
8038 * a.dig(1, 2, 3) # => nil
8040 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8043 static VALUE
8044 rb_ary_dig(int argc, VALUE *argv, VALUE self)
8046 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
8047 self = rb_ary_at(self, *argv);
8048 if (!--argc) return self;
8049 ++argv;
8050 return rb_obj_dig(argc, argv, self, Qnil);
8053 static inline VALUE
8054 finish_exact_sum(long n, VALUE r, VALUE v, int z)
8056 if (n != 0)
8057 v = rb_fix_plus(LONG2FIX(n), v);
8058 if (!UNDEF_P(r)) {
8059 v = rb_rational_plus(r, v);
8061 else if (!n && z) {
8062 v = rb_fix_plus(LONG2FIX(0), v);
8064 return v;
8068 * call-seq:
8069 * sum(init = 0) -> object
8070 * sum(init = 0) {|element| ... } -> object
8072 * With no block given, returns the sum of +init+ and all elements of +self+;
8073 * for array +array+ and value +init+, equivalent to:
8075 * sum = init
8076 * array.each {|element| sum += element }
8077 * sum
8079 * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
8081 * Examples:
8083 * [0, 1, 2, 3].sum # => 6
8084 * [0, 1, 2, 3].sum(100) # => 106
8085 * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
8086 * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
8087 * # => [2, 3, :foo, :bar, "foo", "bar"]
8089 * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
8091 * # Raises TypeError: Array can't be coerced into Integer.
8092 * [[:foo, :bar], ['foo', 'bar']].sum(2)
8094 * With a block given, calls the block with each element of +self+;
8095 * the block's return value (instead of the element itself) is used as the addend:
8097 * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
8098 * # => "Coerced and concatenated: zero1two"
8100 * Notes:
8102 * - Array#join and Array#flatten may be faster than Array#sum
8103 * for an array of strings or an array of arrays.
8104 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8108 static VALUE
8109 rb_ary_sum(int argc, VALUE *argv, VALUE ary)
8111 VALUE e, v, r;
8112 long i, n;
8113 int block_given;
8115 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
8117 block_given = rb_block_given_p();
8119 if (RARRAY_LEN(ary) == 0)
8120 return v;
8122 n = 0;
8123 r = Qundef;
8125 if (!FIXNUM_P(v) && !RB_BIGNUM_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
8126 i = 0;
8127 goto init_is_a_value;
8130 for (i = 0; i < RARRAY_LEN(ary); i++) {
8131 e = RARRAY_AREF(ary, i);
8132 if (block_given)
8133 e = rb_yield(e);
8134 if (FIXNUM_P(e)) {
8135 n += FIX2LONG(e); /* should not overflow long type */
8136 if (!FIXABLE(n)) {
8137 v = rb_big_plus(LONG2NUM(n), v);
8138 n = 0;
8141 else if (RB_BIGNUM_TYPE_P(e))
8142 v = rb_big_plus(e, v);
8143 else if (RB_TYPE_P(e, T_RATIONAL)) {
8144 if (UNDEF_P(r))
8145 r = e;
8146 else
8147 r = rb_rational_plus(r, e);
8149 else
8150 goto not_exact;
8152 v = finish_exact_sum(n, r, v, argc!=0);
8153 return v;
8155 not_exact:
8156 v = finish_exact_sum(n, r, v, i!=0);
8158 if (RB_FLOAT_TYPE_P(e)) {
8160 * Kahan-Babuska balancing compensated summation algorithm
8161 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8163 double f, c;
8164 double x, t;
8166 f = NUM2DBL(v);
8167 c = 0.0;
8168 goto has_float_value;
8169 for (; i < RARRAY_LEN(ary); i++) {
8170 e = RARRAY_AREF(ary, i);
8171 if (block_given)
8172 e = rb_yield(e);
8173 if (RB_FLOAT_TYPE_P(e))
8174 has_float_value:
8175 x = RFLOAT_VALUE(e);
8176 else if (FIXNUM_P(e))
8177 x = FIX2LONG(e);
8178 else if (RB_BIGNUM_TYPE_P(e))
8179 x = rb_big2dbl(e);
8180 else if (RB_TYPE_P(e, T_RATIONAL))
8181 x = rb_num2dbl(e);
8182 else
8183 goto not_float;
8185 if (isnan(f)) continue;
8186 if (isnan(x)) {
8187 f = x;
8188 continue;
8190 if (isinf(x)) {
8191 if (isinf(f) && signbit(x) != signbit(f))
8192 f = NAN;
8193 else
8194 f = x;
8195 continue;
8197 if (isinf(f)) continue;
8199 t = f + x;
8200 if (fabs(f) >= fabs(x))
8201 c += ((f - t) + x);
8202 else
8203 c += ((x - t) + f);
8204 f = t;
8206 f += c;
8207 return DBL2NUM(f);
8209 not_float:
8210 v = DBL2NUM(f);
8213 goto has_some_value;
8214 init_is_a_value:
8215 for (; i < RARRAY_LEN(ary); i++) {
8216 e = RARRAY_AREF(ary, i);
8217 if (block_given)
8218 e = rb_yield(e);
8219 has_some_value:
8220 v = rb_funcall(v, idPLUS, 1, e);
8222 return v;
8225 /* :nodoc: */
8226 static VALUE
8227 rb_ary_deconstruct(VALUE ary)
8229 return ary;
8233 * An \Array object is an ordered, integer-indexed collection of objects,
8234 * called _elements_;
8235 * the object represents
8236 * an {array data structure}[https://en.wikipedia.org/wiki/Array_(data_structure)].
8238 * An element may be any object (even another array);
8239 * elements may be any mixture of objects of different types.
8241 * Important data structures that use arrays include:
8243 * - {Coordinate vector}[https://en.wikipedia.org/wiki/Coordinate_vector].
8244 * - {Matrix}[https://en.wikipedia.org/wiki/Matrix_(mathematics)].
8245 * - {Heap}[https://en.wikipedia.org/wiki/Heap_(data_structure)].
8246 * - {Hash table}[https://en.wikipedia.org/wiki/Hash_table].
8247 * - {Deque (double-ended queue)}[https://en.wikipedia.org/wiki/Double-ended_queue].
8248 * - {Queue}[https://en.wikipedia.org/wiki/Queue_(abstract_data_type)].
8249 * - {Stack}[https://en.wikipedia.org/wiki/Stack_(abstract_data_type)].
8251 * There are also array-like data structures:
8253 * - {Associative array}[https://en.wikipedia.org/wiki/Associative_array] (see Hash).
8254 * - {Directory}[https://en.wikipedia.org/wiki/Directory_(computing)] (see Dir).
8255 * - {Environment}[https://en.wikipedia.org/wiki/Environment_variable] (see ENV).
8256 * - {Set}[https://en.wikipedia.org/wiki/Set_(abstract_data_type)] (see Set).
8257 * - {String}[https://en.wikipedia.org/wiki/String_(computer_science)] (see String).
8259 * == \Array Indexes
8261 * \Array indexing starts at 0, as in C or Java.
8263 * A non-negative index is an offset from the first element:
8265 * - Index 0 indicates the first element.
8266 * - Index 1 indicates the second element.
8267 * - ...
8269 * A negative index is an offset, backwards, from the end of the array:
8271 * - Index -1 indicates the last element.
8272 * - Index -2 indicates the next-to-last element.
8273 * - ...
8276 * === In-Range and Out-of-Range Indexes
8278 * A non-negative index is <i>in range</i> if and only if it is smaller than
8279 * the size of the array. For a 3-element array:
8281 * - Indexes 0 through 2 are in range.
8282 * - Index 3 is out of range.
8284 * A negative index is <i>in range</i> if and only if its absolute value is
8285 * not larger than the size of the array. For a 3-element array:
8287 * - Indexes -1 through -3 are in range.
8288 * - Index -4 is out of range.
8290 * === Effective Index
8292 * Although the effective index into an array is always an integer,
8293 * some methods (both within class \Array and elsewhere)
8294 * accept one or more non-integer arguments that are
8295 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8297 * == Creating Arrays
8299 * You can create an \Array object explicitly with:
8301 * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
8303 * [1, 'one', :one, [2, 'two', :two]]
8305 * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8307 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8308 * %w[1 % *] # => ["1", "%", "*"]
8310 * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8312 * %i[foo bar baz] # => [:foo, :bar, :baz]
8313 * %i[1 % *] # => [:"1", :%, :*]
8315 * - Method Kernel#Array:
8317 * Array(["a", "b"]) # => ["a", "b"]
8318 * Array(1..5) # => [1, 2, 3, 4, 5]
8319 * Array(key: :value) # => [[:key, :value]]
8320 * Array(nil) # => []
8321 * Array(1) # => [1]
8322 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8324 * - Method Array.new:
8326 * Array.new # => []
8327 * Array.new(3) # => [nil, nil, nil]
8328 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8329 * Array.new(3, true) # => [true, true, true]
8331 * Note that the last example above populates the array
8332 * with references to the same object.
8333 * This is recommended only in cases where that object is a natively immutable object
8334 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8336 * Another way to create an array with various objects, using a block;
8337 * this usage is safe for mutable objects such as hashes, strings or
8338 * other arrays:
8340 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8342 * Here is a way to create a multi-dimensional array:
8344 * Array.new(3) {Array.new(3)}
8345 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8347 * A number of Ruby methods, both in the core and in the standard library,
8348 * provide instance method +to_a+, which converts an object to an array.
8350 * - ARGF#to_a
8351 * - Array#to_a
8352 * - Enumerable#to_a
8353 * - Hash#to_a
8354 * - MatchData#to_a
8355 * - NilClass#to_a
8356 * - OptionParser#to_a
8357 * - Range#to_a
8358 * - Set#to_a
8359 * - Struct#to_a
8360 * - Time#to_a
8361 * - Benchmark::Tms#to_a
8362 * - CSV::Table#to_a
8363 * - Enumerator::Lazy#to_a
8364 * - Gem::List#to_a
8365 * - Gem::NameTuple#to_a
8366 * - Gem::Platform#to_a
8367 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8368 * - Gem::SourceList#to_a
8369 * - OpenSSL::X509::Extension#to_a
8370 * - OpenSSL::X509::Name#to_a
8371 * - Racc::ISet#to_a
8372 * - Rinda::RingFinger#to_a
8373 * - Ripper::Lexer::Elem#to_a
8374 * - RubyVM::InstructionSequence#to_a
8375 * - YAML::DBM#to_a
8377 * == Example Usage
8379 * In addition to the methods it mixes in through the Enumerable module,
8380 * class \Array has proprietary methods for accessing, searching and otherwise
8381 * manipulating arrays.
8383 * Some of the more common ones are illustrated below.
8385 * == Accessing Elements
8387 * Elements in an array can be retrieved using the Array#[] method. It can
8388 * take a single integer argument (a numeric index), a pair of arguments
8389 * (start and length) or a range. Negative indices start counting from the end,
8390 * with -1 being the last element.
8392 * arr = [1, 2, 3, 4, 5, 6]
8393 * arr[2] #=> 3
8394 * arr[100] #=> nil
8395 * arr[-3] #=> 4
8396 * arr[2, 3] #=> [3, 4, 5]
8397 * arr[1..4] #=> [2, 3, 4, 5]
8398 * arr[1..-3] #=> [2, 3, 4]
8400 * Another way to access a particular array element is by using the #at method
8402 * arr.at(0) #=> 1
8404 * The #slice method works in an identical manner to Array#[].
8406 * To raise an error for indices outside of the array bounds or else to
8407 * provide a default value when that happens, you can use #fetch.
8409 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8410 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8411 * arr.fetch(100, "oops") #=> "oops"
8413 * The special methods #first and #last will return the first and last
8414 * elements of an array, respectively.
8416 * arr.first #=> 1
8417 * arr.last #=> 6
8419 * To return the first +n+ elements of an array, use #take
8421 * arr.take(3) #=> [1, 2, 3]
8423 * #drop does the opposite of #take, by returning the elements after +n+
8424 * elements have been dropped:
8426 * arr.drop(3) #=> [4, 5, 6]
8428 * == Obtaining Information about an \Array
8430 * An array keeps track of its own length at all times. To query an array
8431 * about the number of elements it contains, use #length, #count or #size.
8433 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8434 * browsers.length #=> 5
8435 * browsers.count #=> 5
8437 * To check whether an array contains any elements at all
8439 * browsers.empty? #=> false
8441 * To check whether a particular item is included in the array
8443 * browsers.include?('Konqueror') #=> false
8445 * == Adding Items to an \Array
8447 * Items can be added to the end of an array by using either #push or #<<
8449 * arr = [1, 2, 3, 4]
8450 * arr.push(5) #=> [1, 2, 3, 4, 5]
8451 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8453 * #unshift will add a new item to the beginning of an array.
8455 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8457 * With #insert you can add a new element to an array at any position.
8459 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8461 * Using the #insert method, you can also insert multiple values at once:
8463 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8464 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8466 * == Removing Items from an \Array
8468 * The method #pop removes the last element in an array and returns it:
8470 * arr = [1, 2, 3, 4, 5, 6]
8471 * arr.pop #=> 6
8472 * arr #=> [1, 2, 3, 4, 5]
8474 * To retrieve and at the same time remove the first item, use #shift:
8476 * arr.shift #=> 1
8477 * arr #=> [2, 3, 4, 5]
8479 * To delete an element at a particular index:
8481 * arr.delete_at(2) #=> 4
8482 * arr #=> [2, 3, 5]
8484 * To delete a particular element anywhere in an array, use #delete:
8486 * arr = [1, 2, 2, 3]
8487 * arr.delete(2) #=> 2
8488 * arr #=> [1,3]
8490 * A useful method if you need to remove +nil+ values from an array is
8491 * #compact:
8493 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8494 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8495 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8496 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8497 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8499 * Another common need is to remove duplicate elements from an array.
8501 * It has the non-destructive #uniq, and destructive method #uniq!
8503 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8504 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8506 * == Iterating over an \Array
8508 * Like all classes that include the Enumerable module, class \Array has an each
8509 * method, which defines what elements should be iterated over and how. In
8510 * case of Array#each, all elements in +self+ are yielded to
8511 * the supplied block in sequence.
8513 * Note that this operation leaves the array unchanged.
8515 * arr = [1, 2, 3, 4, 5]
8516 * arr.each {|a| print a -= 10, " "}
8517 * # prints: -9 -8 -7 -6 -5
8518 * #=> [1, 2, 3, 4, 5]
8520 * Another sometimes useful iterator is #reverse_each which will iterate over
8521 * the elements in the array in reverse order.
8523 * words = %w[first second third fourth fifth sixth]
8524 * str = ""
8525 * words.reverse_each {|word| str += "#{word} "}
8526 * p str #=> "sixth fifth fourth third second first "
8528 * The #map method can be used to create a new array based on the original
8529 * array, but with the values modified by the supplied block:
8531 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8532 * arr #=> [1, 2, 3, 4, 5]
8533 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8534 * arr #=> [1, 4, 9, 16, 25]
8537 * == Selecting Items from an \Array
8539 * Elements can be selected from an array according to criteria defined in a
8540 * block. The selection can happen in a destructive or a non-destructive
8541 * manner. While the destructive operations will modify the array they were
8542 * called on, the non-destructive methods usually return a new array with the
8543 * selected elements, but leave the original array unchanged.
8545 * === Non-destructive Selection
8547 * arr = [1, 2, 3, 4, 5, 6]
8548 * arr.select {|a| a > 3} #=> [4, 5, 6]
8549 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8550 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8551 * arr #=> [1, 2, 3, 4, 5, 6]
8553 * === Destructive Selection
8555 * #select! and #reject! are the corresponding destructive methods to #select
8556 * and #reject
8558 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8559 * opposite result when supplied with the same block:
8561 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8562 * arr #=> [4, 5, 6]
8564 * arr = [1, 2, 3, 4, 5, 6]
8565 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8566 * arr #=> [1, 2, 3]
8568 * == What's Here
8570 * First, what's elsewhere. Class \Array:
8572 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8573 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8574 * which provides dozens of additional methods.
8576 * Here, class \Array provides methods that are useful for:
8578 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8579 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8580 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8581 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8582 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8583 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8584 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8585 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8586 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8587 * - {And more....}[rdoc-ref:Array@Other+Methods]
8589 * === Methods for Creating an \Array
8591 * - ::[]: Returns a new array populated with given objects.
8592 * - ::new: Returns a new array.
8593 * - ::try_convert: Returns a new array created from a given object.
8595 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8597 * === Methods for Querying
8599 * - #all?: Returns whether all elements meet a given criterion.
8600 * - #any?: Returns whether any element meets a given criterion.
8601 * - #count: Returns the count of elements that meet a given criterion.
8602 * - #empty?: Returns whether there are no elements.
8603 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8604 * - #hash: Returns the integer hash code.
8605 * - #include?: Returns whether any element <tt>==</tt> a given object.
8606 * - #length (aliased as #size): Returns the count of elements.
8607 * - #none?: Returns whether no element <tt>==</tt> a given object.
8608 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8609 * - #rindex: Returns the index of the last element that meets a given criterion.
8611 * === Methods for Comparing
8613 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or greater than a given object.
8614 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element in a given object.
8615 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding element in a given object.
8617 * === Methods for Fetching
8619 * These methods do not modify +self+.
8621 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8622 * - #assoc: Returns the first element that is an array whose first element <tt>==</tt> a given object.
8623 * - #at: Returns the element at a given offset.
8624 * - #bsearch: Returns an element selected via a binary search as determined by a given block.
8625 * - #bsearch_index: Returns the index of an element selected via a binary search as determined by a given block.
8626 * - #compact: Returns an array containing all non-+nil+ elements.
8627 * - #dig: Returns the object in nested objects that is specified by a given index and additional arguments.
8628 * - #drop: Returns trailing elements as determined by a given index.
8629 * - #drop_while: Returns trailing elements as determined by a given block.
8630 * - #fetch: Returns the element at a given offset.
8631 * - #fetch_values: Returns elements at given offsets.
8632 * - #first: Returns one or more leading elements.
8633 * - #last: Returns one or more trailing elements.
8634 * - #max: Returns one or more maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8635 * - #min: Returns one or more minimum-valued elements, as determined by <tt>#<=></tt> or a given block.
8636 * - #minmax: Returns the minimum-valued and maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8637 * - #rassoc: Returns the first element that is an array whose second element <tt>==</tt> a given object.
8638 * - #reject: Returns an array containing elements not rejected by a given block.
8639 * - #reverse: Returns all elements in reverse order.
8640 * - #rotate: Returns all elements with some rotated from one end to the other.
8641 * - #sample: Returns one or more random elements.
8642 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8643 * - #shuffle: Returns elements in a random order.
8644 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8645 * - #take: Returns leading elements as determined by a given index.
8646 * - #take_while: Returns leading elements as determined by a given block.
8647 * - #uniq: Returns an array containing non-duplicate elements.
8648 * - #values_at: Returns the elements at given offsets.
8650 * === Methods for Assigning
8652 * These methods add, replace, or reorder elements in +self+.
8654 * - #<<: Appends an element.
8655 * - #[]=: Assigns specified elements with a given object.
8656 * - #concat: Appends all elements from given arrays.
8657 * - #fill: Replaces specified elements with specified objects.
8658 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8659 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8660 * - #insert: Inserts given objects at a given offset; does not replace elements.
8661 * - #push (aliased as #append): Appends elements.
8662 * - #reverse!: Replaces +self+ with its elements reversed.
8663 * - #rotate!: Replaces +self+ with its elements rotated.
8664 * - #shuffle!: Replaces +self+ with its elements in random order.
8665 * - #sort!: Replaces +self+ with its elements sorted, as determined by <tt>#<=></tt> or a given block.
8666 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8667 * - #unshift (aliased as #prepend): Prepends leading elements.
8669 * === Methods for Deleting
8671 * Each of these methods removes elements from +self+:
8673 * - #clear: Removes all elements.
8674 * - #compact!: Removes all +nil+ elements.
8675 * - #delete: Removes elements equal to a given object.
8676 * - #delete_at: Removes the element at a given offset.
8677 * - #delete_if: Removes elements specified by a given block.
8678 * - #keep_if: Removes elements not specified by a given block.
8679 * - #pop: Removes and returns the last element.
8680 * - #reject!: Removes elements specified by a given block.
8681 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8682 * - #shift: Removes and returns the first element.
8683 * - #slice!: Removes and returns a sequence of elements.
8684 * - #uniq!: Removes duplicates.
8686 * === Methods for Combining
8688 * - #&: Returns an array containing elements found both in +self+ and a given array.
8689 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8690 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8691 * - #|: Returns an array containing all element of +self+ and all elements of a given array, duplicates removed.
8692 * - #difference: Returns an array containing all elements of +self+ that are not found in any of the given arrays..
8693 * - #intersection: Returns an array containing elements found both in +self+ and in each given array.
8694 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8695 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8696 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, duplicates removed.
8698 * === Methods for Iterating
8700 * - #combination: Calls a given block with combinations of elements of +self+; a combination does not use the same element more than once.
8701 * - #cycle: Calls a given block with each element, then does so again, for a specified number of times, or forever.
8702 * - #each: Passes each element to a given block.
8703 * - #each_index: Passes each element index to a given block.
8704 * - #permutation: Calls a given block with permutations of elements of +self+; a permutation does not use the same element more than once.
8705 * - #repeated_combination: Calls a given block with combinations of elements of +self+; a combination may use the same element more than once.
8706 * - #repeated_permutation: Calls a given block with permutations of elements of +self+; a permutation may use the same element more than once.
8707 * - #reverse_each: Passes each element, in reverse order, to a given block.
8709 * === Methods for Converting
8711 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8712 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8713 * - #flatten: Returns an array that is a recursive flattening of +self+.
8714 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8715 * - #join: Returns a newsString containing the elements joined by the field separator.
8716 * - #to_a: Returns +self+ or a new array containing all elements.
8717 * - #to_ary: Returns +self+.
8718 * - #to_h: Returns a new hash formed from the elements.
8719 * - #transpose: Transposes +self+, which must be an array of arrays.
8720 * - #zip: Returns a new array of arrays containing +self+ and given arrays.
8722 * === Other Methods
8724 * - #*: Returns one of the following:
8726 * - With integer argument +n+, a new array that is the concatenation
8727 * of +n+ copies of +self+.
8728 * - With string argument +field_separator+, a new string that is equivalent to
8729 * <tt>join(field_separator)</tt>.
8731 * - #pack: Packs the elements into a binary sequence.
8732 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8735 void
8736 Init_Array(void)
8738 fake_ary_flags = init_fake_ary_flags();
8740 rb_cArray = rb_define_class("Array", rb_cObject);
8741 rb_include_module(rb_cArray, rb_mEnumerable);
8743 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
8744 rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
8745 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
8746 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
8747 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
8748 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
8750 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
8751 rb_define_alias(rb_cArray, "to_s", "inspect");
8752 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
8753 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
8754 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
8756 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
8757 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
8758 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
8760 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
8761 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
8762 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
8763 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
8764 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
8765 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
8766 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
8767 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
8768 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
8769 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
8770 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
8771 rb_define_alias(rb_cArray, "append", "push");
8772 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
8773 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
8774 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
8775 rb_define_alias(rb_cArray, "prepend", "unshift");
8776 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
8777 rb_define_method(rb_cArray, "each", rb_ary_each, 0);
8778 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
8779 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
8780 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
8781 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
8782 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
8783 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
8784 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
8785 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
8786 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
8787 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
8788 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
8789 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
8790 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
8791 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
8792 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
8793 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
8794 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
8795 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
8796 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
8797 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
8798 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
8799 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
8800 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
8801 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
8802 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
8803 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
8804 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
8805 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
8806 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
8807 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
8808 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
8809 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
8810 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
8811 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
8812 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
8813 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
8814 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
8815 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
8817 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
8818 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
8820 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
8821 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
8823 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
8824 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
8826 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
8827 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
8828 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
8830 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
8831 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
8832 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
8834 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
8835 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
8836 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
8837 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
8838 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
8839 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
8840 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
8841 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
8842 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
8843 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
8844 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
8845 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
8846 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
8848 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
8849 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
8850 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
8851 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
8852 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
8853 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
8854 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
8855 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
8856 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
8857 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
8858 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
8859 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
8860 rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
8862 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
8864 rb_cArray_empty_frozen = rb_ary_freeze(rb_ary_new());
8865 rb_vm_register_global_object(rb_cArray_empty_frozen);
8868 #include "array.rbinc"